[4/6] webservices: Add support for incoming UDP connections.
Hans Leidekker
hans at codeweavers.com
Fri Apr 21 05:37:03 CDT 2017
Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
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 3663fdf29d..d35da4e310 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 a82897e589..7d49b73d32 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 f420b027ef..6b30f64601 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;
--
2.11.0
More information about the wine-patches
mailing list