libfreerdp-core: refactor tsg virtual connection, in/out channels

This commit is contained in:
Marc-André Moreau 2015-02-11 15:26:22 -05:00
parent 70fab69347
commit 75cad064f1
7 changed files with 191 additions and 204 deletions

View File

@ -33,63 +33,53 @@
#define TAG FREERDP_TAG("core.gateway.ntlm")
wStream* rpc_ntlm_http_request(rdpRpc* rpc, SecBuffer* ntlm_token, int content_length, TSG_CHANNEL channel)
wStream* rpc_ntlm_http_request(rdpRpc* rpc, HttpContext* http, SecBuffer* ntlmToken, int contentLength, TSG_CHANNEL channel)
{
wStream* s;
HttpContext* http_context;
HttpRequest* http_request;
char* base64_ntlm_token = NULL;
HttpRequest* request;
char* base64NtlmToken = NULL;
http_request = http_request_new();
request = http_request_new();
if (ntlm_token)
base64_ntlm_token = crypto_base64_encode(ntlm_token->pvBuffer, ntlm_token->cbBuffer);
if (ntlmToken)
base64NtlmToken = crypto_base64_encode(ntlmToken->pvBuffer, ntlmToken->cbBuffer);
if (channel == TSG_CHANNEL_IN)
{
http_context = rpc->NtlmHttpIn->context;
http_request_set_method(http_request, "RPC_IN_DATA");
}
http_request_set_method(request, "RPC_IN_DATA");
else if (channel == TSG_CHANNEL_OUT)
http_request_set_method(request, "RPC_OUT_DATA");
request->ContentLength = contentLength;
http_request_set_uri(request, http->URI);
if (base64NtlmToken)
{
http_context = rpc->NtlmHttpOut->context;
http_request_set_method(http_request, "RPC_OUT_DATA");
}
else
{
return NULL;
http_request_set_auth_scheme(request, "NTLM");
http_request_set_auth_param(request, base64NtlmToken);
}
http_request->ContentLength = content_length;
http_request_set_uri(http_request, http_context->URI);
s = http_request_write(http, request);
http_request_free(request);
if (base64_ntlm_token)
{
http_request_set_auth_scheme(http_request, "NTLM");
http_request_set_auth_param(http_request, base64_ntlm_token);
}
s = http_request_write(http_context, http_request);
http_request_free(http_request);
free(base64_ntlm_token);
free(base64NtlmToken);
return s;
}
int rpc_ncacn_http_send_in_channel_request(rdpRpc* rpc)
int rpc_ncacn_http_send_in_channel_request(rdpRpc* rpc, RpcInChannel* inChannel)
{
wStream* s;
int status;
int contentLength;
BOOL continueNeeded;
rdpNtlm* ntlm = rpc->NtlmHttpIn->ntlm;
rdpNtlm* ntlm = inChannel->ntlm;
HttpContext* http = inChannel->http;
continueNeeded = ntlm_authenticate(ntlm);
contentLength = (continueNeeded) ? 0 : 0x40000000;
s = rpc_ntlm_http_request(rpc, &ntlm->outputBuffer[0], contentLength, TSG_CHANNEL_IN);
s = rpc_ntlm_http_request(rpc, http, &ntlm->outputBuffer[0], contentLength, TSG_CHANNEL_IN);
if (!s)
return -1;
@ -101,12 +91,12 @@ int rpc_ncacn_http_send_in_channel_request(rdpRpc* rpc)
return (status > 0) ? 1 : -1;
}
int rpc_ncacn_http_recv_in_channel_response(rdpRpc* rpc, HttpResponse* response)
int rpc_ncacn_http_recv_in_channel_response(rdpRpc* rpc, RpcInChannel* inChannel, HttpResponse* response)
{
char* token64 = NULL;
int ntlmTokenLength = 0;
BYTE* ntlmTokenData = NULL;
rdpNtlm* ntlm = rpc->NtlmHttpIn->ntlm;
rdpNtlm* ntlm = inChannel->ntlm;
if (ListDictionary_Contains(response->Authenticates, "NTLM"))
{
@ -137,13 +127,13 @@ int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, TSG_CHANNEL channel)
if (channel == TSG_CHANNEL_IN)
{
ntlm = rpc->NtlmHttpIn->ntlm;
tls = rpc->VirtualConnection->DefaultInChannel->tls;
ntlm = rpc->VirtualConnection->DefaultInChannel->ntlm;
}
else if (channel == TSG_CHANNEL_OUT)
{
ntlm = rpc->NtlmHttpOut->ntlm;
tls = rpc->VirtualConnection->DefaultOutChannel->tls;
ntlm = rpc->VirtualConnection->DefaultOutChannel->ntlm;
}
if (!settings->GatewayPassword || !settings->GatewayUsername ||
@ -188,31 +178,34 @@ void rpc_ncacn_http_ntlm_uninit(rdpRpc* rpc, TSG_CHANNEL channel)
{
if (channel == TSG_CHANNEL_IN)
{
ntlm_client_uninit(rpc->NtlmHttpIn->ntlm);
ntlm_free(rpc->NtlmHttpIn->ntlm);
rpc->NtlmHttpIn->ntlm = NULL;
RpcInChannel* inChannel = rpc->VirtualConnection->DefaultInChannel;
ntlm_client_uninit(inChannel->ntlm);
ntlm_free(inChannel->ntlm);
inChannel->ntlm = NULL;
}
else if (channel == TSG_CHANNEL_OUT)
{
ntlm_client_uninit(rpc->NtlmHttpOut->ntlm);
ntlm_free(rpc->NtlmHttpOut->ntlm);
rpc->NtlmHttpOut->ntlm = NULL;
RpcOutChannel* outChannel = rpc->VirtualConnection->DefaultOutChannel;
ntlm_client_uninit(outChannel->ntlm);
ntlm_free(outChannel->ntlm);
outChannel->ntlm = NULL;
}
}
int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc)
int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc, RpcOutChannel* outChannel)
{
wStream* s;
int status;
int contentLength;
BOOL continueNeeded;
rdpNtlm* ntlm = rpc->NtlmHttpOut->ntlm;
rdpNtlm* ntlm = outChannel->ntlm;
HttpContext* http = outChannel->http;
continueNeeded = ntlm_authenticate(ntlm);
contentLength = (continueNeeded) ? 0 : 76;
s = rpc_ntlm_http_request(rpc, &ntlm->outputBuffer[0], contentLength, TSG_CHANNEL_OUT);
s = rpc_ntlm_http_request(rpc, http, &ntlm->outputBuffer[0], contentLength, TSG_CHANNEL_OUT);
if (!s)
return -1;
@ -224,12 +217,12 @@ int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc)
return (status > 0) ? 1 : -1;
}
int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc, HttpResponse* response)
int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc, RpcOutChannel* outChannel, HttpResponse* response)
{
char* token64 = NULL;
int ntlmTokenLength = 0;
BYTE* ntlmTokenData = NULL;
rdpNtlm* ntlm = rpc->NtlmHttpOut->ntlm;
rdpNtlm* ntlm = outChannel->ntlm;
if (ListDictionary_Contains(response->Authenticates, "NTLM"))
{
@ -250,87 +243,29 @@ int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc, HttpResponse* response
return 1;
}
int rpc_http_send_replacement_out_channel_request(rdpRpc* rpc)
{
int status;
wStream* s;
s = rpc_ntlm_http_request(rpc, NULL, 120, TSG_CHANNEL_OUT);
if (!s)
return -1;
WLog_DBG(TAG, "\n%s", Stream_Buffer(s));
status = rpc_out_write(rpc, Stream_Buffer(s), Stream_Length(s));
Stream_Free(s, TRUE);
return (status > 0) ? 1 : -1;
}
void rpc_ntlm_http_init_channel(rdpRpc* rpc, rdpNtlmHttp* ntlm_http, TSG_CHANNEL channel)
void rpc_ntlm_http_init_channel(rdpRpc* rpc, HttpContext* http, TSG_CHANNEL channel)
{
if (channel == TSG_CHANNEL_IN)
http_context_set_method(ntlm_http->context, "RPC_IN_DATA");
http_context_set_method(http, "RPC_IN_DATA");
else if (channel == TSG_CHANNEL_OUT)
http_context_set_method(ntlm_http->context, "RPC_OUT_DATA");
http_context_set_method(http, "RPC_OUT_DATA");
http_context_set_uri(ntlm_http->context, "/rpc/rpcproxy.dll?localhost:3388");
http_context_set_accept(ntlm_http->context, "application/rpc");
http_context_set_cache_control(ntlm_http->context, "no-cache");
http_context_set_connection(ntlm_http->context, "Keep-Alive");
http_context_set_user_agent(ntlm_http->context, "MSRPC");
http_context_set_host(ntlm_http->context, rpc->settings->GatewayHostname);
http_context_set_uri(http, "/rpc/rpcproxy.dll?localhost:3388");
http_context_set_accept(http, "application/rpc");
http_context_set_cache_control(http, "no-cache");
http_context_set_connection(http, "Keep-Alive");
http_context_set_user_agent(http, "MSRPC");
http_context_set_host(http, rpc->settings->GatewayHostname);
if (channel == TSG_CHANNEL_IN)
{
http_context_set_pragma(ntlm_http->context,
http_context_set_pragma(http,
"ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729");
}
else if (channel == TSG_CHANNEL_OUT)
{
http_context_set_pragma(ntlm_http->context,
http_context_set_pragma(http,
"ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729, "
"SessionId=fbd9c34f-397d-471d-a109-1b08cc554624");
}
}
rdpNtlmHttp* ntlm_http_new()
{
rdpNtlmHttp* ntlm_http;
ntlm_http = (rdpNtlmHttp*) calloc(1, sizeof(rdpNtlmHttp));
if (!ntlm_http)
return NULL;
ntlm_http->ntlm = ntlm_new();
if (!ntlm_http->ntlm)
goto out_free;
ntlm_http->context = http_context_new();
if (!ntlm_http->context)
goto out_free_ntlm;
return ntlm_http;
out_free_ntlm:
ntlm_free(ntlm_http->ntlm);
out_free:
free(ntlm_http);
return NULL;
}
void ntlm_http_free(rdpNtlmHttp* ntlm_http)
{
if (!ntlm_http)
return;
ntlm_free(ntlm_http->ntlm);
http_context_free(ntlm_http->context);
free(ntlm_http);
}

View File

@ -34,17 +34,12 @@
int rpc_ncacn_http_ntlm_init(rdpRpc* rpc, TSG_CHANNEL channel);
void rpc_ncacn_http_ntlm_uninit(rdpRpc* rpc, TSG_CHANNEL channel);
int rpc_ncacn_http_send_in_channel_request(rdpRpc* rpc);
int rpc_ncacn_http_recv_in_channel_response(rdpRpc* rpc, HttpResponse* response);
int rpc_ncacn_http_send_in_channel_request(rdpRpc* rpc, RpcInChannel* inChannel);
int rpc_ncacn_http_recv_in_channel_response(rdpRpc* rpc, RpcInChannel* inChannel, HttpResponse* response);
int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc);
int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc, HttpResponse* response);
int rpc_ncacn_http_send_out_channel_request(rdpRpc* rpc, RpcOutChannel* outChannel);
int rpc_ncacn_http_recv_out_channel_response(rdpRpc* rpc, RpcOutChannel* outChannel, HttpResponse* response);
void rpc_ntlm_http_init_channel(rdpRpc* rpc, rdpNtlmHttp* ntlm_http, TSG_CHANNEL channel);
int rpc_http_send_replacement_out_channel_request(rdpRpc* rpc);
rdpNtlmHttp* ntlm_http_new(void);
void ntlm_http_free(rdpNtlmHttp* ntlm_http);
void rpc_ntlm_http_init_channel(rdpRpc* rpc, HttpContext* http, TSG_CHANNEL channel);
#endif

View File

@ -23,7 +23,6 @@
#define FREERDP_CORE_NTLM_H
typedef struct rdp_ntlm rdpNtlm;
typedef struct rdp_ntlm_http rdpNtlmHttp;
#include "../tcp.h"
#include "../transport.h"
@ -65,12 +64,6 @@ struct rdp_ntlm
SecPkgContext_Bindings* Bindings;
};
struct rdp_ntlm_http
{
rdpNtlm* ntlm;
HttpContext* context;
};
BOOL ntlm_authenticate(rdpNtlm* ntlm);
BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL confidentiality, char* user,

