From c6dc14d81b7cb7c1d81868382122eca56009c673 Mon Sep 17 00:00:00 2001 From: Rob Shearman Date: Thu, 12 Jul 2007 15:32:43 +0100 Subject: [PATCH] rpcrt4: Make binding to an interface a function of RpcAssoc instead of binding handles, since binding requires information from the association and not from the binding handle. --- dlls/rpcrt4/rpc_binding.c | 82 ++------------------------------- dlls/rpcrt4/rpc_binding.h | 2 +- dlls/rpcrt4/rpc_transport.c | 92 ++++++++++++++++++++++++++++++++++++- 3 files changed, 96 insertions(+), 80 deletions(-) diff --git a/dlls/rpcrt4/rpc_binding.c b/dlls/rpcrt4/rpc_binding.c index 79ecedac47d..db30be63ba8 100644 --- a/dlls/rpcrt4/rpc_binding.c +++ b/dlls/rpcrt4/rpc_binding.c @@ -277,93 +277,21 @@ RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection, PRPC_SYNTAX_IDENTIFIER TransferSyntax, PRPC_SYNTAX_IDENTIFIER InterfaceId) { - RpcConnection* NewConnection; - RPC_STATUS status; - TRACE("(Binding == ^%p)\n", Binding); if (!Binding->server) { - /* try to find a compatible connection from the connection pool */ - NewConnection = RpcAssoc_GetIdleConnection(Binding->Assoc, InterfaceId, - TransferSyntax, Binding->AuthInfo, Binding->QOS); - if (NewConnection) { - *Connection = NewConnection; - return RPC_S_OK; - } + return RpcAssoc_GetClientConnection(Binding->Assoc, InterfaceId, + TransferSyntax, Binding->AuthInfo, Binding->QOS, Connection); } else { /* we already have a connection with acceptable binding, so use it */ if (Binding->FromConn) { *Connection = Binding->FromConn; return RPC_S_OK; + } else { + ERR("no connection in binding\n"); + return RPC_S_INTERNAL_ERROR; } } - - /* create a new connection */ - status = RPCRT4_CreateConnection(&NewConnection, Binding->server, - Binding->Protseq, Binding->NetworkAddr, - Binding->Endpoint, Binding->NetworkOptions, - Binding->AuthInfo, Binding->QOS); - if (status != RPC_S_OK) - return status; - - status = RPCRT4_OpenClientConnection(NewConnection); - if (status != RPC_S_OK) - { - RPCRT4_DestroyConnection(NewConnection); - return status; - } - - /* we need to send a binding packet if we are client. */ - if (!NewConnection->server) { - RpcPktHdr *hdr; - RpcPktHdr *response_hdr; - RPC_MESSAGE msg; - - TRACE("sending bind request to server\n"); - - hdr = RPCRT4_BuildBindHeader(NDR_LOCAL_DATA_REPRESENTATION, - RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, - Binding->Assoc->assoc_group_id, - InterfaceId, TransferSyntax); - - status = RPCRT4_Send(NewConnection, hdr, NULL, 0); - RPCRT4_FreeHeader(hdr); - if (status != RPC_S_OK) { - RPCRT4_DestroyConnection(NewConnection); - return status; - } - - status = RPCRT4_Receive(NewConnection, &response_hdr, &msg); - if (status != RPC_S_OK) { - ERR("receive failed\n"); - RPCRT4_DestroyConnection(NewConnection); - return status; - } - - if (response_hdr->common.ptype != PKT_BIND_ACK || - response_hdr->bind_ack.max_tsize < RPC_MIN_PACKET_SIZE) { - ERR("failed to bind for interface %s, %d.%d\n", - debugstr_guid(&InterfaceId->SyntaxGUID), - InterfaceId->SyntaxVersion.MajorVersion, - InterfaceId->SyntaxVersion.MinorVersion); - RPCRT4_FreeHeader(response_hdr); - RPCRT4_DestroyConnection(NewConnection); - return RPC_S_PROTOCOL_ERROR; - } - - /* FIXME: do more checks? */ - - NewConnection->MaxTransmissionSize = response_hdr->bind_ack.max_tsize; - NewConnection->assoc_group_id = response_hdr->bind_ack.assoc_gid; - NewConnection->ActiveInterface = *InterfaceId; - RPCRT4_FreeHeader(response_hdr); - } - - if (Binding->server) - Binding->FromConn = NewConnection; - *Connection = NewConnection; - - return RPC_S_OK; } RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection) diff --git a/dlls/rpcrt4/rpc_binding.h b/dlls/rpcrt4/rpc_binding.h index 58f2d062c81..5113b27e358 100644 --- a/dlls/rpcrt4/rpc_binding.h +++ b/dlls/rpcrt4/rpc_binding.h @@ -146,7 +146,7 @@ ULONG RpcQualityOfService_Release(RpcQualityOfService *qos); BOOL RpcQualityOfService_IsEqual(const RpcQualityOfService *qos1, const RpcQualityOfService *qos2); RPC_STATUS RPCRT4_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, RpcAssoc **assoc); -RpcConnection *RpcAssoc_GetIdleConnection(RpcAssoc *assoc, const RPC_SYNTAX_IDENTIFIER *InterfaceId, const RPC_SYNTAX_IDENTIFIER *TransferSyntax, const RpcAuthInfo *AuthInfo, const RpcQualityOfService *QOS); +RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc, const RPC_SYNTAX_IDENTIFIER *InterfaceId, const RPC_SYNTAX_IDENTIFIER *TransferSyntax, RpcAuthInfo *AuthInfo, RpcQualityOfService *QOS, RpcConnection **Connection); void RpcAssoc_ReleaseIdleConnection(RpcAssoc *assoc, RpcConnection *Connection); ULONG RpcAssoc_Release(RpcAssoc *assoc); diff --git a/dlls/rpcrt4/rpc_transport.c b/dlls/rpcrt4/rpc_transport.c index 2bb891d1d05..413bcbb5f32 100644 --- a/dlls/rpcrt4/rpc_transport.c +++ b/dlls/rpcrt4/rpc_transport.c @@ -1473,15 +1473,63 @@ ULONG RpcAssoc_Release(RpcAssoc *assoc) return refs; } -RpcConnection *RpcAssoc_GetIdleConnection(RpcAssoc *assoc, +static RPC_STATUS RpcAssoc_BindConnection(RpcAssoc *assoc, RpcConnection *conn, + const RPC_SYNTAX_IDENTIFIER *InterfaceId, + const RPC_SYNTAX_IDENTIFIER *TransferSyntax) +{ + RpcPktHdr *hdr; + RpcPktHdr *response_hdr; + RPC_MESSAGE msg; + RPC_STATUS status; + + TRACE("sending bind request to server\n"); + + hdr = RPCRT4_BuildBindHeader(NDR_LOCAL_DATA_REPRESENTATION, + RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, + assoc->assoc_group_id, + InterfaceId, TransferSyntax); + + status = RPCRT4_Send(conn, hdr, NULL, 0); + RPCRT4_FreeHeader(hdr); + if (status != RPC_S_OK) + return status; + + status = RPCRT4_Receive(conn, &response_hdr, &msg); + if (status != RPC_S_OK) + { + ERR("receive failed\n"); + return status; + } + + if (response_hdr->common.ptype != PKT_BIND_ACK) + { + ERR("failed to bind for interface %s, %d.%d\n", + debugstr_guid(&InterfaceId->SyntaxGUID), + InterfaceId->SyntaxVersion.MajorVersion, + InterfaceId->SyntaxVersion.MinorVersion); + RPCRT4_FreeHeader(response_hdr); + return RPC_S_PROTOCOL_ERROR; + } + + /* FIXME: do more checks? */ + + conn->assoc_group_id = response_hdr->bind_ack.assoc_gid; + conn->MaxTransmissionSize = response_hdr->bind_ack.max_tsize; + conn->ActiveInterface = *InterfaceId; + RPCRT4_FreeHeader(response_hdr); + return RPC_S_OK; +} + +static RpcConnection *RpcAssoc_GetIdleConnection(RpcAssoc *assoc, const RPC_SYNTAX_IDENTIFIER *InterfaceId, const RPC_SYNTAX_IDENTIFIER *TransferSyntax, const RpcAuthInfo *AuthInfo, const RpcQualityOfService *QOS) { RpcConnection *Connection; - /* try to find a compatible connection from the connection pool */ EnterCriticalSection(&assoc->cs); + /* try to find a compatible connection from the connection pool */ LIST_FOR_EACH_ENTRY(Connection, &assoc->connection_pool, RpcConnection, conn_pool_entry) + { if (!memcmp(&Connection->ActiveInterface, InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER)) && RpcAuthInfo_IsEqual(Connection->AuthInfo, AuthInfo) && @@ -1492,11 +1540,51 @@ RpcConnection *RpcAssoc_GetIdleConnection(RpcAssoc *assoc, TRACE("got connection from pool %p\n", Connection); return Connection; } + } LeaveCriticalSection(&assoc->cs); return NULL; } +RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc, + const RPC_SYNTAX_IDENTIFIER *InterfaceId, + const RPC_SYNTAX_IDENTIFIER *TransferSyntax, RpcAuthInfo *AuthInfo, + RpcQualityOfService *QOS, RpcConnection **Connection) +{ + RpcConnection *NewConnection; + RPC_STATUS status; + + *Connection = RpcAssoc_GetIdleConnection(assoc, InterfaceId, TransferSyntax, AuthInfo, QOS); + if (*Connection) + return RPC_S_OK; + + /* create a new connection */ + status = RPCRT4_CreateConnection(&NewConnection, FALSE /* is this a server connection? */, + assoc->Protseq, assoc->NetworkAddr, + assoc->Endpoint, assoc->NetworkOptions, + AuthInfo, QOS); + if (status != RPC_S_OK) + return status; + + status = RPCRT4_OpenClientConnection(NewConnection); + if (status != RPC_S_OK) + { + RPCRT4_DestroyConnection(NewConnection); + return status; + } + + status = RpcAssoc_BindConnection(assoc, NewConnection, InterfaceId, TransferSyntax); + if (status != RPC_S_OK) + { + RPCRT4_DestroyConnection(NewConnection); + return status; + } + + *Connection = NewConnection; + + return RPC_S_OK; +} + void RpcAssoc_ReleaseIdleConnection(RpcAssoc *assoc, RpcConnection *Connection) { assert(!Connection->server);