Module: wine Branch: master Commit: 3099fda2547096c3d4b258ec1cc010dabffe0b8f URL: https://source.winehq.org/git/wine.git/?a=commit;h=3099fda2547096c3d4b258ec1...
Author: Jacek Caban jacek@codeweavers.com Date: Tue Oct 16 14:38:49 2018 +0200
rpcrt4: Try reconnecting when to server in IRpcSend on broken connection.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/rpcrt4/rpc_assoc.c | 12 +++++++++--- dlls/rpcrt4/rpc_assoc.h | 2 +- dlls/rpcrt4/rpc_binding.c | 4 ++-- dlls/rpcrt4/rpc_binding.h | 3 ++- dlls/rpcrt4/rpc_message.c | 42 ++++++++++++++++++++++++++++-------------- 5 files changed, 42 insertions(+), 21 deletions(-)
diff --git a/dlls/rpcrt4/rpc_assoc.c b/dlls/rpcrt4/rpc_assoc.c index 8a823f4..044ef09 100644 --- a/dlls/rpcrt4/rpc_assoc.c +++ b/dlls/rpcrt4/rpc_assoc.c @@ -391,14 +391,18 @@ static RpcConnection *RpcAssoc_GetIdleConnection(RpcAssoc *assoc, RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc, const RPC_SYNTAX_IDENTIFIER *InterfaceId, const RPC_SYNTAX_IDENTIFIER *TransferSyntax, RpcAuthInfo *AuthInfo, - RpcQualityOfService *QOS, LPCWSTR CookieAuth, RpcConnection **Connection) + RpcQualityOfService *QOS, LPCWSTR CookieAuth, + RpcConnection **Connection, BOOL *from_cache) { RpcConnection *NewConnection; RPC_STATUS status;
*Connection = RpcAssoc_GetIdleConnection(assoc, InterfaceId, TransferSyntax, AuthInfo, QOS); - if (*Connection) + if (*Connection) { + TRACE("return idle connection %p for association %p\n", *Connection, assoc); + if (from_cache) *from_cache = TRUE; return RPC_S_OK; + }
/* create a new connection */ status = RPCRT4_CreateConnection(&NewConnection, FALSE /* is this a server connection? */, @@ -424,8 +428,10 @@ RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc, }
InterlockedIncrement(&assoc->connection_cnt); - *Connection = NewConnection;
+ TRACE("return new connection %p for association %p\n", *Connection, assoc); + *Connection = NewConnection; + if (from_cache) *from_cache = FALSE; return RPC_S_OK; }
diff --git a/dlls/rpcrt4/rpc_assoc.h b/dlls/rpcrt4/rpc_assoc.h index f4c5f3a..c8c8772 100644 --- a/dlls/rpcrt4/rpc_assoc.h +++ b/dlls/rpcrt4/rpc_assoc.h @@ -50,7 +50,7 @@ typedef struct _RpcAssoc RPC_STATUS RPCRT4_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, RpcAssoc **assoc) DECLSPEC_HIDDEN; RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc, const RPC_SYNTAX_IDENTIFIER *InterfaceId, const RPC_SYNTAX_IDENTIFIER *TransferSyntax, RpcAuthInfo *AuthInfo, RpcQualityOfService *QOS, - LPCWSTR CookieAuth, RpcConnection **Connection) DECLSPEC_HIDDEN; + LPCWSTR CookieAuth, RpcConnection **Connection, BOOL *from_cache) DECLSPEC_HIDDEN; void RpcAssoc_ReleaseIdleConnection(RpcAssoc *assoc, RpcConnection *Connection) DECLSPEC_HIDDEN; ULONG RpcAssoc_Release(RpcAssoc *assoc) DECLSPEC_HIDDEN; RPC_STATUS RpcServerAssoc_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, ULONG assoc_gid, RpcAssoc **assoc_out) DECLSPEC_HIDDEN; diff --git a/dlls/rpcrt4/rpc_binding.c b/dlls/rpcrt4/rpc_binding.c index ec38b86..ae63abd 100644 --- a/dlls/rpcrt4/rpc_binding.c +++ b/dlls/rpcrt4/rpc_binding.c @@ -272,13 +272,13 @@ RPC_STATUS RPCRT4_ReleaseBinding(RpcBinding* Binding)
RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection, const RPC_SYNTAX_IDENTIFIER *TransferSyntax, - const RPC_SYNTAX_IDENTIFIER *InterfaceId) + const RPC_SYNTAX_IDENTIFIER *InterfaceId, BOOL *from_cache) { TRACE("(Binding == ^%p)\n", Binding);
if (!Binding->server) { return RpcAssoc_GetClientConnection(Binding->Assoc, InterfaceId, - TransferSyntax, Binding->AuthInfo, Binding->QOS, Binding->CookieAuth, Connection); + TransferSyntax, Binding->AuthInfo, Binding->QOS, Binding->CookieAuth, Connection, from_cache); } else { /* we already have a connection with acceptable binding, so use it */ if (Binding->FromConn) { diff --git a/dlls/rpcrt4/rpc_binding.h b/dlls/rpcrt4/rpc_binding.h index ca53887..8faacbd 100644 --- a/dlls/rpcrt4/rpc_binding.h +++ b/dlls/rpcrt4/rpc_binding.h @@ -174,7 +174,8 @@ RPC_STATUS RPCRT4_MakeBinding(RpcBinding** Binding, RpcConnection* Connection) D void RPCRT4_AddRefBinding(RpcBinding* Binding) DECLSPEC_HIDDEN; RPC_STATUS RPCRT4_ReleaseBinding(RpcBinding* Binding) DECLSPEC_HIDDEN; RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection, - const RPC_SYNTAX_IDENTIFIER *TransferSyntax, const RPC_SYNTAX_IDENTIFIER *InterfaceId) DECLSPEC_HIDDEN; + const RPC_SYNTAX_IDENTIFIER *TransferSyntax, const RPC_SYNTAX_IDENTIFIER *InterfaceId, + BOOL *from_cache) DECLSPEC_HIDDEN; RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection) DECLSPEC_HIDDEN;
void rpcrt4_conn_release_and_wait(RpcConnection *connection) DECLSPEC_HIDDEN; diff --git a/dlls/rpcrt4/rpc_message.c b/dlls/rpcrt4/rpc_message.c index 9642213..3eea88a 100644 --- a/dlls/rpcrt4/rpc_message.c +++ b/dlls/rpcrt4/rpc_message.c @@ -38,6 +38,7 @@ #include "rpc_binding.h" #include "rpc_defs.h" #include "rpc_message.h" +#include "rpc_assoc.h" #include "ncastatus.h"
WINE_DEFAULT_DEBUG_CHANNEL(rpc); @@ -1598,7 +1599,7 @@ RPC_STATUS WINAPI I_RpcNegotiateTransferSyntax(PRPC_MESSAGE pMsg) }
status = RPCRT4_OpenBinding(bind, &conn, &cif->TransferSyntax, - &cif->InterfaceId); + &cif->InterfaceId, NULL);
if (status == RPC_S_OK) { @@ -1789,26 +1790,39 @@ static DWORD WINAPI async_notifier_proc(LPVOID p) RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg) { RpcBinding* bind = pMsg->Handle; + RPC_CLIENT_INTERFACE *cif; RpcConnection* conn; RPC_STATUS status; RpcPktHdr *hdr; + BOOL from_cache = TRUE;
TRACE("(%p)\n", pMsg); if (!bind || bind->server || !pMsg->ReservedForRuntime) return RPC_S_INVALID_BINDING;
- conn = pMsg->ReservedForRuntime; - - hdr = RPCRT4_BuildRequestHeader(pMsg->DataRepresentation, - pMsg->BufferLength, - pMsg->ProcNum & ~RPC_FLAGS_VALID_BIT, - &bind->ObjectUuid); - if (!hdr) - return ERROR_OUTOFMEMORY; - hdr->common.call_id = conn->NextCallId++; - - status = RPCRT4_Send(conn, hdr, pMsg->Buffer, pMsg->BufferLength); - - RPCRT4_FreeHeader(hdr); + for (;;) + { + conn = pMsg->ReservedForRuntime; + hdr = RPCRT4_BuildRequestHeader(pMsg->DataRepresentation, + pMsg->BufferLength, + pMsg->ProcNum & ~RPC_FLAGS_VALID_BIT, + &bind->ObjectUuid); + if (!hdr) + return ERROR_OUTOFMEMORY; + + hdr->common.call_id = conn->NextCallId++; + status = RPCRT4_Send(conn, hdr, pMsg->Buffer, pMsg->BufferLength); + RPCRT4_FreeHeader(hdr); + if (status == RPC_S_OK || conn->server || !from_cache) + break; + + WARN("Send failed, trying to reconnect\n"); + cif = pMsg->RpcInterfaceInformation; + RPCRT4_ReleaseConnection(conn); + pMsg->ReservedForRuntime = NULL; + status = RPCRT4_OpenBinding(bind, &conn, &cif->TransferSyntax, &cif->InterfaceId, &from_cache); + if (status != RPC_S_OK) break; + pMsg->ReservedForRuntime = conn; + }
if (status == RPC_S_OK && pMsg->RpcFlags & RPC_BUFFER_ASYNC) {