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.
This commit is contained in:
Rob Shearman 2007-07-12 15:32:43 +01:00 committed by Alexandre Julliard
parent 1cd222b451
commit c6dc14d81b
3 changed files with 96 additions and 80 deletions

View File

@ -277,93 +277,21 @@ RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection,
PRPC_SYNTAX_IDENTIFIER TransferSyntax, PRPC_SYNTAX_IDENTIFIER TransferSyntax,
PRPC_SYNTAX_IDENTIFIER InterfaceId) PRPC_SYNTAX_IDENTIFIER InterfaceId)
{ {
RpcConnection* NewConnection;
RPC_STATUS status;
TRACE("(Binding == ^%p)\n", Binding); TRACE("(Binding == ^%p)\n", Binding);
if (!Binding->server) { if (!Binding->server) {
/* try to find a compatible connection from the connection pool */ return RpcAssoc_GetClientConnection(Binding->Assoc, InterfaceId,
NewConnection = RpcAssoc_GetIdleConnection(Binding->Assoc, InterfaceId, TransferSyntax, Binding->AuthInfo, Binding->QOS, Connection);
TransferSyntax, Binding->AuthInfo, Binding->QOS);
if (NewConnection) {
*Connection = NewConnection;
return RPC_S_OK;
}
} 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) {
*Connection = Binding->FromConn; *Connection = Binding->FromConn;
return RPC_S_OK; 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) RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection)

View File

@ -146,7 +146,7 @@ ULONG RpcQualityOfService_Release(RpcQualityOfService *qos);
BOOL RpcQualityOfService_IsEqual(const RpcQualityOfService *qos1, const RpcQualityOfService *qos2); BOOL RpcQualityOfService_IsEqual(const RpcQualityOfService *qos1, const RpcQualityOfService *qos2);
RPC_STATUS RPCRT4_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, RpcAssoc **assoc); 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); void RpcAssoc_ReleaseIdleConnection(RpcAssoc *assoc, RpcConnection *Connection);
ULONG RpcAssoc_Release(RpcAssoc *assoc); ULONG RpcAssoc_Release(RpcAssoc *assoc);

View File

@ -1473,15 +1473,63 @@ ULONG RpcAssoc_Release(RpcAssoc *assoc)
return refs; 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 *InterfaceId,
const RPC_SYNTAX_IDENTIFIER *TransferSyntax, const RpcAuthInfo *AuthInfo, const RPC_SYNTAX_IDENTIFIER *TransferSyntax, const RpcAuthInfo *AuthInfo,
const RpcQualityOfService *QOS) const RpcQualityOfService *QOS)
{ {
RpcConnection *Connection; RpcConnection *Connection;
/* try to find a compatible connection from the connection pool */
EnterCriticalSection(&assoc->cs); 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) LIST_FOR_EACH_ENTRY(Connection, &assoc->connection_pool, RpcConnection, conn_pool_entry)
{
if (!memcmp(&Connection->ActiveInterface, InterfaceId, if (!memcmp(&Connection->ActiveInterface, InterfaceId,
sizeof(RPC_SYNTAX_IDENTIFIER)) && sizeof(RPC_SYNTAX_IDENTIFIER)) &&
RpcAuthInfo_IsEqual(Connection->AuthInfo, AuthInfo) && RpcAuthInfo_IsEqual(Connection->AuthInfo, AuthInfo) &&
@ -1492,11 +1540,51 @@ RpcConnection *RpcAssoc_GetIdleConnection(RpcAssoc *assoc,
TRACE("got connection from pool %p\n", Connection); TRACE("got connection from pool %p\n", Connection);
return Connection; return Connection;
} }
}
LeaveCriticalSection(&assoc->cs); LeaveCriticalSection(&assoc->cs);
return NULL; 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) void RpcAssoc_ReleaseIdleConnection(RpcAssoc *assoc, RpcConnection *Connection)
{ {
assert(!Connection->server); assert(!Connection->server);