Moved HTTP Proxy methods out of transport.c into new proxy.c; use not in transport.c but in tcp.c
This commit is contained in:
parent
844ce44473
commit
ac90c23c71
@ -101,6 +101,8 @@ set(${MODULE_PREFIX}_SRCS
|
||||
rdp.h
|
||||
tcp.c
|
||||
tcp.h
|
||||
proxy.c
|
||||
proxy.h
|
||||
tpdu.c
|
||||
tpdu.h
|
||||
tpkt.c
|
||||
|
149
libfreerdp/core/proxy.c
Normal file
149
libfreerdp/core/proxy.c
Normal file
@ -0,0 +1,149 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* HTTP Proxy support
|
||||
*
|
||||
* Copyright 2014 Christian Plattner <ccpp@gmx.at>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
#include "freerdp/settings.h"
|
||||
#include "tcp.h"
|
||||
|
||||
#include "winpr/environment.h"
|
||||
/* For GetEnvironmentVariableA */
|
||||
|
||||
/* TODO move into core/tcp.c? */
|
||||
void http_proxy_read_environment(rdpSettings *settings, char *envname)
|
||||
{
|
||||
char env[256];
|
||||
DWORD envlen;
|
||||
char *hostname, *pport;
|
||||
|
||||
envlen = GetEnvironmentVariableA(envname, env, sizeof(env));
|
||||
if(!envlen)
|
||||
return;
|
||||
|
||||
if (strncmp(env, "http://", 7)) {
|
||||
fprintf(stderr, "Proxy url must have scheme http. Ignoring.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
settings->HTTPProxyEnabled = TRUE;
|
||||
|
||||
hostname = env + 7;
|
||||
pport = strchr(hostname, ':');
|
||||
if (pport) {
|
||||
*pport = '\0';
|
||||
settings->HTTPProxyPort = atoi(pport+1);
|
||||
}
|
||||
else {
|
||||
/* The default is 80. Also for Proxys. */
|
||||
settings->HTTPProxyPort = 80;
|
||||
|
||||
pport = strchr(hostname, '/');
|
||||
if(pport)
|
||||
*pport = '\0';
|
||||
}
|
||||
|
||||
freerdp_set_param_string(settings, FreeRDP_HTTPProxyHostname, hostname);
|
||||
}
|
||||
|
||||
BOOL http_proxy_connect(rdpTcp* tcp, const char* hostname, UINT16 port)
|
||||
{
|
||||
int status;
|
||||
wStream* s;
|
||||
char str[256], *eol;
|
||||
int resultsize;
|
||||
int send_length;
|
||||
|
||||
_itoa_s(port, str, sizeof(str), 10);
|
||||
|
||||
s = Stream_New(NULL, 200);
|
||||
Stream_Write(s, "CONNECT ", 8);
|
||||
Stream_Write(s, hostname, strlen(hostname));
|
||||
Stream_Write_UINT8(s, ':');
|
||||
Stream_Write(s, str, strlen(str));
|
||||
Stream_Write(s, " HTTP/1.1\r\n\r\nHost: ", 19);
|
||||
Stream_Write(s, hostname, strlen(hostname));
|
||||
Stream_Write_UINT8(s, ':');
|
||||
Stream_Write(s, str, strlen(str));
|
||||
Stream_Write(s, "\r\n\r\n", 4);
|
||||
|
||||
send_length = Stream_GetPosition(s);
|
||||
Stream_SetPosition(s, 0);
|
||||
while (send_length > 0) {
|
||||
status = tcp_write(tcp, Stream_Pointer(s), send_length);
|
||||
if (status < 0) {
|
||||
fprintf(stderr, "HTTP Proxy connection: error while writing: %d\n", status);
|
||||
return FALSE;
|
||||
}
|
||||
if (status == 0) {
|
||||
fprintf(stderr, "HTTP Proxy blocking?\n");
|
||||
return FALSE;
|
||||
}
|
||||
fprintf(stderr, "HTTP Proxy: sent %d bytes\n", status);
|
||||
send_length -= status;
|
||||
}
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
s = NULL;
|
||||
|
||||
/* Read result until CR-LF-CR-LF.
|
||||
* Keep str a null-terminated string. */
|
||||
|
||||
memset(str, '\0', sizeof(str));
|
||||
resultsize = 0;
|
||||
while ( strstr(str, "\r\n\r\n") == NULL ) {
|
||||
if (resultsize >= sizeof(str)-1) {
|
||||
fprintf(stderr, "HTTP Reply headers too long.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
status = tcp_read(tcp, (BYTE*)str + resultsize, sizeof(str)-resultsize-1);
|
||||
if (status < 0) {
|
||||
/* Error? */
|
||||
return FALSE;
|
||||
}
|
||||
else if (status == 0) {
|
||||
/* Error? */
|
||||
fprintf(stderr, "tcp_read() returned zero\n");
|
||||
return FALSE;
|
||||
}
|
||||
fprintf(stderr, "HTTP Proxy: received %d bytes\n", status);
|
||||
resultsize += status;
|
||||
}
|
||||
|
||||
/* Extract HTTP status line */
|
||||
eol = strchr(str, '\r');
|
||||
if (!eol) {
|
||||
/* should never happen */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*eol = '\0';
|
||||
|
||||
fprintf(stderr, "HTTP proxy: %s\n", str);
|
||||
|
||||
if (strlen(str) < 12) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
str[7] = 'X';
|
||||
if (strncmp(str, "HTTP/1.X 200", 12))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
26
libfreerdp/core/proxy.h
Normal file
26
libfreerdp/core/proxy.h
Normal file
@ -0,0 +1,26 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* HTTP proxy support
|
||||
*
|
||||
* Copyright 2014 Christian Plattner <ccpp@gmx.at>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __HTTP_PROXY_H
|
||||
#define __HTTP_PROXY_H
|
||||
|
||||
void http_proxy_read_environment(rdpSettings *settings, char *envname);
|
||||
BOOL http_proxy_connect(rdpTcp* tcp, const char* hostname, UINT16 port);
|
||||
|
||||
#endif
|
@ -59,6 +59,7 @@
|
||||
#include <winpr/stream.h>
|
||||
|
||||
#include "tcp.h"
|
||||
#include "proxy.h"
|
||||
|
||||
void tcp_get_ip_address(rdpTcp* tcp)
|
||||
{
|
||||
@ -136,7 +137,15 @@ BOOL tcp_connect(rdpTcp* tcp, const char* hostname, int port)
|
||||
}
|
||||
else
|
||||
{
|
||||
tcp->sockfd = freerdp_tcp_connect(hostname, port);
|
||||
if (tcp->settings->HTTPProxyEnabled) {
|
||||
printf("HTTP Proxy enabled: %s:%d!\n", tcp->settings->HTTPProxyHostname, tcp->settings->HTTPProxyPort);
|
||||
tcp->sockfd = freerdp_tcp_connect(tcp->settings->HTTPProxyHostname, tcp->settings->HTTPProxyPort);
|
||||
if (!http_proxy_connect(tcp, hostname, port))
|
||||
return FALSE;
|
||||
} else {
|
||||
printf("HTTP Proxy disabled\n");
|
||||
tcp->sockfd = freerdp_tcp_connect(hostname, port);
|
||||
}
|
||||
|
||||
if (tcp->sockfd < 0)
|
||||
return FALSE;
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "fastpath.h"
|
||||
#include "transport.h"
|
||||
#include "rdp.h"
|
||||
#include "proxy.h"
|
||||
|
||||
#define BUFFER_SIZE 16384
|
||||
|
||||
@ -327,127 +328,6 @@ BOOL transport_connect_nla(rdpTransport* transport)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* For GetEnvironmentVariableA */
|
||||
#include "winpr/environment.h"
|
||||
|
||||
/* TODO move into core/tcp.c? */
|
||||
void transport_http_proxy_read_environment(rdpSettings *settings, char *envname)
|
||||
{
|
||||
char env[256];
|
||||
DWORD envlen;
|
||||
char *hostname, *pport;
|
||||
|
||||
envlen = GetEnvironmentVariableA(envname, env, sizeof(env));
|
||||
if(!envlen)
|
||||
return;
|
||||
|
||||
if (strncmp(env, "http://", 7)) {
|
||||
fprintf(stderr, "Proxy url must have scheme http. Ignoring.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
settings->HTTPProxyEnabled = TRUE;
|
||||
|
||||
hostname = env + 7;
|
||||
pport = strchr(hostname, ':');
|
||||
if (pport) {
|
||||
*pport = '\0';
|
||||
settings->HTTPProxyPort = atoi(pport+1);
|
||||
}
|
||||
else {
|
||||
/* The default is 80. Also for Proxys. */
|
||||
settings->HTTPProxyPort = 80;
|
||||
|
||||
pport = strchr(hostname, '/');
|
||||
if(pport)
|
||||
*pport = '\0';
|
||||
}
|
||||
|
||||
freerdp_set_param_string(settings, FreeRDP_HTTPProxyHostname, hostname);
|
||||
}
|
||||
|
||||
BOOL transport_http_proxy_connect(rdpTransport* transport, const char* hostname, UINT16 port)
|
||||
{
|
||||
int status;
|
||||
wStream* s;
|
||||
char str[256], *eol;
|
||||
rdpTcp *tcp;
|
||||
int resultsize;
|
||||
|
||||
if (transport->layer == TRANSPORT_LAYER_HTTP_PROXY_IN)
|
||||
tcp = transport->TcpIn;
|
||||
else
|
||||
tcp = transport->TcpOut;
|
||||
|
||||
_itoa_s(port, str, sizeof(str), 10);
|
||||
|
||||
s = Stream_New(NULL, 200);
|
||||
Stream_Write(s, "CONNECT ", 8);
|
||||
Stream_Write(s, hostname, strlen(hostname));
|
||||
Stream_Write_UINT8(s, ':');
|
||||
Stream_Write(s, str, strlen(str));
|
||||
Stream_Write(s, " HTTP/1.1\r\n\r\nHost: ", 19);
|
||||
Stream_Write(s, hostname, strlen(hostname));
|
||||
Stream_Write_UINT8(s, ':');
|
||||
Stream_Write(s, str, strlen(str));
|
||||
Stream_Write(s, "\r\n\r\n", 4);
|
||||
|
||||
status = transport_write(transport, s);
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
s = NULL;
|
||||
|
||||
if (status < 0) {
|
||||
fprintf(stderr, "Error writing: status=%d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Read result until CR-LF-CR-LF.
|
||||
* Keep str a null-terminated string. */
|
||||
|
||||
memset(str, '\0', sizeof(str));
|
||||
resultsize = 0;
|
||||
while ( strstr(str, "\r\n\r\n") == NULL ) {
|
||||
if (resultsize >= sizeof(str)-1) {
|
||||
fprintf(stderr, "HTTP Reply headers too long.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
status = tcp_read(tcp, (BYTE*)str + resultsize, sizeof(str)-resultsize-1);
|
||||
if (status < 0) {
|
||||
/* Error? */
|
||||
return FALSE;
|
||||
}
|
||||
else if (status == 0) {
|
||||
/* Error? */
|
||||
fprintf(stderr, "tcp_read() returned zero\n");
|
||||
return FALSE;
|
||||
}
|
||||
resultsize += status;
|
||||
}
|
||||
|
||||
/* Extract HTTP status line */
|
||||
eol = strchr(str, '\r');
|
||||
if (!eol) {
|
||||
/* should never happen */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*eol = '\0';
|
||||
|
||||
fprintf(stderr, "HTTP proxy: %s\n", str);
|
||||
|
||||
if (strlen(str) < 12) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
str[7] = 'X';
|
||||
if (strncmp(str, "HTTP/1.X 200", 12))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL transport_tsg_connect(rdpTransport* transport, const char* hostname, UINT16 port)
|
||||
{
|
||||
rdpTsg* tsg = tsg_new(transport);
|
||||
@ -498,63 +378,31 @@ BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 por
|
||||
/* For TSGateway, find the system HTTPS proxy automatically */
|
||||
if (settings->GatewayEnabled) {
|
||||
if (!transport->settings->HTTPProxyEnabled)
|
||||
transport_http_proxy_read_environment(settings, "https_proxy");
|
||||
http_proxy_read_environment(settings, "https_proxy");
|
||||
|
||||
if (!transport->settings->HTTPProxyEnabled)
|
||||
transport_http_proxy_read_environment(settings, "HTTPS_PROXY");
|
||||
http_proxy_read_environment(settings, "HTTPS_PROXY");
|
||||
}
|
||||
|
||||
if (transport->settings->GatewayEnabled)
|
||||
{
|
||||
transport->layer = TRANSPORT_LAYER_TSG;
|
||||
transport->TcpOut = tcp_new(settings);
|
||||
|
||||
if (settings->HTTPProxyEnabled) {
|
||||
status = tcp_connect(transport->TcpIn, settings->HTTPProxyHostname, settings->HTTPProxyPort);
|
||||
|
||||
transport->layer = TRANSPORT_LAYER_HTTP_PROXY_IN;
|
||||
status = transport_http_proxy_connect(transport, settings->GatewayHostname, settings->GatewayPort);
|
||||
}
|
||||
else {
|
||||
status = tcp_connect(transport->TcpIn, settings->GatewayHostname, settings->GatewayPort);
|
||||
}
|
||||
status = tcp_connect(transport->TcpIn, settings->GatewayHostname, settings->GatewayPort);
|
||||
|
||||
if (status)
|
||||
{
|
||||
/* Connect second channel */
|
||||
if (settings->HTTPProxyEnabled)
|
||||
{
|
||||
transport->TcpOut = tcp_new(settings);
|
||||
status = tcp_connect(transport->TcpOut, settings->HTTPProxyHostname, settings->HTTPProxyPort);
|
||||
|
||||
if (status) {
|
||||
transport->layer = TRANSPORT_LAYER_HTTP_PROXY_OUT;
|
||||
status = transport_http_proxy_connect(transport, settings->GatewayHostname, settings->GatewayPort);
|
||||
}
|
||||
}
|
||||
else {
|
||||
status = tcp_connect(transport->TcpOut, settings->GatewayHostname, settings->GatewayPort);
|
||||
}
|
||||
status = tcp_connect(transport->TcpOut, settings->GatewayHostname, settings->GatewayPort);
|
||||
}
|
||||
|
||||
transport->layer = TRANSPORT_LAYER_TSG;
|
||||
|
||||
if (status)
|
||||
status = transport_tsg_connect(transport, hostname, port);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (settings->HTTPProxyEnabled) {
|
||||
status = tcp_connect(transport->TcpIn, settings->HTTPProxyHostname, settings->HTTPProxyPort);
|
||||
transport->layer = TRANSPORT_LAYER_HTTP_PROXY_IN;
|
||||
|
||||
if (status) {
|
||||
status = transport_http_proxy_connect(transport, hostname, port);
|
||||
transport->layer = TRANSPORT_LAYER_TCP;
|
||||
}
|
||||
}
|
||||
else {
|
||||
status = tcp_connect(transport->TcpIn, hostname, port);
|
||||
}
|
||||
status = tcp_connect(transport->TcpIn, hostname, port);
|
||||
|
||||
transport->SplitInputOutput = FALSE;
|
||||
transport->TcpOut = transport->TcpIn;
|
||||
@ -719,10 +567,6 @@ int transport_read_layer(rdpTransport* transport, BYTE* data, int bytes)
|
||||
status = tsg_read(transport->tsg, data + read, bytes - read);
|
||||
else if (transport->layer == TRANSPORT_LAYER_TSG_TLS)
|
||||
status = tls_read(transport->TsgTls, data + read, bytes - read);
|
||||
else if (transport->layer == TRANSPORT_LAYER_HTTP_PROXY_IN)
|
||||
status = tcp_read(transport->TcpIn, data + read, bytes - read);
|
||||
else if (transport->layer == TRANSPORT_LAYER_HTTP_PROXY_OUT)
|
||||
status = tcp_read(transport->TcpOut, data + read, bytes - read);
|
||||
|
||||
/* blocking means that we can't continue until this is read */
|
||||
|
||||
@ -905,10 +749,6 @@ int transport_write(rdpTransport* transport, wStream* s)
|
||||
status = tsg_write(transport->tsg, Stream_Pointer(s), length);
|
||||
else if (transport->layer == TRANSPORT_LAYER_TSG_TLS)
|
||||
status = tls_write(transport->TsgTls, Stream_Pointer(s), length);
|
||||
else if (transport->layer == TRANSPORT_LAYER_HTTP_PROXY_IN)
|
||||
status = tcp_write(transport->TcpIn, Stream_Pointer(s), length);
|
||||
else if (transport->layer == TRANSPORT_LAYER_HTTP_PROXY_OUT)
|
||||
status = tcp_write(transport->TcpOut, Stream_Pointer(s), length);
|
||||
|
||||
if (status < 0)
|
||||
break; /* error occurred */
|
||||
@ -929,10 +769,6 @@ int transport_write(rdpTransport* transport, wStream* s)
|
||||
tcp_wait_write(transport->TcpOut);
|
||||
else if (transport->layer == TRANSPORT_LAYER_TSG_TLS)
|
||||
tls_wait_write(transport->TsgTls);
|
||||
else if (transport->layer == TRANSPORT_LAYER_HTTP_PROXY_IN)
|
||||
tcp_wait_write(transport->TcpIn);
|
||||
else if (transport->layer == TRANSPORT_LAYER_HTTP_PROXY_OUT)
|
||||
tcp_wait_write(transport->TcpOut);
|
||||
else
|
||||
USleep(transport->SleepInterval);
|
||||
}
|
||||
|
@ -26,9 +26,7 @@ typedef enum
|
||||
TRANSPORT_LAYER_TLS,
|
||||
TRANSPORT_LAYER_TSG,
|
||||
TRANSPORT_LAYER_TSG_TLS,
|
||||
TRANSPORT_LAYER_CLOSED,
|
||||
TRANSPORT_LAYER_HTTP_PROXY_IN,
|
||||
TRANSPORT_LAYER_HTTP_PROXY_OUT,
|
||||
TRANSPORT_LAYER_CLOSED
|
||||
} TRANSPORT_LAYER;
|
||||
|
||||
typedef struct rdp_transport rdpTransport;
|
||||
|
Loading…
Reference in New Issue
Block a user