• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*******************************************************************************
2  * Copyright (c) 2009, 2021 Diehl Metering.
3  *
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v2.0
6  * and Eclipse Distribution License v1.0 which accompany this distribution.
7  *
8  * The Eclipse Public License is available at
9  *    https://www.eclipse.org/legal/epl-2.0/
10  * and the Eclipse Distribution License is available at
11  *   http://www.eclipse.org/org/documents/edl-v10.php.
12  *
13  * Contributors:
14  *    Keith Holman - initial implementation and documentation
15  *    Sven Gambel - move WebSocket proxy support to generic proxy support
16  *******************************************************************************/
17 
18 #include <stdio.h>
19 #include <string.h>
20 // for timeout process in Proxy_connect()
21 #include <time.h>
22 #if defined(_WIN32) || defined(_WIN64)
23 	#include <windows.h>
24 	#if defined(_MSC_VER) && _MSC_VER < 1900
25 		#define snprintf _snprintf
26 	#endif
27 #else
28 	#include <unistd.h>
29 #endif
30 
31 #include "Log.h"
32 #include "MQTTProtocolOut.h"
33 #include "StackTrace.h"
34 #include "Heap.h"
35 
36 #if defined(OPENSSL)
37 #include "SSLSocket.h"
38 #include <openssl/rand.h>
39 #endif /* defined(OPENSSL) */
40 #include "Socket.h"
41 
42 /**
43  * Notify the IP address and port of the endpoint to proxy, and wait connection to endpoint.
44  *
45  * @param[in]  net               network connection to proxy.
46  * @param[in]  ssl               enable ssl.
47  * @param[in]  hostname          hostname of endpoint.
48  *
49  * @retval SOCKET_ERROR          failed to network connection
50  * @retval 0                     connection to endpoint
51  *
52  */
Proxy_connect(networkHandles * net,int ssl,const char * hostname)53 int Proxy_connect(networkHandles *net, int ssl, const char *hostname)
54 {
55 	int port, i, rc = 0, buf_len=0;
56 	char *buf = NULL;
57 	size_t hostname_len, actual_len = 0;
58 	time_t current, timeout;
59 	PacketBuffers nulbufs = {0, NULL, NULL, NULL, {0, 0, 0, 0}};
60 
61 	FUNC_ENTRY;
62 	hostname_len = MQTTProtocol_addressPort(hostname, &port, NULL, PROXY_DEFAULT_PORT);
63 	for ( i = 0; i < 2; ++i ) {
64 #if defined(OPENSSL)
65 		if(ssl) {
66 			if (net->https_proxy_auth) {
67 				buf_len = snprintf( buf, (size_t)buf_len, "CONNECT %.*s:%d HTTP/1.1\r\n"
68 					"Host: %.*s\r\n"
69 					"Proxy-authorization: Basic %s\r\n"
70 					"\r\n",
71 					(int)hostname_len, hostname, port,
72 					(int)hostname_len, hostname, net->https_proxy_auth);
73 			}
74 			else {
75 				buf_len = snprintf( buf, (size_t)buf_len, "CONNECT %.*s:%d HTTP/1.1\r\n"
76 					"Host: %.*s\r\n"
77 					"\r\n",
78 					(int)hostname_len, hostname, port,
79 					(int)hostname_len, hostname);
80 			}
81 		}
82 		else {
83 #endif
84 			if (net->http_proxy_auth) {
85 				buf_len = snprintf( buf, (size_t)buf_len, "CONNECT %.*s:%d HTTP/1.1\r\n"
86 					"Host: %.*s\r\n"
87 					"Proxy-authorization: Basic %s\r\n"
88 					"\r\n",
89 					(int)hostname_len, hostname, port,
90 					(int)hostname_len, hostname, net->http_proxy_auth);
91 			}
92 			else {
93 				buf_len = snprintf( buf, (size_t)buf_len, "CONNECT %.*s:%d HTTP/1.1\r\n"
94 					"Host: %.*s\r\n"
95 					"\r\n",
96 					(int)hostname_len, hostname, port,
97 					(int)hostname_len, hostname);
98 			}
99 #if defined(OPENSSL)
100 		}
101 #endif
102 		if ( i==0 && buf_len > 0 ) {
103 			++buf_len;
104 			if ((buf = malloc( buf_len )) == NULL)
105 			{
106 				rc = PAHO_MEMORY_ERROR;
107 				goto exit;
108 			}
109 
110 		}
111 	}
112 	Log(TRACE_PROTOCOL, -1, "Proxy_connect: \"%s\"", buf);
113 
114 	Socket_putdatas(net->socket, buf, buf_len, nulbufs);
115 	free(buf);
116 	buf = NULL;
117 
118 	time(&timeout);
119 	timeout += (time_t)10;
120 
121 	while(1) {
122 		buf = Socket_getdata(net->socket, (size_t)12, &actual_len, &rc);
123 		if(actual_len) {
124 			if ( (strncmp( buf, "HTTP/1.0 200", 12 ) != 0) &&  (strncmp( buf, "HTTP/1.1 200", 12 ) != 0) )
125 				rc = SOCKET_ERROR;
126 			break;
127 		}
128 		else {
129 			time(&current);
130 			if(current > timeout) {
131 				rc = SOCKET_ERROR;
132 				break;
133 			}
134 #if defined(_WIN32) || defined(_WIN64)
135 			Sleep(250);
136 #else
137 			usleep(250000);
138 #endif
139 		}
140 	}
141 
142 	/* flush the SocketBuffer */
143 	actual_len = 1;
144 	while (actual_len)
145 	{
146 		int rc1;
147 
148 		buf = Socket_getdata(net->socket, (size_t)1, &actual_len, &rc1);
149 	}
150 
151 exit:
152 	FUNC_EXIT_RC(rc);
153 	return rc;
154 }
155