diff --git a/libfreerdp/core/gateway/rpc.c b/libfreerdp/core/gateway/rpc.c index ad2b787e0..4d4c67503 100644 --- a/libfreerdp/core/gateway/rpc.c +++ b/libfreerdp/core/gateway/rpc.c @@ -379,6 +379,7 @@ int rpc_write(rdpRpc* rpc, BYTE* data, int length, UINT16 opnum) WLog_ERR(TAG, "QueryContextAttributes SECPKG_ATTR_SIZES failure"); return -1; } + ZeroMemory(&Buffers, sizeof(Buffers)); request_pdu = (rpcconn_request_hdr_t*) calloc(1, sizeof(rpcconn_request_hdr_t)); @@ -459,19 +460,15 @@ int rpc_write(rdpRpc* rpc, BYTE* data, int length, UINT16 opnum) if (rpc_send_enqueue_pdu(rpc, buffer, request_pdu->frag_length) < 0) length = -1; - free (buffer); free(request_pdu); return length; out_free_clientCall: rpc_client_call_free(clientCall); out_free_pdu: - if (buffer) - free (buffer); - if (Buffers[1].pvBuffer) - free (Buffers[1].pvBuffer); - if (request_pdu) - free(request_pdu); + free (buffer); + free (Buffers[1].pvBuffer); + free(request_pdu); return -1; } diff --git a/libfreerdp/core/gateway/rpc_client.c b/libfreerdp/core/gateway/rpc_client.c index f9271c867..4a5544e37 100644 --- a/libfreerdp/core/gateway/rpc_client.c +++ b/libfreerdp/core/gateway/rpc_client.c @@ -354,7 +354,10 @@ int rpc_send_enqueue_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length) pdu = (RPC_PDU*) malloc(sizeof(RPC_PDU)); if (!pdu) + { + free(buffer); return -1; + } pdu->s = Stream_New(buffer, length); diff --git a/libfreerdp/core/gateway/tsg.c b/libfreerdp/core/gateway/tsg.c index 43b45a7c7..cdd7d098f 100644 --- a/libfreerdp/core/gateway/tsg.c +++ b/libfreerdp/core/gateway/tsg.c @@ -1401,6 +1401,16 @@ BOOL tsg_disconnect(rdpTsg* tsg) return TRUE; } +/** + * @brief + * + * @param[in] tsg + * @param[in] data + * @param[in] length + * @return < 0 on error; 0 if not enough data is available (non blocking mode); > 0 bytes to read + */ + + int tsg_read(rdpTsg* tsg, BYTE* data, UINT32 length) { int CopyLength; @@ -1434,16 +1444,32 @@ int tsg_read(rdpTsg* tsg, BYTE* data, UINT32 length) return CopyLength; } - tsg->pdu = rpc_recv_peek_pdu(rpc); - if (!tsg->pdu) + do { + tsg->pdu = rpc_recv_peek_pdu(rpc); + + /* there is a pdu to process - move on*/ + if (tsg->pdu) + break; + + /* + * no pdu available and synchronous is not required + * return 0 to indicate that there is no data + * available at the moment + */ if (!tsg->rpc->client->SynchronousReceive) return 0; - // weird !!!! - return tsg_read(tsg, data, length); - } + /* ensure that the transport wasn't already closed - in case of a retry */ + if (rpc->transport->layer == TRANSPORT_LAYER_CLOSED) + { + WLog_ERR(TAG, "tsg_read error: connection lost"); + return -1; + } + + /* retry in case synchronous receive is required */ + } while (tsg->rpc->client->SynchronousReceive); tsg->PendingPdu = TRUE; tsg->BytesAvailable = Stream_Length(tsg->pdu->s); diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c index 01f648a59..5154c198b 100644 --- a/libfreerdp/core/transport.c +++ b/libfreerdp/core/transport.c @@ -149,12 +149,16 @@ static int transport_bio_tsg_read(BIO* bio, char* buf, int size) { BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY); } + else if (status == 0) + { + BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY); + } else { BIO_set_flags(bio, BIO_FLAGS_READ); } - return status >= 0 ? status : -1; + return status > 0 ? status : -1; } static int transport_bio_tsg_puts(BIO* bio, const char* str) diff --git a/libfreerdp/crypto/tls.c b/libfreerdp/crypto/tls.c index 22522956d..9f52e6d62 100644 --- a/libfreerdp/crypto/tls.c +++ b/libfreerdp/crypto/tls.c @@ -167,8 +167,7 @@ static int bio_rdp_tls_read(BIO* bio, char* buf, int size) case SSL_ERROR_SYSCALL: error = WSAGetLastError(); if ((error == WSAEWOULDBLOCK) || (error == WSAEINTR) || - (error == WSAEINPROGRESS) || (error == WSAEALREADY) || - (error == 0)) + (error == WSAEINPROGRESS) || (error == WSAEALREADY)) { BIO_set_flags(bio, (BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY)); }