summaryrefslogtreecommitdiff
path: root/toxcore/TCP_client.c
diff options
context:
space:
mode:
authoriphydf <iphydf@users.noreply.github.com>2018-07-12 17:22:20 +0000
committeriphydf <iphydf@users.noreply.github.com>2018-07-12 20:21:42 +0000
commitbeeb9b4335d9ca6f947a52528453753a51f194f3 (patch)
tree242cad42e2e90ebf5ed04283fd79f42f4e3afa60 /toxcore/TCP_client.c
parentcbda01021c561bd061cb03a1c1bab58199ac2307 (diff)
Style fixes in TCP code; remove MIN and PAIR from util.h.
* Moved PAIR to toxav, where it's used (but really this should die). * Replace most MIN calls with typed `min_*` calls. Didn't replace the ones where the desired semantics are unclear. Moved the MIN macro to the one place where it's still used. * Avoid assignments in `while` loops. Instead, factored out the loop body into a separate `bool`-returning function. * Use named types for callbacks (`_cb` types). * Avoid assignments in `if` conditions. * Removed `MAKE_REALLOC` and expanded its two calls. We can't have templates in C, and this fake templating is ugly and hard to analyse and debug (it expands on a single line). * Moved epoll system include to the .c file, out of the .h file. * Avoid assignments in expressions (`a = b = c;`). * Avoid multiple declarators per struct member declaration. * Fix naming inconsistencies. * Replace `net_to_host` macro with function.
Diffstat (limited to 'toxcore/TCP_client.c')
-rw-r--r--toxcore/TCP_client.c281
1 files changed, 146 insertions, 135 deletions
diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c
index 1291d276..381d9b80 100644
--- a/toxcore/TCP_client.c
+++ b/toxcore/TCP_client.c
@@ -34,8 +34,15 @@
34#include "mono_time.h" 34#include "mono_time.h"
35#include "util.h" 35#include "util.h"
36 36
37typedef struct TCP_Client_Conn {
38 // TODO(iphydf): Add an enum for this.
39 uint8_t status; /* 0 if not used, 1 if other is offline, 2 if other is online. */
40 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
41 uint32_t number;
42} TCP_Client_Conn;
43
37struct TCP_Client_Connection { 44struct TCP_Client_Connection {
38 TCP_CLIENT_STATUS status; 45 TCP_Client_Status status;
39 Socket sock; 46 Socket sock;
40 uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* our public key */ 47 uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* our public key */
41 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* public key of the server */ 48 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* public key of the server */
@@ -52,7 +59,8 @@ struct TCP_Client_Connection {
52 uint16_t last_packet_length; 59 uint16_t last_packet_length;
53 uint16_t last_packet_sent; 60 uint16_t last_packet_sent;
54 61
55 TCP_Priority_List *priority_queue_start, *priority_queue_end; 62 TCP_Priority_List *priority_queue_start;
63 TCP_Priority_List *priority_queue_end;
56 64
57 uint64_t kill_at; 65 uint64_t kill_at;
58 66
@@ -62,22 +70,17 @@ struct TCP_Client_Connection {
62 uint64_t ping_response_id; 70 uint64_t ping_response_id;
63 uint64_t ping_request_id; 71 uint64_t ping_request_id;
64 72
65 struct { 73 TCP_Client_Conn connections[NUM_CLIENT_CONNECTIONS];
66 uint8_t status; /* 0 if not used, 1 if other is offline, 2 if other is online. */ 74 tcp_routing_response_cb *response_callback;
67 uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
68 uint32_t number;
69 } connections[NUM_CLIENT_CONNECTIONS];
70 int (*response_callback)(void *object, uint8_t connection_id, const uint8_t *public_key);
71 void *response_callback_object; 75 void *response_callback_object;
72 int (*status_callback)(void *object, uint32_t number, uint8_t connection_id, uint8_t status); 76 tcp_routing_status_cb *status_callback;
73 void *status_callback_object; 77 void *status_callback_object;
74 int (*data_callback)(void *object, uint32_t number, uint8_t connection_id, const uint8_t *data, uint16_t length, 78 tcp_routing_data_cb *data_callback;
75 void *userdata);
76 void *data_callback_object; 79 void *data_callback_object;
77 int (*oob_data_callback)(void *object, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata); 80 tcp_oob_data_cb *oob_data_callback;
78 void *oob_data_callback_object; 81 void *oob_data_callback_object;
79 82
80 int (*onion_callback)(void *object, const uint8_t *data, uint16_t length, void *userdata); 83 tcp_onion_response_cb *onion_callback;
81 void *onion_callback_object; 84 void *onion_callback_object;
82 85
83 /* Can be used by user. */ 86 /* Can be used by user. */
@@ -95,7 +98,7 @@ IP_Port tcp_con_ip_port(const TCP_Client_Connection *con)
95 return con->ip_port; 98 return con->ip_port;
96} 99}
97 100
98TCP_CLIENT_STATUS tcp_con_status(const TCP_Client_Connection *con) 101TCP_Client_Status tcp_con_status(const TCP_Client_Connection *con)
99{ 102{
100 return con->status; 103 return con->status;
101} 104}
@@ -133,7 +136,7 @@ static int connect_sock_to(Socket sock, IP_Port ip_port, TCP_Proxy_Info *proxy_i
133/* return 1 on success. 136/* return 1 on success.
134 * return 0 on failure. 137 * return 0 on failure.
135 */ 138 */
136static int proxy_http_generate_connection_request(TCP_Client_Connection *TCP_conn) 139static int proxy_http_generate_connection_request(TCP_Client_Connection *tcp_conn)
137{ 140{
138 char one[] = "CONNECT "; 141 char one[] = "CONNECT ";
139 char two[] = " HTTP/1.1\nHost: "; 142 char two[] = " HTTP/1.1\nHost: ";
@@ -141,20 +144,20 @@ static int proxy_http_generate_connection_request(TCP_Client_Connection *TCP_con
141 144
142 char ip[TOX_INET6_ADDRSTRLEN]; 145 char ip[TOX_INET6_ADDRSTRLEN];
143 146
144 if (!ip_parse_addr(&TCP_conn->ip_port.ip, ip, sizeof(ip))) { 147 if (!ip_parse_addr(&tcp_conn->ip_port.ip, ip, sizeof(ip))) {
145 return 0; 148 return 0;
146 } 149 }
147 150
148 const uint16_t port = net_ntohs(TCP_conn->ip_port.port); 151 const uint16_t port = net_ntohs(tcp_conn->ip_port.port);
149 const int written = snprintf((char *)TCP_conn->last_packet, MAX_PACKET_SIZE, "%s%s:%hu%s%s:%hu%s", one, ip, port, two, 152 const int written = snprintf((char *)tcp_conn->last_packet, MAX_PACKET_SIZE, "%s%s:%hu%s%s:%hu%s", one, ip, port, two,
150 ip, port, three); 153 ip, port, three);
151 154
152 if (written < 0 || MAX_PACKET_SIZE < written) { 155 if (written < 0 || MAX_PACKET_SIZE < written) {
153 return 0; 156 return 0;
154 } 157 }
155 158
156 TCP_conn->last_packet_length = written; 159 tcp_conn->last_packet_length = written;
157 TCP_conn->last_packet_sent = 0; 160 tcp_conn->last_packet_sent = 0;
158 161
159 return 1; 162 return 1;
160} 163}
@@ -163,12 +166,12 @@ static int proxy_http_generate_connection_request(TCP_Client_Connection *TCP_con
163 * return 0 if no data received. 166 * return 0 if no data received.
164 * return -1 on failure (connection refused). 167 * return -1 on failure (connection refused).
165 */ 168 */
166static int proxy_http_read_connection_response(TCP_Client_Connection *TCP_conn) 169static int proxy_http_read_connection_response(TCP_Client_Connection *tcp_conn)
167{ 170{
168 char success[] = "200"; 171 char success[] = "200";
169 uint8_t data[16]; // draining works the best if the length is a power of 2 172 uint8_t data[16]; // draining works the best if the length is a power of 2
170 173
171 int ret = read_TCP_packet(TCP_conn->sock, data, sizeof(data) - 1); 174 int ret = read_TCP_packet(tcp_conn->sock, data, sizeof(data) - 1);
172 175
173 if (ret == -1) { 176 if (ret == -1) {
174 return 0; 177 return 0;
@@ -178,11 +181,11 @@ static int proxy_http_read_connection_response(TCP_Client_Connection *TCP_conn)
178 181
179 if (strstr((char *)data, success)) { 182 if (strstr((char *)data, success)) {
180 // drain all data 183 // drain all data
181 unsigned int data_left = net_socket_data_recv_buffer(TCP_conn->sock); 184 unsigned int data_left = net_socket_data_recv_buffer(tcp_conn->sock);
182 185
183 if (data_left) { 186 if (data_left) {
184 VLA(uint8_t, temp_data, data_left); 187 VLA(uint8_t, temp_data, data_left);
185 read_TCP_packet(TCP_conn->sock, temp_data, data_left); 188 read_TCP_packet(tcp_conn->sock, temp_data, data_left);
186 } 189 }
187 190
188 return 1; 191 return 1;
@@ -191,24 +194,24 @@ static int proxy_http_read_connection_response(TCP_Client_Connection *TCP_conn)
191 return -1; 194 return -1;
192} 195}
193 196
194static void proxy_socks5_generate_handshake(TCP_Client_Connection *TCP_conn) 197static void proxy_socks5_generate_handshake(TCP_Client_Connection *tcp_conn)
195{ 198{
196 TCP_conn->last_packet[0] = 5; /* SOCKSv5 */ 199 tcp_conn->last_packet[0] = 5; /* SOCKSv5 */
197 TCP_conn->last_packet[1] = 1; /* number of authentication methods supported */ 200 tcp_conn->last_packet[1] = 1; /* number of authentication methods supported */
198 TCP_conn->last_packet[2] = 0; /* No authentication */ 201 tcp_conn->last_packet[2] = 0; /* No authentication */
199 202
200 TCP_conn->last_packet_length = 3; 203 tcp_conn->last_packet_length = 3;
201 TCP_conn->last_packet_sent = 0; 204 tcp_conn->last_packet_sent = 0;
202} 205}
203 206
204/* return 1 on success. 207/* return 1 on success.
205 * return 0 if no data received. 208 * return 0 if no data received.
206 * return -1 on failure (connection refused). 209 * return -1 on failure (connection refused).
207 */ 210 */
208static int socks5_read_handshake_response(TCP_Client_Connection *TCP_conn) 211static int socks5_read_handshake_response(TCP_Client_Connection *tcp_conn)
209{ 212{
210 uint8_t data[2]; 213 uint8_t data[2];
211 int ret = read_TCP_packet(TCP_conn->sock, data, sizeof(data)); 214 int ret = read_TCP_packet(tcp_conn->sock, data, sizeof(data));
212 215
213 if (ret == -1) { 216 if (ret == -1) {
214 return 0; 217 return 0;
@@ -221,41 +224,41 @@ static int socks5_read_handshake_response(TCP_Client_Connection *TCP_conn)
221 return -1; 224 return -1;
222} 225}
223 226
224static void proxy_socks5_generate_connection_request(TCP_Client_Connection *TCP_conn) 227static void proxy_socks5_generate_connection_request(TCP_Client_Connection *tcp_conn)
225{ 228{
226 TCP_conn->last_packet[0] = 5; /* SOCKSv5 */ 229 tcp_conn->last_packet[0] = 5; /* SOCKSv5 */
227 TCP_conn->last_packet[1] = 1; /* command code: establish a TCP/IP stream connection */ 230 tcp_conn->last_packet[1] = 1; /* command code: establish a TCP/IP stream connection */
228 TCP_conn->last_packet[2] = 0; /* reserved, must be 0 */ 231 tcp_conn->last_packet[2] = 0; /* reserved, must be 0 */
229 uint16_t length = 3; 232 uint16_t length = 3;
230 233
231 if (net_family_is_ipv4(TCP_conn->ip_port.ip.family)) { 234 if (net_family_is_ipv4(tcp_conn->ip_port.ip.family)) {
232 TCP_conn->last_packet[3] = 1; /* IPv4 address */ 235 tcp_conn->last_packet[3] = 1; /* IPv4 address */
233 ++length; 236 ++length;
234 memcpy(TCP_conn->last_packet + length, TCP_conn->ip_port.ip.ip.v4.uint8, sizeof(IP4)); 237 memcpy(tcp_conn->last_packet + length, tcp_conn->ip_port.ip.ip.v4.uint8, sizeof(IP4));
235 length += sizeof(IP4); 238 length += sizeof(IP4);
236 } else { 239 } else {
237 TCP_conn->last_packet[3] = 4; /* IPv6 address */ 240 tcp_conn->last_packet[3] = 4; /* IPv6 address */
238 ++length; 241 ++length;
239 memcpy(TCP_conn->last_packet + length, TCP_conn->ip_port.ip.ip.v6.uint8, sizeof(IP6)); 242 memcpy(tcp_conn->last_packet + length, tcp_conn->ip_port.ip.ip.v6.uint8, sizeof(IP6));
240 length += sizeof(IP6); 243 length += sizeof(IP6);
241 } 244 }
242 245
243 memcpy(TCP_conn->last_packet + length, &TCP_conn->ip_port.port, sizeof(uint16_t)); 246 memcpy(tcp_conn->last_packet + length, &tcp_conn->ip_port.port, sizeof(uint16_t));
244 length += sizeof(uint16_t); 247 length += sizeof(uint16_t);
245 248
246 TCP_conn->last_packet_length = length; 249 tcp_conn->last_packet_length = length;
247 TCP_conn->last_packet_sent = 0; 250 tcp_conn->last_packet_sent = 0;
248} 251}
249 252
250/* return 1 on success. 253/* return 1 on success.
251 * return 0 if no data received. 254 * return 0 if no data received.
252 * return -1 on failure (connection refused). 255 * return -1 on failure (connection refused).
253 */ 256 */
254static int proxy_socks5_read_connection_response(TCP_Client_Connection *TCP_conn) 257static int proxy_socks5_read_connection_response(TCP_Client_Connection *tcp_conn)
255{ 258{
256 if (net_family_is_ipv4(TCP_conn->ip_port.ip.family)) { 259 if (net_family_is_ipv4(tcp_conn->ip_port.ip.family)) {
257 uint8_t data[4 + sizeof(IP4) + sizeof(uint16_t)]; 260 uint8_t data[4 + sizeof(IP4) + sizeof(uint16_t)];
258 int ret = read_TCP_packet(TCP_conn->sock, data, sizeof(data)); 261 int ret = read_TCP_packet(tcp_conn->sock, data, sizeof(data));
259 262
260 if (ret == -1) { 263 if (ret == -1) {
261 return 0; 264 return 0;
@@ -266,7 +269,7 @@ static int proxy_socks5_read_connection_response(TCP_Client_Connection *TCP_conn
266 } 269 }
267 } else { 270 } else {
268 uint8_t data[4 + sizeof(IP6) + sizeof(uint16_t)]; 271 uint8_t data[4 + sizeof(IP6) + sizeof(uint16_t)];
269 int ret = read_TCP_packet(TCP_conn->sock, data, sizeof(data)); 272 int ret = read_TCP_packet(tcp_conn->sock, data, sizeof(data));
270 273
271 if (ret == -1) { 274 if (ret == -1) {
272 return 0; 275 return 0;
@@ -283,23 +286,23 @@ static int proxy_socks5_read_connection_response(TCP_Client_Connection *TCP_conn
283/* return 0 on success. 286/* return 0 on success.
284 * return -1 on failure. 287 * return -1 on failure.
285 */ 288 */
286static int generate_handshake(TCP_Client_Connection *TCP_conn) 289static int generate_handshake(TCP_Client_Connection *tcp_conn)
287{ 290{
288 uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE]; 291 uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE];
289 crypto_new_keypair(plain, TCP_conn->temp_secret_key); 292 crypto_new_keypair(plain, tcp_conn->temp_secret_key);
290 random_nonce(TCP_conn->sent_nonce); 293 random_nonce(tcp_conn->sent_nonce);
291 memcpy(plain + CRYPTO_PUBLIC_KEY_SIZE, TCP_conn->sent_nonce, CRYPTO_NONCE_SIZE); 294 memcpy(plain + CRYPTO_PUBLIC_KEY_SIZE, tcp_conn->sent_nonce, CRYPTO_NONCE_SIZE);
292 memcpy(TCP_conn->last_packet, TCP_conn->self_public_key, CRYPTO_PUBLIC_KEY_SIZE); 295 memcpy(tcp_conn->last_packet, tcp_conn->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
293 random_nonce(TCP_conn->last_packet + CRYPTO_PUBLIC_KEY_SIZE); 296 random_nonce(tcp_conn->last_packet + CRYPTO_PUBLIC_KEY_SIZE);
294 int len = encrypt_data_symmetric(TCP_conn->shared_key, TCP_conn->last_packet + CRYPTO_PUBLIC_KEY_SIZE, plain, 297 int len = encrypt_data_symmetric(tcp_conn->shared_key, tcp_conn->last_packet + CRYPTO_PUBLIC_KEY_SIZE, plain,
295 sizeof(plain), TCP_conn->last_packet + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE); 298 sizeof(plain), tcp_conn->last_packet + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
296 299
297 if (len != sizeof(plain) + CRYPTO_MAC_SIZE) { 300 if (len != sizeof(plain) + CRYPTO_MAC_SIZE) {
298 return -1; 301 return -1;
299 } 302 }
300 303
301 TCP_conn->last_packet_length = CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + sizeof(plain) + CRYPTO_MAC_SIZE; 304 tcp_conn->last_packet_length = CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + sizeof(plain) + CRYPTO_MAC_SIZE;
302 TCP_conn->last_packet_sent = 0; 305 tcp_conn->last_packet_sent = 0;
303 return 0; 306 return 0;
304} 307}
305 308
@@ -308,19 +311,19 @@ static int generate_handshake(TCP_Client_Connection *TCP_conn)
308 * return 0 on success. 311 * return 0 on success.
309 * return -1 on failure. 312 * return -1 on failure.
310 */ 313 */
311static int handle_handshake(TCP_Client_Connection *TCP_conn, const uint8_t *data) 314static int handle_handshake(TCP_Client_Connection *tcp_conn, const uint8_t *data)
312{ 315{
313 uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE]; 316 uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE];
314 int len = decrypt_data_symmetric(TCP_conn->shared_key, data, data + CRYPTO_NONCE_SIZE, 317 int len = decrypt_data_symmetric(tcp_conn->shared_key, data, data + CRYPTO_NONCE_SIZE,
315 TCP_SERVER_HANDSHAKE_SIZE - CRYPTO_NONCE_SIZE, plain); 318 TCP_SERVER_HANDSHAKE_SIZE - CRYPTO_NONCE_SIZE, plain);
316 319
317 if (len != sizeof(plain)) { 320 if (len != sizeof(plain)) {
318 return -1; 321 return -1;
319 } 322 }
320 323
321 memcpy(TCP_conn->recv_nonce, plain + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_NONCE_SIZE); 324 memcpy(tcp_conn->recv_nonce, plain + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_NONCE_SIZE);
322 encrypt_precompute(plain, TCP_conn->temp_secret_key, TCP_conn->shared_key); 325 encrypt_precompute(plain, tcp_conn->temp_secret_key, tcp_conn->shared_key);
323 crypto_memzero(TCP_conn->temp_secret_key, CRYPTO_SECRET_KEY_SIZE); 326 crypto_memzero(tcp_conn->temp_secret_key, CRYPTO_SECRET_KEY_SIZE);
324 return 0; 327 return 0;
325} 328}
326 329
@@ -504,15 +507,13 @@ int send_routing_request(TCP_Client_Connection *con, uint8_t *public_key)
504 return write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1); 507 return write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1);
505} 508}
506 509
507void routing_response_handler(TCP_Client_Connection *con, int (*response_callback)(void *object, uint8_t connection_id, 510void routing_response_handler(TCP_Client_Connection *con, tcp_routing_response_cb *response_callback, void *object)
508 const uint8_t *public_key), void *object)
509{ 511{
510 con->response_callback = response_callback; 512 con->response_callback = response_callback;
511 con->response_callback_object = object; 513 con->response_callback_object = object;
512} 514}
513 515
514void routing_status_handler(TCP_Client_Connection *con, int (*status_callback)(void *object, uint32_t number, 516void routing_status_handler(TCP_Client_Connection *con, tcp_routing_status_cb *status_callback, void *object)
515 uint8_t connection_id, uint8_t status), void *object)
516{ 517{
517 con->status_callback = status_callback; 518 con->status_callback = status_callback;
518 con->status_callback_object = object; 519 con->status_callback_object = object;
@@ -584,15 +585,13 @@ int set_tcp_connection_number(TCP_Client_Connection *con, uint8_t con_id, uint32
584 return 0; 585 return 0;
585} 586}
586 587
587void routing_data_handler(TCP_Client_Connection *con, int (*data_callback)(void *object, uint32_t number, 588void routing_data_handler(TCP_Client_Connection *con, tcp_routing_data_cb *data_callback, void *object)
588 uint8_t connection_id, const uint8_t *data, uint16_t length, void *userdata), void *object)
589{ 589{
590 con->data_callback = data_callback; 590 con->data_callback = data_callback;
591 con->data_callback_object = object; 591 con->data_callback_object = object;
592} 592}
593 593
594void oob_data_handler(TCP_Client_Connection *con, int (*oob_data_callback)(void *object, const uint8_t *public_key, 594void oob_data_handler(TCP_Client_Connection *con, tcp_oob_data_cb *oob_data_callback, void *object)
595 const uint8_t *data, uint16_t length, void *userdata), void *object)
596{ 595{
597 con->oob_data_callback = oob_data_callback; 596 con->oob_data_callback = oob_data_callback;
598 con->oob_data_callback_object = object; 597 con->oob_data_callback_object = object;
@@ -623,9 +622,9 @@ static int tcp_send_ping_request(TCP_Client_Connection *con)
623 uint8_t packet[1 + sizeof(uint64_t)]; 622 uint8_t packet[1 + sizeof(uint64_t)];
624 packet[0] = TCP_PACKET_PING; 623 packet[0] = TCP_PACKET_PING;
625 memcpy(packet + 1, &con->ping_request_id, sizeof(uint64_t)); 624 memcpy(packet + 1, &con->ping_request_id, sizeof(uint64_t));
626 int ret; 625 const int ret = write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1);
627 626
628 if ((ret = write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1)) == 1) { 627 if (ret == 1) {
629 con->ping_request_id = 0; 628 con->ping_request_id = 0;
630 } 629 }
631 630
@@ -645,9 +644,9 @@ static int tcp_send_ping_response(TCP_Client_Connection *con)
645 uint8_t packet[1 + sizeof(uint64_t)]; 644 uint8_t packet[1 + sizeof(uint64_t)];
646 packet[0] = TCP_PACKET_PONG; 645 packet[0] = TCP_PACKET_PONG;
647 memcpy(packet + 1, &con->ping_response_id, sizeof(uint64_t)); 646 memcpy(packet + 1, &con->ping_response_id, sizeof(uint64_t));
648 int ret; 647 const int ret = write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1);
649 648
650 if ((ret = write_packet_TCP_client_secure_connection(con, packet, sizeof(packet), 1)) == 1) { 649 if (ret == 1) {
651 con->ping_response_id = 0; 650 con->ping_response_id = 0;
652 } 651 }
653 652
@@ -681,8 +680,7 @@ int send_onion_request(TCP_Client_Connection *con, const uint8_t *data, uint16_t
681 return write_packet_TCP_client_secure_connection(con, packet, SIZEOF_VLA(packet), 0); 680 return write_packet_TCP_client_secure_connection(con, packet, SIZEOF_VLA(packet), 0);
682} 681}
683 682
684void onion_response_handler(TCP_Client_Connection *con, int (*onion_callback)(void *object, const uint8_t *data, 683void onion_response_handler(TCP_Client_Connection *con, tcp_onion_response_cb *onion_callback, void *object)
685 uint16_t length, void *userdata), void *object)
686{ 684{
687 con->onion_callback = onion_callback; 685 con->onion_callback = onion_callback;
688 con->onion_callback_object = object; 686 con->onion_callback_object = object;
@@ -928,15 +926,35 @@ static int handle_TCP_client_packet(TCP_Client_Connection *conn, const uint8_t *
928 return 0; 926 return 0;
929} 927}
930 928
929static bool tcp_process_packet(TCP_Client_Connection *conn, void *userdata)
930{
931 uint8_t packet[MAX_PACKET_SIZE];
932 const int len = read_packet_TCP_secure_connection(conn->sock, &conn->next_packet_length, conn->shared_key,
933 conn->recv_nonce, packet, sizeof(packet));
934
935 if (len == 0) {
936 return false;
937 }
938
939 if (len == -1) {
940 conn->status = TCP_CLIENT_DISCONNECTED;
941 return false;
942 }
943
944 if (handle_TCP_client_packet(conn, packet, len, userdata) == -1) {
945 conn->status = TCP_CLIENT_DISCONNECTED;
946 return false;
947 }
948
949 return true;
950}
951
931static int do_confirmed_TCP(TCP_Client_Connection *conn, void *userdata) 952static int do_confirmed_TCP(TCP_Client_Connection *conn, void *userdata)
932{ 953{
933 client_send_pending_data(conn); 954 client_send_pending_data(conn);
934 tcp_send_ping_response(conn); 955 tcp_send_ping_response(conn);
935 tcp_send_ping_request(conn); 956 tcp_send_ping_request(conn);
936 957
937 uint8_t packet[MAX_PACKET_SIZE];
938 int len;
939
940 if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY)) { 958 if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY)) {
941 uint64_t ping_id = random_u64(); 959 uint64_t ping_id = random_u64();
942 960
@@ -944,7 +962,8 @@ static int do_confirmed_TCP(TCP_Client_Connection *conn, void *userdata)
944 ++ping_id; 962 ++ping_id;
945 } 963 }
946 964
947 conn->ping_request_id = conn->ping_id = ping_id; 965 conn->ping_request_id = ping_id;
966 conn->ping_id = ping_id;
948 tcp_send_ping_request(conn); 967 tcp_send_ping_request(conn);
949 conn->last_pinged = unix_time(); 968 conn->last_pinged = unix_time();
950 } 969 }
@@ -954,17 +973,9 @@ static int do_confirmed_TCP(TCP_Client_Connection *conn, void *userdata)
954 return 0; 973 return 0;
955 } 974 }
956 975
957 while ((len = read_packet_TCP_secure_connection(conn->sock, &conn->next_packet_length, conn->shared_key, 976 while (tcp_process_packet(conn, userdata)) {
958 conn->recv_nonce, packet, sizeof(packet)))) { 977 // Keep reading until error or out of data.
959 if (len == -1) { 978 continue;
960 conn->status = TCP_CLIENT_DISCONNECTED;
961 break;
962 }
963
964 if (handle_TCP_client_packet(conn, packet, len, userdata) == -1) {
965 conn->status = TCP_CLIENT_DISCONNECTED;
966 break;
967 }
968 } 979 }
969 980
970 return 0; 981 return 0;
@@ -972,102 +983,102 @@ static int do_confirmed_TCP(TCP_Client_Connection *conn, void *userdata)
972 983
973/* Run the TCP connection 984/* Run the TCP connection
974 */ 985 */
975void do_TCP_connection(TCP_Client_Connection *TCP_connection, void *userdata) 986void do_TCP_connection(TCP_Client_Connection *tcp_connection, void *userdata)
976{ 987{
977 unix_time_update(); 988 unix_time_update();
978 989
979 if (TCP_connection->status == TCP_CLIENT_DISCONNECTED) { 990 if (tcp_connection->status == TCP_CLIENT_DISCONNECTED) {
980 return; 991 return;
981 } 992 }
982 993
983 if (TCP_connection->status == TCP_CLIENT_PROXY_HTTP_CONNECTING) { 994 if (tcp_connection->status == TCP_CLIENT_PROXY_HTTP_CONNECTING) {
984 if (client_send_pending_data(TCP_connection) == 0) { 995 if (client_send_pending_data(tcp_connection) == 0) {
985 int ret = proxy_http_read_connection_response(TCP_connection); 996 int ret = proxy_http_read_connection_response(tcp_connection);
986 997
987 if (ret == -1) { 998 if (ret == -1) {
988 TCP_connection->kill_at = 0; 999 tcp_connection->kill_at = 0;
989 TCP_connection->status = TCP_CLIENT_DISCONNECTED; 1000 tcp_connection->status = TCP_CLIENT_DISCONNECTED;
990 } 1001 }
991 1002
992 if (ret == 1) { 1003 if (ret == 1) {
993 generate_handshake(TCP_connection); 1004 generate_handshake(tcp_connection);
994 TCP_connection->status = TCP_CLIENT_CONNECTING; 1005 tcp_connection->status = TCP_CLIENT_CONNECTING;
995 } 1006 }
996 } 1007 }
997 } 1008 }
998 1009
999 if (TCP_connection->status == TCP_CLIENT_PROXY_SOCKS5_CONNECTING) { 1010 if (tcp_connection->status == TCP_CLIENT_PROXY_SOCKS5_CONNECTING) {
1000 if (client_send_pending_data(TCP_connection) == 0) { 1011 if (client_send_pending_data(tcp_connection) == 0) {
1001 int ret = socks5_read_handshake_response(TCP_connection); 1012 int ret = socks5_read_handshake_response(tcp_connection);
1002 1013
1003 if (ret == -1) { 1014 if (ret == -1) {
1004 TCP_connection->kill_at = 0; 1015 tcp_connection->kill_at = 0;
1005 TCP_connection->status = TCP_CLIENT_DISCONNECTED; 1016 tcp_connection->status = TCP_CLIENT_DISCONNECTED;
1006 } 1017 }
1007 1018
1008 if (ret == 1) { 1019 if (ret == 1) {
1009 proxy_socks5_generate_connection_request(TCP_connection); 1020 proxy_socks5_generate_connection_request(tcp_connection);
1010 TCP_connection->status = TCP_CLIENT_PROXY_SOCKS5_UNCONFIRMED; 1021 tcp_connection->status = TCP_CLIENT_PROXY_SOCKS5_UNCONFIRMED;
1011 } 1022 }
1012 } 1023 }
1013 } 1024 }
1014 1025
1015 if (TCP_connection->status == TCP_CLIENT_PROXY_SOCKS5_UNCONFIRMED) { 1026 if (tcp_connection->status == TCP_CLIENT_PROXY_SOCKS5_UNCONFIRMED) {
1016 if (client_send_pending_data(TCP_connection) == 0) { 1027 if (client_send_pending_data(tcp_connection) == 0) {
1017 int ret = proxy_socks5_read_connection_response(TCP_connection); 1028 int ret = proxy_socks5_read_connection_response(tcp_connection);
1018 1029
1019 if (ret == -1) { 1030 if (ret == -1) {
1020 TCP_connection->kill_at = 0; 1031 tcp_connection->kill_at = 0;
1021 TCP_connection->status = TCP_CLIENT_DISCONNECTED; 1032 tcp_connection->status = TCP_CLIENT_DISCONNECTED;
1022 } 1033 }
1023 1034
1024 if (ret == 1) { 1035 if (ret == 1) {
1025 generate_handshake(TCP_connection); 1036 generate_handshake(tcp_connection);
1026 TCP_connection->status = TCP_CLIENT_CONNECTING; 1037 tcp_connection->status = TCP_CLIENT_CONNECTING;
1027 } 1038 }
1028 } 1039 }
1029 } 1040 }
1030 1041
1031 if (TCP_connection->status == TCP_CLIENT_CONNECTING) { 1042 if (tcp_connection->status == TCP_CLIENT_CONNECTING) {
1032 if (client_send_pending_data(TCP_connection) == 0) { 1043 if (client_send_pending_data(tcp_connection) == 0) {
1033 TCP_connection->status = TCP_CLIENT_UNCONFIRMED; 1044 tcp_connection->status = TCP_CLIENT_UNCONFIRMED;
1034 } 1045 }
1035 } 1046 }
1036 1047
1037 if (TCP_connection->status == TCP_CLIENT_UNCONFIRMED) { 1048 if (tcp_connection->status == TCP_CLIENT_UNCONFIRMED) {
1038 uint8_t data[TCP_SERVER_HANDSHAKE_SIZE]; 1049 uint8_t data[TCP_SERVER_HANDSHAKE_SIZE];
1039 int len = read_TCP_packet(TCP_connection->sock, data, sizeof(data)); 1050 int len = read_TCP_packet(tcp_connection->sock, data, sizeof(data));
1040 1051
1041 if (sizeof(data) == len) { 1052 if (sizeof(data) == len) {
1042 if (handle_handshake(TCP_connection, data) == 0) { 1053 if (handle_handshake(tcp_connection, data) == 0) {
1043 TCP_connection->kill_at = ~0; 1054 tcp_connection->kill_at = ~0;
1044 TCP_connection->status = TCP_CLIENT_CONFIRMED; 1055 tcp_connection->status = TCP_CLIENT_CONFIRMED;
1045 } else { 1056 } else {
1046 TCP_connection->kill_at = 0; 1057 tcp_connection->kill_at = 0;
1047 TCP_connection->status = TCP_CLIENT_DISCONNECTED; 1058 tcp_connection->status = TCP_CLIENT_DISCONNECTED;
1048 } 1059 }
1049 } 1060 }
1050 } 1061 }
1051 1062
1052 if (TCP_connection->status == TCP_CLIENT_CONFIRMED) { 1063 if (tcp_connection->status == TCP_CLIENT_CONFIRMED) {
1053 do_confirmed_TCP(TCP_connection, userdata); 1064 do_confirmed_TCP(tcp_connection, userdata);
1054 } 1065 }
1055 1066
1056 if (TCP_connection->kill_at <= unix_time()) { 1067 if (tcp_connection->kill_at <= unix_time()) {
1057 TCP_connection->status = TCP_CLIENT_DISCONNECTED; 1068 tcp_connection->status = TCP_CLIENT_DISCONNECTED;
1058 } 1069 }
1059} 1070}
1060 1071
1061/* Kill the TCP connection 1072/* Kill the TCP connection
1062 */ 1073 */
1063void kill_TCP_connection(TCP_Client_Connection *TCP_connection) 1074void kill_TCP_connection(TCP_Client_Connection *tcp_connection)
1064{ 1075{
1065 if (TCP_connection == nullptr) { 1076 if (tcp_connection == nullptr) {
1066 return; 1077 return;
1067 } 1078 }
1068 1079
1069 wipe_priority_list(TCP_connection); 1080 wipe_priority_list(tcp_connection);
1070 kill_sock(TCP_connection->sock); 1081 kill_sock(tcp_connection->sock);
1071 crypto_memzero(TCP_connection, sizeof(TCP_Client_Connection)); 1082 crypto_memzero(tcp_connection, sizeof(TCP_Client_Connection));
1072 free(TCP_connection); 1083 free(tcp_connection);
1073} 1084}