Robert Shearman : rpcrt4:
Abstract out the way incoming connections are waited for so that we no
longer need to wait on Win32 handles .
Alexandre Julliard
julliard at wine.codeweavers.com
Mon Oct 16 13:57:17 CDT 2006
Module: wine
Branch: master
Commit: 1ceeb058e37ee6e3aeb7e6d37c7a68aa8d92e9a2
URL: http://source.winehq.org/git/wine.git/?a=commit;h=1ceeb058e37ee6e3aeb7e6d37c7a68aa8d92e9a2
Author: Robert Shearman <rob at codeweavers.com>
Date: Mon Oct 16 16:48:57 2006 +0100
rpcrt4: Abstract out the way incoming connections are waited for so that we no longer need to wait on Win32 handles.
---
dlls/rpcrt4/rpc_server.c | 220 +++++++++++++++++++++++++++++++++++-----------
dlls/rpcrt4/rpc_server.h | 18 +++-
2 files changed, 183 insertions(+), 55 deletions(-)
diff --git a/dlls/rpcrt4/rpc_server.c b/dlls/rpcrt4/rpc_server.c
index 4d034ba..b613def 100644
--- a/dlls/rpcrt4/rpc_server.c
+++ b/dlls/rpcrt4/rpc_server.c
@@ -347,45 +347,164 @@ static void RPCRT4_new_client(RpcConnect
CloseHandle( thread );
}
-static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg)
+typedef struct _RpcServerProtseq_np
{
- HANDLE m_event, b_handle;
- HANDLE *objs = NULL;
- DWORD count, res;
- RpcServerProtseq* cps = the_arg;
- RpcConnection* conn;
- RpcConnection* cconn;
- BOOL set_ready_event = FALSE;
+ RpcServerProtseq common;
+ HANDLE mgr_event;
+} RpcServerProtseq_np;
- TRACE("(the_arg == ^%p)\n", the_arg);
+static RpcServerProtseq *rpcrt4_protseq_np_alloc(void)
+{
+ RpcServerProtseq_np *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps));
+ if (ps)
+ ps->mgr_event = CreateEventW(NULL, FALSE, FALSE, NULL);
+ return &ps->common;
+}
+
+static void rpcrt4_protseq_np_signal_state_changed(RpcServerProtseq *protseq)
+{
+ RpcServerProtseq_np *npps = CONTAINING_RECORD(protseq, RpcServerProtseq_np, common);
+ SetEvent(npps->mgr_event);
+}
- m_event = cps->mgr_event;
+static void *rpcrt4_protseq_np_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count)
+{
+ HANDLE *objs = prev_array;
+ RpcConnection* conn;
+ RpcServerProtseq_np *npps = CONTAINING_RECORD(protseq, RpcServerProtseq_np, common);
- for (;;) {
- EnterCriticalSection(&server_cs);
/* open and count connections */
- count = 1;
- conn = cps->conn;
+ *count = 1;
+ conn = protseq->conn;
while (conn) {
- RPCRT4_OpenConnection(conn);
- if (rpcrt4_conn_get_wait_object(conn))
- count++;
- conn = conn->Next;
+ RPCRT4_OpenConnection(conn);
+ if (rpcrt4_conn_get_wait_object(conn))
+ (*count)++;
+ conn = conn->Next;
}
+
/* make array of connections */
if (objs)
- objs = HeapReAlloc(GetProcessHeap(), 0, objs, count*sizeof(HANDLE));
+ objs = HeapReAlloc(GetProcessHeap(), 0, objs, *count*sizeof(HANDLE));
else
- objs = HeapAlloc(GetProcessHeap(), 0, count*sizeof(HANDLE));
-
- objs[0] = m_event;
- count = 1;
- conn = cps->conn;
+ objs = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(HANDLE));
+ if (!objs)
+ {
+ ERR("couldn't allocate objs\n");
+ return NULL;
+ }
+
+ objs[0] = npps->mgr_event;
+ *count = 1;
+ conn = protseq->conn;
while (conn) {
- if ((objs[count] = rpcrt4_conn_get_wait_object(conn)))
- count++;
- conn = conn->Next;
+ if ((objs[*count] = rpcrt4_conn_get_wait_object(conn)))
+ (*count)++;
+ conn = conn->Next;
}
+ return objs;
+}
+
+static void rpcrt4_protseq_np_free_wait_array(RpcServerProtseq *protseq, void *array)
+{
+ HeapFree(GetProcessHeap(), 0, array);
+}
+
+static int rpcrt4_protseq_np_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array)
+{
+ HANDLE b_handle;
+ HANDLE *objs = wait_array;
+ DWORD res;
+ RpcConnection* cconn;
+ RpcConnection* conn;
+
+ if (!objs)
+ return -1;
+
+ res = WaitForMultipleObjects(count, objs, FALSE, INFINITE);
+ if (res == WAIT_OBJECT_0)
+ return 0;
+ else if (res == WAIT_FAILED)
+ {
+ ERR("wait failed with error %ld\n", GetLastError());
+ return -1;
+ }
+ else
+ {
+ b_handle = objs[res - WAIT_OBJECT_0];
+ /* find which connection got a RPC */
+ EnterCriticalSection(&server_cs);
+ conn = protseq->conn;
+ while (conn) {
+ if (b_handle == rpcrt4_conn_get_wait_object(conn)) break;
+ conn = conn->Next;
+ }
+ cconn = NULL;
+ if (conn)
+ RPCRT4_SpawnConnection(&cconn, conn);
+ else
+ ERR("failed to locate connection for handle %p\n", b_handle);
+ LeaveCriticalSection(&server_cs);
+ if (cconn)
+ {
+ RPCRT4_new_client(cconn);
+ return 1;
+ }
+ else return -1;
+ }
+}
+
+static const struct protseq_ops protseq_list[] =
+{
+ {
+ "ncacn_np",
+ rpcrt4_protseq_np_alloc,
+ rpcrt4_protseq_np_signal_state_changed,
+ rpcrt4_protseq_np_get_wait_array,
+ rpcrt4_protseq_np_free_wait_array,
+ rpcrt4_protseq_np_wait_for_new_connection,
+ },
+ {
+ "ncalrpc",
+ rpcrt4_protseq_np_alloc,
+ rpcrt4_protseq_np_signal_state_changed,
+ rpcrt4_protseq_np_get_wait_array,
+ rpcrt4_protseq_np_free_wait_array,
+ rpcrt4_protseq_np_wait_for_new_connection,
+ },
+ {
+ "ncacn_ip_tcp",
+ rpcrt4_protseq_np_alloc,
+ rpcrt4_protseq_np_signal_state_changed,
+ rpcrt4_protseq_np_get_wait_array,
+ rpcrt4_protseq_np_free_wait_array,
+ rpcrt4_protseq_np_wait_for_new_connection,
+ },
+};
+
+static const struct protseq_ops *rpcrt4_get_protseq_ops(const char *protseq)
+{
+ int i;
+ for(i=0; i < sizeof(protseq_list)/sizeof(protseq_list[0]); i++)
+ if (!strcmp(protseq_list[i].name, protseq))
+ return &protseq_list[i];
+ return NULL;
+}
+
+static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg)
+{
+ int res;
+ unsigned int count;
+ void *objs = NULL;
+ RpcServerProtseq* cps = the_arg;
+ RpcConnection* conn;
+ BOOL set_ready_event = FALSE;
+
+ TRACE("(the_arg == ^%p)\n", the_arg);
+
+ for (;;) {
+ EnterCriticalSection(&server_cs);
+ objs = cps->ops->get_wait_array(cps, objs, &count);
LeaveCriticalSection(&server_cs);
if (set_ready_event)
@@ -396,8 +515,11 @@ static DWORD CALLBACK RPCRT4_server_thre
}
/* start waiting */
- res = WaitForMultipleObjects(count, objs, FALSE, INFINITE);
- if (res == WAIT_OBJECT_0) {
+ res = cps->ops->wait_for_new_connection(cps, count, objs);
+ if (res == -1)
+ break;
+ else if (res == 0)
+ {
if (!std_listen)
{
SetEvent(cps->server_ready_event);
@@ -405,28 +527,8 @@ static DWORD CALLBACK RPCRT4_server_thre
}
set_ready_event = TRUE;
}
- else if (res == WAIT_FAILED) {
- ERR("wait failed\n");
- }
- else {
- b_handle = objs[res - WAIT_OBJECT_0];
- /* find which connection got a RPC */
- EnterCriticalSection(&server_cs);
- conn = cps->conn;
- while (conn) {
- if (b_handle == rpcrt4_conn_get_wait_object(conn)) break;
- conn = conn->Next;
- }
- cconn = NULL;
- if (conn)
- RPCRT4_SpawnConnection(&cconn, conn);
- else
- ERR("failed to locate connection for handle %p\n", b_handle);
- LeaveCriticalSection(&server_cs);
- if (cconn) RPCRT4_new_client(cconn);
- }
}
- HeapFree(GetProcessHeap(), 0, objs);
+ cps->ops->free_wait_array(cps, objs);
EnterCriticalSection(&server_cs);
/* close connections */
conn = cps->conn;
@@ -447,7 +549,8 @@ static void RPCRT4_sync_with_server_thre
* the server_ready_event when the new state hasn't yet been applied */
WaitForSingleObject(ps->mgr_mutex, INFINITE);
- SetEvent(ps->mgr_event);
+ ps->ops->signal_state_changed(ps);
+
/* wait for server thread to make the requested changes before returning */
WaitForSingleObject(ps->server_ready_event, INFINITE);
@@ -463,7 +566,6 @@ static RPC_STATUS RPCRT4_start_listen_pr
if (ps->is_listening) goto done;
if (!ps->mgr_mutex) ps->mgr_mutex = CreateMutexW(NULL, FALSE, NULL);
- if (!ps->mgr_event) ps->mgr_event = CreateEventW(NULL, FALSE, FALSE, NULL);
if (!ps->server_ready_event) ps->server_ready_event = CreateEventW(NULL, FALSE, FALSE, NULL);
server_thread = CreateThread(NULL, 0, RPCRT4_server_thread, ps, 0, NULL);
if (!server_thread)
@@ -654,11 +756,23 @@ RPC_STATUS WINAPI RpcServerUseProtseqEpW
static RpcServerProtseq *alloc_serverprotoseq(UINT MaxCalls, char *Protseq, char *Endpoint)
{
RpcServerProtseq* ps;
+ const struct protseq_ops *ops = rpcrt4_get_protseq_ops(Protseq);
+
+ if (!ops)
+ return NULL;
- ps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcServerProtseq));
+ ps = ops->alloc();
+ if (!ps)
+ return NULL;
ps->MaxCalls = MaxCalls;
ps->Protseq = Protseq;
ps->Endpoint = Endpoint;
+ ps->ops = ops;
+ ps->MaxCalls = 0;
+ ps->conn = NULL;
+ ps->is_listening = FALSE;
+ ps->mgr_mutex = NULL;
+ ps->server_ready_event = NULL;
return ps;
}
diff --git a/dlls/rpcrt4/rpc_server.h b/dlls/rpcrt4/rpc_server.h
index 3a24112..9452ace 100644
--- a/dlls/rpcrt4/rpc_server.h
+++ b/dlls/rpcrt4/rpc_server.h
@@ -23,8 +23,11 @@ #define __WINE_RPC_SERVER_H
#include "rpc_binding.h"
+struct protseq_ops;
+
typedef struct _RpcServerProtseq
{
+ const struct protseq_ops *ops;
struct _RpcServerProtseq* Next;
LPSTR Protseq;
LPSTR Endpoint;
@@ -33,14 +36,25 @@ typedef struct _RpcServerProtseq
/* is the server currently listening? */
BOOL is_listening;
- /* set on change of configuration (e.g. listening on new protseq) */
- HANDLE mgr_event;
/* mutex for ensuring only one thread can change state at a time */
HANDLE mgr_mutex;
/* set when server thread has finished opening connections */
HANDLE server_ready_event;
} RpcServerProtseq;
+struct protseq_ops
+{
+ const char *name;
+ RpcServerProtseq *(*alloc)(void);
+ void (*signal_state_changed)(RpcServerProtseq *protseq);
+ /* previous array is passed in to allow reuse of memory */
+ void *(*get_wait_array)(RpcServerProtseq *protseq, void *prev_array, unsigned int *count);
+ void (*free_wait_array)(RpcServerProtseq *protseq, void *array);
+ /* returns -1 for failure, 0 for server state changed and 1 to indicate a
+ * new connection was established */
+ int (*wait_for_new_connection)(RpcServerProtseq *protseq, unsigned int count, void *wait_array);
+};
+
typedef struct _RpcServerInterface
{
struct _RpcServerInterface* Next;
More information about the wine-cvs
mailing list