Module: wine Branch: master Commit: 0ab53b3f91a138b3d248e724adbdce8e9421259a URL: http://source.winehq.org/git/wine.git/?a=commit;h=0ab53b3f91a138b3d248e724ad...
Author: Hans Leidekker hans@codeweavers.com Date: Fri Apr 21 12:37:03 2017 +0200
webservices: Add support for incoming UDP connections.
Signed-off-by: Hans Leidekker hans@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/webservices/channel.c | 29 +++++++++++++++++++++ dlls/webservices/listener.c | 63 +++++++++++++++++++++++++++++++++++++++++++-- dlls/webservices/sock.h | 1 + 3 files changed, 91 insertions(+), 2 deletions(-)
diff --git a/dlls/webservices/channel.c b/dlls/webservices/channel.c index 3663fdf..d35da4e 100644 --- a/dlls/webservices/channel.c +++ b/dlls/webservices/channel.c @@ -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; +} diff --git a/dlls/webservices/listener.c b/dlls/webservices/listener.c index a82897e..7d49b73 100644 --- a/dlls/webservices/listener.c +++ b/dlls/webservices/listener.c @@ -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; diff --git a/dlls/webservices/sock.h b/dlls/webservices/sock.h index f420b02..6b30f64 100644 --- a/dlls/webservices/sock.h +++ b/dlls/webservices/sock.h @@ -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;