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;
|
||||
}
|
||||
|
||||
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 );
|
||||
return E_INVALIDARG;
|
||||
case 0:
|
||||
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)
|
||||
{
|
||||
LeaveCriticalSection( &channel->cs );
|
||||
return HRESULT_FROM_WIN32( WSAGetLastError() );
|
||||
}
|
||||
|
||||
LeaveCriticalSection( &channel->cs );
|
||||
return S_OK;
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT sock_wait( SOCKET socket )
|
||||
{
|
||||
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 )
|
||||
HRESULT channel_accept_tcp( SOCKET socket, HANDLE wait, HANDLE cancel, WS_CHANNEL *handle )
|
||||
{
|
||||
struct channel *channel = (struct channel *)handle;
|
||||
HRESULT hr;
|
||||
|
@ -1213,7 +1213,54 @@ HRESULT channel_accept_udp( SOCKET socket, WS_CHANNEL *handle )
|
|||
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 );
|
||||
return hr;
|
||||
|
|
|
@ -75,6 +75,9 @@ struct listener
|
|||
WS_CHANNEL_TYPE type;
|
||||
WS_CHANNEL_BINDING binding;
|
||||
WS_LISTENER_STATE state;
|
||||
HANDLE wait;
|
||||
HANDLE cancel;
|
||||
WS_CHANNEL *channel;
|
||||
union
|
||||
{
|
||||
struct
|
||||
|
@ -101,6 +104,17 @@ static struct listener *alloc_listener(void)
|
|||
if (!(ret = heap_alloc_zero( size ))) return NULL;
|
||||
|
||||
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 );
|
||||
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 )
|
||||
{
|
||||
listener->state = WS_LISTENER_STATE_CREATED;
|
||||
SetEvent( listener->cancel );
|
||||
listener->channel = NULL;
|
||||
|
||||
switch (listener->binding)
|
||||
{
|
||||
|
@ -132,6 +148,10 @@ static void reset_listener( struct listener *listener )
|
|||
static void free_listener( struct listener *listener )
|
||||
{
|
||||
reset_listener( listener );
|
||||
|
||||
CloseHandle( listener->wait );
|
||||
CloseHandle( listener->cancel );
|
||||
|
||||
listener->cs.DebugInfo->Spare[0] = 0;
|
||||
DeleteCriticalSection( &listener->cs );
|
||||
heap_free( listener );
|
||||
|
@ -569,7 +589,8 @@ HRESULT WINAPI WsAcceptChannel( WS_LISTENER *handle, WS_CHANNEL *channel_handle,
|
|||
WS_ERROR *error )
|
||||
{
|
||||
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 );
|
||||
if (error) FIXME( "ignoring error parameter\n" );
|
||||
|
@ -585,27 +606,34 @@ HRESULT WINAPI WsAcceptChannel( WS_LISTENER *handle, WS_CHANNEL *channel_handle,
|
|||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (listener->state != WS_LISTENER_STATE_OPEN)
|
||||
if (listener->state != WS_LISTENER_STATE_OPEN || listener->channel)
|
||||
{
|
||||
LeaveCriticalSection( &listener->cs );
|
||||
return WS_E_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
wait = listener->wait;
|
||||
cancel = listener->cancel;
|
||||
listener->channel = channel_handle;
|
||||
|
||||
switch (listener->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:
|
||||
/* hand over socket on success */
|
||||
if ((hr = channel_accept_udp( listener->u.udp.socket, channel_handle )) == S_OK)
|
||||
listener->u.udp.socket = -1;
|
||||
break;
|
||||
{
|
||||
SOCKET socket = listener->u.udp.socket;
|
||||
|
||||
LeaveCriticalSection( &listener->cs );
|
||||
return channel_accept_udp( socket, wait, cancel, channel_handle );
|
||||
}
|
||||
default:
|
||||
FIXME( "listener binding %u not supported\n", listener->binding );
|
||||
hr = E_NOTIMPL;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,5 +20,5 @@
|
|||
|
||||
void winsock_init(void) 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_udp( SOCKET, WS_CHANNEL * ) DECLSPEC_HIDDEN;
|
||||
HRESULT channel_accept_tcp( SOCKET, HANDLE, HANDLE, 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 );
|
||||
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 );
|
||||
ok( hr == S_OK, "got %08x\n", hr );
|
||||
|
||||
|
|
Loading…
Reference in New Issue