diff options
Diffstat (limited to 'toxcore/TCP_client.c')
-rw-r--r-- | toxcore/TCP_client.c | 178 |
1 files changed, 143 insertions, 35 deletions
diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index 087188f7..45220538 100644 --- a/toxcore/TCP_client.c +++ b/toxcore/TCP_client.c | |||
@@ -109,7 +109,7 @@ static int handle_handshake(TCP_Client_Connection *TCP_conn, const uint8_t *data | |||
109 | /* return 0 if pending data was sent completely | 109 | /* return 0 if pending data was sent completely |
110 | * return -1 if it wasn't | 110 | * return -1 if it wasn't |
111 | */ | 111 | */ |
112 | static int send_pending_data(TCP_Client_Connection *con) | 112 | static int send_pending_data_nonpriority(TCP_Client_Connection *con) |
113 | { | 113 | { |
114 | if (con->last_packet_length == 0) { | 114 | if (con->last_packet_length == 0) { |
115 | return 0; | 115 | return 0; |
@@ -127,24 +127,95 @@ static int send_pending_data(TCP_Client_Connection *con) | |||
127 | return 0; | 127 | return 0; |
128 | } | 128 | } |
129 | 129 | ||
130 | if (len > left) | 130 | con->last_packet_sent += len; |
131 | return -1; | ||
132 | } | ||
133 | |||
134 | /* return 0 if pending data was sent completely | ||
135 | * return -1 if it wasn't | ||
136 | */ | ||
137 | static int send_pending_data(TCP_Client_Connection *con) | ||
138 | { | ||
139 | /* finish sending current non-priority packet */ | ||
140 | if (send_pending_data_nonpriority(con) == -1) { | ||
131 | return -1; | 141 | return -1; |
142 | } | ||
143 | |||
144 | TCP_Priority_List *p = con->priority_queue_start; | ||
145 | |||
146 | while (p) { | ||
147 | uint16_t left = p->size - p->sent; | ||
148 | int len = send(con->sock, p->data + p->sent, left, MSG_NOSIGNAL); | ||
149 | |||
150 | if (len != left) { | ||
151 | if (len > 0) { | ||
152 | p->sent += len; | ||
153 | } | ||
154 | |||
155 | break; | ||
156 | } | ||
157 | |||
158 | TCP_Priority_List *pp = p; | ||
159 | p = p->next; | ||
160 | free(pp); | ||
161 | } | ||
162 | |||
163 | con->priority_queue_start = p; | ||
164 | |||
165 | if (!p) { | ||
166 | con->priority_queue_end = NULL; | ||
167 | return 0; | ||
168 | } | ||
132 | 169 | ||
133 | con->last_packet_sent += len; | ||
134 | return -1; | 170 | return -1; |
135 | } | 171 | } |
136 | 172 | ||
173 | /* return 0 on failure (only if malloc fails) | ||
174 | * return 1 on success | ||
175 | */ | ||
176 | static _Bool add_priority(TCP_Client_Connection *con, const uint8_t *packet, uint16_t size, uint16_t sent) | ||
177 | { | ||
178 | TCP_Priority_List *p = con->priority_queue_end, *new; | ||
179 | new = malloc(sizeof(TCP_Priority_List) + size); | ||
180 | |||
181 | if (!new) { | ||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | new->next = NULL; | ||
186 | new->size = size; | ||
187 | new->sent = sent; | ||
188 | memcpy(new->data, packet, size); | ||
189 | |||
190 | if (p) { | ||
191 | p->next = new; | ||
192 | } else { | ||
193 | con->priority_queue_start = new; | ||
194 | } | ||
195 | |||
196 | con->priority_queue_end = new; | ||
197 | return 1; | ||
198 | } | ||
199 | |||
137 | /* return 1 on success. | 200 | /* return 1 on success. |
138 | * return 0 if could not send packet. | 201 | * return 0 if could not send packet. |
139 | * return -1 on failure (connection must be killed). | 202 | * return -1 on failure (connection must be killed). |
140 | */ | 203 | */ |
141 | static int write_packet_TCP_secure_connection(TCP_Client_Connection *con, const uint8_t *data, uint16_t length) | 204 | static int write_packet_TCP_secure_connection(TCP_Client_Connection *con, const uint8_t *data, uint16_t length, |
205 | _Bool priority) | ||
142 | { | 206 | { |
143 | if (length + crypto_box_MACBYTES > MAX_PACKET_SIZE) | 207 | if (length + crypto_box_MACBYTES > MAX_PACKET_SIZE) |
144 | return -1; | 208 | return -1; |
145 | 209 | ||
146 | if (send_pending_data(con) == -1) | 210 | _Bool sendpriority = 1; |
147 | return 0; | 211 | |
212 | if (send_pending_data(con) == -1) { | ||
213 | if (priority) { | ||
214 | sendpriority = 0; | ||
215 | } else { | ||
216 | return 0; | ||
217 | } | ||
218 | } | ||
148 | 219 | ||
149 | uint8_t packet[sizeof(uint16_t) + length + crypto_box_MACBYTES]; | 220 | uint8_t packet[sizeof(uint16_t) + length + crypto_box_MACBYTES]; |
150 | 221 | ||
@@ -155,17 +226,33 @@ static int write_packet_TCP_secure_connection(TCP_Client_Connection *con, const | |||
155 | if ((unsigned int)len != (sizeof(packet) - sizeof(uint16_t))) | 226 | if ((unsigned int)len != (sizeof(packet) - sizeof(uint16_t))) |
156 | return -1; | 227 | return -1; |
157 | 228 | ||
158 | increment_nonce(con->sent_nonce); | 229 | if (priority) { |
230 | len = sendpriority ? send(con->sock, packet, sizeof(packet), MSG_NOSIGNAL) : 0; | ||
159 | 231 | ||
160 | len = send(con->sock, packet, sizeof(packet), MSG_NOSIGNAL); | 232 | if (len <= 0) { |
233 | len = 0; | ||
234 | } | ||
161 | 235 | ||
162 | if ((unsigned int)len == sizeof(packet)) | 236 | increment_nonce(con->sent_nonce); |
163 | return 1; | 237 | |
238 | if (len == sizeof(packet)) { | ||
239 | return 1; | ||
240 | } | ||
241 | |||
242 | return add_priority(con, packet, sizeof(packet), len); | ||
243 | } | ||
244 | |||
245 | len = send(con->sock, packet, sizeof(packet), MSG_NOSIGNAL); | ||
164 | 246 | ||
165 | if (len <= 0) | 247 | if (len <= 0) |
166 | return 0; | 248 | return 0; |
167 | 249 | ||
168 | memcpy(con->last_packet, packet, length); | 250 | increment_nonce(con->sent_nonce); |
251 | |||
252 | if ((unsigned int)len == sizeof(packet)) | ||
253 | return 1; | ||
254 | |||
255 | memcpy(con->last_packet, packet, sizeof(packet)); | ||
169 | con->last_packet_length = sizeof(packet); | 256 | con->last_packet_length = sizeof(packet); |
170 | con->last_packet_sent = len; | 257 | con->last_packet_sent = len; |
171 | return 1; | 258 | return 1; |
@@ -180,7 +267,7 @@ int send_routing_request(TCP_Client_Connection *con, uint8_t *public_key) | |||
180 | uint8_t packet[1 + crypto_box_PUBLICKEYBYTES]; | 267 | uint8_t packet[1 + crypto_box_PUBLICKEYBYTES]; |
181 | packet[0] = TCP_PACKET_ROUTING_REQUEST; | 268 | packet[0] = TCP_PACKET_ROUTING_REQUEST; |
182 | memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES); | 269 | memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES); |
183 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); | 270 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet), 1); |
184 | } | 271 | } |
185 | 272 | ||
186 | void routing_response_handler(TCP_Client_Connection *con, int (*response_callback)(void *object, uint8_t connection_id, | 273 | void routing_response_handler(TCP_Client_Connection *con, int (*response_callback)(void *object, uint8_t connection_id, |
@@ -197,6 +284,9 @@ void routing_status_handler(TCP_Client_Connection *con, int (*status_callback)(v | |||
197 | con->status_callback_object = object; | 284 | con->status_callback_object = object; |
198 | } | 285 | } |
199 | 286 | ||
287 | static int send_ping_response(TCP_Client_Connection *con); | ||
288 | static int send_ping_request(TCP_Client_Connection *con); | ||
289 | |||
200 | /* return 1 on success. | 290 | /* return 1 on success. |
201 | * return 0 if could not send packet. | 291 | * return 0 if could not send packet. |
202 | * return -1 on failure. | 292 | * return -1 on failure. |
@@ -209,10 +299,13 @@ int send_data(TCP_Client_Connection *con, uint8_t con_id, const uint8_t *data, u | |||
209 | if (con->connections[con_id].status != 2) | 299 | if (con->connections[con_id].status != 2) |
210 | return -1; | 300 | return -1; |
211 | 301 | ||
302 | if (send_ping_response(con) == 0 || send_ping_request(con) == 0) | ||
303 | return 0; | ||
304 | |||
212 | uint8_t packet[1 + length]; | 305 | uint8_t packet[1 + length]; |
213 | packet[0] = con_id + NUM_RESERVED_PORTS; | 306 | packet[0] = con_id + NUM_RESERVED_PORTS; |
214 | memcpy(packet + 1, data, length); | 307 | memcpy(packet + 1, data, length); |
215 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); | 308 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet), 0); |
216 | } | 309 | } |
217 | 310 | ||
218 | /* return 1 on success. | 311 | /* return 1 on success. |
@@ -228,7 +321,7 @@ int send_oob_packet(TCP_Client_Connection *con, const uint8_t *public_key, const | |||
228 | packet[0] = TCP_PACKET_OOB_SEND; | 321 | packet[0] = TCP_PACKET_OOB_SEND; |
229 | memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES); | 322 | memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES); |
230 | memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, data, length); | 323 | memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, data, length); |
231 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); | 324 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet), 0); |
232 | } | 325 | } |
233 | 326 | ||
234 | 327 | ||
@@ -274,31 +367,49 @@ static int send_disconnect_notification(TCP_Client_Connection *con, uint8_t id) | |||
274 | uint8_t packet[1 + 1]; | 367 | uint8_t packet[1 + 1]; |
275 | packet[0] = TCP_PACKET_DISCONNECT_NOTIFICATION; | 368 | packet[0] = TCP_PACKET_DISCONNECT_NOTIFICATION; |
276 | packet[1] = id; | 369 | packet[1] = id; |
277 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); | 370 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet), 1); |
278 | } | 371 | } |
279 | 372 | ||
280 | /* return 1 on success. | 373 | /* return 1 on success. |
281 | * return 0 if could not send packet. | 374 | * return 0 if could not send packet. |
282 | * return -1 on failure (connection must be killed). | 375 | * return -1 on failure (connection must be killed). |
283 | */ | 376 | */ |
284 | static int send_ping_request(TCP_Client_Connection *con, uint64_t ping_id) | 377 | static int send_ping_request(TCP_Client_Connection *con) |
285 | { | 378 | { |
379 | if (!con->ping_request_id) | ||
380 | return 1; | ||
381 | |||
286 | uint8_t packet[1 + sizeof(uint64_t)]; | 382 | uint8_t packet[1 + sizeof(uint64_t)]; |
287 | packet[0] = TCP_PACKET_PING; | 383 | packet[0] = TCP_PACKET_PING; |
288 | memcpy(packet + 1, &ping_id, sizeof(uint64_t)); | 384 | memcpy(packet + 1, &con->ping_request_id, sizeof(uint64_t)); |
289 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); | 385 | int ret; |
386 | |||
387 | if ((ret = write_packet_TCP_secure_connection(con, packet, sizeof(packet), 1)) == 1) { | ||
388 | con->ping_request_id = 0; | ||
389 | } | ||
390 | |||
391 | return ret; | ||
290 | } | 392 | } |
291 | 393 | ||
292 | /* return 1 on success. | 394 | /* return 1 on success. |
293 | * return 0 if could not send packet. | 395 | * return 0 if could not send packet. |
294 | * return -1 on failure (connection must be killed). | 396 | * return -1 on failure (connection must be killed). |
295 | */ | 397 | */ |
296 | static int send_ping_response(TCP_Client_Connection *con, uint64_t ping_id) | 398 | static int send_ping_response(TCP_Client_Connection *con) |
297 | { | 399 | { |
400 | if (!con->ping_response_id) | ||
401 | return 1; | ||
402 | |||
298 | uint8_t packet[1 + sizeof(uint64_t)]; | 403 | uint8_t packet[1 + sizeof(uint64_t)]; |
299 | packet[0] = TCP_PACKET_PONG; | 404 | packet[0] = TCP_PACKET_PONG; |
300 | memcpy(packet + 1, &ping_id, sizeof(uint64_t)); | 405 | memcpy(packet + 1, &con->ping_response_id, sizeof(uint64_t)); |
301 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); | 406 | int ret; |
407 | |||
408 | if ((ret = write_packet_TCP_secure_connection(con, packet, sizeof(packet), 1)) == 1) { | ||
409 | con->ping_response_id = 0; | ||
410 | } | ||
411 | |||
412 | return ret; | ||
302 | } | 413 | } |
303 | 414 | ||
304 | /* return 1 on success. | 415 | /* return 1 on success. |
@@ -324,7 +435,7 @@ int send_onion_request(TCP_Client_Connection *con, const uint8_t *data, uint16_t | |||
324 | uint8_t packet[1 + length]; | 435 | uint8_t packet[1 + length]; |
325 | packet[0] = TCP_PACKET_ONION_REQUEST; | 436 | packet[0] = TCP_PACKET_ONION_REQUEST; |
326 | memcpy(packet + 1, data, length); | 437 | memcpy(packet + 1, data, length); |
327 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); | 438 | return write_packet_TCP_secure_connection(con, packet, sizeof(packet), 0); |
328 | } | 439 | } |
329 | 440 | ||
330 | void onion_response_handler(TCP_Client_Connection *con, int (*onion_callback)(void *object, const uint8_t *data, | 441 | void onion_response_handler(TCP_Client_Connection *con, int (*onion_callback)(void *object, const uint8_t *data, |
@@ -427,7 +538,7 @@ static int handle_TCP_packet(TCP_Client_Connection *conn, const uint8_t *data, u | |||
427 | uint8_t con_id = data[1] - NUM_RESERVED_PORTS; | 538 | uint8_t con_id = data[1] - NUM_RESERVED_PORTS; |
428 | 539 | ||
429 | if (conn->connections[con_id].status != 1) | 540 | if (conn->connections[con_id].status != 1) |
430 | return -1; | 541 | return 0; |
431 | 542 | ||
432 | conn->connections[con_id].status = 2; | 543 | conn->connections[con_id].status = 2; |
433 | 544 | ||
@@ -451,7 +562,7 @@ static int handle_TCP_packet(TCP_Client_Connection *conn, const uint8_t *data, u | |||
451 | return 0; | 562 | return 0; |
452 | 563 | ||
453 | if (conn->connections[con_id].status != 2) | 564 | if (conn->connections[con_id].status != 2) |
454 | return -1; | 565 | return 0; |
455 | 566 | ||
456 | conn->connections[con_id].status = 1; | 567 | conn->connections[con_id].status = 1; |
457 | 568 | ||
@@ -468,7 +579,8 @@ static int handle_TCP_packet(TCP_Client_Connection *conn, const uint8_t *data, u | |||
468 | 579 | ||
469 | uint64_t ping_id; | 580 | uint64_t ping_id; |
470 | memcpy(&ping_id, data + 1, sizeof(uint64_t)); | 581 | memcpy(&ping_id, data + 1, sizeof(uint64_t)); |
471 | send_ping_response(conn, ping_id); | 582 | conn->ping_response_id = ping_id; |
583 | send_ping_response(conn); | ||
472 | return 0; | 584 | return 0; |
473 | } | 585 | } |
474 | 586 | ||
@@ -523,6 +635,9 @@ static int handle_TCP_packet(TCP_Client_Connection *conn, const uint8_t *data, u | |||
523 | static int do_confirmed_TCP(TCP_Client_Connection *conn) | 635 | static int do_confirmed_TCP(TCP_Client_Connection *conn) |
524 | { | 636 | { |
525 | send_pending_data(conn); | 637 | send_pending_data(conn); |
638 | send_ping_response(conn); | ||
639 | send_ping_request(conn); | ||
640 | |||
526 | uint8_t packet[MAX_PACKET_SIZE]; | 641 | uint8_t packet[MAX_PACKET_SIZE]; |
527 | int len; | 642 | int len; |
528 | 643 | ||
@@ -532,16 +647,9 @@ static int do_confirmed_TCP(TCP_Client_Connection *conn) | |||
532 | if (!ping_id) | 647 | if (!ping_id) |
533 | ++ping_id; | 648 | ++ping_id; |
534 | 649 | ||
535 | int ret = send_ping_request(conn, ping_id); | 650 | conn->ping_request_id = conn->ping_id = ping_id; |
536 | 651 | send_ping_request(conn); | |
537 | if (ret == 1) { | 652 | conn->last_pinged = unix_time(); |
538 | conn->last_pinged = unix_time(); | ||
539 | conn->ping_id = ping_id; | ||
540 | } else { | ||
541 | if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY + TCP_PING_TIMEOUT)) { | ||
542 | conn->status = TCP_CLIENT_DISCONNECTED; | ||
543 | } | ||
544 | } | ||
545 | } | 653 | } |
546 | 654 | ||
547 | if (conn->ping_id && is_timeout(conn->last_pinged, TCP_PING_TIMEOUT)) { | 655 | if (conn->ping_id && is_timeout(conn->last_pinged, TCP_PING_TIMEOUT)) { |