[08/10] webservices: Add support for incoming UDP connections.

Hans Leidekker hans at codeweavers.com
Thu Apr 20 03:45:50 CDT 2017


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/webservices/channel.c             | 29 ++++++++++++++++
 dlls/webservices/listener.c            | 63 ++++++++++++++++++++++++++++++++--
 dlls/webservices/webservices_private.h |  1 +
 3 files changed, 91 insertions(+), 2 deletions(-)

diff --git a/dlls/webservices/channel.c b/dlls/webservices/channel.c
index aa00feb8e9..05cc8d10f0 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 249eed87b3..2e67ba0811 100644
--- a/dlls/webservices/listener.c
+++ b/dlls/webservices/listener.c
@@ -80,6 +80,10 @@ struct listener
         {
             SOCKET socket;
         } tcp;
+        struct
+        {
+            SOCKET socket;
+        } udp;
     } u;
     ULONG                   prop_count;
     struct prop             prop[sizeof(listener_props)/sizeof(listener_props[0])];
@@ -115,6 +119,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;
     }
 }
@@ -156,6 +165,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;
     }
 
@@ -180,12 +193,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;
@@ -321,6 +334,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)
@@ -328,6 +378,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;
@@ -543,6 +596,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/webservices_private.h b/dlls/webservices/webservices_private.h
index 7832f3c270..ba98fde1e5 100644
--- a/dlls/webservices/webservices_private.h
+++ b/dlls/webservices/webservices_private.h
@@ -119,6 +119,7 @@ void message_do_receive_callback( WS_MESSAGE * ) DECLSPEC_HIDDEN;
 HRESULT message_insert_http_headers( WS_MESSAGE *, HINTERNET ) DECLSPEC_HIDDEN;
 
 HRESULT channel_accept_tcp( SOCKET, WS_CHANNEL * ) DECLSPEC_HIDDEN;
+HRESULT channel_accept_udp( SOCKET, WS_CHANNEL * ) DECLSPEC_HIDDEN;
 HRESULT channel_send_message( WS_CHANNEL *, WS_MESSAGE * ) DECLSPEC_HIDDEN;
 HRESULT channel_receive_message( WS_CHANNEL * ) DECLSPEC_HIDDEN;
 HRESULT channel_get_reader( WS_CHANNEL *, WS_XML_READER ** ) DECLSPEC_HIDDEN;
-- 
2.11.0




More information about the wine-patches mailing list