diff --git a/toxcore/TCP_server.c b/toxcore/TCP_server.c index e7ef0d3a..8b7d5fdd 100644 --- a/toxcore/TCP_server.c +++ b/toxcore/TCP_server.c @@ -306,25 +306,94 @@ static int send_pending_data(TCP_Secure_Connection *con) return 0; } - if (len > left) - return -1; - con->last_packet_sent += len; return -1; } +/* return 0 if pending data was sent completely + * return -1 if it wasn't + */ +static int send_pending_data_priority(TCP_Secure_Connection *con) +{ + TCP_Priority_List *p = con->priority_queue_start; + + while(p) { + uint16_t left = p->size - p->sent; + int len = send(con->sock, p->data + p->sent, left, MSG_NOSIGNAL); + + if(len != left) { + if(len > 0) { + p->sent += len; + } + break; + } + + TCP_Priority_List *pp = p; + p = p->next; + free(pp); + } + + con->priority_queue_start = p; + if(!p) { + con->priority_queue_end = NULL; + return 0; + } + + return -1; +} + +/* return 0 on failure (only if malloc fails) + * return 1 on success + */ +static _Bool add_priority(TCP_Secure_Connection *con, const uint8_t *packet, uint16_t size, int sent) +{ + if(sent == size) { + return 1; + } + + if(sent <= 0) { + sent = 0; + } + + TCP_Priority_List *p = con->priority_queue_end, *new; + new = malloc(sizeof(TCP_Priority_List) + size); + if(!new) { + return 0; + } + + new->next = NULL; + new->size = size; + new->sent = sent; + memcpy(new->data, packet, size); + + if(p) { + p->next = new; + } else { + con->priority_queue_start = new; + } + + con->priority_queue_end = new; + return 1; +} + /* return 1 on success. * return 0 if could not send packet. * return -1 on failure (connection must be killed). */ -static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, const uint8_t *data, uint16_t length) +static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, const uint8_t *data, uint16_t length, _Bool priority) { if (length + crypto_box_MACBYTES > MAX_PACKET_SIZE) return -1; - if (send_pending_data(con) == -1) - return 0; + _Bool sendpriority = 1; + if (send_pending_data_priority(con) == -1) { + if (priority) { + sendpriority = 0; + } else { + return 0; + } + } uint8_t packet[sizeof(uint16_t) + length + crypto_box_MACBYTES]; @@ -332,6 +401,13 @@ static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, const memcpy(packet, &c_length, sizeof(uint16_t)); int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); + if (priority) { + return add_priority(con, packet, sizeof(packet), sendpriority ? send(con->sock, packet, sizeof(packet), MSG_NOSIGNAL) : 0); + } + + if (send_pending_data(con) == -1) + return 0; + if ((unsigned int)len != (sizeof(packet) - sizeof(uint16_t))) return -1; @@ -459,7 +535,7 @@ static int send_routing_response(TCP_Secure_Connection *con, uint8_t rpid, const data[1] = rpid; memcpy(data + 2, public_key, crypto_box_PUBLICKEYBYTES); - return write_packet_TCP_secure_connection(con, data, sizeof(data)); + return write_packet_TCP_secure_connection(con, data, sizeof(data), 1); } /* return 1 on success. @@ -469,7 +545,7 @@ static int send_routing_response(TCP_Secure_Connection *con, uint8_t rpid, const static int send_connect_notification(TCP_Secure_Connection *con, uint8_t id) { uint8_t data[2] = {TCP_PACKET_CONNECTION_NOTIFICATION, id + NUM_RESERVED_PORTS}; - return write_packet_TCP_secure_connection(con, data, sizeof(data)); + return write_packet_TCP_secure_connection(con, data, sizeof(data), 1); } /* return 1 on success. @@ -479,7 +555,7 @@ static int send_connect_notification(TCP_Secure_Connection *con, uint8_t id) static int send_disconnect_notification(TCP_Secure_Connection *con, uint8_t id) { uint8_t data[2] = {TCP_PACKET_DISCONNECT_NOTIFICATION, id + NUM_RESERVED_PORTS}; - return write_packet_TCP_secure_connection(con, data, sizeof(data)); + return write_packet_TCP_secure_connection(con, data, sizeof(data), 1); } /* return 0 on success. @@ -579,7 +655,7 @@ static int handle_TCP_oob_send(TCP_Server *TCP_server, uint32_t con_id, const ui memcpy(resp_packet + 1, con->public_key, crypto_box_PUBLICKEYBYTES); memcpy(resp_packet + 1 + crypto_box_PUBLICKEYBYTES, data, length); write_packet_TCP_secure_connection(&TCP_server->accepted_connection_array[other_index], resp_packet, - sizeof(resp_packet)); + sizeof(resp_packet), 0); } return 0; @@ -637,7 +713,7 @@ static int handle_onion_recv_1(void *object, IP_Port dest, const uint8_t *data, memcpy(packet + 1, data, length); packet[0] = TCP_PACKET_ONION_RESPONSE; - if (write_packet_TCP_secure_connection(con, packet, sizeof(packet)) != 1) + if (write_packet_TCP_secure_connection(con, packet, sizeof(packet), 0) != 1) return 1; return 0; @@ -682,7 +758,7 @@ static int handle_TCP_packet(TCP_Server *TCP_server, uint32_t con_id, const uint uint8_t response[1 + sizeof(uint64_t)]; response[0] = TCP_PACKET_PONG; memcpy(response + 1, data + 1, sizeof(uint64_t)); - write_packet_TCP_secure_connection(con, response, sizeof(response)); + write_packet_TCP_secure_connection(con, response, sizeof(response), 1); return 0; } @@ -752,7 +828,7 @@ static int handle_TCP_packet(TCP_Server *TCP_server, uint32_t con_id, const uint uint8_t new_data[length]; memcpy(new_data, data, length); new_data[0] = other_c_id; - int ret = write_packet_TCP_secure_connection(&TCP_server->accepted_connection_array[index], new_data, length); + int ret = write_packet_TCP_secure_connection(&TCP_server->accepted_connection_array[index], new_data, length, 0); if (ret == -1) return -1; @@ -1058,7 +1134,7 @@ static void do_TCP_confirmed(TCP_Server *TCP_server) ++ping_id; memcpy(ping + 1, &ping_id, sizeof(uint64_t)); - int ret = write_packet_TCP_secure_connection(conn, ping, sizeof(ping)); + int ret = write_packet_TCP_secure_connection(conn, ping, sizeof(ping), 1); if (ret == 1) { conn->last_pinged = unix_time(); @@ -1076,7 +1152,10 @@ static void do_TCP_confirmed(TCP_Server *TCP_server) continue; } - send_pending_data(conn); + /* try sending queued priority packets first */ + if(send_pending_data_priority(conn) == 0) { + send_pending_data(conn); + } #ifndef TCP_SERVER_USE_EPOLL diff --git a/toxcore/TCP_server.h b/toxcore/TCP_server.h index def0a978..81507acb 100644 --- a/toxcore/TCP_server.h +++ b/toxcore/TCP_server.h @@ -80,6 +80,14 @@ enum { TCP_STATUS_CONFIRMED, }; +typedef struct TCP_Priority_List TCP_Priority_List; + +struct TCP_Priority_List { + TCP_Priority_List *next; + uint16_t size, sent; + uint8_t data[0]; +}; + typedef struct TCP_Secure_Connection { uint8_t status; sock_t sock; @@ -98,6 +106,8 @@ typedef struct TCP_Secure_Connection { uint16_t last_packet_length; uint16_t last_packet_sent; + TCP_Priority_List *priority_queue_start, *priority_queue_end; + uint64_t identifier; uint64_t last_pinged;