rpcrt4: Add a Win32 implementation of ncacn_ip_tcp transport.
This commit is contained in:
parent
06c2982a39
commit
324b4d0243
|
@ -912,7 +912,12 @@ typedef struct _RpcConnection_tcp
|
||||||
{
|
{
|
||||||
RpcConnection common;
|
RpcConnection common;
|
||||||
int sock;
|
int sock;
|
||||||
|
#ifdef HAVE_SOCKETPAIR
|
||||||
int cancel_fds[2];
|
int cancel_fds[2];
|
||||||
|
#else
|
||||||
|
HANDLE sock_event;
|
||||||
|
HANDLE cancel_event;
|
||||||
|
#endif
|
||||||
} RpcConnection_tcp;
|
} RpcConnection_tcp;
|
||||||
|
|
||||||
#ifdef HAVE_SOCKETPAIR
|
#ifdef HAVE_SOCKETPAIR
|
||||||
|
@ -978,30 +983,78 @@ static void rpcrt4_sock_wait_destroy(RpcConnection_tcp *tcpc)
|
||||||
|
|
||||||
static BOOL rpcrt4_sock_wait_init(RpcConnection_tcp *tcpc)
|
static BOOL rpcrt4_sock_wait_init(RpcConnection_tcp *tcpc)
|
||||||
{
|
{
|
||||||
/* FIXME */
|
static BOOL wsa_inited;
|
||||||
return FALSE;
|
if (!wsa_inited)
|
||||||
|
{
|
||||||
|
WSADATA wsadata;
|
||||||
|
WSAStartup(MAKEWORD(2, 2), &wsadata);
|
||||||
|
/* Note: WSAStartup can be called more than once so we don't bother with
|
||||||
|
* making accesses to wsa_inited thread-safe */
|
||||||
|
wsa_inited = TRUE;
|
||||||
|
}
|
||||||
|
tcpc->sock_event = CreateEventW(NULL, FALSE, FALSE, NULL);
|
||||||
|
tcpc->cancel_event = CreateEventW(NULL, FALSE, FALSE, NULL);
|
||||||
|
if (!tcpc->sock_event || !tcpc->cancel_event)
|
||||||
|
{
|
||||||
|
ERR("event creation failed\n");
|
||||||
|
if (tcpc->sock_event) CloseHandle(tcpc->sock_event);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL rpcrt4_sock_wait_for_recv(RpcConnection_tcp *tcpc)
|
static BOOL rpcrt4_sock_wait_for_recv(RpcConnection_tcp *tcpc)
|
||||||
{
|
{
|
||||||
/* FIXME */
|
HANDLE wait_handles[2];
|
||||||
return FALSE;
|
DWORD res;
|
||||||
|
if (WSAEventSelect(tcpc->sock, tcpc->sock_event, FD_READ | FD_CLOSE) == SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError());
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
wait_handles[0] = tcpc->sock_event;
|
||||||
|
wait_handles[1] = tcpc->cancel_event;
|
||||||
|
res = WaitForMultipleObjects(2, wait_handles, FALSE, INFINITE);
|
||||||
|
switch (res)
|
||||||
|
{
|
||||||
|
case WAIT_OBJECT_0:
|
||||||
|
return TRUE;
|
||||||
|
case WAIT_OBJECT_0 + 1:
|
||||||
|
return FALSE;
|
||||||
|
default:
|
||||||
|
ERR("WaitForMultipleObjects() failed with error %d\n", GetLastError());
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL rpcrt4_sock_wait_for_send(RpcConnection_tcp *tcpc)
|
static BOOL rpcrt4_sock_wait_for_send(RpcConnection_tcp *tcpc)
|
||||||
{
|
{
|
||||||
/* FIXME */
|
DWORD res;
|
||||||
return FALSE;
|
if (WSAEventSelect(tcpc->sock, tcpc->sock_event, FD_WRITE | FD_CLOSE) == SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError());
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
res = WaitForSingleObject(tcpc->sock_event, INFINITE);
|
||||||
|
switch (res)
|
||||||
|
{
|
||||||
|
case WAIT_OBJECT_0:
|
||||||
|
return TRUE;
|
||||||
|
default:
|
||||||
|
ERR("WaitForMultipleObjects() failed with error %d\n", GetLastError());
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rpcrt4_sock_wait_cancel(RpcConnection_tcp *tcpc)
|
static void rpcrt4_sock_wait_cancel(RpcConnection_tcp *tcpc)
|
||||||
{
|
{
|
||||||
/* FIXME */
|
SetEvent(tcpc->cancel_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rpcrt4_sock_wait_destroy(RpcConnection_tcp *tcpc)
|
static void rpcrt4_sock_wait_destroy(RpcConnection_tcp *tcpc)
|
||||||
{
|
{
|
||||||
/* FIXME */
|
CloseHandle(tcpc->sock_event);
|
||||||
|
CloseHandle(tcpc->cancel_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1105,8 +1158,6 @@ static RPC_STATUS rpcrt4_ncacn_ip_tcp_open(RpcConnection* Connection)
|
||||||
return RPC_S_SERVER_UNAVAILABLE;
|
return RPC_S_SERVER_UNAVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_SOCKETPAIR
|
|
||||||
|
|
||||||
static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *protseq, const char *endpoint)
|
static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *protseq, const char *endpoint)
|
||||||
{
|
{
|
||||||
RPC_STATUS status = RPC_S_CANT_CREATE_ENDPOINT;
|
RPC_STATUS status = RPC_S_CANT_CREATE_ENDPOINT;
|
||||||
|
@ -1266,8 +1317,6 @@ static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *pr
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static RPC_STATUS rpcrt4_conn_tcp_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
|
static RPC_STATUS rpcrt4_conn_tcp_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -1520,6 +1569,149 @@ static int rpcrt4_protseq_sock_wait_for_new_connection(RpcServerProtseq *protseq
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else /* HAVE_SOCKETPAIR */
|
||||||
|
|
||||||
|
typedef struct _RpcServerProtseq_sock
|
||||||
|
{
|
||||||
|
RpcServerProtseq common;
|
||||||
|
HANDLE mgr_event;
|
||||||
|
} RpcServerProtseq_sock;
|
||||||
|
|
||||||
|
static RpcServerProtseq *rpcrt4_protseq_sock_alloc(void)
|
||||||
|
{
|
||||||
|
RpcServerProtseq_sock *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps));
|
||||||
|
if (ps)
|
||||||
|
{
|
||||||
|
static BOOL wsa_inited;
|
||||||
|
if (!wsa_inited)
|
||||||
|
{
|
||||||
|
WSADATA wsadata;
|
||||||
|
WSAStartup(MAKEWORD(2, 2), &wsadata);
|
||||||
|
/* Note: WSAStartup can be called more than once so we don't bother with
|
||||||
|
* making accesses to wsa_inited thread-safe */
|
||||||
|
wsa_inited = TRUE;
|
||||||
|
}
|
||||||
|
ps->mgr_event = CreateEventW(NULL, FALSE, FALSE, NULL);
|
||||||
|
}
|
||||||
|
return &ps->common;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rpcrt4_protseq_sock_signal_state_changed(RpcServerProtseq *protseq)
|
||||||
|
{
|
||||||
|
RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common);
|
||||||
|
SetEvent(sockps->mgr_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *rpcrt4_protseq_sock_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count)
|
||||||
|
{
|
||||||
|
HANDLE *objs = prev_array;
|
||||||
|
RpcConnection_tcp *conn;
|
||||||
|
RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common);
|
||||||
|
|
||||||
|
EnterCriticalSection(&protseq->cs);
|
||||||
|
|
||||||
|
/* open and count connections */
|
||||||
|
*count = 1;
|
||||||
|
conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);
|
||||||
|
while (conn)
|
||||||
|
{
|
||||||
|
if (conn->sock != -1)
|
||||||
|
(*count)++;
|
||||||
|
conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make array of connections */
|
||||||
|
if (objs)
|
||||||
|
objs = HeapReAlloc(GetProcessHeap(), 0, objs, *count*sizeof(HANDLE));
|
||||||
|
else
|
||||||
|
objs = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(HANDLE));
|
||||||
|
if (!objs)
|
||||||
|
{
|
||||||
|
ERR("couldn't allocate objs\n");
|
||||||
|
LeaveCriticalSection(&protseq->cs);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
objs[0] = sockps->mgr_event;
|
||||||
|
*count = 1;
|
||||||
|
conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);
|
||||||
|
while (conn)
|
||||||
|
{
|
||||||
|
if (conn->sock != -1)
|
||||||
|
{
|
||||||
|
int res = WSAEventSelect(conn->sock, conn->sock_event, FD_ACCEPT);
|
||||||
|
if (res == SOCKET_ERROR)
|
||||||
|
ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError());
|
||||||
|
else
|
||||||
|
{
|
||||||
|
objs[*count] = conn->sock_event;
|
||||||
|
(*count)++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);
|
||||||
|
}
|
||||||
|
LeaveCriticalSection(&protseq->cs);
|
||||||
|
return objs;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rpcrt4_protseq_sock_free_wait_array(RpcServerProtseq *protseq, void *array)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, array);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rpcrt4_protseq_sock_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array)
|
||||||
|
{
|
||||||
|
HANDLE b_handle;
|
||||||
|
HANDLE *objs = wait_array;
|
||||||
|
DWORD res;
|
||||||
|
RpcConnection *cconn;
|
||||||
|
RpcConnection_tcp *conn;
|
||||||
|
|
||||||
|
if (!objs)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
/* an alertable wait isn't strictly necessary, but due to our
|
||||||
|
* overlapped I/O implementation in Wine we need to free some memory
|
||||||
|
* by the file user APC being called, even if no completion routine was
|
||||||
|
* specified at the time of starting the async operation */
|
||||||
|
res = WaitForMultipleObjectsEx(count, objs, FALSE, INFINITE, TRUE);
|
||||||
|
} while (res == WAIT_IO_COMPLETION);
|
||||||
|
|
||||||
|
if (res == WAIT_OBJECT_0)
|
||||||
|
return 0;
|
||||||
|
else if (res == WAIT_FAILED)
|
||||||
|
{
|
||||||
|
ERR("wait failed with error %d\n", GetLastError());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
b_handle = objs[res - WAIT_OBJECT_0];
|
||||||
|
/* find which connection got a RPC */
|
||||||
|
EnterCriticalSection(&protseq->cs);
|
||||||
|
conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);
|
||||||
|
while (conn)
|
||||||
|
{
|
||||||
|
if (b_handle == conn->sock_event) break;
|
||||||
|
conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);
|
||||||
|
}
|
||||||
|
cconn = NULL;
|
||||||
|
if (conn)
|
||||||
|
RPCRT4_SpawnConnection(&cconn, &conn->common);
|
||||||
|
else
|
||||||
|
ERR("failed to locate connection for handle %p\n", b_handle);
|
||||||
|
LeaveCriticalSection(&protseq->cs);
|
||||||
|
if (cconn)
|
||||||
|
{
|
||||||
|
RPCRT4_new_client(cconn);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* HAVE_SOCKETPAIR */
|
#endif /* HAVE_SOCKETPAIR */
|
||||||
|
|
||||||
static RPC_STATUS rpcrt4_ncacn_ip_tcp_parse_top_of_tower(const unsigned char *tower_data,
|
static RPC_STATUS rpcrt4_ncacn_ip_tcp_parse_top_of_tower(const unsigned char *tower_data,
|
||||||
|
@ -2551,7 +2743,6 @@ static const struct protseq_ops protseq_list[] =
|
||||||
rpcrt4_protseq_np_wait_for_new_connection,
|
rpcrt4_protseq_np_wait_for_new_connection,
|
||||||
rpcrt4_protseq_ncalrpc_open_endpoint,
|
rpcrt4_protseq_ncalrpc_open_endpoint,
|
||||||
},
|
},
|
||||||
#ifdef HAVE_SOCKETPAIR
|
|
||||||
{
|
{
|
||||||
"ncacn_ip_tcp",
|
"ncacn_ip_tcp",
|
||||||
rpcrt4_protseq_sock_alloc,
|
rpcrt4_protseq_sock_alloc,
|
||||||
|
@ -2561,7 +2752,6 @@ static const struct protseq_ops protseq_list[] =
|
||||||
rpcrt4_protseq_sock_wait_for_new_connection,
|
rpcrt4_protseq_sock_wait_for_new_connection,
|
||||||
rpcrt4_protseq_ncacn_ip_tcp_open_endpoint,
|
rpcrt4_protseq_ncacn_ip_tcp_open_endpoint,
|
||||||
},
|
},
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ARRAYSIZE(a) (sizeof((a)) / sizeof((a)[0]))
|
#define ARRAYSIZE(a) (sizeof((a)) / sizeof((a)[0]))
|
||||||
|
|
Loading…
Reference in New Issue