webservices: Add support for incoming UDP connections.
Signed-off-by: Hans Leidekker <hans@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
17a3dd17ce
commit
0ab53b3f91
|
@ -1067,3 +1067,32 @@ HRESULT channel_accept_tcp( SOCKET socket, WS_CHANNEL *handle )
|
|||
LeaveCriticalSection( &channel->cs );
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
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 )) == S_OK) channel->u.udp.socket = socket;
|
||||
|
||||
LeaveCriticalSection( &channel->cs );
|
||||
return hr;
|
||||
}
|
||||
|
|
|
@ -81,6 +81,10 @@ struct listener
|
|||
{
|
||||
SOCKET socket;
|
||||
} tcp;
|
||||
struct
|
||||
{
|
||||
SOCKET socket;
|
||||
} udp;
|
||||
} u;
|
||||
ULONG prop_count;
|
||||
struct prop prop[sizeof(listener_props)/sizeof(listener_props[0])];
|
||||
|
@ -116,6 +120,11 @@ static void reset_listener( struct listener *listener )
|
|||
listener->u.tcp.socket = -1;
|
||||
break;
|
||||
|
||||
case WS_UDP_CHANNEL_BINDING:
|
||||
closesocket( listener->u.udp.socket );
|
||||
listener->u.udp.socket = -1;
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
@ -157,6 +166,10 @@ static HRESULT create_listener( WS_CHANNEL_TYPE type, WS_CHANNEL_BINDING binding
|
|||
listener->u.tcp.socket = -1;
|
||||
break;
|
||||
|
||||
case WS_UDP_CHANNEL_BINDING:
|
||||
listener->u.udp.socket = -1;
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
|
@ -181,12 +194,12 @@ HRESULT WINAPI WsCreateListener( WS_CHANNEL_TYPE type, WS_CHANNEL_BINDING bindin
|
|||
|
||||
if (!handle) return E_INVALIDARG;
|
||||
|
||||
if (type != WS_CHANNEL_TYPE_DUPLEX_SESSION)
|
||||
if (type != WS_CHANNEL_TYPE_DUPLEX_SESSION && type != WS_CHANNEL_TYPE_DUPLEX)
|
||||
{
|
||||
FIXME( "channel type %u not implemented\n", type );
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
if (binding != WS_TCP_CHANNEL_BINDING)
|
||||
if (binding != WS_TCP_CHANNEL_BINDING && binding != WS_UDP_CHANNEL_BINDING)
|
||||
{
|
||||
FIXME( "channel binding %u not implemented\n", binding );
|
||||
return E_NOTIMPL;
|
||||
|
@ -322,6 +335,43 @@ static HRESULT open_listener_tcp( struct listener *listener, const WS_STRING *ur
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT open_listener_udp( struct listener *listener, const WS_STRING *url )
|
||||
{
|
||||
struct sockaddr_storage storage;
|
||||
struct sockaddr *addr = (struct sockaddr *)&storage;
|
||||
int addr_len;
|
||||
WS_URL_SCHEME_TYPE scheme;
|
||||
WCHAR *host;
|
||||
USHORT port;
|
||||
HRESULT hr;
|
||||
|
||||
if ((hr = parse_url( url, &scheme, &host, &port )) != S_OK) return hr;
|
||||
if (scheme != WS_URL_SOAPUDP_SCHEME_TYPE)
|
||||
{
|
||||
heap_free( host );
|
||||
return WS_E_INVALID_ENDPOINT_URL;
|
||||
}
|
||||
|
||||
winsock_init();
|
||||
|
||||
hr = resolve_hostname( host, port, addr, &addr_len );
|
||||
heap_free( host );
|
||||
if (hr != S_OK) return hr;
|
||||
|
||||
if ((listener->u.udp.socket = socket( addr->sa_family, SOCK_DGRAM, 0 )) == -1)
|
||||
return HRESULT_FROM_WIN32( WSAGetLastError() );
|
||||
|
||||
if (bind( listener->u.udp.socket, addr, addr_len ) < 0)
|
||||
{
|
||||
closesocket( listener->u.udp.socket );
|
||||
listener->u.udp.socket = -1;
|
||||
return HRESULT_FROM_WIN32( WSAGetLastError() );
|
||||
}
|
||||
|
||||
listener->state = WS_LISTENER_STATE_OPEN;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT open_listener( struct listener *listener, const WS_STRING *url )
|
||||
{
|
||||
switch (listener->binding)
|
||||
|
@ -329,6 +379,9 @@ static HRESULT open_listener( struct listener *listener, const WS_STRING *url )
|
|||
case WS_TCP_CHANNEL_BINDING:
|
||||
return open_listener_tcp( listener, url );
|
||||
|
||||
case WS_UDP_CHANNEL_BINDING:
|
||||
return open_listener_udp( listener, url );
|
||||
|
||||
default:
|
||||
ERR( "unhandled binding %u\n", listener->binding );
|
||||
return E_NOTIMPL;
|
||||
|
@ -544,6 +597,12 @@ HRESULT WINAPI WsAcceptChannel( WS_LISTENER *handle, WS_CHANNEL *channel_handle,
|
|||
hr = channel_accept_tcp( listener->u.tcp.socket, channel_handle );
|
||||
break;
|
||||
|
||||
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;
|
||||
|
||||
default:
|
||||
FIXME( "listener binding %u not supported\n", listener->binding );
|
||||
hr = E_NOTIMPL;
|
||||
|
|
|
@ -21,3 +21,4 @@
|
|||
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;
|
||||
|
|
Loading…
Reference in New Issue