webservices: Allow listeners to be cancelled.
Signed-off-by: Hans Leidekker <hans@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
5f7848595f
commit
350cf6654e
|
@ -1168,39 +1168,39 @@ HRESULT WINAPI WsWriteMessageEnd( WS_CHANNEL *handle, WS_MESSAGE *msg, const WS_
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT channel_accept_tcp( SOCKET socket, WS_CHANNEL *handle )
|
static HRESULT sock_accept( SOCKET socket, HANDLE wait, HANDLE cancel, SOCKET *ret )
|
||||||
{
|
{
|
||||||
struct channel *channel = (struct channel *)handle;
|
HANDLE handles[] = { wait, cancel };
|
||||||
|
ULONG nonblocking = 0;
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
EnterCriticalSection( &channel->cs );
|
if (WSAEventSelect( socket, handles[0], FD_ACCEPT )) return HRESULT_FROM_WIN32( WSAGetLastError() );
|
||||||
|
|
||||||
if (channel->magic != CHANNEL_MAGIC)
|
switch (WSAWaitForMultipleEvents( 2, handles, FALSE, WSA_INFINITE, FALSE ))
|
||||||
{
|
{
|
||||||
LeaveCriticalSection( &channel->cs );
|
case 0:
|
||||||
return E_INVALIDARG;
|
if ((*ret = accept( socket, NULL, NULL )) != -1)
|
||||||
|
{
|
||||||
|
WSAEventSelect( *ret, NULL, 0 );
|
||||||
|
ioctlsocket( *ret, FIONBIO, &nonblocking );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
hr = HRESULT_FROM_WIN32( WSAGetLastError() );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
hr = WS_E_OPERATION_ABORTED;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
hr = HRESULT_FROM_WIN32( WSAGetLastError() );
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((channel->u.tcp.socket = accept( socket, NULL, NULL )) == -1)
|
return hr;
|
||||||
{
|
|
||||||
LeaveCriticalSection( &channel->cs );
|
|
||||||
return HRESULT_FROM_WIN32( WSAGetLastError() );
|
|
||||||
}
|
|
||||||
|
|
||||||
LeaveCriticalSection( &channel->cs );
|
|
||||||
return S_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT sock_wait( SOCKET socket )
|
HRESULT channel_accept_tcp( SOCKET socket, HANDLE wait, HANDLE cancel, WS_CHANNEL *handle )
|
||||||
{
|
|
||||||
fd_set read;
|
|
||||||
|
|
||||||
FD_ZERO( &read );
|
|
||||||
FD_SET( socket, &read );
|
|
||||||
if (select( socket + 1, &read, NULL, NULL, NULL ) < 0) return HRESULT_FROM_WIN32( WSAGetLastError() );
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT channel_accept_udp( SOCKET socket, WS_CHANNEL *handle )
|
|
||||||
{
|
{
|
||||||
struct channel *channel = (struct channel *)handle;
|
struct channel *channel = (struct channel *)handle;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
@ -1213,7 +1213,54 @@ HRESULT channel_accept_udp( SOCKET socket, WS_CHANNEL *handle )
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((hr = sock_wait( socket )) == S_OK) channel->u.udp.socket = socket;
|
hr = sock_accept( socket, wait, cancel, &channel->u.tcp.socket );
|
||||||
|
|
||||||
|
LeaveCriticalSection( &channel->cs );
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT sock_wait( SOCKET socket, HANDLE wait, HANDLE cancel )
|
||||||
|
{
|
||||||
|
HANDLE handles[] = { wait, cancel };
|
||||||
|
ULONG nonblocking = 0;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
if (WSAEventSelect( socket, handles[0], FD_READ )) return HRESULT_FROM_WIN32( WSAGetLastError() );
|
||||||
|
|
||||||
|
switch (WSAWaitForMultipleEvents( 2, handles, FALSE, WSA_INFINITE, FALSE ))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
hr = S_OK;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
hr = WS_E_OPERATION_ABORTED;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
hr = HRESULT_FROM_WIN32( WSAGetLastError() );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
WSAEventSelect( socket, NULL, 0 );
|
||||||
|
ioctlsocket( socket, FIONBIO, &nonblocking );
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT channel_accept_udp( SOCKET socket, HANDLE wait, HANDLE cancel, WS_CHANNEL *handle )
|
||||||
|
{
|
||||||
|
struct channel *channel = (struct channel *)handle;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
EnterCriticalSection( &channel->cs );
|
||||||
|
|
||||||
|
if (channel->magic != CHANNEL_MAGIC)
|
||||||
|
{
|
||||||
|
LeaveCriticalSection( &channel->cs );
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((hr = sock_wait( socket, wait, cancel )) == S_OK) channel->u.udp.socket = socket;
|
||||||
|
|
||||||
LeaveCriticalSection( &channel->cs );
|
LeaveCriticalSection( &channel->cs );
|
||||||
return hr;
|
return hr;
|
||||||
|
|
|
@ -75,6 +75,9 @@ struct listener
|
||||||
WS_CHANNEL_TYPE type;
|
WS_CHANNEL_TYPE type;
|
||||||
WS_CHANNEL_BINDING binding;
|
WS_CHANNEL_BINDING binding;
|
||||||
WS_LISTENER_STATE state;
|
WS_LISTENER_STATE state;
|
||||||
|
HANDLE wait;
|
||||||
|
HANDLE cancel;
|
||||||
|
WS_CHANNEL *channel;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
|
@ -101,6 +104,17 @@ static struct listener *alloc_listener(void)
|
||||||
if (!(ret = heap_alloc_zero( size ))) return NULL;
|
if (!(ret = heap_alloc_zero( size ))) return NULL;
|
||||||
|
|
||||||
ret->magic = LISTENER_MAGIC;
|
ret->magic = LISTENER_MAGIC;
|
||||||
|
if (!(ret->wait = CreateEventW( NULL, FALSE, FALSE, NULL )))
|
||||||
|
{
|
||||||
|
heap_free( ret );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!(ret->cancel = CreateEventW( NULL, FALSE, FALSE, NULL )))
|
||||||
|
{
|
||||||
|
CloseHandle( ret->wait );
|
||||||
|
heap_free( ret );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
InitializeCriticalSection( &ret->cs );
|
InitializeCriticalSection( &ret->cs );
|
||||||
ret->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": listener.cs");
|
ret->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": listener.cs");
|
||||||
|
|
||||||
|
@ -112,6 +126,8 @@ static struct listener *alloc_listener(void)
|
||||||
static void reset_listener( struct listener *listener )
|
static void reset_listener( struct listener *listener )
|
||||||
{
|
{
|
||||||
listener->state = WS_LISTENER_STATE_CREATED;
|
listener->state = WS_LISTENER_STATE_CREATED;
|
||||||
|
SetEvent( listener->cancel );
|
||||||
|
listener->channel = NULL;
|
||||||
|
|
||||||
switch (listener->binding)
|
switch (listener->binding)
|
||||||
{
|
{
|
||||||
|
@ -132,6 +148,10 @@ static void reset_listener( struct listener *listener )
|
||||||
static void free_listener( struct listener *listener )
|
static void free_listener( struct listener *listener )
|
||||||
{
|
{
|
||||||
reset_listener( listener );
|
reset_listener( listener );
|
||||||
|
|
||||||
|
CloseHandle( listener->wait );
|
||||||
|
CloseHandle( listener->cancel );
|
||||||
|
|
||||||
listener->cs.DebugInfo->Spare[0] = 0;
|
listener->cs.DebugInfo->Spare[0] = 0;
|
||||||
DeleteCriticalSection( &listener->cs );
|
DeleteCriticalSection( &listener->cs );
|
||||||
heap_free( listener );
|
heap_free( listener );
|
||||||
|
@ -569,7 +589,8 @@ HRESULT WINAPI WsAcceptChannel( WS_LISTENER *handle, WS_CHANNEL *channel_handle,
|
||||||
WS_ERROR *error )
|
WS_ERROR *error )
|
||||||
{
|
{
|
||||||
struct listener *listener = (struct listener *)handle;
|
struct listener *listener = (struct listener *)handle;
|
||||||
HRESULT hr;
|
HRESULT hr = E_NOTIMPL;
|
||||||
|
HANDLE wait, cancel;
|
||||||
|
|
||||||
TRACE( "%p %p %p %p\n", handle, channel_handle, ctx, error );
|
TRACE( "%p %p %p %p\n", handle, channel_handle, ctx, error );
|
||||||
if (error) FIXME( "ignoring error parameter\n" );
|
if (error) FIXME( "ignoring error parameter\n" );
|
||||||
|
@ -585,27 +606,34 @@ HRESULT WINAPI WsAcceptChannel( WS_LISTENER *handle, WS_CHANNEL *channel_handle,
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listener->state != WS_LISTENER_STATE_OPEN)
|
if (listener->state != WS_LISTENER_STATE_OPEN || listener->channel)
|
||||||
{
|
{
|
||||||
LeaveCriticalSection( &listener->cs );
|
LeaveCriticalSection( &listener->cs );
|
||||||
return WS_E_INVALID_OPERATION;
|
return WS_E_INVALID_OPERATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wait = listener->wait;
|
||||||
|
cancel = listener->cancel;
|
||||||
|
listener->channel = channel_handle;
|
||||||
|
|
||||||
switch (listener->binding)
|
switch (listener->binding)
|
||||||
{
|
{
|
||||||
case WS_TCP_CHANNEL_BINDING:
|
case WS_TCP_CHANNEL_BINDING:
|
||||||
hr = channel_accept_tcp( listener->u.tcp.socket, channel_handle );
|
{
|
||||||
break;
|
SOCKET socket = listener->u.tcp.socket;
|
||||||
|
|
||||||
|
LeaveCriticalSection( &listener->cs );
|
||||||
|
return channel_accept_tcp( socket, wait, cancel, channel_handle );
|
||||||
|
}
|
||||||
case WS_UDP_CHANNEL_BINDING:
|
case WS_UDP_CHANNEL_BINDING:
|
||||||
/* hand over socket on success */
|
{
|
||||||
if ((hr = channel_accept_udp( listener->u.udp.socket, channel_handle )) == S_OK)
|
SOCKET socket = listener->u.udp.socket;
|
||||||
listener->u.udp.socket = -1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
LeaveCriticalSection( &listener->cs );
|
||||||
|
return channel_accept_udp( socket, wait, cancel, channel_handle );
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
FIXME( "listener binding %u not supported\n", listener->binding );
|
FIXME( "listener binding %u not supported\n", listener->binding );
|
||||||
hr = E_NOTIMPL;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,5 +20,5 @@
|
||||||
|
|
||||||
void winsock_init(void) DECLSPEC_HIDDEN;
|
void winsock_init(void) DECLSPEC_HIDDEN;
|
||||||
HRESULT resolve_hostname( const WCHAR *, USHORT, struct sockaddr *, int * ) DECLSPEC_HIDDEN;
|
HRESULT resolve_hostname( const WCHAR *, USHORT, struct sockaddr *, int * ) DECLSPEC_HIDDEN;
|
||||||
HRESULT channel_accept_tcp( SOCKET, WS_CHANNEL * ) DECLSPEC_HIDDEN;
|
HRESULT channel_accept_tcp( SOCKET, HANDLE, HANDLE, WS_CHANNEL * ) DECLSPEC_HIDDEN;
|
||||||
HRESULT channel_accept_udp( SOCKET, WS_CHANNEL * ) DECLSPEC_HIDDEN;
|
HRESULT channel_accept_udp( SOCKET, HANDLE, HANDLE, WS_CHANNEL * ) DECLSPEC_HIDDEN;
|
||||||
|
|
|
@ -282,6 +282,9 @@ static DWORD CALLBACK listener_proc( void *arg )
|
||||||
hr = WsAcceptChannel( listener, channel, NULL, NULL );
|
hr = WsAcceptChannel( listener, channel, NULL, NULL );
|
||||||
ok( hr == S_OK, "got %08x\n", hr );
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
|
|
||||||
|
hr = WsAcceptChannel( listener, channel, NULL, NULL );
|
||||||
|
ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
|
||||||
|
|
||||||
hr = WsCreateMessageForChannel( channel, NULL, 0, &msg, NULL );
|
hr = WsCreateMessageForChannel( channel, NULL, 0, &msg, NULL );
|
||||||
ok( hr == S_OK, "got %08x\n", hr );
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue