From 8e24771fc41597dd9e3e02a192eb0b5b43771ac1 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 2 May 2014 10:36:48 -0400 Subject: Remove Lossless UDP (This breaks Tox.) --- testing/Lossless_UDP_testclient.c | 260 --------- testing/Lossless_UDP_testserver.c | 237 -------- testing/Makefile.inc | 36 -- toxcore/Lossless_UDP.c | 1168 ------------------------------------- toxcore/Lossless_UDP.h | 262 --------- toxcore/Makefile.inc | 2 - toxcore/Messenger.c | 70 ++- toxcore/Messenger.h | 1 + toxcore/net_crypto.c | 381 +----------- toxcore/net_crypto.h | 41 +- toxcore/tox.c | 2 +- 11 files changed, 60 insertions(+), 2400 deletions(-) delete mode 100644 testing/Lossless_UDP_testclient.c delete mode 100644 testing/Lossless_UDP_testserver.c delete mode 100644 toxcore/Lossless_UDP.c delete mode 100644 toxcore/Lossless_UDP.h diff --git a/testing/Lossless_UDP_testclient.c b/testing/Lossless_UDP_testclient.c deleted file mode 100644 index 535509e0..00000000 --- a/testing/Lossless_UDP_testclient.c +++ /dev/null @@ -1,260 +0,0 @@ -/* Lossless_UDP testclient - * A program that connects and sends a file using our lossless UDP algorithm. - * NOTE: this program simulates a 33% packet loss. - * - * Best used in combination with Lossless_UDP_testserver - * - * Compile with: gcc -O2 -Wall -lsodium -o testclient ../toxcore/network.c ../toxcore/Lossless_UDP.c ../toxcore/util.c Lossless_UDP_testclient.c - * - * Command line arguments are the ip and port to connect and send the file to. - * EX: ./testclient --ipv4 127.0.0.1 33445 filename.txt - * - * Copyright (C) 2013 Tox project All Rights Reserved. - * - * This file is part of Tox. - * - * Tox is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Tox is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Tox. If not, see . - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "../toxcore/network.h" -#include "../toxcore/Lossless_UDP.h" -#include "../toxcore/util.h" -#include "misc_tools.c" - -#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) - -#define c_sleep(x) Sleep(1*x) - -#else -#include -#include -#define c_sleep(x) usleep(1000*x) - -#endif - -#define PORT 33446 - -void printpacket(uint8_t *data, uint32_t length, IP_Port ip_port) -{ - uint32_t i; - printf("UNHANDLED PACKET RECEIVED\nLENGTH:%u\nCONTENTS:\n", length); - printf("--------------------BEGIN-----------------------------\n"); - - for (i = 0; i < length; i++) { - if (data[i] < 16) - printf("0"); - - printf("%hhX", data[i]); - } - - printf("\n--------------------END-----------------------------\n\n\n"); -} - -void printip(IP_Port ip_port) -{ - printf("\nIP: %s Port: %u", ip_ntoa(&ip_port.ip), ntohs(ip_port.port)); -} -/* -void printpackets(Data test) -{ - int i; - if(test.size == 0) - return; - printf("SIZE: %u\n", test.size); - for(i =0; i < test.size; i++) - { - printf("%hhX", test.data[i]); - } - printf("\n"); -} - -void printconnection(int connection_id) -{ - printf("--------------------BEGIN---------------------\n"); - IP_Port ip_port = connections[connection_id].ip_port; - printf("IP: %u.%u.%u.%u Port: %u\n",ip_port.ip.c[0],ip_port.ip.c[1],ip_port.ip.c[2],ip_port.ip.c[3],ntohs(ip_port.port)); - printf("status: %u, inbound: %u, SYNC_rate: %u\n", connections[connection_id].status, - connections[connection_id].inbound, connections[connection_id].SYNC_rate); - printf("data rate: %u, last sync: %llu, last sent: %llu, last recv: %llu \n", connections[connection_id].data_rate, - connections[connection_id].last_SYNC, connections[connection_id].last_sent, connections[connection_id].last_recv); - int i; - for(i =0; i < MAX_QUEUE_NUM; i++) - { - printf(" %u ",i); - printpackets(connections[connection_id].sendbuffer[i]); - } - for(i =0; i < MAX_QUEUE_NUM; i++) - { - printf(" %u ",i); - printpackets(connections[connection_id].recvbuffer[i]); - } - Data sendbuffer[MAX_QUEUE_NUM]; - Data recvbuffer[MAX_QUEUE_NUM]; - printf("recv_num: %u, orecv_num: %u, sent_packetnum %u, osent_packetnum: %u, successful_sent: %u, successful_read: %u\n", - connections[connection_id].recv_packetnum, - connections[connection_id].orecv_packetnum, connections[connection_id].sent_packetnum, connections[connection_id].osent_packetnum, - connections[connection_id].successful_sent, - connections[connection_id].successful_read); - - printf("req packets: \n"); - for(i = 0; i < BUFFER_PACKET_NUM; i++) - { - printf(" %u ", connections[connection_id].req_packets[i]); - } - printf("\nNumber: %u recv_counter: %u, send_counter: %u\n", connections[connection_id].num_req_paquets, - connections[connection_id].recv_counter, connections[connection_id].send_counter); - - printf("--------------------END---------------------\n"); - -} -*/ - -/*( receive packets and send them to the packethandler */ -/*run doLossless_UDP(); */ -//void Lossless_UDP() -//{ -/* IP_Port ip_port; - uint8_t data[MAX_UDP_PACKET_SIZE]; - uint32_t length; - while (receivepacket(&ip_port, data, &length) != -1) { - printf("packet with length: %u\n", length); */ -/* if(rand() % 3 != 1)//add packet loss - { */ -/* - if (LosslessUDP_handlepacket(data, length, ip_port)) - printpacket(data, length, ip_port); - else - printf("Received handled packet with length: %u\n", length); //printconnection(0); */ - -/* } */ -/* }*/ - -//networking_poll(); - -//doLossless_UDP(); - -//} - -int main(int argc, char *argv[]) -{ - /* let user override default by cmdline */ - uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */ - int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled); - - if (argvoffset < 0) - exit(1); - - if (argc < argvoffset + 4) { - printf("Usage: %s [--ipv4|--ipv6] ip port filename\n", argv[0]); - exit(0); - } - - uint8_t buffer[MAX_DATA_SIZE]; - int read; - - FILE *file = fopen(argv[argvoffset + 3], "rb"); - - if (file == NULL) { - printf("Failed to open file \"%s\".\n", argv[argvoffset + 3]); - return 1; - } - - - /* initialize networking */ - /* bind to ip 0.0.0.0:PORT */ - IP ip; - ip_init(&ip, ipv6enabled); - - Lossless_UDP *ludp = new_lossless_udp(new_networking(ip, PORT)); - perror("Initialization"); - - IP_Port serverip; - ip_init(&serverip.ip, ipv6enabled); - - if (!addr_resolve(argv[argvoffset + 1], &serverip.ip, NULL)) { - printf("Failed to convert \"%s\" into an IP address.\n", argv[argvoffset + 1]); - return 1; - } - - serverip.port = htons(atoi(argv[argvoffset + 2])); - printip(serverip); - - int connection = new_connection(ludp, serverip); - uint64_t timer = current_time(); - - while (1) { - /* printconnection(connection); */ - networking_poll(ludp->net); - do_lossless_udp(ludp); - - if (is_connected(ludp, connection) == LUDP_ESTABLISHED) { - printf("Connecting took: %llu us\n", (unsigned long long)(current_time() - timer)); - break; - } - - if (is_connected(ludp, connection) == LUDP_NO_CONNECTION) { - printf("Connection timeout after: %llu us\n", (unsigned long long)(current_time() - timer)); - return 1; - } - - c_sleep(1); - } - - timer = current_time(); - unsigned long long bytes_sent = 0; - - /*read first part of file */ - read = fread(buffer, 1, MAX_DATA_SIZE, file); - - while (1) { - /* printconnection(connection); */ - networking_poll(ludp->net); - do_lossless_udp(ludp); - - if (is_connected(ludp, connection) == LUDP_ESTABLISHED) { - - while (write_packet(ludp, connection, buffer, read)) { - bytes_sent += read; - /* printf("Wrote data.\n"); */ - read = fread(buffer, 1, MAX_DATA_SIZE, file); - - } - - /* printf("%u\n", sendqueue(connection)); */ - if (sendqueue(ludp, connection) == 0) { - if (read == 0) { - unsigned long long us = (unsigned long long)(current_time() - timer); - printf("Sent file successfully in: %llu us = %llu seconds. Average speed: %llu KB/s\n", us, us / 1000000UL, - bytes_sent / (us / 1024UL)); - //printf("Total bytes sent: %llu B, Total data sent: %llu B, overhead: %llu B\n", total_bytes_sent, bytes_sent, total_bytes_sent-bytes_sent); - break; - } - } - } else { - printf("%u Client Connecting Lost after: %llu us\n", is_connected(ludp, connection), - (unsigned long long)(current_time() - timer)); - return 0; - } - - } - - c_sleep(25); - - return 0; -} diff --git a/testing/Lossless_UDP_testserver.c b/testing/Lossless_UDP_testserver.c deleted file mode 100644 index dd4612f5..00000000 --- a/testing/Lossless_UDP_testserver.c +++ /dev/null @@ -1,237 +0,0 @@ -/* Lossless_UDP testserver - * A program that waits for a lossless UDP connection and then saves all the data received to a file. - * NOTE: this program simulates a 33% packet loss. - * - * Best used in combination with Lossless_UDP_testclient - * - * Compile with: gcc -O2 -Wall -lsodium -o testserver ../toxcore/network.c ../toxcore/Lossless_UDP.c ../toxcore/util.c Lossless_UDP_testserver.c - * - * Command line argument is the name of the file to save what we receive to. - * EX: ./testserver filename1.txt - * - * Copyright (C) 2013 Tox project All Rights Reserved. - * - * This file is part of Tox. - * - * Tox is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Tox is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Tox. If not, see . - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "../toxcore/network.h" -#include "../toxcore/Lossless_UDP.h" -#include "../toxcore/util.h" -#include "misc_tools.c" - -//Sleep function (x = milliseconds) -#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) - -#define c_sleep(x) Sleep(1*x) - -#else -#include -#include -#define c_sleep(x) usleep(1000*x) - -#endif - -#define PORT 33445 - -void printpacket(uint8_t *data, uint32_t length, IP_Port ip_port) -{ - uint32_t i; - printf("UNHANDLED PACKET RECEIVED\nLENGTH:%u\nCONTENTS:\n", length); - printf("--------------------BEGIN-----------------------------\n"); - - for (i = 0; i < length; i++) { - if (data[i] < 16) - printf("0"); - - printf("%hhX", data[i]); - } - - printf("\n--------------------END-----------------------------\n\n\n"); -} - -/* -void printpackets(Data test) -{ - int i; - if(test.size == 0) - return; - printf("SIZE: %u\n", test.size); - for(i =0; i < test.size; i++) - { - printf("%hhX", test.data[i]); - } - printf("\n"); -} - -void printconnection(int connection_id) -{ - printf("--------------------BEGIN---------------------\n"); - IP_Port ip_port = connections[connection_id].ip_port; - printf("IP: %u.%u.%u.%u Port: %u\n",ip_port.ip.c[0],ip_port.ip.c[1],ip_port.ip.c[2],ip_port.ip.c[3],ntohs(ip_port.port)); - printf("status: %u, inbound: %u, SYNC_rate: %u\n", connections[connection_id].status, - connections[connection_id].inbound, connections[connection_id].SYNC_rate); - printf("data rate: %u, last sync: %llu, last sent: %llu, last recv: %llu \n", connections[connection_id].data_rate, - connections[connection_id].last_SYNC, connections[connection_id].last_sent, connections[connection_id].last_recv); - int i; - for(i =0; i < MAX_QUEUE_NUM; i++) - { - printf(" %u ",i); - printpackets(connections[connection_id].sendbuffer[i]); - } - for(i =0; i < MAX_QUEUE_NUM; i++) - { - printf(" %u ",i); - printpackets(connections[connection_id].recvbuffer[i]); - } - Data sendbuffer[MAX_QUEUE_NUM]; - Data recvbuffer[MAX_QUEUE_NUM]; - printf("recv_num: %u, orecv_num: %u, sent_packetnum %u, osent_packetnum: %u, successful_sent: %u, successful_read: %u\n", - connections[connection_id].recv_packetnum, - connections[connection_id].orecv_packetnum, connections[connection_id].sent_packetnum, connections[connection_id].osent_packetnum, - connections[connection_id].successful_sent, - connections[connection_id].successful_read); - - printf("req packets: \n"); - for(i = 0; i < BUFFER_PACKET_NUM; i++) - { - printf(" %u ", connections[connection_id].req_packets[i]); - } - printf("\nNumber: %u recv_counter: %u, send_counter: %u\n", connections[connection_id].num_req_paquets, - connections[connection_id].recv_counter, connections[connection_id].send_counter); - - printf("--------------------END---------------------\n"); - -} -*/ - -/* receive packets and send them to the packethandler - * run doLossless_UDP(); */ -//void Lossless_UDP() -//{ -// IP_Port ip_port; -// uint8_t data[MAX_UDP_PACKET_SIZE]; -// uint32_t length; -// while (receivepacket(&ip_port, data, &length) != -1) { -//if(rand() % 3 != 1)//add packet loss -//{ -// if (LosslessUDP_handlepacket(data, length, ip_port)) { -// printpacket(data, length, ip_port); -// } else { -//printconnection(0); -// printf("Received handled packet with length: %u\n", length); -// } -//} -// } - -// networking_poll(); - -//doLossless_UDP(); -//} - - -int main(int argc, char *argv[]) -{ - /* let user override default by cmdline */ - uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */ - int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled); - - if (argvoffset < 0) - exit(1); - - if (argc < argvoffset + 2) { - printf("Usage: %s [--ipv4|--ipv6] filename\n", argv[0]); - exit(0); - } - - uint8_t buffer[MAX_DATA_SIZE]; - int read; - - FILE *file = fopen(argv[argvoffset + 1], "wb"); - - if (file == NULL) { - printf("Failed to open file \"%s\".\n", argv[argvoffset + 1]); - return 1; - } - - - //initialize networking - //bind to ip 0.0.0.0:PORT - IP ip; - ip_init(&ip, ipv6enabled); - - Lossless_UDP *ludp = new_lossless_udp(new_networking(ip, PORT)); - perror("Initialization"); - - int connection; - uint64_t timer = current_time(); - - while (1) { - networking_poll(ludp->net); - do_lossless_udp(ludp); - connection = incoming_connection(ludp, 0); - - if (connection != -1) { - if (is_connected(ludp, connection) == LUDP_NOT_CONFIRMED) { - printf("Received the connection.\n"); - - } - - break; - } - - c_sleep(1); - } - - timer = current_time(); - - while (1) { - //printconnection(0); - networking_poll(ludp->net); - - if (is_connected(ludp, connection) >= LUDP_NOT_CONFIRMED) { - confirm_connection(ludp, connection); - - while (1) { - read = read_packet(ludp, connection, buffer); - - if (read != 0) { - // printf("Received data.\n"); - if (!fwrite(buffer, read, 1, file)) - printf("file write error\n"); - } else { - break; - } - } - } - - do_lossless_udp(ludp); - - if (is_connected(ludp, connection) == LUDP_TIMED_OUT) { - printf("Server Connecting Lost after: %llu us\n", (unsigned long long)(current_time() - timer)); - fclose(file); - return 1; - } - - c_sleep(25); - } - - return 0; -} diff --git a/testing/Makefile.inc b/testing/Makefile.inc index 812a5be1..b3912033 100644 --- a/testing/Makefile.inc +++ b/testing/Makefile.inc @@ -22,8 +22,6 @@ endif if BUILD_TESTING noinst_PROGRAMS += DHT_test \ - Lossless_UDP_testclient \ - Lossless_UDP_testserver \ Messenger_test \ crypto_speed_test @@ -41,40 +39,6 @@ DHT_test_LDADD = $(LIBSODIUM_LDFLAGS) \ $(WINSOCK2_LIBS) -Lossless_UDP_testclient_SOURCES = \ - ../testing/Lossless_UDP_testclient.c - -Lossless_UDP_testclient_CFLAGS = \ - $(LIBSODIUM_CFLAGS) \ - $(NACL_CFLAGS) - -Lossless_UDP_testclient_LDADD = \ - $(LIBSODIUM_LDFLAGS) \ - $(NACL_LDFLAGS) \ - libtoxcore.la \ - $(LIBSODIUM_LIBS) \ - $(NACL_OBJECTS) \ - $(NACL_LIBS) \ - $(WINSOCK2_LIBS) - - -Lossless_UDP_testserver_SOURCES = \ - ../testing/Lossless_UDP_testserver.c - -Lossless_UDP_testserver_CFLAGS = \ - $(LIBSODIUM_CFLAGS) \ - $(NACL_CFLAGS) - -Lossless_UDP_testserver_LDADD = \ - $(LIBSODIUM_LDFLAGS) \ - $(NACL_LDFLAGS) \ - libtoxcore.la \ - $(LIBSODIUM_LIBS) \ - $(NACL_OBJECTS) \ - $(NACL_LIBS) \ - $(WINSOCK2_LIBS) - - Messenger_test_SOURCES = \ ../testing/Messenger_test.c diff --git a/toxcore/Lossless_UDP.c b/toxcore/Lossless_UDP.c deleted file mode 100644 index c0db8a10..00000000 --- a/toxcore/Lossless_UDP.c +++ /dev/null @@ -1,1168 +0,0 @@ -/* Lossless_UDP.c - * - * An implementation of the Lossless_UDP protocol as seen in http://wiki.tox.im/index.php/Lossless_UDP - * - * Copyright (C) 2013 Tox project All Rights Reserved. - * - * This file is part of Tox. - * - * Tox is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Tox is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Tox. If not, see . - * - */ - -/* - * TODO: clean this file a bit. - * There are a couple of useless variables to get rid of. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "Lossless_UDP.h" - -#define LUDP_CONNECTION_OUTBOUND 0 -#define LUDP_CONNECTION_INBOUND_HANDLED 1 -#define LUDP_CONNECTION_INBOUND 2 - -/* Functions */ - -/* - * Get connection id from IP_Port. - * - * return -1 if there are no connections like we are looking for. - * return id if it found it. - */ -int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port) -{ - tox_array_for_each(&ludp->connections, Connection, tmp) { - if (tmp->status != LUDP_NO_CONNECTION && ipport_equal(&tmp->ip_port, &ip_port)) { - return tmp_i; - } - } - - return -1; -} - -/* Resize a queue - * return length of queue on success. - * return ~0 on failure. - */ -uint32_t resize_queue(Data **buffer, uint32_t length, uint32_t new_length, uint32_t min_packetnum, - uint32_t max_packetnum) -{ - if (MAX_QUEUE_NUM < new_length) - new_length = MAX_QUEUE_NUM; - - if (max_packetnum - min_packetnum > new_length) - return ~0; - - if (length == new_length) - return new_length; - - Data *temp = calloc(1, sizeof(Data) * new_length); - - if (temp == NULL) - return ~0; - - if (*buffer == NULL) { - *buffer = temp; - return new_length; - } - - uint32_t i; - - for (i = min_packetnum; i != max_packetnum; ++i) - memcpy(temp + (i % new_length), *buffer + (i % length), sizeof(Data)); - - free(*buffer); - *buffer = temp; - return new_length; -} - - - -/* - * Generate a handshake_id which depends on the ip_port. - * This function will always give one unique handshake_id per ip_port. - * - * TODO: make this better - */ - -static uint32_t randtable_initget(Lossless_UDP *ludp, uint32_t index, uint8_t value) -{ - if (ludp->randtable[index][value] == 0) - ludp->randtable[index][value] = random_int(); - - return ludp->randtable[index][value]; -} - -static uint32_t handshake_id(Lossless_UDP *ludp, IP_Port source) -{ - uint32_t id = 0, i = 0; - - uint8_t *uint8; - uint8 = (uint8_t *)&source.port; - id ^= randtable_initget(ludp, i, *uint8); - i++, uint8++; - id ^= randtable_initget(ludp, i, *uint8); - i++; - - if (source.ip.family == AF_INET) { - int k; - - for (k = 0; k < 4; k++) { - id ^= randtable_initget(ludp, i++, source.ip.ip4.uint8[k]); - } - } - - if (source.ip.family == AF_INET6) { - int k; - - for (k = 0; k < 16; k++) { - id ^= randtable_initget(ludp, i++, source.ip.ip6.uint8[k]); - } - } - - /* id can't be zero. */ - if (id == 0) - id = 1; - - return id; -} - -/* - * Change the handshake id associated with that ip_port. - * - * TODO: Make this better - */ -static void change_handshake(Lossless_UDP *ludp, IP_Port source) -{ - uint8_t rand; - - if (source.ip.family == AF_INET) { - rand = random_int() % 4; - } else if (source.ip.family == AF_INET6) { - rand = random_int() % 16; - } else { - return; - } - - /* Forced to be more robust against strange definitions of sa_family_t */ - ludp->randtable[2 + rand][((uint8_t *)&source.ip.ip6)[rand]] = random_int(); -} - -/* - * Initialize a new connection to ip_port - * - * return an integer corresponding to the connection id. - * return -1 if it could not initialize the connectiont - * If there already was an existing connection to that ip_port return its number. - */ -int new_connection(Lossless_UDP *ludp, IP_Port ip_port) -{ - int connection_id = getconnection_id(ludp, ip_port); - - if (connection_id != -1) { - confirm_connection(ludp, connection_id); - return connection_id; - } - - tox_array_for_each(&ludp->connections, Connection, tmp) { - if (tmp->status == LUDP_NO_CONNECTION) { - connection_id = tmp_i; - break; - } - } - - if (connection_id == -1) { - if (tox_array_push_ptr(&ludp->connections, 0) == 0) - return -1; - - connection_id = ludp->connections.len - 1; - } - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - memset(connection, 0, sizeof(Connection)); - - uint32_t handshake_id1 = handshake_id(ludp, ip_port); - /* Add randomness to timeout to prevent connections getting stuck in a loop. */ - uint8_t timeout = CONNECTION_TIMEOUT + rand() % CONNECTION_TIMEOUT; - - *connection = (Connection) { - .ip_port = ip_port, - .status = LUDP_HANDSHAKE_SENDING, - .inbound = LUDP_CONNECTION_OUTBOUND, - .handshake_id1 = handshake_id1, - .sent_packetnum = handshake_id1, - .sendbuff_packetnum = handshake_id1, - .successful_sent = handshake_id1, - .SYNC_rate = SYNC_RATE, - .data_rate = DATA_SYNC_RATE, - .last_recvSYNC = current_time(), - .last_sent = current_time(), - .killat = ~0, - .send_counter = 0, - .timeout = timeout, - .confirmed = 1 - }; - connection->sendbuffer_length = resize_queue(&connection->sendbuffer, 0, DEFAULT_QUEUE_NUM, 0, 0); - connection->recvbuffer_length = resize_queue(&connection->recvbuffer, 0, DEFAULT_QUEUE_NUM, 0, 0); - - if (connection->sendbuffer_length == (uint32_t)~0 || connection->recvbuffer_length == (uint32_t)~0) { - free(connection->sendbuffer); - free(connection->recvbuffer); - memset(connection, 0, sizeof(Connection)); - return -1; - } - - return connection_id; -} - -/* - * Initialize a new inbound connection from ip_port. - * - * return an integer corresponding to the connection id. - * return -1 if it could not initialize the connection. - */ -static int new_inconnection(Lossless_UDP *ludp, IP_Port ip_port) -{ - if (getconnection_id(ludp, ip_port) != -1) - return -1; /* TODO: return existing connection instead? */ - - int connection_id = -1; - tox_array_for_each(&ludp->connections, Connection, tmp) { - if (tmp->status == LUDP_NO_CONNECTION) { - connection_id = tmp_i; - break; - } - } - - if (connection_id == -1) { - if (tox_array_push_ptr(&ludp->connections, 0) == 0) - return -1; - - connection_id = ludp->connections.len - 1; - } - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - memset(connection, 0, sizeof(Connection)); - /* Add randomness to timeout to prevent connections getting stuck in a loop. */ - uint8_t timeout = CONNECTION_TIMEOUT + rand() % CONNECTION_TIMEOUT; - - *connection = (Connection) { - .ip_port = ip_port, - .status = LUDP_NOT_CONFIRMED, - .inbound = LUDP_CONNECTION_INBOUND, - .SYNC_rate = SYNC_RATE, - .data_rate = DATA_SYNC_RATE, - .last_recvSYNC = current_time(), - .last_sent = current_time(), - .send_counter = 127, - - .timeout = timeout, - - /* If this connection isn't handled within the timeout kill it. */ - .killat = current_time() + 1000000ULL * timeout, - .confirmed = 0 - }; - connection->sendbuffer_length = resize_queue(&connection->sendbuffer, 0, DEFAULT_QUEUE_NUM, 0, 0); - connection->recvbuffer_length = resize_queue(&connection->recvbuffer, 0, DEFAULT_QUEUE_NUM, 0, 0); - - if (connection->sendbuffer_length == (uint32_t)~0 || connection->recvbuffer_length == (uint32_t)~0) { - free(connection->sendbuffer); - free(connection->recvbuffer); - memset(connection, 0, sizeof(Connection)); - return -1; - } - - return connection_id; -} - -/* - * return an integer corresponding to the next connection in our incoming connection list with at least numpackets in the recieve queue. - * return -1 if there are no new incoming connections in the list. - */ -int incoming_connection(Lossless_UDP *ludp, uint32_t numpackets) -{ - tox_array_for_each(&ludp->connections, Connection, tmp) { - if (tmp->inbound == LUDP_CONNECTION_INBOUND && tmp->recv_packetnum - tmp->successful_read >= numpackets) { - tmp->inbound = LUDP_CONNECTION_INBOUND_HANDLED; - return tmp_i; - } - } - return -1; -} -/* Try to free some memory from the connections array. */ -static void free_connections(Lossless_UDP *ludp) -{ - uint32_t i; - - for (i = ludp->connections.len; i != 0; --i) { - Connection *connection = &tox_array_get(&ludp->connections, i - 1, Connection); - - if (connection->status != LUDP_NO_CONNECTION) - break; - } - - if (ludp->connections.len == i) - return; - - return tox_array_pop(&ludp->connections, ludp->connections.len - i); -} -/* return -1 if it could not kill the connection. - * return 0 if killed successfully. - */ -int kill_connection(Lossless_UDP *ludp, int connection_id) -{ - if ((unsigned int)connection_id < ludp->connections.len) { - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - if (connection->status != LUDP_NO_CONNECTION) { - connection->status = LUDP_NO_CONNECTION; - change_handshake(ludp, connection->ip_port); - free(connection->sendbuffer); - free(connection->recvbuffer); - memset(connection, 0, sizeof(Connection)); - free_connections(ludp); - return 0; - } - } - - return -1; -} - -/* - * timeout connection in seconds. - * - * return -1 if it can not kill the connection. - * return 0 if it will kill it. - */ -int timeout_connection_in(Lossless_UDP *ludp, int connection_id, uint32_t seconds) -{ - if ((unsigned int)connection_id < ludp->connections.len) { - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - if (connection->status != LUDP_NO_CONNECTION) { - connection->killat = current_time() + 1000000ULL * seconds; - return 0; - } - } - - return -1; -} - -/* - * Check if connection is connected: - * - * return LUDP_NO_CONNECTION if not. - * return LUDP_HANDSHAKE_SENDING if attempting handshake. - * return LUDP_NOT_CONFIRMED if handshake is done. - * return LUDP_ESTABLISHED if fully connected. - * return LUDP_TIMED_OUT if timed out and waiting to be killed. - */ -int is_connected(Lossless_UDP *ludp, int connection_id) -{ - if ((unsigned int)connection_id < ludp->connections.len) - return tox_array_get(&ludp->connections, connection_id, Connection).status; - - return 0; -} - -/* Check if connection is confirmed. - * - * returns 1 if yes. - * returns 0 if no/failure. - */ -int connection_confirmed(Lossless_UDP *ludp, int connection_id) -{ - if ((unsigned int)connection_id >= ludp->connections.len) - return 0; - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - if (connection->status == LUDP_NO_CONNECTION) - return 0; - - if (connection->confirmed == 1) - return 1; - - return 0; -} - -/* Confirm an incoming connection. - * Also disable the auto kill timeout on incomming connections. - * - * return 0 on success - * return -1 on failure. - */ -int confirm_connection(Lossless_UDP *ludp, int connection_id) -{ - if ((unsigned int)connection_id >= ludp->connections.len) - return -1; - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - if (connection->status == LUDP_NO_CONNECTION) - return -1; - - connection->killat = ~0; - connection->confirmed = 1; - connection->inbound = LUDP_CONNECTION_OUTBOUND; - return 0; -} - -/* return the ip_port of the corresponding connection. */ -IP_Port connection_ip(Lossless_UDP *ludp, int connection_id) -{ - if ((unsigned int)connection_id < ludp->connections.len) - return tox_array_get(&ludp->connections, connection_id, Connection).ip_port; - - IP_Port zero; - ip_reset(&zero.ip); - zero.port = 0; - return zero; -} - -/* return the number of packets in the queue waiting to be successfully sent. */ -uint32_t sendqueue(Lossless_UDP *ludp, int connection_id) -{ - if ((unsigned int)connection_id >= ludp->connections.len) - return 0; - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - if (connection->status == LUDP_NO_CONNECTION) - return 0; - - return connection->sendbuff_packetnum - connection->successful_sent; -} - -/* return number of packets in all queues waiting to be successfully sent. */ -uint32_t sendqueue_total(Lossless_UDP *ludp) -{ - uint32_t i, total = 0; - - for (i = 0; i < ludp->connections.len; i++) { - Connection *connection = &tox_array_get(&ludp->connections, i, Connection); - - if (connection->status != 0) - total += connection->sendbuff_packetnum - connection->successful_sent; - } - - return total; -} - -/* return the number of packets in the queue waiting to be successfully read with read_packet(...). */ -uint32_t recvqueue(Lossless_UDP *ludp, int connection_id) -{ - if ((unsigned int)connection_id >= ludp->connections.len) - return 0; - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - if (connection->status == LUDP_NO_CONNECTION) - return 0; - - return connection->recv_packetnum - connection->successful_read; -} - -/* return the id of the next packet in the queue. - * return ~0 if no packet in queue. - */ -uint8_t id_packet(Lossless_UDP *ludp, int connection_id) -{ - if (recvqueue(ludp, connection_id) == 0) - return ~0; - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - if (connection->status != LUDP_NO_CONNECTION) - return connection->recvbuffer[connection->successful_read % connection->recvbuffer_length].data[0]; - - return ~0; -} - -/* return 0 if there is no received data in the buffer. - * return length of received packet if successful. - */ -int read_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data) -{ - if (recvqueue(ludp, connection_id) == 0) - return 0; - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - if (connection->status == LUDP_NO_CONNECTION) - return 0; - - uint16_t index = connection->successful_read % connection->recvbuffer_length; - uint16_t size = connection->recvbuffer[index].size; - memcpy(data, connection->recvbuffer[index].data, size); - ++connection->successful_read; - connection->recvbuffer[index].size = 0; - return size; -} - -/* Like read_packet() but does leaves the queue as is. - * return 0 if there is no received data in the buffer. - * return length of received packet if successful. - */ -int read_packet_silent(Lossless_UDP *ludp, int connection_id, uint8_t *data) -{ - if (recvqueue(ludp, connection_id) == 0) - return 0; - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - if (connection->status == LUDP_NO_CONNECTION) - return 0; - - uint16_t index = connection->successful_read % connection->recvbuffer_length; - uint16_t size = connection->recvbuffer[index].size; - memcpy(data, connection->recvbuffer[index].data, size); - return size; -} -/* Discard the next packet to be read from the queue - * return 0 if success. - * return -1 if failure. - */ -int discard_packet(Lossless_UDP *ludp, int connection_id) -{ - if (recvqueue(ludp, connection_id) == 0) - return -1; - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - uint16_t index = connection->successful_read % connection->recvbuffer_length; - ++connection->successful_read; - connection->recvbuffer[index].size = 0; - return 0; -} - -#define MAX_SYNC_RATE 20 -#define MIN_SLOTS 16 -/* returns the number of packet slots left in the sendbuffer. - * return 0 if failure. - */ -uint32_t num_free_sendqueue_slots(Lossless_UDP *ludp, int connection_id) -{ - if ((unsigned int)connection_id >= ludp->connections.len) - return 0; - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - uint32_t max_slots = (connection->data_rate / MAX_SYNC_RATE) * 1.5; - - if (max_slots > MAX_QUEUE_NUM) - max_slots = MAX_QUEUE_NUM; - - if (max_slots < MIN_SLOTS) - max_slots = MIN_SLOTS; - - if (sendqueue(ludp, connection_id) > max_slots) - return 0; - - return max_slots - sendqueue(ludp, connection_id); -} - - -/* return 0 if data could not be put in packet queue. - * return 1 if data was put into the queue. - */ -int write_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data, uint32_t length) -{ - if ((unsigned int)connection_id >= ludp->connections.len) - return 0; - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - if (connection->status == LUDP_NO_CONNECTION) - return 0; - - if (length > MAX_DATA_SIZE || length == 0 || sendqueue(ludp, connection_id) >= MAX_QUEUE_NUM) - return 0; - - if (num_free_sendqueue_slots(ludp, connection_id) == 0) - return 0; - - if (sendqueue(ludp, connection_id) >= connection->sendbuffer_length && connection->sendbuffer_length != 0) { - uint32_t newlen = connection->sendbuffer_length = resize_queue(&connection->sendbuffer, connection->sendbuffer_length, - connection->sendbuffer_length * 2, connection->successful_sent, connection->sendbuff_packetnum); - - if (newlen == (uint32_t)~0) - return 0; - - connection->sendbuffer_length = newlen; - return write_packet(ludp, connection_id, data, length); - } - - uint32_t index = connection->sendbuff_packetnum % connection->sendbuffer_length; - memcpy(connection->sendbuffer[index].data, data, length); - connection->sendbuffer[index].size = length; - connection->sendbuff_packetnum++; - return 1; -} - -/* Put the packet numbers the we are missing in requested and return the number. */ -static uint32_t missing_packets(Lossless_UDP *ludp, int connection_id, uint32_t *requested) -{ - if ((unsigned int)connection_id >= ludp->connections.len) - return 0; - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - /* Don't request packets if the buffer is full. */ - if (recvqueue(ludp, connection_id) >= (connection->recvbuffer_length - 1)) - return 0; - - uint32_t number = 0; - uint32_t i; - uint32_t temp; - - for (i = connection->recv_packetnum; - i != connection->osent_packetnum; - i++) { - if (connection->recvbuffer[i % connection->recvbuffer_length].size == 0) { - temp = htonl(i); - memcpy(requested + number, &temp, 4); - ++number; - } - - if (number >= MAX_REQUESTED_PACKETS) - return number; - } - - if (number == 0) - connection->recv_packetnum = connection->osent_packetnum; - - return number; -} - -/* - * BEGIN Packet sending functions. - * One per packet type. - * See http://wiki.tox.im/index.php/Lossless_UDP for more information. - */ - -static int send_handshake(Lossless_UDP *ludp, IP_Port ip_port, uint32_t handshake_id1, uint32_t handshake_id2) -{ - uint8_t packet[1 + 4 + 4]; - uint32_t temp; - - packet[0] = NET_PACKET_HANDSHAKE; - temp = htonl(handshake_id1); - memcpy(packet + 1, &temp, 4); - temp = htonl(handshake_id2); - memcpy(packet + 5, &temp, 4); - - return sendpacket(ludp->net, ip_port, packet, sizeof(packet)); -} - -static int send_SYNC(Lossless_UDP *ludp, int connection_id) -{ - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - uint8_t packet[(MAX_REQUESTED_PACKETS * 4 + 4 + 4 + 2)]; - uint16_t index = 0; - - IP_Port ip_port = connection->ip_port; - uint8_t counter = connection->send_counter; - uint32_t recv_packetnum = htonl(connection->recv_packetnum); - uint32_t sent_packetnum = htonl(connection->sent_packetnum); - - uint32_t requested[MAX_REQUESTED_PACKETS]; - uint32_t number = missing_packets(ludp, connection_id, requested); - - packet[0] = NET_PACKET_SYNC; - index += 1; - memcpy(packet + index, &counter, 1); - index += 1; - memcpy(packet + index, &recv_packetnum, 4); - index += 4; - memcpy(packet + index, &sent_packetnum, 4); - index += 4; - memcpy(packet + index, requested, 4 * number); - - return sendpacket(ludp->net, ip_port, packet, (number * 4 + 4 + 4 + 2)); - -} - -static int send_data_packet(Lossless_UDP *ludp, int connection_id, uint32_t packet_num) -{ - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - uint32_t index = packet_num % connection->sendbuffer_length; - uint32_t temp; - uint8_t packet[1 + 4 + MAX_DATA_SIZE]; - packet[0] = NET_PACKET_DATA; - temp = htonl(packet_num); - memcpy(packet + 1, &temp, 4); - memcpy(packet + 5, connection->sendbuffer[index].data, connection->sendbuffer[index].size); - return sendpacket(ludp->net, connection->ip_port, packet, 1 + 4 + connection->sendbuffer[index].size); -} - -/* Sends 1 data packet. */ -static int send_DATA(Lossless_UDP *ludp, int connection_id) -{ - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - int ret; - uint32_t buffer[MAX_REQUESTED_PACKETS]; - - if (connection->num_req_paquets > 0) { - ret = send_data_packet(ludp, connection_id, connection->req_packets[0]); - connection->num_req_paquets--; - memcpy(buffer, connection->req_packets + 1, connection->num_req_paquets * 4); - memcpy(connection->req_packets, buffer, connection->num_req_paquets * 4); - return ret; - } - - if (connection->sendbuff_packetnum != connection->sent_packetnum) { - ret = send_data_packet(ludp, connection_id, connection->sent_packetnum); - connection->sent_packetnum++; - return ret; - } - - return 0; -} - -/* - * END of packet sending functions. - * - * - * BEGIN Packet handling functions. - * One to handle each type of packets we receive. - */ - - -/* return 0 if handled correctly. - * return 1 if packet is bad. - */ -static int handle_handshake(void *object, IP_Port source, uint8_t *packet, uint32_t length) -{ - Lossless_UDP *ludp = object; - - if (length != (1 + 4 + 4)) - return 1; - - uint32_t temp; - uint32_t handshake_id1, handshake_id2; - int connection_id = getconnection_id(ludp, source); - - memcpy(&temp, packet + 1, 4); - handshake_id1 = ntohl(temp); - memcpy(&temp, packet + 5, 4); - handshake_id2 = ntohl(temp); - - - if (handshake_id2 == 0 && is_connected(ludp, connection_id) != LUDP_ESTABLISHED && - is_connected(ludp, connection_id) != LUDP_TIMED_OUT) { - send_handshake(ludp, source, handshake_id(ludp, source), handshake_id1); - return 0; - } - - if (is_connected(ludp, connection_id) != LUDP_HANDSHAKE_SENDING) - return 1; - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - /* if handshake_id2 is what we sent previously as handshake_id1 */ - if (handshake_id2 == connection->handshake_id1) { - connection->status = LUDP_NOT_CONFIRMED; - /* NOTE: Is this necessary? - connection->handshake_id2 = handshake_id1; */ - connection->orecv_packetnum = handshake_id2; - connection->osent_packetnum = handshake_id1; - connection->recv_packetnum = handshake_id1; - connection->successful_read = handshake_id1; - } - - return 0; -} - -/* return 1 if sync packet is valid. - * return 0 if not. - */ -static int SYNC_valid(uint32_t length) -{ - if (length < 4 + 4 + 2) - return 0; - - if (length > (MAX_REQUESTED_PACKETS * 4 + 4 + 4 + 2) || - ((length - 4 - 4 - 2) % 4) != 0) - return 0; - - return 1; -} - -/* case 1 in handle_SYNC: */ -static int handle_SYNC1(Lossless_UDP *ludp, IP_Port source, uint32_t recv_packetnum, uint32_t sent_packetnum) -{ - if (handshake_id(ludp, source) == recv_packetnum) { - int connection_id = new_inconnection(ludp, source); - - if (connection_id != -1) { - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - connection->orecv_packetnum = recv_packetnum; - connection->sent_packetnum = recv_packetnum; - connection->sendbuff_packetnum = recv_packetnum; - connection->successful_sent = recv_packetnum; - connection->osent_packetnum = sent_packetnum; - connection->recv_packetnum = sent_packetnum; - connection->successful_read = sent_packetnum; - - return connection_id; - } - } - - return -1; -} - -/* case 2 in handle_SYNC: */ -static int handle_SYNC2(Lossless_UDP *ludp, int connection_id, uint8_t counter, uint32_t recv_packetnum, - uint32_t sent_packetnum) -{ - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - if (recv_packetnum == connection->orecv_packetnum && sent_packetnum == connection->osent_packetnum) { - connection->status = LUDP_ESTABLISHED; - connection->recv_counter = counter; - ++connection->send_counter; - send_SYNC(ludp, connection_id); - return 0; - } - - return 1; -} - -/* - * Automatically adjusts send rates of data packets for optimal transmission. - * - * TODO: Improve this. - */ -static void adjust_datasendspeed(Connection *connection, uint32_t req_packets) -{ - /* if there are no packets in send buffer */ - if (connection->sendbuff_packetnum - connection->successful_sent == 0) { - connection->data_rate -= connection->data_rate / 8; - - if (connection->data_rate < DATA_SYNC_RATE) - connection->data_rate = DATA_SYNC_RATE; - - return; - } - - if (req_packets <= (connection->data_rate / connection->SYNC_rate) / 4 || req_packets <= 10) { - connection->data_rate += (connection->data_rate / 4) + 1; - - if (connection->data_rate > connection->sendbuffer_length * connection->SYNC_rate) - connection->data_rate = connection->sendbuffer_length * connection->SYNC_rate; - } else { - connection->data_rate -= connection->data_rate / 8; - } -} - - -/* case 3 in handle_SYNC: */ -static int handle_SYNC3(Lossless_UDP *ludp, int connection_id, uint8_t counter, uint32_t recv_packetnum, - uint32_t sent_packetnum, - uint32_t *req_packets, - uint16_t number) -{ - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - uint8_t comp_counter = (counter - connection->recv_counter); - uint32_t i, temp; - /* uint32_t comp_1 = (recv_packetnum - connection->successful_sent); - uint32_t comp_2 = (sent_packetnum - connection->successful_read); */ - uint32_t comp_1 = (recv_packetnum - connection->orecv_packetnum); - uint32_t comp_2 = (sent_packetnum - connection->osent_packetnum); - - /* Packet valid. */ - if (comp_1 <= connection->sendbuffer_length && - comp_2 <= MAX_QUEUE_NUM && - comp_counter != 0 && comp_counter < 8) { - connection->orecv_packetnum = recv_packetnum; - connection->osent_packetnum = sent_packetnum; - connection->successful_sent = recv_packetnum; - connection->last_recvSYNC = current_time(); - - connection->recv_counter = counter; - - ++connection->send_counter; - - for (i = 0; i < number; ++i) { - temp = ntohl(req_packets[i]); - memcpy(connection->req_packets + i, &temp, sizeof(uint32_t)); - } - - connection->num_req_paquets = number; - adjust_datasendspeed(connection, number); - return 0; - } - - return 1; -} - -static int handle_SYNC(void *object, IP_Port source, uint8_t *packet, uint32_t length) -{ - Lossless_UDP *ludp = object; - - if (!SYNC_valid(length)) - return 1; - - uint8_t counter; - uint32_t temp; - uint32_t recv_packetnum, sent_packetnum; - uint16_t number = (length - 4 - 4 - 2) / 4; - uint32_t req_packets[number]; - - memcpy(&counter, packet + 1, 1); - memcpy(&temp, packet + 2, 4); - recv_packetnum = ntohl(temp); - memcpy(&temp, packet + 6, 4); - sent_packetnum = ntohl(temp); - - if (number != 0) - memcpy(req_packets, packet + 10, 4 * number); - - int connection_id = getconnection_id(ludp, source); - - if (connection_id == -1) - return handle_SYNC1(ludp, source, recv_packetnum, sent_packetnum); - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - if (connection->status == LUDP_NOT_CONFIRMED) - return handle_SYNC2(ludp, connection_id, counter, - recv_packetnum, sent_packetnum); - - if (connection->status == LUDP_ESTABLISHED) - return handle_SYNC3(ludp, connection_id, counter, recv_packetnum, - sent_packetnum, req_packets, number); - - return 0; -} - -/* - * Add a packet to the received buffer and set the recv_packetnum of the - * connection to its proper value. - * - * return 1 if data was too big. - * return 0 if not. - */ -static int add_recv(Lossless_UDP *ludp, int connection_id, uint32_t data_num, uint8_t *data, uint16_t size) -{ - if (size > MAX_DATA_SIZE) - return 1; - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - uint32_t i; - uint32_t test = data_num - connection->recv_packetnum; - - if (test > MAX_QUEUE_NUM) - return 0; - - if (test > connection->recvbuffer_length) { - if (connection->confirmed == 0) - return 0; - - uint32_t len = resize_queue(&connection->recvbuffer, connection->recvbuffer_length, test * 2, - connection->successful_read, connection->successful_read + connection->recvbuffer_length); - - if (len == (uint32_t)~0) - return 0; - - connection->recvbuffer_length = len; - } - - uint32_t maxnum = connection->successful_read + connection->recvbuffer_length; - uint32_t sent_packet = data_num - connection->osent_packetnum; - - for (i = connection->recv_packetnum; i != maxnum; ++i) { - if (i == data_num) { - memcpy(connection->recvbuffer[data_num % connection->recvbuffer_length].data, data, size); - - connection->recvbuffer[data_num % connection->recvbuffer_length].size = size; - connection->last_recvdata = current_time(); - - if (sent_packet < connection->recvbuffer_length) - connection->osent_packetnum = data_num; - - break; - } - } - - for (i = connection->recv_packetnum; i != maxnum; ++i) { - if (connection->recvbuffer[i % connection->recvbuffer_length].size != 0) - connection->recv_packetnum = i; - else - break; - } - - return 0; -} - -static int handle_data(void *object, IP_Port source, uint8_t *packet, uint32_t length) -{ - Lossless_UDP *ludp = object; - int connection_id = getconnection_id(ludp, source); - - /* Drop the data packet if connection is not connected. */ - if (connection_id == -1) - return 1; - - if (tox_array_get(&ludp->connections, connection_id, Connection).status != LUDP_ESTABLISHED) - return 1; - - if (length > 1 + 4 + MAX_DATA_SIZE || length < 1 + 4 + 1) - return 1; - - uint32_t temp; - uint32_t number; - uint16_t size = length - 1 - 4; - - memcpy(&temp, packet + 1, 4); - number = ntohl(temp); - - return add_recv(ludp, connection_id, number, packet + 5, size); -} - -/* - * END of packet handling functions. - */ - -Lossless_UDP *new_lossless_udp(Networking_Core *net) -{ - if (net == NULL) - return NULL; - - Lossless_UDP *temp = calloc(1, sizeof(Lossless_UDP)); - - if (temp == NULL) - return NULL; - - tox_array_init(&temp->connections, sizeof(Connection)); - - temp->net = net; - networking_registerhandler(net, NET_PACKET_HANDSHAKE, &handle_handshake, temp); - networking_registerhandler(net, NET_PACKET_SYNC, &handle_SYNC, temp); - networking_registerhandler(net, NET_PACKET_DATA, &handle_data, temp); - return temp; -} - -/* - * Send handshake requests. - * Handshake packets are sent at the same rate as SYNC packets. - */ -static void do_new(Lossless_UDP *ludp) -{ - uint64_t temp_time = current_time(); - - tox_array_for_each(&ludp->connections, Connection, tmp) { - if (tmp->status == LUDP_HANDSHAKE_SENDING && (tmp->last_sent + (1000000ULL / tmp->SYNC_rate)) <= temp_time) { - send_handshake(ludp, tmp->ip_port, tmp->handshake_id1, 0); - tmp->last_sent = temp_time; - } - - /* kill all timed out connections */ - if (tmp->status != LUDP_NO_CONNECTION && (tmp->last_recvSYNC + tmp->timeout * 1000000ULL) < temp_time - && tmp->status != LUDP_TIMED_OUT) { - tmp->status = LUDP_TIMED_OUT; - /* kill_connection(i); */ - } - - if (tmp->status != LUDP_NO_CONNECTION && tmp->killat < temp_time) - tmp->status = LUDP_TIMED_OUT; - - if (tmp->inbound == LUDP_CONNECTION_INBOUND && tmp->status == LUDP_TIMED_OUT) - kill_connection(ludp, tmp_i); - } -} - -static void do_SYNC(Lossless_UDP *ludp) -{ - uint64_t temp_time = current_time(); - - tox_array_for_each(&ludp->connections, Connection, tmp) { - if (tmp->status == LUDP_NOT_CONFIRMED || tmp->status == LUDP_ESTABLISHED) - if ((tmp->last_SYNC + (1000000ULL / tmp->SYNC_rate)) <= temp_time) { - send_SYNC(ludp, tmp_i); - tmp->last_SYNC = temp_time; - } - } -} - -static void do_data(Lossless_UDP *ludp) -{ - uint64_t j; - uint64_t temp_time = current_time(); - - tox_array_for_each(&ludp->connections, Connection, tmp) { - if (tmp->status == LUDP_ESTABLISHED && sendqueue(ludp, tmp_i) != 0 && - (tmp->last_sent + (1000000ULL / tmp->data_rate)) <= temp_time) { - for (j = tmp->last_sent; j < temp_time; j += (1000000ULL / tmp->data_rate)) - if (send_DATA(ludp, tmp_i) <= 0) - break; - - tmp->last_sent = temp_time; - - } - } -} - - - -/* - * Automatically adjusts send rates of packets for optimal transmission. - * - * TODO: Flow control. - */ -static void adjust_rates(Lossless_UDP *ludp) -{ - uint64_t temp_time = current_time(); - - tox_array_for_each(&ludp->connections, Connection, tmp) { - if (tmp->status == LUDP_HANDSHAKE_SENDING || tmp->status == LUDP_NOT_CONFIRMED) - tmp->SYNC_rate = MAX_SYNC_RATE; - - if (tmp->status == LUDP_ESTABLISHED) { - if (sendqueue(ludp, tmp_i) != 0) { - tmp->SYNC_rate = MAX_SYNC_RATE; - } else if (tmp->last_recvdata + 200000ULL > temp_time) { /* 200 ms */ - tmp->SYNC_rate = MAX_SYNC_RATE; - } else { - tmp->SYNC_rate = SYNC_RATE; - } - } - } -} - -/* Call this function a couple times per second. It is the main loop. */ -void do_lossless_udp(Lossless_UDP *ludp) -{ - do_new(ludp); - do_SYNC(ludp); - do_data(ludp); - adjust_rates(ludp); -} - -void kill_lossless_udp(Lossless_UDP *ludp) -{ - uint32_t i; - - for (i = 0; i < ludp->connections.len; ++i) - kill_connection(ludp, i); - - tox_array_delete(&ludp->connections); - free(ludp); -} diff --git a/toxcore/Lossless_UDP.h b/toxcore/Lossless_UDP.h deleted file mode 100644 index 587cd9ff..00000000 --- a/toxcore/Lossless_UDP.h +++ /dev/null @@ -1,262 +0,0 @@ -/* Lossless_UDP.h - * - * An implementation of the Lossless_UDP protocol as seen in http://wiki.tox.im/index.php/Lossless_UDP - * - * Copyright (C) 2013 Tox project All Rights Reserved. - * - * This file is part of Tox. - * - * Tox is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Tox is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Tox. If not, see . - * - */ - -#ifndef LOSSLESS_UDP_H -#define LOSSLESS_UDP_H - -#include "network.h" -#include "crypto_core.h" -#include "misc_tools.h" - - -/* Maximum length of the data in the data packets. */ -#define MAX_DATA_SIZE 1024 - -/* Maximum data packets in sent and receive queues. */ -#define MAX_QUEUE_NUM 1024 -#define DEFAULT_QUEUE_NUM 4 - -/* Maximum number of data packets in the buffer. */ -#define MAX_REQUESTED_PACKETS 256 - -/* Timeout per connection is randomly set between CONNECTION_TIMEOUT and 2*CONNECTION_TIMEOUT. */ -#define CONNECTION_TIMEOUT 5 - -/* Initial amount of sync/handshake packets to send per second. */ -#define SYNC_RATE 2 - -/* Initial send rate of data. */ -#define DATA_SYNC_RATE 30 - -typedef struct { - uint8_t data[MAX_DATA_SIZE]; - uint16_t size; -} Data; - -#define LUDP_NO_CONNECTION 0 -#define LUDP_HANDSHAKE_SENDING 1 -#define LUDP_NOT_CONFIRMED 2 -#define LUDP_ESTABLISHED 3 -#define LUDP_TIMED_OUT 4 - -typedef struct { - IP_Port ip_port; - - /* - * return LUDP_NO_CONNECTION if connection is dead. - * return LUDP_HANDSHAKE_SENDING if attempting handshake. - * return LUDP_NOT_CONFIRMED if handshake is done (we start sending SYNC packets). - * return LUDP_ESTABLISHED if we are sending SYNC packets and can send data. - * return LUDP_TIMED_OUT if the connection has timed out. - */ - uint8_t status; - - /* - * return 0 if connection was not initiated by someone else. - * return 1 if incoming_connection() has returned. - * return 2 if it has not. - */ - uint8_t inbound; - - uint16_t SYNC_rate; /* Current SYNC packet send rate packets per second. */ - uint32_t data_rate; /* Current data packet send rate packets per second. */ - - uint64_t last_SYNC; /* Time our last SYNC packet was sent. */ - uint64_t last_sent; /* Time our last data or handshake packet was sent. */ - uint64_t last_recvSYNC; /* Time we last received a SYNC packet from the other. */ - uint64_t last_recvdata; /* Time we last received a DATA packet from the other. */ - uint64_t killat; /* Time to kill the connection. */ - - Data *sendbuffer; /* packet send buffer. */ - uint32_t sendbuffer_length; - Data *recvbuffer; /* packet receive buffer. */ - uint32_t recvbuffer_length; - uint32_t handshake_id1; - uint32_t handshake_id2; - - /* Number of data packets received (also used as handshake_id1). */ - uint32_t recv_packetnum; - - /* Number of packets received by the other peer. */ - uint32_t orecv_packetnum; - - /* Number of data packets sent. */ - uint32_t sent_packetnum; - - /* Number of packets sent by the other peer. */ - uint32_t osent_packetnum; - - /* Number of latest packet written onto the sendbuffer. */ - uint32_t sendbuff_packetnum; - - /* We know all packets before that number were successfully sent. */ - uint32_t successful_sent; - - /* Packet number of last packet read with the read_packet function. */ - uint32_t successful_read; - - /* List of currently requested packet numbers(by the other person). */ - uint32_t req_packets[MAX_REQUESTED_PACKETS]; - - /* Total number of currently requested packets(by the other person). */ - uint16_t num_req_paquets; - - uint8_t recv_counter; - uint8_t send_counter; - uint8_t timeout; /* connection timeout in seconds. */ - - /* Is the connection confirmed or not? 1 if yes, 0 if no */ - uint8_t confirmed; -} Connection; - -typedef struct { - Networking_Core *net; - - tox_array connections; - - /* Table of random numbers used in handshake_id. */ - /* IPv6 (16) + port (2)*/ - uint32_t randtable[18][256]; -} Lossless_UDP; - -/* - * Initialize a new connection to ip_port. - * - * return an integer corresponding to the connection id. - * return -1 if it could not initialize the connection. - * return number if there already was an existing connection to that ip_port. - */ -int new_connection(Lossless_UDP *ludp, IP_Port ip_port); - -/* - * Get connection id from IP_Port. - * - * return -1 if there are no connections like we are looking for. - * return id if it found it . - */ -int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port); - -/* - * return an integer corresponding to the next connection in our incoming connection list with at least numpackets in the recieve queue. - * return -1 if there are no new incoming connections in the list. - */ -int incoming_connection(Lossless_UDP *ludp, uint32_t numpackets); - -/* return -1 if it could not kill the connection. - * return 0 if killed successfully. - */ -int kill_connection(Lossless_UDP *ludp, int connection_id); - -/* - * timeout connection in seconds seconds. - * - * return -1 if it can not kill the connection. - * return 0 if it will kill it. - */ -int timeout_connection_in(Lossless_UDP *ludp, int connection_id, uint32_t seconds); - - -/* Check if connection is confirmed. - * - * returns 1 if yes. - * returns 0 if no. - */ -int connection_confirmed(Lossless_UDP *ludp, int connection_id); - -/* Confirm an incoming connection. - * Also disables the auto kill timeout on incomming connections. - * - * return 0 on success - * return -1 on failure. - */ -int confirm_connection(Lossless_UDP *ludp, int connection_id); - -/* returns the ip_port of the corresponding connection. - * return 0 if there is no such connection. - */ -IP_Port connection_ip(Lossless_UDP *ludp, int connection_id); - -/* returns the id of the next packet in the queue. - * return -1 if no packet in queue. - */ -uint8_t id_packet(Lossless_UDP *ludp, int connection_id); - -/* return 0 if there is no received data in the buffer. - * return length of received packet if successful. - */ -int read_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data); - -/* Like read_packet() but does leaves the queue as is. - * return 0 if there is no received data in the buffer. - * return length of received packet if successful. - */ -int read_packet_silent(Lossless_UDP *ludp, int connection_id, uint8_t *data); - -/* Discard the next packet to be read from the queue - * return 0 if success. - * return -1 if failure. - */ -int discard_packet(Lossless_UDP *ludp, int connection_id); - -/* returns the number of packet slots left in the sendbuffer. - * return 0 if failure. - */ -uint32_t num_free_sendqueue_slots(Lossless_UDP *ludp, int connection_id); - -/* return 0 if data could not be put in packet queue. - * return 1 if data was put into the queue. - */ -int write_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data, uint32_t length); - -/* return number of packets in the queue waiting to be successfully sent. */ -uint32_t sendqueue(Lossless_UDP *ludp, int connection_id); - -/* return number of packets in all queues waiting to be successfully sent. */ -uint32_t sendqueue_total(Lossless_UDP *ludp); - -/* - * return number of packets in the queue waiting to be successfully - * read with read_packet(...). - */ -uint32_t recvqueue(Lossless_UDP *ludp, int connection_id); - -/* Check if connection is connected: - * - * return LUDP_NO_CONNECTION if not. - * return LUDP_HANDSHAKE_SENDING if attempting handshake. - * return LUDP_NOT_CONFIRMED if handshake is done. - * return LUDP_ESTABLISHED if fully connected. - * return LUDP_TIMED_OUT if timed out and wating to be killed. - */ -int is_connected(Lossless_UDP *ludp, int connection_id); - -/* Call this function a couple times per second. It is the main loop. */ -void do_lossless_udp(Lossless_UDP *ludp); - -/* This function sets up LosslessUDP packet handling. */ -Lossless_UDP *new_lossless_udp(Networking_Core *net); - -void kill_lossless_udp(Lossless_UDP *ludp); - - -#endif diff --git a/toxcore/Makefile.inc b/toxcore/Makefile.inc index 7723aeaf..926b4e3f 100644 --- a/toxcore/Makefile.inc +++ b/toxcore/Makefile.inc @@ -11,8 +11,6 @@ libtoxcore_la_SOURCES = ../toxcore/DHT.h \ ../toxcore/network.c \ ../toxcore/crypto_core.h \ ../toxcore/crypto_core.c \ - ../toxcore/Lossless_UDP.h \ - ../toxcore/Lossless_UDP.c \ ../toxcore/net_crypto.h \ ../toxcore/net_crypto.c \ ../toxcore/friend_requests.h \ diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 308cf14e..1a5c93aa 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -406,10 +406,10 @@ uint32_t m_sendmessage(Messenger *m, int32_t friendnumber, uint8_t *message, uin uint32_t m_sendmessage_withid(Messenger *m, int32_t friendnumber, uint32_t theid, uint8_t *message, uint32_t length) { - if (length >= (MAX_DATA_SIZE - sizeof(theid))) + if (length >= (MAX_CRYPTO_DATA_SIZE - sizeof(theid))) return 0; - uint8_t temp[MAX_DATA_SIZE]; + uint8_t temp[MAX_CRYPTO_DATA_SIZE]; theid = htonl(theid); memcpy(temp, &theid, sizeof(theid)); memcpy(temp + sizeof(theid), message, length); @@ -440,10 +440,10 @@ uint32_t m_sendaction(Messenger *m, int32_t friendnumber, uint8_t *action, uint3 uint32_t m_sendaction_withid(Messenger *m, int32_t friendnumber, uint32_t theid, uint8_t *action, uint32_t length) { - if (length >= (MAX_DATA_SIZE - sizeof(theid))) + if (length >= (MAX_CRYPTO_DATA_SIZE - sizeof(theid))) return 0; - uint8_t temp[MAX_DATA_SIZE]; + uint8_t temp[MAX_CRYPTO_DATA_SIZE]; theid = htonl(theid); memcpy(temp, &theid, sizeof(theid)); memcpy(temp + sizeof(theid), action, length); @@ -840,7 +840,7 @@ int write_cryptpacket_id(Messenger *m, int32_t friendnumber, uint8_t packet_id, if (friend_not_valid(m, friendnumber)) return 0; - if (length >= MAX_DATA_SIZE || m->friendlist[friendnumber].status != FRIEND_ONLINE) + if (length >= MAX_CRYPTO_DATA_SIZE || m->friendlist[friendnumber].status != FRIEND_ONLINE) return 0; uint8_t packet[length + 1]; @@ -888,7 +888,7 @@ static IP_Port get_friend_ipport(Messenger *m, int32_t friendnumber) if (is_cryptoconnected(m->net_crypto, crypt_id) != CRYPTO_CONN_ESTABLISHED) return zero; - return connection_ip(m->net_crypto->lossless_udp, m->net_crypto->crypto_connections[crypt_id].number); + return m->net_crypto->crypto_connections[crypt_id].ip_port; } /* returns the group number of the chat with public key group_public_key. @@ -1395,7 +1395,7 @@ int new_filesender(Messenger *m, int32_t friendnumber, uint64_t filesize, uint8_ int file_control(Messenger *m, int32_t friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t message_id, uint8_t *data, uint16_t length) { - if (length > MAX_DATA_SIZE - 3) + if (length > MAX_CRYPTO_DATA_SIZE - 3) return -1; if (friend_not_valid(m, friendnumber)) @@ -1412,7 +1412,7 @@ int file_control(Messenger *m, int32_t friendnumber, uint8_t send_receive, uint8 if (send_receive > 1) return -1; - uint8_t packet[MAX_DATA_SIZE]; + uint8_t packet[MAX_CRYPTO_DATA_SIZE]; packet[0] = send_receive; packet[1] = filenumber; packet[2] = message_id; @@ -1482,7 +1482,7 @@ int file_control(Messenger *m, int32_t friendnumber, uint8_t send_receive, uint8 */ int file_data(Messenger *m, int32_t friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length) { - if (length > MAX_DATA_SIZE - 1) + if (length > MAX_CRYPTO_DATA_SIZE - 1) return -1; if (friend_not_valid(m, friendnumber)) @@ -1495,7 +1495,7 @@ int file_data(Messenger *m, int32_t friendnumber, uint8_t filenumber, uint8_t *d if (crypto_num_free_sendqueue_slots(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id) < MIN_SLOTS_FREE) return -1; - uint8_t packet[MAX_DATA_SIZE]; + uint8_t packet[MAX_CRYPTO_DATA_SIZE]; packet[0] = filenumber; memcpy(packet + 1, data, length); @@ -1738,6 +1738,23 @@ static void LANdiscovery(Messenger *m) } } +int handle_new_connections(void *object, New_Connection *n_c) +{ + Messenger *m = object; + int friend_id = getfriend_id(m, n_c->public_key); + + if (friend_id != -1) { + if (m->friendlist[friend_id].crypt_connection_id != -1) + return -1; + + m->friendlist[friend_id].crypt_connection_id = accept_crypto_connection(m->net_crypto, n_c); + set_friend_status(m, friend_id, FRIEND_CONFIRMED); + } + + return -1; +} + + /* Run this at startup. */ Messenger *new_messenger(uint8_t ipv6enabled) { @@ -1772,6 +1789,8 @@ Messenger *new_messenger(uint8_t ipv6enabled) return NULL; } + new_connection_handler(m->net_crypto, &handle_new_connections, m); + m->onion = new_onion(m->dht); m->onion_a = new_onion_announce(m->dht); m->onion_c = new_onion_client(m->net_crypto); @@ -1843,7 +1862,7 @@ void do_friends(Messenger *m) { uint32_t i; int len; - uint8_t temp[MAX_DATA_SIZE]; + uint8_t temp[MAX_CRYPTO_DATA_SIZE]; uint64_t temp_time = unix_time(); for (i = 0; i < m->numfriends; ++i) { @@ -2184,32 +2203,8 @@ void do_friends(Messenger *m) } } -void do_inbound(Messenger *m) -{ - uint8_t secret_nonce[crypto_box_NONCEBYTES]; - uint8_t public_key[crypto_box_PUBLICKEYBYTES]; - uint8_t session_key[crypto_box_PUBLICKEYBYTES]; - int inconnection = crypto_inbound(m->net_crypto, public_key, secret_nonce, session_key); - - if (inconnection != -1) { - int friend_id = getfriend_id(m, public_key); - - if (friend_id != -1) { - if (m_get_friend_connectionstatus(m, friend_id) == 1) { - kill_connection(m->net_crypto->lossless_udp, inconnection); - return; - } - crypto_kill(m->net_crypto, m->friendlist[friend_id].crypt_connection_id); - m->friendlist[friend_id].crypt_connection_id = - accept_crypto_inbound(m->net_crypto, inconnection, public_key, secret_nonce, session_key); - set_friend_status(m, friend_id, FRIEND_CONFIRMED); - } else { - kill_connection(m->net_crypto->lossless_udp, inconnection); - } - } -} #ifdef LOGGING #define DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS 60UL @@ -2238,7 +2233,6 @@ void do_messenger(Messenger *m) do_net_crypto(m->net_crypto); do_onion_client(m->onion_c); do_friends(m); - do_inbound(m); do_allgroupchats(m); LANdiscovery(m); @@ -2381,7 +2375,9 @@ size_t wait_data_size() int wait_prepare_messenger(Messenger *m, uint8_t *data) { - return networking_wait_prepare(m->net, sendqueue_total(m->net_crypto->lossless_udp), data); + //TODO + //return networking_wait_prepare(m->net, sendqueue_total(m->net_crypto->lossless_udp), data); + return networking_wait_prepare(m->net, 1024, data); } int wait_execute_messenger(uint8_t *data, long seconds, long microseconds) diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 3d42e911..66ef39e5 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -34,6 +34,7 @@ #include "onion_client.h" #define MAX_NAME_LENGTH 128 +/* TODO: this must depend on other variable. */ #define MAX_STATUSMESSAGE_LENGTH 1007 #define FRIEND_ADDRESS_SIZE (crypto_box_PUBLICKEYBYTES + sizeof(uint32_t) + sizeof(uint16_t)) diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index ad41ce78..6dbb6258 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -705,7 +705,7 @@ static int crypto_connection_add_source(Net_Crypto *c, int crypt_connection_id, * * The set function should return -1 on failure and 0 on success. * - * n_c is only valid for the duration of this function. + * n_c is only valid for the duration of the function call. */ void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void *object, New_Connection *n_c), void *object) @@ -968,31 +968,7 @@ static void send_crypto_packets(Net_Crypto *c) */ int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data) { - if (crypt_connection_id_not_valid(c, crypt_connection_id)) - return 0; - - if (c->crypto_connections[crypt_connection_id].status != CRYPTO_CONN_ESTABLISHED) - return 0; - - uint8_t temp_data[MAX_DATA_SIZE]; - int length = read_packet(c->lossless_udp, c->crypto_connections[crypt_connection_id].number, temp_data); - - if (length == 0) - return 0; - - if (temp_data[0] != 3) - return -1; - int len = decrypt_data_symmetric(c->crypto_connections[crypt_connection_id].shared_key, - c->crypto_connections[crypt_connection_id].recv_nonce, - temp_data + 1, length - 1, data); - - if (len != -1) { - increment_nonce(c->crypto_connections[crypt_connection_id].recv_nonce); - return len; - } - - return -1; } /* returns the number of packet slots left in the sendbuffer. @@ -1000,10 +976,7 @@ int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data) */ uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id) { - if (crypt_connection_id_not_valid(c, crypt_connection_id)) - return 0; - return num_free_sendqueue_slots(c->lossless_udp, c->crypto_connections[crypt_connection_id].number); } /* return 0 if data could not be put in packet queue. @@ -1011,93 +984,7 @@ uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id) */ int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length) { - if (crypt_connection_id_not_valid(c, crypt_connection_id)) - return 0; - - if (length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE - 1) - return 0; - - if (c->crypto_connections[crypt_connection_id].status != CRYPTO_CONN_ESTABLISHED) - return 0; - - uint8_t temp_data[MAX_DATA_SIZE]; - int len = encrypt_data_symmetric(c->crypto_connections[crypt_connection_id].shared_key, - c->crypto_connections[crypt_connection_id].sent_nonce, - data, length, temp_data + 1); - - if (len == -1) - return 0; - - temp_data[0] = 3; - - if (write_packet(c->lossless_udp, c->crypto_connections[crypt_connection_id].number, temp_data, len + 1) == 0) - return 0; - increment_nonce(c->crypto_connections[crypt_connection_id].sent_nonce); - return 1; -} - - -/* Send a crypto handshake packet containing an encrypted secret nonce and session public key - * to peer with connection_id and public_key. - * The packet is encrypted with a random nonce which is sent in plain text with the packet. - */ -static int send_cryptohandshake(Net_Crypto *c, int connection_id, uint8_t *public_key, uint8_t *secret_nonce, - uint8_t *session_key) -{ - uint8_t temp_data[MAX_DATA_SIZE]; - uint8_t temp[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES]; - uint8_t nonce[crypto_box_NONCEBYTES]; - - new_nonce(nonce); - memcpy(temp, secret_nonce, crypto_box_NONCEBYTES); - memcpy(temp + crypto_box_NONCEBYTES, session_key, crypto_box_PUBLICKEYBYTES); - - int len = encrypt_data(public_key, c->self_secret_key, nonce, temp, crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, - 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + temp_data); - - if (len == -1) - return 0; - - temp_data[0] = 2; - memcpy(temp_data + 1, c->self_public_key, crypto_box_PUBLICKEYBYTES); - memcpy(temp_data + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES); - return write_packet(c->lossless_udp, connection_id, temp_data, - len + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES); -} - -/* Extract secret nonce, session public key and public_key from a packet(data) with length length. - * - * return 1 if successful. - * return 0 if failure. - */ -static int handle_cryptohandshake(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, - uint8_t *session_key, uint8_t *data, uint16_t length) -{ - int pad = (- crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES); - - if (length != 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES - + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + pad) { - return 0; - } - - if (data[0] != 2) - return 0; - - uint8_t temp[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES]; - - memcpy(public_key, data + 1, crypto_box_PUBLICKEYBYTES); - - int len = decrypt_data(public_key, c->self_secret_key, data + 1 + crypto_box_PUBLICKEYBYTES, - data + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, - crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + pad, temp); - - if (len != crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES) - return 0; - - memcpy(secret_nonce, temp, crypto_box_NONCEBYTES); - memcpy(session_key, temp + crypto_box_NONCEBYTES, crypto_box_PUBLICKEYBYTES); - return 1; } @@ -1108,92 +995,7 @@ static int handle_cryptohandshake(Net_Crypto *c, uint8_t *public_key, uint8_t *s */ int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port) { - uint32_t i; - int id_existing = getcryptconnection_id(c, public_key); - - if (id_existing != -1) { - IP_Port c_ip = connection_ip(c->lossless_udp, c->crypto_connections[id_existing].number); - if (ipport_equal(&c_ip, &ip_port)) - return -1; - } - - if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == -1 - || c->crypto_connections == NULL) - return -1; - - memset(&(c->crypto_connections[c->crypto_connections_length]), 0, sizeof(Crypto_Connection)); - c->crypto_connections[c->crypto_connections_length].number = ~0; - - for (i = 0; i <= c->crypto_connections_length; ++i) { - if (c->crypto_connections[i].status == CRYPTO_CONN_NO_CONNECTION) { - int id_new = new_connection(c->lossless_udp, ip_port); - - if (id_new == -1) - return -1; - - c->crypto_connections[i].number = id_new; - c->crypto_connections[i].status = CRYPTO_CONN_HANDSHAKE_SENT; - random_nonce(c->crypto_connections[i].recv_nonce); - memcpy(c->crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); - crypto_box_keypair(c->crypto_connections[i].sessionpublic_key, c->crypto_connections[i].sessionsecret_key); - c->crypto_connections[i].timeout = unix_time() + CRYPTO_HANDSHAKE_TIMEOUT; - - if (c->crypto_connections_length == i) - ++c->crypto_connections_length; - - if (send_cryptohandshake(c, id_new, public_key, c->crypto_connections[i].recv_nonce, - c->crypto_connections[i].sessionpublic_key) == 1) { - increment_nonce(c->crypto_connections[i].recv_nonce); - return i; - } - - return -1; /* This should never happen. */ - } - } - - return -1; -} - -/* Handle an incoming connection. - * - * return -1 if no crypto inbound connection. - * return incoming connection id (Lossless_UDP one) if there is an incoming crypto connection. - * - * Put the public key of the peer in public_key, the secret_nonce from the handshake into secret_nonce - * and the session public key for the connection in session_key. - * to accept it see: accept_crypto_inbound(...). - * to refuse it just call kill_connection(...) on the connection id. - */ -int crypto_inbound(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key) -{ - while (1) { - int incoming_con = incoming_connection(c->lossless_udp, 1); - - if (incoming_con != -1) { - if (is_connected(c->lossless_udp, incoming_con) == LUDP_TIMED_OUT) { - kill_connection(c->lossless_udp, incoming_con); - continue; - } - - if (id_packet(c->lossless_udp, incoming_con) == 2) { - uint8_t temp_data[MAX_DATA_SIZE]; - uint16_t len = read_packet_silent(c->lossless_udp, incoming_con, temp_data); - - if (handle_cryptohandshake(c, public_key, secret_nonce, session_key, temp_data, len)) { - return incoming_con; - } else { - kill_connection(c->lossless_udp, incoming_con); - } - } else { - kill_connection(c->lossless_udp, incoming_con); - } - } else { - break; - } - } - - return -1; } /* Kill a crypto connection. @@ -1203,94 +1005,7 @@ int crypto_inbound(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, ui */ int crypto_kill(Net_Crypto *c, int crypt_connection_id) { - if (crypt_connection_id_not_valid(c, crypt_connection_id)) - return 1; - - if (c->crypto_connections[crypt_connection_id].status != CRYPTO_CONN_NO_CONNECTION) { - c->crypto_connections[crypt_connection_id].status = CRYPTO_CONN_NO_CONNECTION; - kill_connection(c->lossless_udp, c->crypto_connections[crypt_connection_id].number); - memset(&(c->crypto_connections[crypt_connection_id]), 0 , sizeof(Crypto_Connection)); - c->crypto_connections[crypt_connection_id].number = ~0; - uint32_t i; - - for (i = c->crypto_connections_length; i != 0; --i) { - if (c->crypto_connections[i - 1].status != CRYPTO_CONN_NO_CONNECTION) - break; - } - - if (c->crypto_connections_length != i) { - c->crypto_connections_length = i; - realloc_cryptoconnection(c, c->crypto_connections_length); - } - - return 0; - } - - return 1; -} - -/* Accept an incoming connection using the parameters provided by crypto_inbound. - * - * return -1 if not successful. - * return the crypt_connection_id if successful. - */ -int accept_crypto_inbound(Net_Crypto *c, int connection_id, uint8_t *public_key, uint8_t *secret_nonce, - uint8_t *session_key) -{ - uint32_t i; - - if (discard_packet(c->lossless_udp, connection_id) == -1) - return -1; - - /* - * if(getcryptconnection_id(public_key) != -1) - * { - * return -1; - * } - */ - - if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == -1 - || c->crypto_connections == NULL) - return -1; - - memset(&(c->crypto_connections[c->crypto_connections_length]), 0, sizeof(Crypto_Connection)); - c->crypto_connections[c->crypto_connections_length].number = ~0; - for (i = 0; i <= c->crypto_connections_length; ++i) { - if (c->crypto_connections[i].status == CRYPTO_CONN_NO_CONNECTION) { - c->crypto_connections[i].number = connection_id; - c->crypto_connections[i].status = CRYPTO_CONN_NOT_CONFIRMED; - c->crypto_connections[i].timeout = unix_time() + CRYPTO_HANDSHAKE_TIMEOUT; - random_nonce(c->crypto_connections[i].recv_nonce); - memcpy(c->crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES); - memcpy(c->crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); - increment_nonce(c->crypto_connections[i].sent_nonce); - memcpy(c->crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); - - crypto_box_keypair(c->crypto_connections[i].sessionpublic_key, c->crypto_connections[i].sessionsecret_key); - - if (c->crypto_connections_length == i) - ++c->crypto_connections_length; - - if (send_cryptohandshake(c, connection_id, public_key, c->crypto_connections[i].recv_nonce, - c->crypto_connections[i].sessionpublic_key) == 1) { - increment_nonce(c->crypto_connections[i].recv_nonce); - uint32_t zero = 0; - encrypt_precompute(c->crypto_connections[i].peersessionpublic_key, - c->crypto_connections[i].sessionsecret_key, - c->crypto_connections[i].shared_key); - c->crypto_connections[i].status = - CRYPTO_CONN_ESTABLISHED; /* Connection status needs to be 3 for write_cryptpacket() to work. */ - write_cryptpacket(c, i, ((uint8_t *)&zero), sizeof(zero)); - c->crypto_connections[i].status = CRYPTO_CONN_NOT_CONFIRMED; /* Set it to its proper value right after. */ - return i; - } - - return -1; /* This should never happen. */ - } - } - - return -1; } /* return 0 if no connection. @@ -1333,84 +1048,7 @@ void load_keys(Net_Crypto *c, uint8_t *keys) /* Handle received packets for not yet established crypto connections. */ static void receive_crypto(Net_Crypto *c) { - uint32_t i; - uint64_t temp_time = unix_time(); - - for (i = 0; i < c->crypto_connections_length; ++i) { - if (c->crypto_connections[i].status == CRYPTO_CONN_NO_CONNECTION) - continue; - - if (c->crypto_connections[i].status == CRYPTO_CONN_HANDSHAKE_SENT) { - uint8_t temp_data[MAX_DATA_SIZE]; - uint8_t secret_nonce[crypto_box_NONCEBYTES]; - uint8_t public_key[crypto_box_PUBLICKEYBYTES]; - uint8_t session_key[crypto_box_PUBLICKEYBYTES]; - uint16_t len; - - if (id_packet(c->lossless_udp, c->crypto_connections[i].number) == 2) { /* Handle handshake packet. */ - len = read_packet(c->lossless_udp, c->crypto_connections[i].number, temp_data); - - if (handle_cryptohandshake(c, public_key, secret_nonce, session_key, temp_data, len)) { - if (memcmp(public_key, c->crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) { - memcpy(c->crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES); - memcpy(c->crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); - increment_nonce(c->crypto_connections[i].sent_nonce); - uint32_t zero = 0; - encrypt_precompute(c->crypto_connections[i].peersessionpublic_key, - c->crypto_connections[i].sessionsecret_key, - c->crypto_connections[i].shared_key); - c->crypto_connections[i].status = - CRYPTO_CONN_ESTABLISHED; /* Connection status needs to be 3 for write_cryptpacket() to work. */ - write_cryptpacket(c, i, ((uint8_t *)&zero), sizeof(zero)); - c->crypto_connections[i].status = CRYPTO_CONN_NOT_CONFIRMED; /* Set it to its proper value right after. */ - } else { - /* This should not happen, timeout the connection if it does. */ - c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT; - } - } else { - /* This should not happen, timeout the connection if it does. */ - c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT; - } - } else if (id_packet(c->lossless_udp, - c->crypto_connections[i].number) != (uint8_t)~0) { - /* This should not happen, timeout the connection if it does. */ - c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT; - } - } - if (c->crypto_connections[i].status == CRYPTO_CONN_NOT_CONFIRMED) { - if (id_packet(c->lossless_udp, c->crypto_connections[i].number) == 3) { - uint8_t temp_data[MAX_DATA_SIZE]; - uint8_t data[MAX_DATA_SIZE]; - int length = read_packet(c->lossless_udp, c->crypto_connections[i].number, temp_data); - int len = decrypt_data(c->crypto_connections[i].peersessionpublic_key, - c->crypto_connections[i].sessionsecret_key, - c->crypto_connections[i].recv_nonce, temp_data + 1, length - 1, data); - uint32_t zero = 0; - - if (len == sizeof(uint32_t) && memcmp(((uint8_t *)&zero), data, sizeof(uint32_t)) == 0) { - increment_nonce(c->crypto_connections[i].recv_nonce); - encrypt_precompute(c->crypto_connections[i].peersessionpublic_key, - c->crypto_connections[i].sessionsecret_key, - c->crypto_connections[i].shared_key); - c->crypto_connections[i].status = CRYPTO_CONN_ESTABLISHED; - c->crypto_connections[i].timeout = ~0; - /* Connection is accepted. */ - confirm_connection(c->lossless_udp, c->crypto_connections[i].number); - } else { - /* This should not happen, timeout the connection if it does. */ - c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT; - } - } else if (id_packet(c->lossless_udp, c->crypto_connections[i].number) != (uint8_t)~0) { - /* This should not happen, timeout the connection if it does. */ - c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT; - } - } - - if (temp_time > c->crypto_connections[i].timeout) { - c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT; - } - } } /* Run this to (re)initialize net_crypto. @@ -1429,12 +1067,6 @@ Net_Crypto *new_net_crypto(DHT *dht) return NULL; temp->dht = dht; - temp->lossless_udp = new_lossless_udp(dht->net); - - if (temp->lossless_udp == NULL) { - free(temp); - return NULL; - } new_keys(temp); new_symmetric_key(temp->secret_symmetric_key); @@ -1451,9 +1083,7 @@ static void kill_timedout(Net_Crypto *c) uint32_t i; for (i = 0; i < c->crypto_connections_length; ++i) { - if (c->crypto_connections[i].status != CRYPTO_CONN_NO_CONNECTION - && is_connected(c->lossless_udp, c->crypto_connections[i].number) == LUDP_TIMED_OUT) - c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT; +//TODO } } @@ -1461,9 +1091,9 @@ static void kill_timedout(Net_Crypto *c) void do_net_crypto(Net_Crypto *c) { unix_time_update(); - do_lossless_udp(c->lossless_udp); kill_timedout(c); receive_crypto(c); + send_crypto_packets(c); } void kill_net_crypto(Net_Crypto *c) @@ -1474,7 +1104,10 @@ void kill_net_crypto(Net_Crypto *c) crypto_kill(c, i); } - kill_lossless_udp(c->lossless_udp); + networking_registerhandler(c->dht->net, NET_PACKET_COOKIE_REQUEST, NULL, NULL); + networking_registerhandler(c->dht->net, NET_PACKET_COOKIE_RESPONSE, NULL, NULL); + networking_registerhandler(c->dht->net, NET_PACKET_CRYPTO_HS, NULL, NULL); + networking_registerhandler(c->dht->net, NET_PACKET_CRYPTO_DATA, NULL, NULL); memset(c, 0, sizeof(Net_Crypto)); free(c); } diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index 736d3070..3d58e5c1 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -24,7 +24,6 @@ #ifndef NET_CRYPTO_H #define NET_CRYPTO_H -#include "Lossless_UDP.h" #include "DHT.h" #define CRYPTO_HANDSHAKE_TIMEOUT (CONNECTION_TIMEOUT * 2) @@ -39,6 +38,8 @@ #define CRYPTO_PACKET_BUFFER_SIZE 64 #define MAX_CRYPTO_PACKET_SIZE 1400 + +/* Max size of data in packets TODO*/ #define MAX_CRYPTO_DATA_SIZE (MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + crypto_box_MACBYTES)) /* Interval in ms between sending cookie request/handshake packets. */ @@ -58,7 +59,6 @@ typedef struct { * 4 if the connection is established. * 5 if the connection is timed out. */ - uint16_t number; /* Lossless_UDP connection number corresponding to this connection. */ uint64_t timeout; uint64_t cookie_request_number; /* number used in the cookie request packets for this connection */ @@ -71,7 +71,6 @@ typedef struct { IP_Port ip_port; /* The ip and port to contact this guy directly.*/ uint64_t direct_lastrecv_time; /* The Time at which we last receive a direct packet. */ - } Crypto_Connection; typedef struct { @@ -84,7 +83,6 @@ typedef struct { } New_Connection; typedef struct { - Lossless_UDP *lossless_udp; DHT *dht; Crypto_Connection *crypto_connections; @@ -103,6 +101,22 @@ typedef struct { } Net_Crypto; +/* Set function to be called when someone requests a new connection to us. + * + * The set function should return -1 on failure and 0 on success. + * + * n_c is only valid for the duration of the function call. + */ +void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void *object, New_Connection *n_c), + void *object); + +/* Accept a crypto connection. + * + * return -1 on failure. + * return connection id on success. + */ +int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c); + /* return 0 if there is no received data in the buffer. * return -1 if the packet was discarded. @@ -134,25 +148,6 @@ int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port); */ int crypto_kill(Net_Crypto *c, int crypt_connection_id); -/* Handle an incoming connection. - * - * return -1 if no crypto inbound connection. - * return incoming connection id (Lossless_UDP one) if there is an incoming crypto connection. - * - * Put the public key of the peer in public_key, the secret_nonce from the handshake into secret_nonce - * and the session public key for the connection in session_key. - * to accept it see: accept_crypto_inbound(...). - * to refuse it just call kill_connection(...) on the connection id. - */ -int crypto_inbound(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key); - -/* Accept an incoming connection using the parameters provided by crypto_inbound. - * - * return -1 if not successful. - * return crypt_connection_id if successful. - */ -int accept_crypto_inbound(Net_Crypto *c, int connection_id, uint8_t *public_key, uint8_t *secret_nonce, - uint8_t *session_key); /* return 0 if no connection. * return 1 we have sent a handshake diff --git a/toxcore/tox.c b/toxcore/tox.c index 6bd24e92..037cb7f5 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -721,7 +721,7 @@ int tox_file_send_data(Tox *tox, int32_t friendnumber, uint8_t filenumber, uint8 */ int tox_file_data_size(Tox *tox, int32_t friendnumber) { - return MAX_DATA_SIZE - crypto_box_MACBYTES - 3; + return MAX_CRYPTO_DATA_SIZE - 3; } /* Give the number of bytes left to be sent/received. -- cgit v1.2.3