View File

@ -136,7 +136,7 @@ BOOL rpc_connect(rdpRpc* rpc)
/* Send IN Channel Request */
if (rpc_ncacn_http_send_in_channel_request(rpc) < 0)
if (rpc_ncacn_http_send_in_channel_request(rpc, inChannel) < 0)
{
WLog_ERR(TAG, "rpc_ncacn_http_send_in_channel_request failure");
return FALSE;
@ -153,7 +153,7 @@ BOOL rpc_connect(rdpRpc* rpc)
/* Send OUT Channel Request */
if (rpc_ncacn_http_send_out_channel_request(rpc) < 0)
if (rpc_ncacn_http_send_out_channel_request(rpc, outChannel) < 0)
{
WLog_ERR(TAG, "rpc_ncacn_http_send_out_channel_request failure");
return FALSE;
@ -592,6 +592,62 @@ int rpc_client_in_channel_transition_to_state(RpcInChannel* inChannel, CLIENT_IN
return status;
}
int rpc_client_in_channel_rpch_init(rdpRpc* rpc, RpcInChannel* inChannel)
{
inChannel->ntlm = ntlm_new();
if (!inChannel->ntlm)
return -1;
inChannel->http = http_context_new();
if (!inChannel->http)
return -1;
rpc_ntlm_http_init_channel(rpc, inChannel->http, TSG_CHANNEL_IN);
return 1;
}
void rpc_client_in_channel_rpch_uninit(RpcInChannel* inChannel)
{
if (inChannel->ntlm)
{
ntlm_free(inChannel->ntlm);
inChannel->ntlm = NULL;
}
if (inChannel->http)
{
http_context_free(inChannel->http);
inChannel->http = NULL;
}
}
RpcInChannel* rpc_client_in_channel_new(rdpRpc* rpc)
{
RpcInChannel* inChannel = NULL;
inChannel = (RpcInChannel*) calloc(1, sizeof(RpcInChannel));
if (inChannel)
{
}
return inChannel;
}
void rpc_client_in_channel_free(RpcInChannel* inChannel)
{
if (!inChannel)
return;
rpc_client_in_channel_rpch_uninit(inChannel);
free(inChannel);
}
int rpc_client_out_channel_transition_to_state(RpcOutChannel* outChannel, CLIENT_OUT_CHANNEL_STATE state)
{
int status = 1;
@ -642,6 +698,62 @@ int rpc_client_out_channel_transition_to_state(RpcOutChannel* outChannel, CLIENT
return status;
}
int rpc_client_out_channel_rpch_init(rdpRpc* rpc, RpcOutChannel* outChannel)
{
outChannel->ntlm = ntlm_new();
if (!outChannel->ntlm)
return -1;
outChannel->http = http_context_new();
if (!outChannel->http)
return -1;
rpc_ntlm_http_init_channel(rpc, outChannel->http, TSG_CHANNEL_OUT);
return 1;
}
void rpc_client_out_channel_rpch_uninit(RpcOutChannel* outChannel)
{
if (outChannel->ntlm)
{
ntlm_free(outChannel->ntlm);
outChannel->ntlm = NULL;
}
if (outChannel->http)
{
http_context_free(outChannel->http);
outChannel->http = NULL;
}
}
RpcOutChannel* rpc_client_out_channel_new(rdpRpc* rpc)
{
RpcOutChannel* outChannel = NULL;
outChannel = (RpcOutChannel*) calloc(1, sizeof(RpcOutChannel));
if (outChannel)
{
}
return outChannel;
}
void rpc_client_out_channel_free(RpcOutChannel* outChannel)
{
if (!outChannel)
return;
rpc_client_out_channel_rpch_uninit(outChannel);
free(outChannel);
}
int rpc_client_virtual_connection_transition_to_state(rdpRpc* rpc,
RpcVirtualConnection* connection, VIRTUAL_CONNECTION_STATE state)
{
@ -693,6 +805,7 @@ void rpc_client_virtual_connection_init(rdpRpc* rpc, RpcVirtualConnection* conne
connection->DefaultInChannel->PingOriginator.KeepAliveInterval = 0;
rts_generate_cookie((BYTE*) &(connection->DefaultInChannelCookie));
rts_generate_cookie((BYTE*) &(connection->NonDefaultInChannelCookie));
rpc_client_in_channel_rpch_init(rpc, connection->DefaultInChannel);
connection->DefaultOutChannel->State = CLIENT_OUT_CHANNEL_STATE_INITIAL;
connection->DefaultOutChannel->BytesReceived = 0;
@ -702,6 +815,7 @@ void rpc_client_virtual_connection_init(rdpRpc* rpc, RpcVirtualConnection* conne
connection->DefaultOutChannel->AvailableWindowAdvertised = rpc->ReceiveWindow;
rts_generate_cookie((BYTE*) &(connection->DefaultOutChannelCookie));
rts_generate_cookie((BYTE*) &(connection->NonDefaultOutChannelCookie));
rpc_client_out_channel_rpch_init(rpc, connection->DefaultOutChannel);
}
RpcVirtualConnection* rpc_client_virtual_connection_new(rdpRpc* rpc)
@ -715,12 +829,12 @@ RpcVirtualConnection* rpc_client_virtual_connection_new(rdpRpc* rpc)
connection->State = VIRTUAL_CONNECTION_STATE_INITIAL;
connection->DefaultInChannel = (RpcInChannel*) calloc(1, sizeof(RpcInChannel));
connection->DefaultInChannel = rpc_client_in_channel_new(rpc);
if (!connection->DefaultInChannel)
goto out_free;
connection->DefaultOutChannel = (RpcOutChannel*) calloc(1, sizeof(RpcOutChannel));
connection->DefaultOutChannel = rpc_client_out_channel_new(rpc);
if (!connection->DefaultOutChannel)
goto out_default_in;
@ -737,12 +851,13 @@ out_free:
void rpc_client_virtual_connection_free(RpcVirtualConnection* virtualConnection)
{
if (virtualConnection)
{
free(virtualConnection->DefaultInChannel);
free(virtualConnection->DefaultOutChannel);
free(virtualConnection);
}
if (!virtualConnection)
return;
rpc_client_in_channel_free(virtualConnection->DefaultInChannel);
rpc_client_out_channel_free(virtualConnection->DefaultOutChannel);
free(virtualConnection);
}
rdpRpc* rpc_new(rdpTransport* transport)
@ -765,19 +880,6 @@ rdpRpc* rpc_new(rdpTransport* transport)
if (!rpc->ntlm)
goto out_free;
rpc->NtlmHttpIn = ntlm_http_new();
if (!rpc->NtlmHttpIn)
goto out_free_ntlm;
rpc->NtlmHttpOut = ntlm_http_new();
if (!rpc->NtlmHttpOut)
goto out_free_ntlm_http_in;
rpc_ntlm_http_init_channel(rpc, rpc->NtlmHttpIn, TSG_CHANNEL_IN);
rpc_ntlm_http_init_channel(rpc, rpc->NtlmHttpOut, TSG_CHANNEL_OUT);
rpc->PipeCallId = 0;
rpc->StubCallId = 0;
rpc->StubFragCount = 0;
@ -801,30 +903,18 @@ rdpRpc* rpc_new(rdpTransport* transport)
rpc->VirtualConnection = rpc_client_virtual_connection_new(rpc);
if (!rpc->VirtualConnection)
goto out_free_ntlm_http_out;
rpc->VirtualConnectionCookieTable = ArrayList_New(TRUE);
if (!rpc->VirtualConnectionCookieTable)
goto out_free_virtual_connection;
rpc->CallId = 2;
if (rpc_client_new(rpc) < 0)
goto out_free_virtualConnectionCookieTable;
goto out_free_rpc_client;
return rpc;
out_free_virtualConnectionCookieTable:
out_free_rpc_client:
rpc_client_free(rpc);
ArrayList_Free(rpc->VirtualConnectionCookieTable);
out_free_virtual_connection:
rpc_client_virtual_connection_free(rpc->VirtualConnection);
out_free_ntlm_http_out:
ntlm_http_free(rpc->NtlmHttpOut);
out_free_ntlm_http_in:
ntlm_http_free(rpc->NtlmHttpIn);
out_free_ntlm:
ntlm_free(rpc->ntlm);
out_free:
free(rpc);
return NULL;
@ -843,21 +933,7 @@ void rpc_free(rdpRpc* rpc)
rpc->ntlm = NULL;
}
if (rpc->NtlmHttpIn)
{
ntlm_http_free(rpc->NtlmHttpIn);
rpc->NtlmHttpIn = NULL;
}
if (rpc->NtlmHttpOut)
{
ntlm_http_free(rpc->NtlmHttpOut);
rpc->NtlmHttpOut = NULL;
}
rpc_client_virtual_connection_free(rpc->VirtualConnection);
ArrayList_Clear(rpc->VirtualConnectionCookieTable);
ArrayList_Free(rpc->VirtualConnectionCookieTable);
free(rpc);
}

View File

@ -621,6 +621,8 @@ struct rpc_in_channel
rdpTcp* tcp;
rdpTls* tls;
rdpNtlm* ntlm;
HttpContext* http;
CLIENT_IN_CHANNEL_STATE State;
@ -656,6 +658,8 @@ struct rpc_out_channel
{
rdpTcp* tcp;
rdpTls* tls;
rdpNtlm* ntlm;
HttpContext* http;
/* Receiving Channel */
@ -735,9 +739,6 @@ struct rdp_rpc
RpcClient* client;
rdpNtlmHttp* NtlmHttpIn;
rdpNtlmHttp* NtlmHttpOut;
rdpContext* context;
rdpSettings* settings;
rdpTransport* transport;
@ -762,8 +763,6 @@ struct rdp_rpc
UINT32 CurrentKeepAliveInterval;
RpcVirtualConnection* VirtualConnection;
wArrayList* VirtualConnectionCookieTable;
};
void rpc_pdu_header_print(rpcconn_hdr_t* header);

View File

@ -549,7 +549,7 @@ int rpc_client_out_channel_recv(rdpRpc* rpc)
{
/* Receive OUT Channel Response */
if (rpc_ncacn_http_recv_out_channel_response(rpc, response) < 0)
if (rpc_ncacn_http_recv_out_channel_response(rpc, outChannel, response) < 0)
{
WLog_ERR(TAG, "rpc_ncacn_http_recv_out_channel_response failure");
return -1;
@ -557,7 +557,7 @@ int rpc_client_out_channel_recv(rdpRpc* rpc)
/* Send OUT Channel Request */
if (rpc_ncacn_http_send_out_channel_request(rpc) < 0)
if (rpc_ncacn_http_send_out_channel_request(rpc, outChannel) < 0)
{
WLog_ERR(TAG, "rpc_ncacn_http_send_out_channel_request failure");
return -1;
@ -659,7 +659,7 @@ int rpc_client_in_channel_recv(rdpRpc* rpc)
if (inChannel->State == CLIENT_IN_CHANNEL_STATE_SECURITY)
{
if (rpc_ncacn_http_recv_in_channel_response(rpc, response) < 0)
if (rpc_ncacn_http_recv_in_channel_response(rpc, inChannel, response) < 0)
{
WLog_ERR(TAG, "rpc_ncacn_http_recv_in_channel_response failure");
return -1;
@ -667,7 +667,7 @@ int rpc_client_in_channel_recv(rdpRpc* rpc)
/* Send IN Channel Request */
if (rpc_ncacn_http_send_in_channel_request(rpc) < 0)
if (rpc_ncacn_http_send_in_channel_request(rpc, inChannel) < 0)
{
WLog_ERR(TAG, "rpc_ncacn_http_send_in_channel_request failure");
return -1;

View File

@ -839,7 +839,6 @@ int rts_send_OUT_R1_A3_pdu(rdpRpc* rpc)
int rts_recv_OUT_R1_A2_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
{
int status;
UINT32 offset;
UINT32 Destination = 0;
@ -850,16 +849,6 @@ int rts_recv_OUT_R1_A2_pdu(rdpRpc* rpc, BYTE* buffer, UINT32 length)
WLog_ERR(TAG, "TS Gateway channel recycling is incomplete");
status = rpc_http_send_replacement_out_channel_request(rpc);
if (status < 0)
return -1;
status = rts_send_OUT_R1_A3_pdu(rpc);
if (status < 0)
return -1;
return 1;
}