Commit 823aa24f authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

webservices: Implement WsOpenListener and WsCloseListener.

parent 79be5ad4
MODULE = webservices.dll
IMPORTLIB = webservices
IMPORTS = winhttp rpcrt4 user32
IMPORTS = winhttp rpcrt4 user32 ws2_32
C_SRCS = \
channel.c \
......
......@@ -20,6 +20,7 @@
#include "windef.h"
#include "winbase.h"
#include "ws2tcpip.h"
#include "webservices.h"
#include "wine/debug.h"
......@@ -29,6 +30,23 @@
WINE_DEFAULT_DEBUG_CHANNEL(webservices);
static BOOL winsock_loaded;
static BOOL WINAPI winsock_startup( INIT_ONCE *once, void *param, void **ctx )
{
int ret;
WSADATA data;
if (!(ret = WSAStartup( MAKEWORD(1,1), &data ))) winsock_loaded = TRUE;
else ERR( "WSAStartup failed: %d\n", ret );
return TRUE;
}
static void winsock_init(void)
{
static INIT_ONCE once = INIT_ONCE_STATIC_INIT;
InitOnceExecuteOnce( &once, winsock_startup, NULL, NULL );
}
static const struct prop_desc listener_props[] =
{
{ sizeof(ULONG), FALSE }, /* WS_LISTENER_PROPERTY_LISTEN_BACKLOG */
......@@ -57,6 +75,7 @@ struct listener
WS_CHANNEL_TYPE type;
WS_CHANNEL_BINDING binding;
WS_LISTENER_STATE state;
SOCKET socket;
ULONG prop_count;
struct prop prop[sizeof(listener_props)/sizeof(listener_props[0])];
};
......@@ -80,8 +99,16 @@ static struct listener *alloc_listener(void)
return ret;
}
static void reset_listener( struct listener *listener )
{
closesocket( listener->socket );
listener->socket = -1;
listener->state = WS_LISTENER_STATE_CREATED;
}
static void free_listener( struct listener *listener )
{
reset_listener( listener );
listener->cs.DebugInfo->Spare[0] = 0;
DeleteCriticalSection( &listener->cs );
heap_free( listener );
......@@ -109,6 +136,7 @@ static HRESULT create_listener( WS_CHANNEL_TYPE type, WS_CHANNEL_BINDING binding
listener->type = type;
listener->binding = binding;
listener->socket = -1;
*ret = listener;
return S_OK;
......@@ -173,6 +201,165 @@ void WINAPI WsFreeListener( WS_LISTENER *handle )
free_listener( listener );
}
static HRESULT resolve_hostname( const WCHAR *host, USHORT port, struct sockaddr *addr, int *addr_len )
{
static const WCHAR fmtW[] = {'%','u',0};
WCHAR service[6];
ADDRINFOW *res, *info;
HRESULT hr = WS_E_ADDRESS_NOT_AVAILABLE;
*addr_len = 0;
sprintfW( service, fmtW, port );
if (GetAddrInfoW( host, service, NULL, &res )) return HRESULT_FROM_WIN32( WSAGetLastError() );
info = res;
while (info && info->ai_family != AF_INET && info->ai_family != AF_INET6) info = info->ai_next;
if (info)
{
memcpy( addr, info->ai_addr, info->ai_addrlen );
*addr_len = info->ai_addrlen;
hr = S_OK;
}
FreeAddrInfoW( res );
return hr;
}
static HRESULT parse_url( const WS_STRING *str, WCHAR **host, USHORT *port )
{
WS_HEAP *heap;
WS_NETTCP_URL *url;
HRESULT hr;
if ((hr = WsCreateHeap( 1 << 8, 0, NULL, 0, &heap, NULL )) != S_OK) return hr;
if ((hr = WsDecodeUrl( str, 0, heap, (WS_URL **)&url, NULL )) != S_OK)
{
WsFreeHeap( heap );
return hr;
}
if (url->host.length == 1 && (url->host.chars[0] == '+' || url->host.chars[0] == '*')) *host = NULL;
else
{
if (!(*host = heap_alloc( (url->host.length + 1) * sizeof(WCHAR) )))
{
WsFreeHeap( heap );
return E_OUTOFMEMORY;
}
memcpy( *host, url->host.chars, url->host.length * sizeof(WCHAR) );
(*host)[url->host.length] = 0;
}
*port = url->port;
WsFreeHeap( heap );
return hr;
}
static HRESULT open_listener( struct listener *listener, const WS_STRING *url )
{
struct sockaddr_storage storage;
struct sockaddr *addr = (struct sockaddr *)&storage;
int addr_len;
WCHAR *host;
USHORT port;
HRESULT hr;
if ((hr = parse_url( url, &host, &port )) != S_OK) return hr;
winsock_init();
hr = resolve_hostname( host, port, addr, &addr_len );
heap_free( host );
if (hr != S_OK) return hr;
if ((listener->socket = socket( addr->sa_family, SOCK_STREAM, 0 )) == -1)
return HRESULT_FROM_WIN32( WSAGetLastError() );
if (bind( listener->socket, addr, addr_len ) < 0)
{
closesocket( listener->socket );
listener->socket = -1;
return HRESULT_FROM_WIN32( WSAGetLastError() );
}
if (listen( listener->socket, 0 ) < 0)
{
closesocket( listener->socket );
listener->socket = -1;
return HRESULT_FROM_WIN32( WSAGetLastError() );
}
listener->state = WS_LISTENER_STATE_OPEN;
return S_OK;
}
/**************************************************************************
* WsOpenListener [webservices.@]
*/
HRESULT WINAPI WsOpenListener( WS_LISTENER *handle, WS_STRING *url, const WS_ASYNC_CONTEXT *ctx, WS_ERROR *error )
{
struct listener *listener = (struct listener *)handle;
HRESULT hr;
TRACE( "%p %s %p %p\n", handle, url ? debugstr_wn(url->chars, url->length) : "null", ctx, error );
if (error) FIXME( "ignoring error parameter\n" );
if (ctx) FIXME( "ignoring ctx parameter\n" );
if (!listener || !url) return E_INVALIDARG;
EnterCriticalSection( &listener->cs );
if (listener->magic != LISTENER_MAGIC)
{
LeaveCriticalSection( &listener->cs );
return E_INVALIDARG;
}
if (listener->state != WS_LISTENER_STATE_CREATED)
{
LeaveCriticalSection( &listener->cs );
return WS_E_INVALID_OPERATION;
}
hr = open_listener( listener, url );
LeaveCriticalSection( &listener->cs );
return hr;
}
static void close_listener( struct listener *listener )
{
reset_listener( listener );
listener->state = WS_LISTENER_STATE_CLOSED;
}
/**************************************************************************
* WsCloseListener [webservices.@]
*/
HRESULT WINAPI WsCloseListener( WS_LISTENER *handle, const WS_ASYNC_CONTEXT *ctx, WS_ERROR *error )
{
struct listener *listener = (struct listener *)handle;
TRACE( "%p %p %p\n", handle, ctx, error );
if (error) FIXME( "ignoring error parameter\n" );
if (ctx) FIXME( "ignoring ctx parameter\n" );
if (!listener) return E_INVALIDARG;
EnterCriticalSection( &listener->cs );
if (listener->magic != LISTENER_MAGIC)
{
LeaveCriticalSection( &listener->cs );
return E_INVALIDARG;
}
close_listener( listener );
LeaveCriticalSection( &listener->cs );
return S_OK;
}
/**************************************************************************
* WsGetListenerProperty [webservices.@]
*/
......
......@@ -79,7 +79,83 @@ static void test_WsCreateListener(void)
WsFreeListener( listener );
}
static void test_WsOpenListener(void)
{
WCHAR str[] =
{'n','e','t','.','t','c','p',':','/','/','+',':','2','0','1','7','/','p','a','t','h'};
WCHAR str2[] =
{'n','e','t','.','t','c','p',':','/','/','l','o','c','a','l','h','o','s','t',':','2','0','1','7'};
WCHAR str3[] =
{'n','e','t','.','t','c','p',':','/','/','1','2','7','.','0','.','0','.','1',':','2','0','1','7'};
WS_STRING url;
WS_LISTENER *listener;
HRESULT hr;
hr = WsOpenListener( NULL, NULL, NULL, NULL );
ok( hr == E_INVALIDARG, "got %08x\n", hr );
hr = WsCreateListener( WS_CHANNEL_TYPE_DUPLEX_SESSION, WS_TCP_CHANNEL_BINDING, NULL, 0, NULL, &listener, NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsCloseListener( listener, NULL, NULL );
ok( hr == S_OK, "got %08x\n", hr );
WsFreeListener( listener );
hr = WsCreateListener( WS_CHANNEL_TYPE_DUPLEX_SESSION, WS_TCP_CHANNEL_BINDING, NULL, 0, NULL, &listener, NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsOpenListener( listener, NULL, NULL, NULL );
ok( hr == E_INVALIDARG, "got %08x\n", hr );
url.length = sizeof(str)/sizeof(str[0]);
url.chars = str;
hr = WsOpenListener( NULL, &url, NULL, NULL );
ok( hr == E_INVALIDARG, "got %08x\n", hr );
hr = WsOpenListener( listener, &url, NULL, NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsOpenListener( listener, &url, NULL, NULL );
ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
hr = WsCloseListener( listener, NULL, NULL );
ok( hr == S_OK, "got %08x\n", hr );
WsFreeListener( listener );
hr = WsCreateListener( WS_CHANNEL_TYPE_DUPLEX_SESSION, WS_TCP_CHANNEL_BINDING, NULL, 0, NULL, &listener, NULL );
ok( hr == S_OK, "got %08x\n", hr );
url.length = sizeof(str2)/sizeof(str2[0]);
url.chars = str2;
hr = WsOpenListener( listener, &url, NULL, NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsCloseListener( listener, NULL, NULL );
ok( hr == S_OK, "got %08x\n", hr );
WsFreeListener( listener );
hr = WsCreateListener( WS_CHANNEL_TYPE_DUPLEX_SESSION, WS_TCP_CHANNEL_BINDING, NULL, 0, NULL, &listener, NULL );
ok( hr == S_OK, "got %08x\n", hr );
url.length = sizeof(str3)/sizeof(str3[0]);
url.chars = str3;
hr = WsOpenListener( listener, &url, NULL, NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsCloseListener( listener, NULL, NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsCloseListener( NULL, NULL, NULL );
ok( hr == E_INVALIDARG, "got %08x\n", hr );
WsFreeListener( listener );
}
START_TEST(listener)
{
test_WsCreateListener();
test_WsOpenListener();
}
......@@ -14,7 +14,7 @@
@ stdcall WsCall(ptr ptr ptr ptr ptr long ptr ptr)
@ stub WsCheckMustUnderstandHeaders
@ stdcall WsCloseChannel(ptr ptr ptr)
@ stub WsCloseListener
@ stdcall WsCloseListener(ptr ptr ptr)
@ stub WsCloseServiceHost
@ stdcall WsCloseServiceProxy(ptr ptr ptr)
@ stub WsCombineUrl
......@@ -96,7 +96,7 @@
@ stdcall WsMoveReader(ptr long ptr ptr)
@ stdcall WsMoveWriter(ptr long ptr ptr)
@ stdcall WsOpenChannel(ptr ptr ptr ptr)
@ stub WsOpenListener
@ stdcall WsOpenListener(ptr ptr ptr ptr)
@ stub WsOpenServiceHost
@ stdcall WsOpenServiceProxy(ptr ptr ptr ptr)
@ stub WsPullBytes
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment