diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index 437429b9..496f48d7 100644 --- a/toxcore/TCP_client.c +++ b/toxcore/TCP_client.c @@ -130,6 +130,103 @@ static int send_pending_data(TCP_Client_Connection *con) 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_Client_Connection *con, uint8_t *data, uint16_t length) +{ + if (length + crypto_box_MACBYTES > MAX_PACKET_SIZE) + return -1; + + if (send_pending_data(con) == -1) + return 0; + + uint8_t packet[sizeof(uint16_t) + length + crypto_box_MACBYTES]; + + uint16_t c_length = htons(length + crypto_box_MACBYTES); + memcpy(packet, &c_length, sizeof(uint16_t)); + int len = encrypt_data_fast(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); + + if ((unsigned int)len != (sizeof(packet) - sizeof(uint16_t))) + return -1; + + increment_nonce(con->sent_nonce); + + len = send(con->sock, packet, sizeof(packet), MSG_NOSIGNAL); + + if ((unsigned int)len == sizeof(packet)) + return 1; + + if (len <= 0) + return 0; + + memcpy(con->last_packet, packet, length); + con->last_packet_length = sizeof(packet); + con->last_packet_sent = len; + return 1; +} + +/* return 1 on success. + * return 0 if could not send packet. + * return -1 on failure (connection must be killed). + */ +static int send_routing_request(TCP_Client_Connection *con, uint8_t *public_key) +{ + uint8_t packet[1 + crypto_box_PUBLICKEYBYTES]; + packet[0] = TCP_PACKET_ROUTING_REQUEST; + memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES); + return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); +} + +/* return 1 on success. + * return 0 if could not send packet. + * return -1 on failure (connection must be killed). + */ +static int send_disconnect_notification(TCP_Client_Connection *con, uint8_t id) +{ + uint8_t packet[1 + 1]; + packet[0] = TCP_PACKET_DISCONNECT_NOTIFICATION; + packet[1] = id; + return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); +} + +/* return 1 on success. + * return 0 if could not send packet. + * return -1 on failure (connection must be killed). + */ +static int send_ping_request(TCP_Client_Connection *con, uint64_t ping_id) +{ + uint8_t packet[1 + sizeof(uint64_t)]; + packet[0] = TCP_PACKET_PING; + memcpy(packet + 1, &ping_id, sizeof(uint64_t)); + return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); +} + +/* return 1 on success. + * return 0 if could not send packet. + * return -1 on failure (connection must be killed). + */ +static int send_ping_response(TCP_Client_Connection *con, uint64_t ping_id) +{ + uint8_t packet[1 + sizeof(uint64_t)]; + packet[0] = TCP_PACKET_PONG; + memcpy(packet + 1, &ping_id, sizeof(uint64_t)); + return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); +} + +/* return 1 on success. + * return 0 if could not send packet. + * return -1 on failure (connection must be killed). + */ +static int send_onion_request(TCP_Client_Connection *con, uint8_t *data, uint16_t length) +{ + uint8_t packet[1 + length]; + packet[0] = TCP_PACKET_ONION_REQUEST; + memcpy(packet + 1, data, length); + return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); +} + /* Create new TCP connection to ip_port/public_key */ TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, uint8_t *public_key, uint8_t *self_public_key, @@ -176,8 +273,51 @@ TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, uint8_t *public_key, return temp; } -static int do_confirmed_TCP(TCP_Client_Connection *TCP_connection) +/* return 0 on success + * return -1 on failure + */ +static int handle_TCP_packet(TCP_Client_Connection *conn, uint8_t *data, uint16_t length) { + if (length == 0) + return -1; + + switch (data[0]) { + case TCP_PACKET_PING: { + if (length != 1 + sizeof(uint64_t)) + return -1; + + uint64_t ping_id; + memcpy(&ping_id, data + 1, sizeof(uint64_t)); + send_ping_response(conn, ping_id); + return 0; + } + + default: { + + } + } + + return 0; +} + +static int do_confirmed_TCP(TCP_Client_Connection *conn) +{ + send_pending_data(conn); + uint8_t packet[MAX_PACKET_SIZE]; + int len; + + while ((len = read_packet_TCP_secure_connection(conn->sock, &conn->next_packet_length, conn->shared_key, + conn->recv_nonce, packet, sizeof(packet)))) { + if (len == -1) { + conn->status = TCP_CLIENT_DISCONNECTED; + break; + } + + if (handle_TCP_packet(conn, packet, len) == -1) { + conn->status = TCP_CLIENT_DISCONNECTED; + break; + } + } return 0; } diff --git a/toxcore/TCP_server.c b/toxcore/TCP_server.c index 4eed1209..847f04e7 100644 --- a/toxcore/TCP_server.c +++ b/toxcore/TCP_server.c @@ -228,10 +228,11 @@ int read_TCP_packet(sock_t sock, uint8_t *data, uint16_t length) * return 0 if could not read any packet. * return -1 on failure (connection must be killed). */ -static int read_packet_TCP_secure_connection(TCP_Secure_Connection *con, uint8_t *data, uint16_t max_len) +int read_packet_TCP_secure_connection(sock_t sock, uint16_t *next_packet_length, uint8_t *shared_key, + uint8_t *recv_nonce, uint8_t *data, uint16_t max_len) { - if (con->next_packet_length == 0) { - uint16_t len = read_TCP_length(con->sock); + if (*next_packet_length == 0) { + uint16_t len = read_TCP_length(sock); if (len == (uint16_t)~0) return -1; @@ -239,26 +240,26 @@ static int read_packet_TCP_secure_connection(TCP_Secure_Connection *con, uint8_t if (len == 0) return 0; - con->next_packet_length = len; + *next_packet_length = len; } - if (max_len + crypto_box_MACBYTES < con->next_packet_length) + if (max_len + crypto_box_MACBYTES < *next_packet_length) return -1; - uint8_t data_encrypted[con->next_packet_length]; - int len_packet = read_TCP_packet(con->sock, data_encrypted, con->next_packet_length); + uint8_t data_encrypted[*next_packet_length]; + int len_packet = read_TCP_packet(sock, data_encrypted, *next_packet_length); - if (len_packet != con->next_packet_length) + if (len_packet != *next_packet_length) return 0; - con->next_packet_length = 0; + *next_packet_length = 0; - int len = decrypt_data_fast(con->shared_key, con->recv_nonce, data_encrypted, len_packet, data); + int len = decrypt_data_fast(shared_key, recv_nonce, data_encrypted, len_packet, data); if (len + crypto_box_MACBYTES != len_packet) return -1; - increment_nonce(con->recv_nonce); + increment_nonce(recv_nonce); return len; } @@ -848,7 +849,8 @@ static void do_TCP_unconfirmed(TCP_Server *TCP_server) continue; uint8_t packet[MAX_PACKET_SIZE]; - int len = read_packet_TCP_secure_connection(conn, packet, sizeof(packet)); + int len = read_packet_TCP_secure_connection(conn->sock, &conn->next_packet_length, conn->shared_key, conn->recv_nonce, + packet, sizeof(packet)); if (len == 0) { continue; @@ -902,7 +904,8 @@ static void do_TCP_confirmed(TCP_Server *TCP_server) uint8_t packet[MAX_PACKET_SIZE]; int len; - while ((len = read_packet_TCP_secure_connection(conn, packet, sizeof(packet)))) { + while ((len = read_packet_TCP_secure_connection(conn->sock, &conn->next_packet_length, conn->shared_key, + conn->recv_nonce, packet, sizeof(packet)))) { if (len == -1) { kill_TCP_connection(conn); del_accepted(TCP_server, i); diff --git a/toxcore/TCP_server.h b/toxcore/TCP_server.h index 3ae0eba4..57313038 100644 --- a/toxcore/TCP_server.h +++ b/toxcore/TCP_server.h @@ -140,4 +140,12 @@ uint16_t read_TCP_length(sock_t sock); */ int read_TCP_packet(sock_t sock, uint8_t *data, uint16_t length); +/* return length of recieved packet on success. + * return 0 if could not read any packet. + * return -1 on failure (connection must be killed). + */ +int read_packet_TCP_secure_connection(sock_t sock, uint16_t *next_packet_length, uint8_t *shared_key, + uint8_t *recv_nonce, uint8_t *data, uint16_t max_len); + + #endif