Commit def211c4 authored by Ove Kaaven's avatar Ove Kaaven Committed by Alexandre Julliard

For better concurrency, separate the connections from the bindings.

parent 586808fd
......@@ -23,20 +23,32 @@
#include "wine/rpcss_shared.h"
typedef struct _RpcConnection
{
struct _RpcConnection* Next;
struct _RpcBinding* Used;
BOOL server;
LPSTR Protseq;
LPSTR NetworkAddr;
LPSTR Endpoint;
HANDLE conn, thread;
OVERLAPPED ovl;
} RpcConnection;
/* don't know what MS's structure looks like */
typedef struct _RpcBinding
{
DWORD refs;
struct _RpcBinding* Next; /* for rpc server */
struct _RpcBinding* Next;
BOOL server;
UUID ObjectUuid;
UUID ActiveUuid;
LPSTR Protseq;
LPSTR NetworkAddr;
LPSTR Endpoint;
RPC_BLOCKING_FN BlockingFn;
ULONG ServerTid;
HANDLE conn, thread;
OVERLAPPED ovl;
RpcConnection* FromConn;
} RpcBinding;
LPSTR RPCRT4_strndupA(LPSTR src, INT len);
......@@ -48,17 +60,23 @@ void RPCRT4_strfree(LPSTR src);
#define RPCRT4_strdupA(x) RPCRT4_strndupA((x),-1)
#define RPCRT4_strdupW(x) RPCRT4_strndupW((x),-1)
RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPSTR Protseq, LPSTR NetworkAddr, LPSTR Endpoint, LPSTR NetworkOptions);
RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection);
RPC_STATUS RPCRT4_OpenConnection(RpcConnection* Connection);
RPC_STATUS RPCRT4_CloseConnection(RpcConnection* Connection);
RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection);
RPC_STATUS RPCRT4_CreateBindingA(RpcBinding** Binding, BOOL server, LPSTR Protseq);
RPC_STATUS RPCRT4_CreateBindingW(RpcBinding** Binding, BOOL server, LPWSTR Protseq);
RPC_STATUS RPCRT4_CompleteBindingA(RpcBinding* Binding, LPSTR NetworkAddr, LPSTR Endpoint, LPSTR NetworkOptions);
RPC_STATUS RPCRT4_CompleteBindingW(RpcBinding* Binding, LPWSTR NetworkAddr, LPWSTR Endpoint, LPWSTR NetworkOptions);
RPC_STATUS RPCRT4_ResolveBinding(RpcBinding* Binding, LPSTR Endpoint);
RPC_STATUS RPCRT4_SetBindingObject(RpcBinding* Binding, UUID* ObjectUuid);
RPC_STATUS RPCRT4_SpawnBinding(RpcBinding** Binding, RpcBinding* OldBinding);
RPC_STATUS RPCRT4_MakeBinding(RpcBinding** Binding, RpcConnection* Connection);
RPC_STATUS RPCRT4_ExportBinding(RpcBinding** Binding, RpcBinding* OldBinding);
RPC_STATUS RPCRT4_DestroyBinding(RpcBinding* Binding);
RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding);
RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding);
RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection);
RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection);
BOOL RPCRT4_RPCSSOnDemandCall(PRPCSS_NP_MESSAGE msg, char *vardata_payload, PRPCSS_NP_REPLY reply);
HANDLE RPCRT4_GetMasterMutex(void);
HANDLE RPCRT4_RpcssNPConnect(void);
......
......@@ -48,9 +48,10 @@ RPC_STATUS WINAPI I_RpcGetBuffer(PRPC_MESSAGE pMsg)
{
void* buf;
TRACE("(%p)\n", pMsg);
TRACE("(%p): BufferLength=%d\n", pMsg, pMsg->BufferLength);
/* FIXME: pfnAllocate? */
buf = HeapReAlloc(GetProcessHeap(), 0, pMsg->Buffer, pMsg->BufferLength);
TRACE("Buffer=%p\n", buf);
if (buf) pMsg->Buffer = buf;
/* FIXME: which errors to return? */
return buf ? S_OK : E_OUTOFMEMORY;
......@@ -74,14 +75,23 @@ RPC_STATUS WINAPI I_RpcFreeBuffer(PRPC_MESSAGE pMsg)
RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg)
{
RpcBinding* bind = (RpcBinding*)pMsg->Handle;
RpcConnection* conn;
RPC_CLIENT_INTERFACE* cif = NULL;
RPC_SERVER_INTERFACE* sif = NULL;
UUID* obj;
UUID* act;
RPC_STATUS status;
RpcPktHdr hdr;
TRACE("(%p)\n", pMsg);
if (!bind) return RPC_S_INVALID_BINDING;
status = RPCRT4_OpenBinding(bind, &conn);
if (status != RPC_S_OK) return status;
obj = &bind->ObjectUuid;
act = &bind->ActiveUuid;
if (bind->server) {
sif = pMsg->RpcInterfaceInformation;
if (!sif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */
......@@ -90,19 +100,17 @@ RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg)
if (!cif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */
}
status = RPCRT4_OpenBinding(bind);
if (status != RPC_S_OK) return status;
/* initialize packet header */
memset(&hdr, 0, sizeof(hdr));
hdr.rpc_ver = 4;
hdr.ptype = PKT_REQUEST;
hdr.object = bind->ObjectUuid; /* FIXME: IIRC iff no object, the header structure excludes this elt */
hdr.ptype = bind->server ? PKT_RESPONSE : PKT_REQUEST;
hdr.object = *obj; /* FIXME: IIRC iff no object, the header structure excludes this elt */
hdr.if_id = (bind->server) ? sif->InterfaceId.SyntaxGUID : cif->InterfaceId.SyntaxGUID;
hdr.if_vers =
(bind->server) ?
MAKELONG(sif->InterfaceId.SyntaxVersion.MinorVersion, sif->InterfaceId.SyntaxVersion.MajorVersion) :
MAKELONG(cif->InterfaceId.SyntaxVersion.MinorVersion, cif->InterfaceId.SyntaxVersion.MajorVersion);
hdr.act_id = *act;
hdr.opnum = pMsg->ProcNum;
/* only the low-order 3 octets of the DataRepresentation go in the header */
hdr.drep[0] = LOBYTE(LOWORD(pMsg->DataRepresentation));
......@@ -111,13 +119,26 @@ RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg)
hdr.len = pMsg->BufferLength;
/* transmit packet */
if (!WriteFile(bind->conn, &hdr, sizeof(hdr), NULL, NULL))
return GetLastError();
if (!WriteFile(bind->conn, pMsg->Buffer, pMsg->BufferLength, NULL, NULL))
return GetLastError();
if (!WriteFile(conn->conn, &hdr, sizeof(hdr), NULL, NULL)) {
status = GetLastError();
goto fail;
}
if (pMsg->BufferLength && !WriteFile(conn->conn, pMsg->Buffer, pMsg->BufferLength, NULL, NULL)) {
status = GetLastError();
goto fail;
}
/* success */
return RPC_S_OK;
if (!bind->server) {
/* save the connection, so the response can be read from it */
pMsg->ReservedForRuntime = conn;
return RPC_S_OK;
}
RPCRT4_CloseBinding(bind, conn);
status = RPC_S_OK;
fail:
return status;
}
/***********************************************************************
......@@ -126,6 +147,8 @@ RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg)
RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg)
{
RpcBinding* bind = (RpcBinding*)pMsg->Handle;
RpcConnection* conn;
UUID* act;
RPC_STATUS status;
RpcPktHdr hdr;
DWORD dwRead;
......@@ -133,44 +156,78 @@ RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg)
TRACE("(%p)\n", pMsg);
if (!bind) return RPC_S_INVALID_BINDING;
status = RPCRT4_OpenBinding(bind);
if (status != RPC_S_OK) return status;
if (pMsg->ReservedForRuntime) {
conn = pMsg->ReservedForRuntime;
pMsg->ReservedForRuntime = NULL;
} else {
status = RPCRT4_OpenBinding(bind, &conn);
if (status != RPC_S_OK) return status;
}
act = &bind->ActiveUuid;
/* read packet header */
for (;;) {
/* read packet header */
#ifdef OVERLAPPED_WORKS
if (!ReadFile(bind->conn, &hdr, sizeof(hdr), &dwRead, &bind->ovl)) {
DWORD err = GetLastError();
if (err != ERROR_IO_PENDING) {
return err;
if (!ReadFile(conn->conn, &hdr, sizeof(hdr), &dwRead, &conn->ovl)) {
DWORD err = GetLastError();
if (err != ERROR_IO_PENDING) {
status = err;
goto fail;
}
if (!GetOverlappedResult(conn->conn, &conn->ovl, &dwRead, TRUE)) {
status = GetLastError();
goto fail;
}
}
if (!GetOverlappedResult(bind->conn, &bind->ovl, &dwRead, TRUE)) return GetLastError();
}
#else
if (!ReadFile(bind->conn, &hdr, sizeof(hdr), &dwRead, NULL))
return GetLastError();
if (!ReadFile(conn->conn, &hdr, sizeof(hdr), &dwRead, NULL)) {
status = GetLastError();
goto fail;
}
#endif
if (dwRead != sizeof(hdr)) return RPC_S_PROTOCOL_ERROR;
if (dwRead != sizeof(hdr)) {
status = RPC_S_PROTOCOL_ERROR;
goto fail;
}
/* read packet body */
pMsg->BufferLength = hdr.len;
status = I_RpcGetBuffer(pMsg);
if (status != RPC_S_OK) return status;
/* read packet body */
pMsg->BufferLength = hdr.len;
status = I_RpcGetBuffer(pMsg);
if (status != RPC_S_OK) goto fail;
if (!pMsg->BufferLength) dwRead = 0; else
#ifdef OVERLAPPED_WORKS
if (!ReadFile(bind->conn, pMsg->Buffer, hdr.len, &dwRead, &bind->ovl)) {
DWORD err = GetLastError();
if (err != ERROR_IO_PENDING) {
return err;
if (!ReadFile(conn->conn, pMsg->Buffer, hdr.len, &dwRead, &conn->ovl)) {
DWORD err = GetLastError();
if (err != ERROR_IO_PENDING) {
status = err;
goto fail;
}
if (!GetOverlappedResult(conn->conn, &conn->ovl, &dwRead, TRUE)) {
status = GetLastError();
goto fail;
}
}
if (!GetOverlappedResult(bind->conn, &bind->ovl, &dwRead, TRUE)) return GetLastError();
}
#else
if (!ReadFile(bind->conn, pMsg->Buffer, hdr.len, &dwRead, NULL))
return GetLastError();
if (!ReadFile(conn->conn, pMsg->Buffer, hdr.len, &dwRead, NULL)) {
status = GetLastError();
goto fail;
}
#endif
if (dwRead != hdr.len) return RPC_S_PROTOCOL_ERROR;
if (dwRead != hdr.len) {
status = RPC_S_PROTOCOL_ERROR;
goto fail;
}
/* success */
return RPC_S_OK;
/* success */
status = RPC_S_OK;
/* FIXME: check packet type, destination, etc? */
break;
}
fail:
RPCRT4_CloseBinding(bind, conn);
return status;
}
/***********************************************************************
......
......@@ -29,7 +29,7 @@ typedef struct _RpcServerProtseq
LPSTR Protseq;
LPSTR Endpoint;
UINT MaxCalls;
RpcBinding* bind;
RpcConnection* conn;
} RpcServerProtseq;
typedef struct _RpcServerInterface
......
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