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.
This commit is contained in:
parent
1412c47a50
commit
58ec282bfb
|
@ -237,16 +237,15 @@ RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection,
|
||||||
|
|
||||||
TRACE("(Binding == ^%p)\n", Binding);
|
TRACE("(Binding == ^%p)\n", Binding);
|
||||||
|
|
||||||
/* if we try to bind a new interface and the connection is already opened,
|
if (!Binding->server) {
|
||||||
* close the current connection and create a new with the new binding. */
|
/* try to find a compatible connection from the connection pool */
|
||||||
if (!Binding->server && Binding->FromConn &&
|
NewConnection = RPCRT4_GetIdleConnection(InterfaceId, TransferSyntax,
|
||||||
(Binding->AuthInfo == Binding->FromConn->AuthInfo) &&
|
Binding->Protseq, Binding->NetworkAddr, Binding->Endpoint,
|
||||||
memcmp(&Binding->FromConn->ActiveInterface, InterfaceId,
|
Binding->AuthInfo);
|
||||||
sizeof(RPC_SYNTAX_IDENTIFIER))) {
|
if (NewConnection) {
|
||||||
|
*Connection = NewConnection;
|
||||||
TRACE("releasing pre-existing connection\n");
|
return RPC_S_OK;
|
||||||
RPCRT4_DestroyConnection(Binding->FromConn);
|
}
|
||||||
Binding->FromConn = NULL;
|
|
||||||
} else {
|
} else {
|
||||||
/* we already have a connection with acceptable binding, so use it */
|
/* we already have a connection with acceptable binding, so use it */
|
||||||
if (Binding->FromConn) {
|
if (Binding->FromConn) {
|
||||||
|
@ -307,6 +306,7 @@ RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection,
|
||||||
RPCRT4_FreeHeader(response_hdr);
|
RPCRT4_FreeHeader(response_hdr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Binding->server)
|
||||||
Binding->FromConn = NewConnection;
|
Binding->FromConn = NewConnection;
|
||||||
*Connection = NewConnection;
|
*Connection = NewConnection;
|
||||||
|
|
||||||
|
@ -317,8 +317,16 @@ RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection)
|
||||||
{
|
{
|
||||||
TRACE("(Binding == ^%p)\n", Binding);
|
TRACE("(Binding == ^%p)\n", Binding);
|
||||||
if (!Connection) return RPC_S_OK;
|
if (!Connection) return RPC_S_OK;
|
||||||
if (Binding->FromConn == Connection) return RPC_S_OK;
|
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);
|
return RPCRT4_DestroyConnection(Connection);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RPCRT4_ReleaseIdleConnection(Connection);
|
||||||
|
return RPC_S_OK;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* utility functions for string composing and parsing */
|
/* utility functions for string composing and parsing */
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include "wine/rpcss_shared.h"
|
#include "wine/rpcss_shared.h"
|
||||||
#include "security.h"
|
#include "security.h"
|
||||||
|
#include "wine/list.h"
|
||||||
|
|
||||||
|
|
||||||
typedef struct _RpcAuthInfo
|
typedef struct _RpcAuthInfo
|
||||||
|
@ -55,6 +56,9 @@ typedef struct _RpcConnection
|
||||||
TimeStamp exp;
|
TimeStamp exp;
|
||||||
ULONG attr;
|
ULONG attr;
|
||||||
RpcAuthInfo *AuthInfo;
|
RpcAuthInfo *AuthInfo;
|
||||||
|
|
||||||
|
/* client-only */
|
||||||
|
struct list conn_pool_entry;
|
||||||
} RpcConnection;
|
} RpcConnection;
|
||||||
|
|
||||||
struct protseq_ops {
|
struct protseq_ops {
|
||||||
|
@ -101,6 +105,8 @@ void RPCRT4_strfree(LPSTR src);
|
||||||
ULONG RpcAuthInfo_AddRef(RpcAuthInfo *AuthInfo);
|
ULONG RpcAuthInfo_AddRef(RpcAuthInfo *AuthInfo);
|
||||||
ULONG RpcAuthInfo_Release(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_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_DestroyConnection(RpcConnection* Connection);
|
||||||
RPC_STATUS RPCRT4_OpenConnection(RpcConnection* Connection);
|
RPC_STATUS RPCRT4_OpenConnection(RpcConnection* Connection);
|
||||||
|
|
|
@ -68,6 +68,17 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(rpc);
|
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 ****/
|
/**** ncacn_np support ****/
|
||||||
|
|
||||||
typedef struct _RpcConnection_np
|
typedef struct _RpcConnection_np
|
||||||
|
@ -777,6 +788,7 @@ RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server,
|
||||||
NewConnection->NextCallId = 1;
|
NewConnection->NextCallId = 1;
|
||||||
if (AuthInfo) RpcAuthInfo_AddRef(AuthInfo);
|
if (AuthInfo) RpcAuthInfo_AddRef(AuthInfo);
|
||||||
NewConnection->AuthInfo = AuthInfo;
|
NewConnection->AuthInfo = AuthInfo;
|
||||||
|
list_init(&NewConnection->conn_pool_entry);
|
||||||
|
|
||||||
TRACE("connection: %p\n", NewConnection);
|
TRACE("connection: %p\n", NewConnection);
|
||||||
*Connection = NewConnection;
|
*Connection = NewConnection;
|
||||||
|
@ -784,6 +796,40 @@ RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server,
|
||||||
return RPC_S_OK;
|
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 RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection)
|
||||||
{
|
{
|
||||||
RPC_STATUS err;
|
RPC_STATUS err;
|
||||||
|
|
Loading…
Reference in New Issue