[RPCRT4] support for RPC TCP servers
Damjan Jovanovic
damjan.jov at gmail.com
Thu Sep 21 09:22:30 CDT 2006
Changelog:
* Makes RPCRT4 use Winsock2 instead of native sockets (needed for
event object support)
* Adds support for TCP (ncacn_ip_tcp protocol) servers
Damjan Jovanovic
-------------- next part --------------
--- a/include/ws2tcpip.h 2006-08-28 20:35:33.000000000 +0200
+++ b/include/ws2tcpip.h 2006-09-16 08:55:45.000000000 +0200
@@ -137,6 +137,8 @@
#define WS_IFF_MULTICAST 0x00000010 /* multicast is supported */
#endif /* USE_WS_PREFIX */
+#define INET_ADDRSTRLEN 16
+
#ifndef USE_WS_PREFIX
#define IP_OPTIONS 1
#define IP_HDRINCL 2
--- a/dlls/rpcrt4/Makefile.in 2006-09-14 21:35:08.000000000 +0200
+++ b/dlls/rpcrt4/Makefile.in 2006-09-15 22:22:17.000000000 +0200
@@ -5,7 +5,7 @@
VPATH = @srcdir@
MODULE = rpcrt4.dll
IMPORTLIB = librpcrt4.$(IMPLIBEXT)
-IMPORTS = iphlpapi advapi32 kernel32 ntdll
+IMPORTS = iphlpapi advapi32 kernel32 ntdll ws2_32
DELAYIMPORTS = secur32
EXTRALIBS = -luuid
--- a/dlls/rpcrt4/rpcrt4_main.c 2006-09-14 21:35:08.000000000 +0200
+++ b/dlls/rpcrt4/rpcrt4_main.c 2006-09-17 22:16:10.000000000 +0200
@@ -102,6 +102,7 @@
#include "winuser.h"
#include "iptypes.h"
#include "iphlpapi.h"
+#include "winsock2.h"
#include "wine/unicode.h"
#include "rpc.h"
@@ -148,9 +149,13 @@
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
+ WSADATA wsaData;
+
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hinstDLL);
+ if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
+ ERR("winsock failed to initialize\n");
master_mutex = CreateMutexA( NULL, FALSE, RPCSS_MASTER_MUTEX_NAME);
if (!master_mutex)
ERR("Failed to create master mutex\n");
@@ -159,6 +164,7 @@
case DLL_PROCESS_DETACH:
CloseHandle(master_mutex);
master_mutex = NULL;
+ WSACleanup();
break;
}
--- a/dlls/rpcrt4/rpc_transport.c 2006-09-14 22:53:55.000000000 +0200
+++ b/dlls/rpcrt4/rpc_transport.c 2006-09-18 19:02:02.000000000 +0200
@@ -30,31 +30,14 @@
#include <assert.h>
#include <errno.h>
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-#include <fcntl.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#ifdef HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-#ifdef HAVE_ARPA_INET_H
-# include <arpa/inet.h>
-#endif
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
#include "winerror.h"
#include "winreg.h"
#include "winternl.h"
+#include "winsock2.h"
+#include "ws2tcpip.h"
#include "wine/unicode.h"
#include "rpc.h"
@@ -441,13 +424,46 @@
{
RpcConnection common;
int sock;
+ HANDLE event;
} RpcConnection_tcp;
+static const char *gai_strerror(int errcode)
+{
+ switch (errcode)
+ {
+ case EAI_AGAIN: return "Temporary failure in name resolution";
+ case EAI_BADFLAGS: return "Bad value for ai_flags";
+ case EAI_FAIL: return "Non-recoverable failure in name resolution";
+ case EAI_FAMILY: return "ai_family not supported";
+ case EAI_MEMORY: return "Memory allocation failure";
+ case EAI_NONAME: return "Name or service not known";
+ case EAI_SERVICE: return "Servname not supported for ai_socktype";
+ case EAI_SOCKTYPE: return "ai_socktype not supported";
+ }
+ return "Unknown error";
+}
+
+static const char *inet_ntop(int af, const void *src, char *dst, int cnt)
+{
+ if (af == AF_INET)
+ {
+ unsigned int addr = * (unsigned int*) src;
+ if (cnt < INET_ADDRSTRLEN)
+ return NULL;
+ snprintf(dst, cnt, "%u.%u.%u.%u", (addr >> 24) & 0xFF,
+ (addr >> 16) & 0xFF, (addr >> 8) & 0xFF, addr & 0xFF);
+ return dst;
+ }
+ else
+ return NULL;
+}
+
static RpcConnection *rpcrt4_conn_tcp_alloc(void)
{
RpcConnection_tcp *tcpc;
tcpc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcConnection_tcp));
tcpc->sock = -1;
+ tcpc->event = 0;
return &tcpc->common;
}
@@ -462,12 +478,6 @@
TRACE("(%s, %s)\n", Connection->NetworkAddr, Connection->Endpoint);
- if (Connection->server)
- {
- ERR("ncacn_ip_tcp servers not supported yet\n");
- return RPC_S_SERVER_UNAVAILABLE;
- }
-
if (tcpc->sock != -1)
return RPC_S_OK;
@@ -506,51 +516,115 @@
continue;
}
- if (0>connect(sock, ai_cur->ai_addr, ai_cur->ai_addrlen))
+ if (Connection->server)
{
- WARN("connect() failed\n");
- close(sock);
- continue;
+ BOOL success = FALSE;
+ if (bind(sock, ai_cur->ai_addr, ai_cur->ai_addrlen) == 0)
+ {
+ if (listen(sock, 5) == 0)
+ {
+ if ((tcpc->event = WSACreateEvent()) != NULL)
+ {
+ if (WSAEventSelect(sock, tcpc->event, FD_ACCEPT) == 0)
+ success = TRUE;
+ else
+ WARN("WSAEventSelect() failed\n");
+ }
+ else
+ WARN("WSACreateEvent() failed\n");
+ }
+ else
+ WARN("listen() failed\n");
+ }
+ else
+ WARN("bind() failed\n");
+
+ if (!success)
+ {
+ closesocket(sock);
+ if (tcpc->event != NULL)
+ WSACloseEvent(tcpc->event);
+ tcpc->event = NULL;
+ continue;
+ }
+ }
+ else
+ {
+ if (0>connect(sock, ai_cur->ai_addr, ai_cur->ai_addrlen))
+ {
+ WARN("connect() failed\n");
+ closesocket(sock);
+ continue;
+ }
}
tcpc->sock = sock;
freeaddrinfo(ai);
- TRACE("connected\n");
+ TRACE("socket %d %s\n", tcpc->sock,
+ (Connection->server ? "listening" : "connected"));
return RPC_S_OK;
}
freeaddrinfo(ai);
- ERR("couldn't connect to %s:%s\n", Connection->NetworkAddr, Connection->Endpoint);
+ ERR("couldn't open %s:%s\n", Connection->NetworkAddr, Connection->Endpoint);
return RPC_S_SERVER_UNAVAILABLE;
}
static HANDLE rpcrt4_conn_tcp_get_wait_handle(RpcConnection *Connection)
{
- assert(0);
- return 0;
+ RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
+ return tcpc->event;
}
static RPC_STATUS rpcrt4_conn_tcp_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
{
- assert(0);
- return RPC_S_SERVER_UNAVAILABLE;
+ struct sockaddr_in address;
+ int len;
+ u_long zero = 0;
+ RpcConnection_tcp *server = (RpcConnection_tcp *) old_conn;
+ RpcConnection_tcp *client = (RpcConnection_tcp *) new_conn;
+
+ TRACE("Trying to accept new connection...\n");
+ len = sizeof(address);
+ client->sock = accept(server->sock, (struct sockaddr *) &address, &len);
+ WSAResetEvent(server->event);
+ if (client->sock < 0)
+ {
+ WARN("accept failed, error %d\n", WSAGetLastError());
+ return RPC_S_SERVER_UNAVAILABLE;
+ }
+ WSAEventSelect(client->sock, NULL, 0);
+ ioctlsocket(client->sock, FIONBIO, &zero);
+ TRACE("got a new connection, socket %d\n", client->sock);
+ return RPC_S_OK;
}
static int rpcrt4_conn_tcp_read(RpcConnection *Connection,
void *buffer, unsigned int count)
{
RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
- int r = recv(tcpc->sock, buffer, count, MSG_WAITALL);
- TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, r);
- return r;
+ int rtotal = 0;
+ int r = 0;
+ do
+ {
+ r = recv(tcpc->sock, buffer, count, 0);
+ if (r > 0)
+ rtotal += r;
+ else
+ break;
+ } while (rtotal < count);
+ if (r < 0)
+ rtotal = r;
+ TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, rtotal);
+ return rtotal;
}
static int rpcrt4_conn_tcp_write(RpcConnection *Connection,
const void *buffer, unsigned int count)
{
RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
- int r = write(tcpc->sock, buffer, count);
+ int r = send(tcpc->sock, buffer, count, 0);
TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, r);
return r;
}
@@ -561,8 +635,11 @@
TRACE("%d\n", tcpc->sock);
if (tcpc->sock != -1)
- close(tcpc->sock);
+ closesocket(tcpc->sock);
tcpc->sock = -1;
+ if (tcpc->event != NULL)
+ WSACloseEvent(tcpc->event);
+ tcpc->event = NULL;
return 0;
}
More information about the wine-patches
mailing list