Commit 58ec282b authored by Robert Shearman's avatar Robert Shearman Committed by Alexandre Julliard

rpcrt4: Implement a process-wide connection pool for client connections,

rather than relying on the restriction of one connection per binding. This also avoids the problem of two threads using the same connection at the same time.
parent 1412c47a
......@@ -237,16 +237,15 @@ RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection,
TRACE("(Binding == ^%p)\n", Binding);
/* if we try to bind a new interface and the connection is already opened,
* close the current connection and create a new with the new binding. */
if (!Binding->server && Binding->FromConn &&
(Binding->AuthInfo == Binding->FromConn->AuthInfo) &&
memcmp(&Binding->FromConn->ActiveInterface, InterfaceId,
sizeof(RPC_SYNTAX_IDENTIFIER))) {
TRACE("releasing pre-existing connection\n");
RPCRT4_DestroyConnection(Binding->FromConn);
Binding->FromConn = NULL;
if (!Binding->server) {
/* try to find a compatible connection from the connection pool */
NewConnection = RPCRT4_GetIdleConnection(InterfaceId, TransferSyntax,
Binding->Protseq, Binding->NetworkAddr, Binding->Endpoint,
Binding->AuthInfo);
if (NewConnection) {
*Connection = NewConnection;
return RPC_S_OK;
}
} else {
/* we already have a connection with acceptable binding, so use it */
if (Binding->FromConn) {
......@@ -307,7 +306,8 @@ RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection,
RPCRT4_FreeHeader(response_hdr);
}
Binding->FromConn = NewConnection;
if (Binding->server)
Binding->FromConn = NewConnection;
*Connection = NewConnection;
return RPC_S_OK;
......@@ -317,8 +317,16 @@ RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection)
{
TRACE("(Binding == ^%p)\n", Binding);
if (!Connection) return RPC_S_OK;
if (Binding->FromConn == Connection) return RPC_S_OK;
return RPCRT4_DestroyConnection(Connection);
if (Binding->server) {
/* don't destroy a connection that is cached in the binding */
if (Binding->FromConn == Connection)
return RPC_S_OK;
return RPCRT4_DestroyConnection(Connection);
}
else {
RPCRT4_ReleaseIdleConnection(Connection);
return RPC_S_OK;
}
}
/* utility functions for string composing and parsing */
......
......@@ -23,6 +23,7 @@
#include "wine/rpcss_shared.h"
#include "security.h"
#include "wine/list.h"
typedef struct _RpcAuthInfo
......@@ -55,6 +56,9 @@ typedef struct _RpcConnection
TimeStamp exp;
ULONG attr;
RpcAuthInfo *AuthInfo;
/* client-only */
struct list conn_pool_entry;
} RpcConnection;
struct protseq_ops {
......@@ -101,6 +105,8 @@ void RPCRT4_strfree(LPSTR src);
ULONG RpcAuthInfo_AddRef(RpcAuthInfo *AuthInfo);
ULONG RpcAuthInfo_Release(RpcAuthInfo *AuthInfo);
RpcConnection *RPCRT4_GetIdleConnection(const RPC_SYNTAX_IDENTIFIER *InterfaceId, const RPC_SYNTAX_IDENTIFIER *TransferSyntax, LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, RpcAuthInfo* AuthInfo);
void RPCRT4_ReleaseIdleConnection(RpcConnection *Connection);
RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcBinding* Binding);
RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection);
RPC_STATUS RPCRT4_OpenConnection(RpcConnection* Connection);
......
......@@ -68,6 +68,17 @@
WINE_DEFAULT_DEBUG_CHANNEL(rpc);
static CRITICAL_SECTION connection_pool_cs;
static CRITICAL_SECTION_DEBUG connection_pool_cs_debug =
{
0, 0, &connection_pool_cs,
{ &connection_pool_cs_debug.ProcessLocksList, &connection_pool_cs_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": connection_pool") }
};
static CRITICAL_SECTION connection_pool_cs = { &connection_pool_cs_debug, -1, 0, 0, 0, 0 };
static struct list connection_pool = LIST_INIT(connection_pool);
/**** ncacn_np support ****/
typedef struct _RpcConnection_np
......@@ -777,6 +788,7 @@ RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server,
NewConnection->NextCallId = 1;
if (AuthInfo) RpcAuthInfo_AddRef(AuthInfo);
NewConnection->AuthInfo = AuthInfo;
list_init(&NewConnection->conn_pool_entry);
TRACE("connection: %p\n", NewConnection);
*Connection = NewConnection;
......@@ -784,6 +796,40 @@ RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server,
return RPC_S_OK;
}
RpcConnection *RPCRT4_GetIdleConnection(const RPC_SYNTAX_IDENTIFIER *InterfaceId,
const RPC_SYNTAX_IDENTIFIER *TransferSyntax, LPCSTR Protseq, LPCSTR NetworkAddr,
LPCSTR Endpoint, RpcAuthInfo* AuthInfo)
{
RpcConnection *Connection;
/* try to find a compatible connection from the connection pool */
EnterCriticalSection(&connection_pool_cs);
LIST_FOR_EACH_ENTRY(Connection, &connection_pool, RpcConnection, conn_pool_entry)
if ((Connection->AuthInfo == AuthInfo) &&
!memcmp(&Connection->ActiveInterface, InterfaceId,
sizeof(RPC_SYNTAX_IDENTIFIER)) &&
!strcmp(rpcrt4_conn_get_name(Connection), Protseq) &&
!strcmp(Connection->NetworkAddr, NetworkAddr) &&
!strcmp(Connection->Endpoint, Endpoint))
{
list_remove(&Connection->conn_pool_entry);
LeaveCriticalSection(&connection_pool_cs);
TRACE("got connection from pool %p\n", Connection);
return Connection;
}
LeaveCriticalSection(&connection_pool_cs);
return NULL;
}
void RPCRT4_ReleaseIdleConnection(RpcConnection *Connection)
{
assert(!Connection->server);
EnterCriticalSection(&connection_pool_cs);
list_add_head(&connection_pool, &Connection->conn_pool_entry);
LeaveCriticalSection(&connection_pool_cs);
}
RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection)
{
RPC_STATUS err;
......
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