summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2014-05-02 10:36:48 -0400
committerirungentoo <irungentoo@gmail.com>2014-05-02 10:36:48 -0400
commit8e24771fc41597dd9e3e02a192eb0b5b43771ac1 (patch)
tree1082d855140bd1548d87a2db618945f68b66884a
parentdeb8bfc350748555b7de5d0f4911c382b3f2d65e (diff)
Remove Lossless UDP (This breaks Tox.)
-rw-r--r--testing/Lossless_UDP_testclient.c260
-rw-r--r--testing/Lossless_UDP_testserver.c237
-rw-r--r--testing/Makefile.inc36
-rw-r--r--toxcore/Lossless_UDP.c1168
-rw-r--r--toxcore/Lossless_UDP.h262
-rw-r--r--toxcore/Makefile.inc2
-rw-r--r--toxcore/Messenger.c70
-rw-r--r--toxcore/Messenger.h1
-rw-r--r--toxcore/net_crypto.c381
-rw-r--r--toxcore/net_crypto.h41
-rw-r--r--toxcore/tox.c2
11 files changed, 60 insertions, 2400 deletions
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 @@
1/* Lossless_UDP testclient
2 * A program that connects and sends a file using our lossless UDP algorithm.
3 * NOTE: this program simulates a 33% packet loss.
4 *
5 * Best used in combination with Lossless_UDP_testserver
6 *
7 * Compile with: gcc -O2 -Wall -lsodium -o testclient ../toxcore/network.c ../toxcore/Lossless_UDP.c ../toxcore/util.c Lossless_UDP_testclient.c
8 *
9 * Command line arguments are the ip and port to connect and send the file to.
10 * EX: ./testclient --ipv4 127.0.0.1 33445 filename.txt
11 *
12 * Copyright (C) 2013 Tox project All Rights Reserved.
13 *
14 * This file is part of Tox.
15 *
16 * Tox is free software: you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation, either version 3 of the License, or
19 * (at your option) any later version.
20 *
21 * Tox is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
28 *
29 */
30
31#ifdef HAVE_CONFIG_H
32#include "config.h"
33#endif
34
35#include "../toxcore/network.h"
36#include "../toxcore/Lossless_UDP.h"
37#include "../toxcore/util.h"
38#include "misc_tools.c"
39
40#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
41
42#define c_sleep(x) Sleep(1*x)
43
44#else
45#include <unistd.h>
46#include <arpa/inet.h>
47#define c_sleep(x) usleep(1000*x)
48
49#endif
50
51#define PORT 33446
52
53void printpacket(uint8_t *data, uint32_t length, IP_Port ip_port)
54{
55 uint32_t i;
56 printf("UNHANDLED PACKET RECEIVED\nLENGTH:%u\nCONTENTS:\n", length);
57 printf("--------------------BEGIN-----------------------------\n");
58
59 for (i = 0; i < length; i++) {
60 if (data[i] < 16)
61 printf("0");
62
63 printf("%hhX", data[i]);
64 }
65
66 printf("\n--------------------END-----------------------------\n\n\n");
67}
68
69void printip(IP_Port ip_port)
70{
71 printf("\nIP: %s Port: %u", ip_ntoa(&ip_port.ip), ntohs(ip_port.port));
72}
73/*
74void printpackets(Data test)
75{
76 int i;
77 if(test.size == 0)
78 return;
79 printf("SIZE: %u\n", test.size);
80 for(i =0; i < test.size; i++)
81 {
82 printf("%hhX", test.data[i]);
83 }
84 printf("\n");
85}
86
87void printconnection(int connection_id)
88{
89 printf("--------------------BEGIN---------------------\n");
90 IP_Port ip_port = connections[connection_id].ip_port;
91 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));
92 printf("status: %u, inbound: %u, SYNC_rate: %u\n", connections[connection_id].status,
93 connections[connection_id].inbound, connections[connection_id].SYNC_rate);
94 printf("data rate: %u, last sync: %llu, last sent: %llu, last recv: %llu \n", connections[connection_id].data_rate,
95 connections[connection_id].last_SYNC, connections[connection_id].last_sent, connections[connection_id].last_recv);
96 int i;
97 for(i =0; i < MAX_QUEUE_NUM; i++)
98 {
99 printf(" %u ",i);
100 printpackets(connections[connection_id].sendbuffer[i]);
101 }
102 for(i =0; i < MAX_QUEUE_NUM; i++)
103 {
104 printf(" %u ",i);
105 printpackets(connections[connection_id].recvbuffer[i]);
106 }
107 Data sendbuffer[MAX_QUEUE_NUM];
108 Data recvbuffer[MAX_QUEUE_NUM];
109 printf("recv_num: %u, orecv_num: %u, sent_packetnum %u, osent_packetnum: %u, successful_sent: %u, successful_read: %u\n",
110 connections[connection_id].recv_packetnum,
111 connections[connection_id].orecv_packetnum, connections[connection_id].sent_packetnum, connections[connection_id].osent_packetnum,
112 connections[connection_id].successful_sent,
113 connections[connection_id].successful_read);
114
115 printf("req packets: \n");
116 for(i = 0; i < BUFFER_PACKET_NUM; i++)
117 {
118 printf(" %u ", connections[connection_id].req_packets[i]);
119 }
120 printf("\nNumber: %u recv_counter: %u, send_counter: %u\n", connections[connection_id].num_req_paquets,
121 connections[connection_id].recv_counter, connections[connection_id].send_counter);
122
123 printf("--------------------END---------------------\n");
124
125}
126*/
127
128/*( receive packets and send them to the packethandler */
129/*run doLossless_UDP(); */
130//void Lossless_UDP()
131//{
132/* IP_Port ip_port;
133 uint8_t data[MAX_UDP_PACKET_SIZE];
134 uint32_t length;
135 while (receivepacket(&ip_port, data, &length) != -1) {
136 printf("packet with length: %u\n", length); */
137/* if(rand() % 3 != 1)//add packet loss
138 { */
139/*
140 if (LosslessUDP_handlepacket(data, length, ip_port))
141 printpacket(data, length, ip_port);
142 else
143 printf("Received handled packet with length: %u\n", length); //printconnection(0); */
144
145/* } */
146/* }*/
147
148//networking_poll();
149
150//doLossless_UDP();
151
152//}
153
154int main(int argc, char *argv[])
155{
156 /* let user override default by cmdline */
157 uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */
158 int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled);
159
160 if (argvoffset < 0)
161 exit(1);
162
163 if (argc < argvoffset + 4) {
164 printf("Usage: %s [--ipv4|--ipv6] ip port filename\n", argv[0]);
165 exit(0);
166 }
167
168 uint8_t buffer[MAX_DATA_SIZE];
169 int read;
170
171 FILE *file = fopen(argv[argvoffset + 3], "rb");
172
173 if (file == NULL) {
174 printf("Failed to open file \"%s\".\n", argv[argvoffset + 3]);
175 return 1;
176 }
177
178
179 /* initialize networking */
180 /* bind to ip 0.0.0.0:PORT */
181 IP ip;
182 ip_init(&ip, ipv6enabled);
183
184 Lossless_UDP *ludp = new_lossless_udp(new_networking(ip, PORT));
185 perror("Initialization");
186
187 IP_Port serverip;
188 ip_init(&serverip.ip, ipv6enabled);
189
190 if (!addr_resolve(argv[argvoffset + 1], &serverip.ip, NULL)) {
191 printf("Failed to convert \"%s\" into an IP address.\n", argv[argvoffset + 1]);
192 return 1;
193 }
194
195 serverip.port = htons(atoi(argv[argvoffset + 2]));
196 printip(serverip);
197
198 int connection = new_connection(ludp, serverip);
199 uint64_t timer = current_time();
200
201 while (1) {
202 /* printconnection(connection); */
203 networking_poll(ludp->net);
204 do_lossless_udp(ludp);
205
206 if (is_connected(ludp, connection) == LUDP_ESTABLISHED) {
207 printf("Connecting took: %llu us\n", (unsigned long long)(current_time() - timer));
208 break;
209 }
210
211 if (is_connected(ludp, connection) == LUDP_NO_CONNECTION) {
212 printf("Connection timeout after: %llu us\n", (unsigned long long)(current_time() - timer));
213 return 1;
214 }
215
216 c_sleep(1);
217 }
218
219 timer = current_time();
220 unsigned long long bytes_sent = 0;
221
222 /*read first part of file */
223 read = fread(buffer, 1, MAX_DATA_SIZE, file);
224
225 while (1) {
226 /* printconnection(connection); */
227 networking_poll(ludp->net);
228 do_lossless_udp(ludp);
229
230 if (is_connected(ludp, connection) == LUDP_ESTABLISHED) {
231
232 while (write_packet(ludp, connection, buffer, read)) {
233 bytes_sent += read;
234 /* printf("Wrote data.\n"); */
235 read = fread(buffer, 1, MAX_DATA_SIZE, file);
236
237 }
238
239 /* printf("%u\n", sendqueue(connection)); */
240 if (sendqueue(ludp, connection) == 0) {
241 if (read == 0) {
242 unsigned long long us = (unsigned long long)(current_time() - timer);
243 printf("Sent file successfully in: %llu us = %llu seconds. Average speed: %llu KB/s\n", us, us / 1000000UL,
244 bytes_sent / (us / 1024UL));
245 //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);
246 break;
247 }
248 }
249 } else {
250 printf("%u Client Connecting Lost after: %llu us\n", is_connected(ludp, connection),
251 (unsigned long long)(current_time() - timer));
252 return 0;
253 }
254
255 }
256
257 c_sleep(25);
258
259 return 0;
260}
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 @@
1/* Lossless_UDP testserver
2 * A program that waits for a lossless UDP connection and then saves all the data received to a file.
3 * NOTE: this program simulates a 33% packet loss.
4 *
5 * Best used in combination with Lossless_UDP_testclient
6 *
7 * Compile with: gcc -O2 -Wall -lsodium -o testserver ../toxcore/network.c ../toxcore/Lossless_UDP.c ../toxcore/util.c Lossless_UDP_testserver.c
8 *
9 * Command line argument is the name of the file to save what we receive to.
10 * EX: ./testserver filename1.txt
11 *
12 * Copyright (C) 2013 Tox project All Rights Reserved.
13 *
14 * This file is part of Tox.
15 *
16 * Tox is free software: you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation, either version 3 of the License, or
19 * (at your option) any later version.
20 *
21 * Tox is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
28 *
29 */
30
31#ifdef HAVE_CONFIG_H
32#include "config.h"
33#endif
34
35#include "../toxcore/network.h"
36#include "../toxcore/Lossless_UDP.h"
37#include "../toxcore/util.h"
38#include "misc_tools.c"
39
40//Sleep function (x = milliseconds)
41#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
42
43#define c_sleep(x) Sleep(1*x)
44
45#else
46#include <unistd.h>
47#include <arpa/inet.h>
48#define c_sleep(x) usleep(1000*x)
49
50#endif
51
52#define PORT 33445
53
54void printpacket(uint8_t *data, uint32_t length, IP_Port ip_port)
55{
56 uint32_t i;
57 printf("UNHANDLED PACKET RECEIVED\nLENGTH:%u\nCONTENTS:\n", length);
58 printf("--------------------BEGIN-----------------------------\n");
59
60 for (i = 0; i < length; i++) {
61 if (data[i] < 16)
62 printf("0");
63
64 printf("%hhX", data[i]);
65 }
66
67 printf("\n--------------------END-----------------------------\n\n\n");
68}
69
70/*
71void printpackets(Data test)
72{
73 int i;
74 if(test.size == 0)
75 return;
76 printf("SIZE: %u\n", test.size);
77 for(i =0; i < test.size; i++)
78 {
79 printf("%hhX", test.data[i]);
80 }
81 printf("\n");
82}
83
84void printconnection(int connection_id)
85{
86 printf("--------------------BEGIN---------------------\n");
87 IP_Port ip_port = connections[connection_id].ip_port;
88 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));
89 printf("status: %u, inbound: %u, SYNC_rate: %u\n", connections[connection_id].status,
90 connections[connection_id].inbound, connections[connection_id].SYNC_rate);
91 printf("data rate: %u, last sync: %llu, last sent: %llu, last recv: %llu \n", connections[connection_id].data_rate,
92 connections[connection_id].last_SYNC, connections[connection_id].last_sent, connections[connection_id].last_recv);
93 int i;
94 for(i =0; i < MAX_QUEUE_NUM; i++)
95 {
96 printf(" %u ",i);
97 printpackets(connections[connection_id].sendbuffer[i]);
98 }
99 for(i =0; i < MAX_QUEUE_NUM; i++)
100 {
101 printf(" %u ",i);
102 printpackets(connections[connection_id].recvbuffer[i]);
103 }
104 Data sendbuffer[MAX_QUEUE_NUM];
105 Data recvbuffer[MAX_QUEUE_NUM];
106 printf("recv_num: %u, orecv_num: %u, sent_packetnum %u, osent_packetnum: %u, successful_sent: %u, successful_read: %u\n",
107 connections[connection_id].recv_packetnum,
108 connections[connection_id].orecv_packetnum, connections[connection_id].sent_packetnum, connections[connection_id].osent_packetnum,
109 connections[connection_id].successful_sent,
110 connections[connection_id].successful_read);
111
112 printf("req packets: \n");
113 for(i = 0; i < BUFFER_PACKET_NUM; i++)
114 {
115 printf(" %u ", connections[connection_id].req_packets[i]);
116 }
117 printf("\nNumber: %u recv_counter: %u, send_counter: %u\n", connections[connection_id].num_req_paquets,
118 connections[connection_id].recv_counter, connections[connection_id].send_counter);
119
120 printf("--------------------END---------------------\n");
121
122}
123*/
124
125/* receive packets and send them to the packethandler
126 * run doLossless_UDP(); */
127//void Lossless_UDP()
128//{
129// IP_Port ip_port;
130// uint8_t data[MAX_UDP_PACKET_SIZE];
131// uint32_t length;
132// while (receivepacket(&ip_port, data, &length) != -1) {
133//if(rand() % 3 != 1)//add packet loss
134//{
135// if (LosslessUDP_handlepacket(data, length, ip_port)) {
136// printpacket(data, length, ip_port);
137// } else {
138//printconnection(0);
139// printf("Received handled packet with length: %u\n", length);
140// }
141//}
142// }
143
144// networking_poll();
145
146//doLossless_UDP();
147//}
148
149
150int main(int argc, char *argv[])
151{
152 /* let user override default by cmdline */
153 uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */
154 int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled);
155
156 if (argvoffset < 0)
157 exit(1);
158
159 if (argc < argvoffset + 2) {
160 printf("Usage: %s [--ipv4|--ipv6] filename\n", argv[0]);
161 exit(0);
162 }
163
164 uint8_t buffer[MAX_DATA_SIZE];
165 int read;
166
167 FILE *file = fopen(argv[argvoffset + 1], "wb");
168
169 if (file == NULL) {
170 printf("Failed to open file \"%s\".\n", argv[argvoffset + 1]);
171 return 1;
172 }
173
174
175 //initialize networking
176 //bind to ip 0.0.0.0:PORT
177 IP ip;
178 ip_init(&ip, ipv6enabled);
179
180 Lossless_UDP *ludp = new_lossless_udp(new_networking(ip, PORT));
181 perror("Initialization");
182
183 int connection;
184 uint64_t timer = current_time();
185
186 while (1) {
187 networking_poll(ludp->net);
188 do_lossless_udp(ludp);
189 connection = incoming_connection(ludp, 0);
190
191 if (connection != -1) {
192 if (is_connected(ludp, connection) == LUDP_NOT_CONFIRMED) {
193 printf("Received the connection.\n");
194
195 }
196
197 break;
198 }
199
200 c_sleep(1);
201 }
202
203 timer = current_time();
204
205 while (1) {
206 //printconnection(0);
207 networking_poll(ludp->net);
208
209 if (is_connected(ludp, connection) >= LUDP_NOT_CONFIRMED) {
210 confirm_connection(ludp, connection);
211
212 while (1) {
213 read = read_packet(ludp, connection, buffer);
214
215 if (read != 0) {
216 // printf("Received data.\n");
217 if (!fwrite(buffer, read, 1, file))
218 printf("file write error\n");
219 } else {
220 break;
221 }
222 }
223 }
224
225 do_lossless_udp(ludp);
226
227 if (is_connected(ludp, connection) == LUDP_TIMED_OUT) {
228 printf("Server Connecting Lost after: %llu us\n", (unsigned long long)(current_time() - timer));
229 fclose(file);
230 return 1;
231 }
232
233 c_sleep(25);
234 }
235
236 return 0;
237}
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
22if BUILD_TESTING 22if BUILD_TESTING
23 23
24noinst_PROGRAMS += DHT_test \ 24noinst_PROGRAMS += DHT_test \
25 Lossless_UDP_testclient \
26 Lossless_UDP_testserver \
27 Messenger_test \ 25 Messenger_test \
28 crypto_speed_test 26 crypto_speed_test
29 27
@@ -41,40 +39,6 @@ DHT_test_LDADD = $(LIBSODIUM_LDFLAGS) \
41 $(WINSOCK2_LIBS) 39 $(WINSOCK2_LIBS)
42 40
43 41
44Lossless_UDP_testclient_SOURCES = \
45 ../testing/Lossless_UDP_testclient.c
46
47Lossless_UDP_testclient_CFLAGS = \
48 $(LIBSODIUM_CFLAGS) \
49 $(NACL_CFLAGS)
50
51Lossless_UDP_testclient_LDADD = \
52 $(LIBSODIUM_LDFLAGS) \
53 $(NACL_LDFLAGS) \
54 libtoxcore.la \
55 $(LIBSODIUM_LIBS) \
56 $(NACL_OBJECTS) \
57 $(NACL_LIBS) \
58 $(WINSOCK2_LIBS)
59
60
61Lossless_UDP_testserver_SOURCES = \
62 ../testing/Lossless_UDP_testserver.c
63
64Lossless_UDP_testserver_CFLAGS = \
65 $(LIBSODIUM_CFLAGS) \
66 $(NACL_CFLAGS)
67
68Lossless_UDP_testserver_LDADD = \
69 $(LIBSODIUM_LDFLAGS) \
70 $(NACL_LDFLAGS) \
71 libtoxcore.la \
72 $(LIBSODIUM_LIBS) \
73 $(NACL_OBJECTS) \
74 $(NACL_LIBS) \
75 $(WINSOCK2_LIBS)
76
77
78Messenger_test_SOURCES = \ 42Messenger_test_SOURCES = \
79 ../testing/Messenger_test.c 43 ../testing/Messenger_test.c
80 44
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 @@
1/* Lossless_UDP.c
2 *
3 * An implementation of the Lossless_UDP protocol as seen in http://wiki.tox.im/index.php/Lossless_UDP
4 *
5 * Copyright (C) 2013 Tox project All Rights Reserved.
6 *
7 * This file is part of Tox.
8 *
9 * Tox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * Tox is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24/*
25 * TODO: clean this file a bit.
26 * There are a couple of useless variables to get rid of.
27 */
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#include "Lossless_UDP.h"
34
35#define LUDP_CONNECTION_OUTBOUND 0
36#define LUDP_CONNECTION_INBOUND_HANDLED 1
37#define LUDP_CONNECTION_INBOUND 2
38
39/* Functions */
40
41/*
42 * Get connection id from IP_Port.
43 *
44 * return -1 if there are no connections like we are looking for.
45 * return id if it found it.
46 */
47int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port)
48{
49 tox_array_for_each(&ludp->connections, Connection, tmp) {
50 if (tmp->status != LUDP_NO_CONNECTION && ipport_equal(&tmp->ip_port, &ip_port)) {
51 return tmp_i;
52 }
53 }
54
55 return -1;
56}
57
58/* Resize a queue
59 * return length of queue on success.
60 * return ~0 on failure.
61 */
62uint32_t resize_queue(Data **buffer, uint32_t length, uint32_t new_length, uint32_t min_packetnum,
63 uint32_t max_packetnum)
64{
65 if (MAX_QUEUE_NUM < new_length)
66 new_length = MAX_QUEUE_NUM;
67
68 if (max_packetnum - min_packetnum > new_length)
69 return ~0;
70
71 if (length == new_length)
72 return new_length;
73
74 Data *temp = calloc(1, sizeof(Data) * new_length);
75
76 if (temp == NULL)
77 return ~0;
78
79 if (*buffer == NULL) {
80 *buffer = temp;
81 return new_length;
82 }
83
84 uint32_t i;
85
86 for (i = min_packetnum; i != max_packetnum; ++i)
87 memcpy(temp + (i % new_length), *buffer + (i % length), sizeof(Data));
88
89 free(*buffer);
90 *buffer = temp;
91 return new_length;
92}
93
94
95
96/*
97 * Generate a handshake_id which depends on the ip_port.
98 * This function will always give one unique handshake_id per ip_port.
99 *
100 * TODO: make this better
101 */
102
103static uint32_t randtable_initget(Lossless_UDP *ludp, uint32_t index, uint8_t value)
104{
105 if (ludp->randtable[index][value] == 0)
106 ludp->randtable[index][value] = random_int();
107
108 return ludp->randtable[index][value];
109}
110
111static uint32_t handshake_id(Lossless_UDP *ludp, IP_Port source)
112{
113 uint32_t id = 0, i = 0;
114
115 uint8_t *uint8;
116 uint8 = (uint8_t *)&source.port;
117 id ^= randtable_initget(ludp, i, *uint8);
118 i++, uint8++;
119 id ^= randtable_initget(ludp, i, *uint8);
120 i++;
121
122 if (source.ip.family == AF_INET) {
123 int k;
124
125 for (k = 0; k < 4; k++) {
126 id ^= randtable_initget(ludp, i++, source.ip.ip4.uint8[k]);
127 }
128 }
129
130 if (source.ip.family == AF_INET6) {
131 int k;
132
133 for (k = 0; k < 16; k++) {
134 id ^= randtable_initget(ludp, i++, source.ip.ip6.uint8[k]);
135 }
136 }
137
138 /* id can't be zero. */
139 if (id == 0)
140 id = 1;
141
142 return id;
143}
144
145/*
146 * Change the handshake id associated with that ip_port.
147 *
148 * TODO: Make this better
149 */
150static void change_handshake(Lossless_UDP *ludp, IP_Port source)
151{
152 uint8_t rand;
153
154 if (source.ip.family == AF_INET) {
155 rand = random_int() % 4;
156 } else if (source.ip.family == AF_INET6) {
157 rand = random_int() % 16;
158 } else {
159 return;
160 }
161
162 /* Forced to be more robust against strange definitions of sa_family_t */
163 ludp->randtable[2 + rand][((uint8_t *)&source.ip.ip6)[rand]] = random_int();
164}
165
166/*
167 * Initialize a new connection to ip_port
168 *
169 * return an integer corresponding to the connection id.
170 * return -1 if it could not initialize the connectiont
171 * If there already was an existing connection to that ip_port return its number.
172 */
173int new_connection(Lossless_UDP *ludp, IP_Port ip_port)
174{
175 int connection_id = getconnection_id(ludp, ip_port);
176
177 if (connection_id != -1) {
178 confirm_connection(ludp, connection_id);
179 return connection_id;
180 }
181
182 tox_array_for_each(&ludp->connections, Connection, tmp) {
183 if (tmp->status == LUDP_NO_CONNECTION) {
184 connection_id = tmp_i;
185 break;
186 }
187 }
188
189 if (connection_id == -1) {
190 if (tox_array_push_ptr(&ludp->connections, 0) == 0)
191 return -1;
192
193 connection_id = ludp->connections.len - 1;
194 }
195
196 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
197
198 memset(connection, 0, sizeof(Connection));
199
200 uint32_t handshake_id1 = handshake_id(ludp, ip_port);
201 /* Add randomness to timeout to prevent connections getting stuck in a loop. */
202 uint8_t timeout = CONNECTION_TIMEOUT + rand() % CONNECTION_TIMEOUT;
203
204 *connection = (Connection) {
205 .ip_port = ip_port,
206 .status = LUDP_HANDSHAKE_SENDING,
207 .inbound = LUDP_CONNECTION_OUTBOUND,
208 .handshake_id1 = handshake_id1,
209 .sent_packetnum = handshake_id1,
210 .sendbuff_packetnum = handshake_id1,
211 .successful_sent = handshake_id1,
212 .SYNC_rate = SYNC_RATE,
213 .data_rate = DATA_SYNC_RATE,
214 .last_recvSYNC = current_time(),
215 .last_sent = current_time(),
216 .killat = ~0,
217 .send_counter = 0,
218 .timeout = timeout,
219 .confirmed = 1
220 };
221 connection->sendbuffer_length = resize_queue(&connection->sendbuffer, 0, DEFAULT_QUEUE_NUM, 0, 0);
222 connection->recvbuffer_length = resize_queue(&connection->recvbuffer, 0, DEFAULT_QUEUE_NUM, 0, 0);
223
224 if (connection->sendbuffer_length == (uint32_t)~0 || connection->recvbuffer_length == (uint32_t)~0) {
225 free(connection->sendbuffer);
226 free(connection->recvbuffer);
227 memset(connection, 0, sizeof(Connection));
228 return -1;
229 }
230
231 return connection_id;
232}
233
234/*
235 * Initialize a new inbound connection from ip_port.
236 *
237 * return an integer corresponding to the connection id.
238 * return -1 if it could not initialize the connection.
239 */
240static int new_inconnection(Lossless_UDP *ludp, IP_Port ip_port)
241{
242 if (getconnection_id(ludp, ip_port) != -1)
243 return -1; /* TODO: return existing connection instead? */
244
245 int connection_id = -1;
246 tox_array_for_each(&ludp->connections, Connection, tmp) {
247 if (tmp->status == LUDP_NO_CONNECTION) {
248 connection_id = tmp_i;
249 break;
250 }
251 }
252
253 if (connection_id == -1) {
254 if (tox_array_push_ptr(&ludp->connections, 0) == 0)
255 return -1;
256
257 connection_id = ludp->connections.len - 1;
258 }
259
260 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
261 memset(connection, 0, sizeof(Connection));
262 /* Add randomness to timeout to prevent connections getting stuck in a loop. */
263 uint8_t timeout = CONNECTION_TIMEOUT + rand() % CONNECTION_TIMEOUT;
264
265 *connection = (Connection) {
266 .ip_port = ip_port,
267 .status = LUDP_NOT_CONFIRMED,
268 .inbound = LUDP_CONNECTION_INBOUND,
269 .SYNC_rate = SYNC_RATE,
270 .data_rate = DATA_SYNC_RATE,
271 .last_recvSYNC = current_time(),
272 .last_sent = current_time(),
273 .send_counter = 127,
274
275 .timeout = timeout,
276
277 /* If this connection isn't handled within the timeout kill it. */
278 .killat = current_time() + 1000000ULL * timeout,
279 .confirmed = 0
280 };
281 connection->sendbuffer_length = resize_queue(&connection->sendbuffer, 0, DEFAULT_QUEUE_NUM, 0, 0);
282 connection->recvbuffer_length = resize_queue(&connection->recvbuffer, 0, DEFAULT_QUEUE_NUM, 0, 0);
283
284 if (connection->sendbuffer_length == (uint32_t)~0 || connection->recvbuffer_length == (uint32_t)~0) {
285 free(connection->sendbuffer);
286 free(connection->recvbuffer);
287 memset(connection, 0, sizeof(Connection));
288 return -1;
289 }
290
291 return connection_id;
292}
293
294/*
295 * return an integer corresponding to the next connection in our incoming connection list with at least numpackets in the recieve queue.
296 * return -1 if there are no new incoming connections in the list.
297 */
298int incoming_connection(Lossless_UDP *ludp, uint32_t numpackets)
299{
300 tox_array_for_each(&ludp->connections, Connection, tmp) {
301 if (tmp->inbound == LUDP_CONNECTION_INBOUND && tmp->recv_packetnum - tmp->successful_read >= numpackets) {
302 tmp->inbound = LUDP_CONNECTION_INBOUND_HANDLED;
303 return tmp_i;
304 }
305 }
306 return -1;
307}
308/* Try to free some memory from the connections array. */
309static void free_connections(Lossless_UDP *ludp)
310{
311 uint32_t i;
312
313 for (i = ludp->connections.len; i != 0; --i) {
314 Connection *connection = &tox_array_get(&ludp->connections, i - 1, Connection);
315
316 if (connection->status != LUDP_NO_CONNECTION)
317 break;
318 }
319
320 if (ludp->connections.len == i)
321 return;
322
323 return tox_array_pop(&ludp->connections, ludp->connections.len - i);
324}
325/* return -1 if it could not kill the connection.
326 * return 0 if killed successfully.
327 */
328int kill_connection(Lossless_UDP *ludp, int connection_id)
329{
330 if ((unsigned int)connection_id < ludp->connections.len) {
331 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
332
333 if (connection->status != LUDP_NO_CONNECTION) {
334 connection->status = LUDP_NO_CONNECTION;
335 change_handshake(ludp, connection->ip_port);
336 free(connection->sendbuffer);
337 free(connection->recvbuffer);
338 memset(connection, 0, sizeof(Connection));
339 free_connections(ludp);
340 return 0;
341 }
342 }
343
344 return -1;
345}
346
347/*
348 * timeout connection in seconds.
349 *
350 * return -1 if it can not kill the connection.
351 * return 0 if it will kill it.
352 */
353int timeout_connection_in(Lossless_UDP *ludp, int connection_id, uint32_t seconds)
354{
355 if ((unsigned int)connection_id < ludp->connections.len) {
356 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
357
358 if (connection->status != LUDP_NO_CONNECTION) {
359 connection->killat = current_time() + 1000000ULL * seconds;
360 return 0;
361 }
362 }
363
364 return -1;
365}
366
367/*
368 * Check if connection is connected:
369 *
370 * return LUDP_NO_CONNECTION if not.
371 * return LUDP_HANDSHAKE_SENDING if attempting handshake.
372 * return LUDP_NOT_CONFIRMED if handshake is done.
373 * return LUDP_ESTABLISHED if fully connected.
374 * return LUDP_TIMED_OUT if timed out and waiting to be killed.
375 */
376int is_connected(Lossless_UDP *ludp, int connection_id)
377{
378 if ((unsigned int)connection_id < ludp->connections.len)
379 return tox_array_get(&ludp->connections, connection_id, Connection).status;
380
381 return 0;
382}
383
384/* Check if connection is confirmed.
385 *
386 * returns 1 if yes.
387 * returns 0 if no/failure.
388 */
389int connection_confirmed(Lossless_UDP *ludp, int connection_id)
390{
391 if ((unsigned int)connection_id >= ludp->connections.len)
392 return 0;
393
394 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
395
396 if (connection->status == LUDP_NO_CONNECTION)
397 return 0;
398
399 if (connection->confirmed == 1)
400 return 1;
401
402 return 0;
403}
404
405/* Confirm an incoming connection.
406 * Also disable the auto kill timeout on incomming connections.
407 *
408 * return 0 on success
409 * return -1 on failure.
410 */
411int confirm_connection(Lossless_UDP *ludp, int connection_id)
412{
413 if ((unsigned int)connection_id >= ludp->connections.len)
414 return -1;
415
416 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
417
418 if (connection->status == LUDP_NO_CONNECTION)
419 return -1;
420
421 connection->killat = ~0;
422 connection->confirmed = 1;
423 connection->inbound = LUDP_CONNECTION_OUTBOUND;
424 return 0;
425}
426
427/* return the ip_port of the corresponding connection. */
428IP_Port connection_ip(Lossless_UDP *ludp, int connection_id)
429{
430 if ((unsigned int)connection_id < ludp->connections.len)
431 return tox_array_get(&ludp->connections, connection_id, Connection).ip_port;
432
433 IP_Port zero;
434 ip_reset(&zero.ip);
435 zero.port = 0;
436 return zero;
437}
438
439/* return the number of packets in the queue waiting to be successfully sent. */
440uint32_t sendqueue(Lossless_UDP *ludp, int connection_id)
441{
442 if ((unsigned int)connection_id >= ludp->connections.len)
443 return 0;
444
445 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
446
447 if (connection->status == LUDP_NO_CONNECTION)
448 return 0;
449
450 return connection->sendbuff_packetnum - connection->successful_sent;
451}
452
453/* return number of packets in all queues waiting to be successfully sent. */
454uint32_t sendqueue_total(Lossless_UDP *ludp)
455{
456 uint32_t i, total = 0;
457
458 for (i = 0; i < ludp->connections.len; i++) {
459 Connection *connection = &tox_array_get(&ludp->connections, i, Connection);
460
461 if (connection->status != 0)
462 total += connection->sendbuff_packetnum - connection->successful_sent;
463 }
464
465 return total;
466}
467
468/* return the number of packets in the queue waiting to be successfully read with read_packet(...). */
469uint32_t recvqueue(Lossless_UDP *ludp, int connection_id)
470{
471 if ((unsigned int)connection_id >= ludp->connections.len)
472 return 0;
473
474 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
475
476 if (connection->status == LUDP_NO_CONNECTION)
477 return 0;
478
479 return connection->recv_packetnum - connection->successful_read;
480}
481
482/* return the id of the next packet in the queue.
483 * return ~0 if no packet in queue.
484 */
485uint8_t id_packet(Lossless_UDP *ludp, int connection_id)
486{
487 if (recvqueue(ludp, connection_id) == 0)
488 return ~0;
489
490 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
491
492 if (connection->status != LUDP_NO_CONNECTION)
493 return connection->recvbuffer[connection->successful_read % connection->recvbuffer_length].data[0];
494
495 return ~0;
496}
497
498/* return 0 if there is no received data in the buffer.
499 * return length of received packet if successful.
500 */
501int read_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data)
502{
503 if (recvqueue(ludp, connection_id) == 0)
504 return 0;
505
506 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
507
508 if (connection->status == LUDP_NO_CONNECTION)
509 return 0;
510
511 uint16_t index = connection->successful_read % connection->recvbuffer_length;
512 uint16_t size = connection->recvbuffer[index].size;
513 memcpy(data, connection->recvbuffer[index].data, size);
514 ++connection->successful_read;
515 connection->recvbuffer[index].size = 0;
516 return size;
517}
518
519/* Like read_packet() but does leaves the queue as is.
520 * return 0 if there is no received data in the buffer.
521 * return length of received packet if successful.
522 */
523int read_packet_silent(Lossless_UDP *ludp, int connection_id, uint8_t *data)
524{
525 if (recvqueue(ludp, connection_id) == 0)
526 return 0;
527
528 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
529
530 if (connection->status == LUDP_NO_CONNECTION)
531 return 0;
532
533 uint16_t index = connection->successful_read % connection->recvbuffer_length;
534 uint16_t size = connection->recvbuffer[index].size;
535 memcpy(data, connection->recvbuffer[index].data, size);
536 return size;
537}
538/* Discard the next packet to be read from the queue
539 * return 0 if success.
540 * return -1 if failure.
541 */
542int discard_packet(Lossless_UDP *ludp, int connection_id)
543{
544 if (recvqueue(ludp, connection_id) == 0)
545 return -1;
546
547 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
548 uint16_t index = connection->successful_read % connection->recvbuffer_length;
549 ++connection->successful_read;
550 connection->recvbuffer[index].size = 0;
551 return 0;
552}
553
554#define MAX_SYNC_RATE 20
555#define MIN_SLOTS 16
556/* returns the number of packet slots left in the sendbuffer.
557 * return 0 if failure.
558 */
559uint32_t num_free_sendqueue_slots(Lossless_UDP *ludp, int connection_id)
560{
561 if ((unsigned int)connection_id >= ludp->connections.len)
562 return 0;
563
564 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
565 uint32_t max_slots = (connection->data_rate / MAX_SYNC_RATE) * 1.5;
566
567 if (max_slots > MAX_QUEUE_NUM)
568 max_slots = MAX_QUEUE_NUM;
569
570 if (max_slots < MIN_SLOTS)
571 max_slots = MIN_SLOTS;
572
573 if (sendqueue(ludp, connection_id) > max_slots)
574 return 0;
575
576 return max_slots - sendqueue(ludp, connection_id);
577}
578
579
580/* return 0 if data could not be put in packet queue.
581 * return 1 if data was put into the queue.
582 */
583int write_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data, uint32_t length)
584{
585 if ((unsigned int)connection_id >= ludp->connections.len)
586 return 0;
587
588 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
589
590 if (connection->status == LUDP_NO_CONNECTION)
591 return 0;
592
593 if (length > MAX_DATA_SIZE || length == 0 || sendqueue(ludp, connection_id) >= MAX_QUEUE_NUM)
594 return 0;
595
596 if (num_free_sendqueue_slots(ludp, connection_id) == 0)
597 return 0;
598
599 if (sendqueue(ludp, connection_id) >= connection->sendbuffer_length && connection->sendbuffer_length != 0) {
600 uint32_t newlen = connection->sendbuffer_length = resize_queue(&connection->sendbuffer, connection->sendbuffer_length,
601 connection->sendbuffer_length * 2, connection->successful_sent, connection->sendbuff_packetnum);
602
603 if (newlen == (uint32_t)~0)
604 return 0;
605
606 connection->sendbuffer_length = newlen;
607 return write_packet(ludp, connection_id, data, length);
608 }
609
610 uint32_t index = connection->sendbuff_packetnum % connection->sendbuffer_length;
611 memcpy(connection->sendbuffer[index].data, data, length);
612 connection->sendbuffer[index].size = length;
613 connection->sendbuff_packetnum++;
614 return 1;
615}
616
617/* Put the packet numbers the we are missing in requested and return the number. */
618static uint32_t missing_packets(Lossless_UDP *ludp, int connection_id, uint32_t *requested)
619{
620 if ((unsigned int)connection_id >= ludp->connections.len)
621 return 0;
622
623 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
624
625 /* Don't request packets if the buffer is full. */
626 if (recvqueue(ludp, connection_id) >= (connection->recvbuffer_length - 1))
627 return 0;
628
629 uint32_t number = 0;
630 uint32_t i;
631 uint32_t temp;
632
633 for (i = connection->recv_packetnum;
634 i != connection->osent_packetnum;
635 i++) {
636 if (connection->recvbuffer[i % connection->recvbuffer_length].size == 0) {
637 temp = htonl(i);
638 memcpy(requested + number, &temp, 4);
639 ++number;
640 }
641
642 if (number >= MAX_REQUESTED_PACKETS)
643 return number;
644 }
645
646 if (number == 0)
647 connection->recv_packetnum = connection->osent_packetnum;
648
649 return number;
650}
651
652/*
653 * BEGIN Packet sending functions.
654 * One per packet type.
655 * See http://wiki.tox.im/index.php/Lossless_UDP for more information.
656 */
657
658static int send_handshake(Lossless_UDP *ludp, IP_Port ip_port, uint32_t handshake_id1, uint32_t handshake_id2)
659{
660 uint8_t packet[1 + 4 + 4];
661 uint32_t temp;
662
663 packet[0] = NET_PACKET_HANDSHAKE;
664 temp = htonl(handshake_id1);
665 memcpy(packet + 1, &temp, 4);
666 temp = htonl(handshake_id2);
667 memcpy(packet + 5, &temp, 4);
668
669 return sendpacket(ludp->net, ip_port, packet, sizeof(packet));
670}
671
672static int send_SYNC(Lossless_UDP *ludp, int connection_id)
673{
674 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
675 uint8_t packet[(MAX_REQUESTED_PACKETS * 4 + 4 + 4 + 2)];
676 uint16_t index = 0;
677
678 IP_Port ip_port = connection->ip_port;
679 uint8_t counter = connection->send_counter;
680 uint32_t recv_packetnum = htonl(connection->recv_packetnum);
681 uint32_t sent_packetnum = htonl(connection->sent_packetnum);
682
683 uint32_t requested[MAX_REQUESTED_PACKETS];
684 uint32_t number = missing_packets(ludp, connection_id, requested);
685
686 packet[0] = NET_PACKET_SYNC;
687 index += 1;
688 memcpy(packet + index, &counter, 1);
689 index += 1;
690 memcpy(packet + index, &recv_packetnum, 4);
691 index += 4;
692 memcpy(packet + index, &sent_packetnum, 4);
693 index += 4;
694 memcpy(packet + index, requested, 4 * number);
695
696 return sendpacket(ludp->net, ip_port, packet, (number * 4 + 4 + 4 + 2));
697
698}
699
700static int send_data_packet(Lossless_UDP *ludp, int connection_id, uint32_t packet_num)
701{
702 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
703
704 uint32_t index = packet_num % connection->sendbuffer_length;
705 uint32_t temp;
706 uint8_t packet[1 + 4 + MAX_DATA_SIZE];
707 packet[0] = NET_PACKET_DATA;
708 temp = htonl(packet_num);
709 memcpy(packet + 1, &temp, 4);
710 memcpy(packet + 5, connection->sendbuffer[index].data, connection->sendbuffer[index].size);
711 return sendpacket(ludp->net, connection->ip_port, packet, 1 + 4 + connection->sendbuffer[index].size);
712}
713
714/* Sends 1 data packet. */
715static int send_DATA(Lossless_UDP *ludp, int connection_id)
716{
717 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
718 int ret;
719 uint32_t buffer[MAX_REQUESTED_PACKETS];
720
721 if (connection->num_req_paquets > 0) {
722 ret = send_data_packet(ludp, connection_id, connection->req_packets[0]);
723 connection->num_req_paquets--;
724 memcpy(buffer, connection->req_packets + 1, connection->num_req_paquets * 4);
725 memcpy(connection->req_packets, buffer, connection->num_req_paquets * 4);
726 return ret;
727 }
728
729 if (connection->sendbuff_packetnum != connection->sent_packetnum) {
730 ret = send_data_packet(ludp, connection_id, connection->sent_packetnum);
731 connection->sent_packetnum++;
732 return ret;
733 }
734
735 return 0;
736}
737
738/*
739 * END of packet sending functions.
740 *
741 *
742 * BEGIN Packet handling functions.
743 * One to handle each type of packets we receive.
744 */
745
746
747/* return 0 if handled correctly.
748 * return 1 if packet is bad.
749 */
750static int handle_handshake(void *object, IP_Port source, uint8_t *packet, uint32_t length)
751{
752 Lossless_UDP *ludp = object;
753
754 if (length != (1 + 4 + 4))
755 return 1;
756
757 uint32_t temp;
758 uint32_t handshake_id1, handshake_id2;
759 int connection_id = getconnection_id(ludp, source);
760
761 memcpy(&temp, packet + 1, 4);
762 handshake_id1 = ntohl(temp);
763 memcpy(&temp, packet + 5, 4);
764 handshake_id2 = ntohl(temp);
765
766
767 if (handshake_id2 == 0 && is_connected(ludp, connection_id) != LUDP_ESTABLISHED &&
768 is_connected(ludp, connection_id) != LUDP_TIMED_OUT) {
769 send_handshake(ludp, source, handshake_id(ludp, source), handshake_id1);
770 return 0;
771 }
772
773 if (is_connected(ludp, connection_id) != LUDP_HANDSHAKE_SENDING)
774 return 1;
775
776 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
777
778 /* if handshake_id2 is what we sent previously as handshake_id1 */
779 if (handshake_id2 == connection->handshake_id1) {
780 connection->status = LUDP_NOT_CONFIRMED;
781 /* NOTE: Is this necessary?
782 connection->handshake_id2 = handshake_id1; */
783 connection->orecv_packetnum = handshake_id2;
784 connection->osent_packetnum = handshake_id1;
785 connection->recv_packetnum = handshake_id1;
786 connection->successful_read = handshake_id1;
787 }
788
789 return 0;
790}
791
792/* return 1 if sync packet is valid.
793 * return 0 if not.
794 */
795static int SYNC_valid(uint32_t length)
796{
797 if (length < 4 + 4 + 2)
798 return 0;
799
800 if (length > (MAX_REQUESTED_PACKETS * 4 + 4 + 4 + 2) ||
801 ((length - 4 - 4 - 2) % 4) != 0)
802 return 0;
803
804 return 1;
805}
806
807/* case 1 in handle_SYNC: */
808static int handle_SYNC1(Lossless_UDP *ludp, IP_Port source, uint32_t recv_packetnum, uint32_t sent_packetnum)
809{
810 if (handshake_id(ludp, source) == recv_packetnum) {
811 int connection_id = new_inconnection(ludp, source);
812
813 if (connection_id != -1) {
814 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
815 connection->orecv_packetnum = recv_packetnum;
816 connection->sent_packetnum = recv_packetnum;
817 connection->sendbuff_packetnum = recv_packetnum;
818 connection->successful_sent = recv_packetnum;
819 connection->osent_packetnum = sent_packetnum;
820 connection->recv_packetnum = sent_packetnum;
821 connection->successful_read = sent_packetnum;
822
823 return connection_id;
824 }
825 }
826
827 return -1;
828}
829
830/* case 2 in handle_SYNC: */
831static int handle_SYNC2(Lossless_UDP *ludp, int connection_id, uint8_t counter, uint32_t recv_packetnum,
832 uint32_t sent_packetnum)
833{
834 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
835
836 if (recv_packetnum == connection->orecv_packetnum && sent_packetnum == connection->osent_packetnum) {
837 connection->status = LUDP_ESTABLISHED;
838 connection->recv_counter = counter;
839 ++connection->send_counter;
840 send_SYNC(ludp, connection_id);
841 return 0;
842 }
843
844 return 1;
845}
846
847/*
848 * Automatically adjusts send rates of data packets for optimal transmission.
849 *
850 * TODO: Improve this.
851 */
852static void adjust_datasendspeed(Connection *connection, uint32_t req_packets)
853{
854 /* if there are no packets in send buffer */
855 if (connection->sendbuff_packetnum - connection->successful_sent == 0) {
856 connection->data_rate -= connection->data_rate / 8;
857
858 if (connection->data_rate < DATA_SYNC_RATE)
859 connection->data_rate = DATA_SYNC_RATE;
860
861 return;
862 }
863
864 if (req_packets <= (connection->data_rate / connection->SYNC_rate) / 4 || req_packets <= 10) {
865 connection->data_rate += (connection->data_rate / 4) + 1;
866
867 if (connection->data_rate > connection->sendbuffer_length * connection->SYNC_rate)
868 connection->data_rate = connection->sendbuffer_length * connection->SYNC_rate;
869 } else {
870 connection->data_rate -= connection->data_rate / 8;
871 }
872}
873
874
875/* case 3 in handle_SYNC: */
876static int handle_SYNC3(Lossless_UDP *ludp, int connection_id, uint8_t counter, uint32_t recv_packetnum,
877 uint32_t sent_packetnum,
878 uint32_t *req_packets,
879 uint16_t number)
880{
881 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
882
883 uint8_t comp_counter = (counter - connection->recv_counter);
884 uint32_t i, temp;
885 /* uint32_t comp_1 = (recv_packetnum - connection->successful_sent);
886 uint32_t comp_2 = (sent_packetnum - connection->successful_read); */
887 uint32_t comp_1 = (recv_packetnum - connection->orecv_packetnum);
888 uint32_t comp_2 = (sent_packetnum - connection->osent_packetnum);
889
890 /* Packet valid. */
891 if (comp_1 <= connection->sendbuffer_length &&
892 comp_2 <= MAX_QUEUE_NUM &&
893 comp_counter != 0 && comp_counter < 8) {
894 connection->orecv_packetnum = recv_packetnum;
895 connection->osent_packetnum = sent_packetnum;
896 connection->successful_sent = recv_packetnum;
897 connection->last_recvSYNC = current_time();
898
899 connection->recv_counter = counter;
900
901 ++connection->send_counter;
902
903 for (i = 0; i < number; ++i) {
904 temp = ntohl(req_packets[i]);
905 memcpy(connection->req_packets + i, &temp, sizeof(uint32_t));
906 }
907
908 connection->num_req_paquets = number;
909 adjust_datasendspeed(connection, number);
910 return 0;
911 }
912
913 return 1;
914}
915
916static int handle_SYNC(void *object, IP_Port source, uint8_t *packet, uint32_t length)
917{
918 Lossless_UDP *ludp = object;
919
920 if (!SYNC_valid(length))
921 return 1;
922
923 uint8_t counter;
924 uint32_t temp;
925 uint32_t recv_packetnum, sent_packetnum;
926 uint16_t number = (length - 4 - 4 - 2) / 4;
927 uint32_t req_packets[number];
928
929 memcpy(&counter, packet + 1, 1);
930 memcpy(&temp, packet + 2, 4);
931 recv_packetnum = ntohl(temp);
932 memcpy(&temp, packet + 6, 4);
933 sent_packetnum = ntohl(temp);
934
935 if (number != 0)
936 memcpy(req_packets, packet + 10, 4 * number);
937
938 int connection_id = getconnection_id(ludp, source);
939
940 if (connection_id == -1)
941 return handle_SYNC1(ludp, source, recv_packetnum, sent_packetnum);
942
943 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
944
945 if (connection->status == LUDP_NOT_CONFIRMED)
946 return handle_SYNC2(ludp, connection_id, counter,
947 recv_packetnum, sent_packetnum);
948
949 if (connection->status == LUDP_ESTABLISHED)
950 return handle_SYNC3(ludp, connection_id, counter, recv_packetnum,
951 sent_packetnum, req_packets, number);
952
953 return 0;
954}
955
956/*
957 * Add a packet to the received buffer and set the recv_packetnum of the
958 * connection to its proper value.
959 *
960 * return 1 if data was too big.
961 * return 0 if not.
962 */
963static int add_recv(Lossless_UDP *ludp, int connection_id, uint32_t data_num, uint8_t *data, uint16_t size)
964{
965 if (size > MAX_DATA_SIZE)
966 return 1;
967
968 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
969 uint32_t i;
970 uint32_t test = data_num - connection->recv_packetnum;
971
972 if (test > MAX_QUEUE_NUM)
973 return 0;
974
975 if (test > connection->recvbuffer_length) {
976 if (connection->confirmed == 0)
977 return 0;
978
979 uint32_t len = resize_queue(&connection->recvbuffer, connection->recvbuffer_length, test * 2,
980 connection->successful_read, connection->successful_read + connection->recvbuffer_length);
981
982 if (len == (uint32_t)~0)
983 return 0;
984
985 connection->recvbuffer_length = len;
986 }
987
988 uint32_t maxnum = connection->successful_read + connection->recvbuffer_length;
989 uint32_t sent_packet = data_num - connection->osent_packetnum;
990
991 for (i = connection->recv_packetnum; i != maxnum; ++i) {
992 if (i == data_num) {
993 memcpy(connection->recvbuffer[data_num % connection->recvbuffer_length].data, data, size);
994
995 connection->recvbuffer[data_num % connection->recvbuffer_length].size = size;
996 connection->last_recvdata = current_time();
997
998 if (sent_packet < connection->recvbuffer_length)
999 connection->osent_packetnum = data_num;
1000
1001 break;
1002 }
1003 }
1004
1005 for (i = connection->recv_packetnum; i != maxnum; ++i) {
1006 if (connection->recvbuffer[i % connection->recvbuffer_length].size != 0)
1007 connection->recv_packetnum = i;
1008 else
1009 break;
1010 }
1011
1012 return 0;
1013}
1014
1015static int handle_data(void *object, IP_Port source, uint8_t *packet, uint32_t length)
1016{
1017 Lossless_UDP *ludp = object;
1018 int connection_id = getconnection_id(ludp, source);
1019
1020 /* Drop the data packet if connection is not connected. */
1021 if (connection_id == -1)
1022 return 1;
1023
1024 if (tox_array_get(&ludp->connections, connection_id, Connection).status != LUDP_ESTABLISHED)
1025 return 1;
1026
1027 if (length > 1 + 4 + MAX_DATA_SIZE || length < 1 + 4 + 1)
1028 return 1;
1029
1030 uint32_t temp;
1031 uint32_t number;
1032 uint16_t size = length - 1 - 4;
1033
1034 memcpy(&temp, packet + 1, 4);
1035 number = ntohl(temp);
1036
1037 return add_recv(ludp, connection_id, number, packet + 5, size);
1038}
1039
1040/*
1041 * END of packet handling functions.
1042 */
1043
1044Lossless_UDP *new_lossless_udp(Networking_Core *net)
1045{
1046 if (net == NULL)
1047 return NULL;
1048
1049 Lossless_UDP *temp = calloc(1, sizeof(Lossless_UDP));
1050
1051 if (temp == NULL)
1052 return NULL;
1053
1054 tox_array_init(&temp->connections, sizeof(Connection));
1055
1056 temp->net = net;
1057 networking_registerhandler(net, NET_PACKET_HANDSHAKE, &handle_handshake, temp);
1058 networking_registerhandler(net, NET_PACKET_SYNC, &handle_SYNC, temp);
1059 networking_registerhandler(net, NET_PACKET_DATA, &handle_data, temp);
1060 return temp;
1061}
1062
1063/*
1064 * Send handshake requests.
1065 * Handshake packets are sent at the same rate as SYNC packets.
1066 */
1067static void do_new(Lossless_UDP *ludp)
1068{
1069 uint64_t temp_time = current_time();
1070
1071 tox_array_for_each(&ludp->connections, Connection, tmp) {
1072 if (tmp->status == LUDP_HANDSHAKE_SENDING && (tmp->last_sent + (1000000ULL / tmp->SYNC_rate)) <= temp_time) {
1073 send_handshake(ludp, tmp->ip_port, tmp->handshake_id1, 0);
1074 tmp->last_sent = temp_time;
1075 }
1076
1077 /* kill all timed out connections */
1078 if (tmp->status != LUDP_NO_CONNECTION && (tmp->last_recvSYNC + tmp->timeout * 1000000ULL) < temp_time
1079 && tmp->status != LUDP_TIMED_OUT) {
1080 tmp->status = LUDP_TIMED_OUT;
1081 /* kill_connection(i); */
1082 }
1083
1084 if (tmp->status != LUDP_NO_CONNECTION && tmp->killat < temp_time)
1085 tmp->status = LUDP_TIMED_OUT;
1086
1087 if (tmp->inbound == LUDP_CONNECTION_INBOUND && tmp->status == LUDP_TIMED_OUT)
1088 kill_connection(ludp, tmp_i);
1089 }
1090}
1091
1092static void do_SYNC(Lossless_UDP *ludp)
1093{
1094 uint64_t temp_time = current_time();
1095
1096 tox_array_for_each(&ludp->connections, Connection, tmp) {
1097 if (tmp->status == LUDP_NOT_CONFIRMED || tmp->status == LUDP_ESTABLISHED)
1098 if ((tmp->last_SYNC + (1000000ULL / tmp->SYNC_rate)) <= temp_time) {
1099 send_SYNC(ludp, tmp_i);
1100 tmp->last_SYNC = temp_time;
1101 }
1102 }
1103}
1104
1105static void do_data(Lossless_UDP *ludp)
1106{
1107 uint64_t j;
1108 uint64_t temp_time = current_time();
1109
1110 tox_array_for_each(&ludp->connections, Connection, tmp) {
1111 if (tmp->status == LUDP_ESTABLISHED && sendqueue(ludp, tmp_i) != 0 &&
1112 (tmp->last_sent + (1000000ULL / tmp->data_rate)) <= temp_time) {
1113 for (j = tmp->last_sent; j < temp_time; j += (1000000ULL / tmp->data_rate))
1114 if (send_DATA(ludp, tmp_i) <= 0)
1115 break;
1116
1117 tmp->last_sent = temp_time;
1118
1119 }
1120 }
1121}
1122
1123
1124
1125/*
1126 * Automatically adjusts send rates of packets for optimal transmission.
1127 *
1128 * TODO: Flow control.
1129 */
1130static void adjust_rates(Lossless_UDP *ludp)
1131{
1132 uint64_t temp_time = current_time();
1133
1134 tox_array_for_each(&ludp->connections, Connection, tmp) {
1135 if (tmp->status == LUDP_HANDSHAKE_SENDING || tmp->status == LUDP_NOT_CONFIRMED)
1136 tmp->SYNC_rate = MAX_SYNC_RATE;
1137
1138 if (tmp->status == LUDP_ESTABLISHED) {
1139 if (sendqueue(ludp, tmp_i) != 0) {
1140 tmp->SYNC_rate = MAX_SYNC_RATE;
1141 } else if (tmp->last_recvdata + 200000ULL > temp_time) { /* 200 ms */
1142 tmp->SYNC_rate = MAX_SYNC_RATE;
1143 } else {
1144 tmp->SYNC_rate = SYNC_RATE;
1145 }
1146 }
1147 }
1148}
1149
1150/* Call this function a couple times per second. It is the main loop. */
1151void do_lossless_udp(Lossless_UDP *ludp)
1152{
1153 do_new(ludp);
1154 do_SYNC(ludp);
1155 do_data(ludp);
1156 adjust_rates(ludp);
1157}
1158
1159void kill_lossless_udp(Lossless_UDP *ludp)
1160{
1161 uint32_t i;
1162
1163 for (i = 0; i < ludp->connections.len; ++i)
1164 kill_connection(ludp, i);
1165
1166 tox_array_delete(&ludp->connections);
1167 free(ludp);
1168}
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 @@
1/* Lossless_UDP.h
2 *
3 * An implementation of the Lossless_UDP protocol as seen in http://wiki.tox.im/index.php/Lossless_UDP
4 *
5 * Copyright (C) 2013 Tox project All Rights Reserved.
6 *
7 * This file is part of Tox.
8 *
9 * Tox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * Tox is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24#ifndef LOSSLESS_UDP_H
25#define LOSSLESS_UDP_H
26
27#include "network.h"
28#include "crypto_core.h"
29#include "misc_tools.h"
30
31
32/* Maximum length of the data in the data packets. */
33#define MAX_DATA_SIZE 1024
34
35/* Maximum data packets in sent and receive queues. */
36#define MAX_QUEUE_NUM 1024
37#define DEFAULT_QUEUE_NUM 4
38
39/* Maximum number of data packets in the buffer. */
40#define MAX_REQUESTED_PACKETS 256
41
42/* Timeout per connection is randomly set between CONNECTION_TIMEOUT and 2*CONNECTION_TIMEOUT. */
43#define CONNECTION_TIMEOUT 5
44
45/* Initial amount of sync/handshake packets to send per second. */
46#define SYNC_RATE 2
47
48/* Initial send rate of data. */
49#define DATA_SYNC_RATE 30
50
51typedef struct {
52 uint8_t data[MAX_DATA_SIZE];
53 uint16_t size;
54} Data;
55
56#define LUDP_NO_CONNECTION 0
57#define LUDP_HANDSHAKE_SENDING 1
58#define LUDP_NOT_CONFIRMED 2
59#define LUDP_ESTABLISHED 3
60#define LUDP_TIMED_OUT 4
61
62typedef struct {
63 IP_Port ip_port;
64
65 /*
66 * return LUDP_NO_CONNECTION if connection is dead.
67 * return LUDP_HANDSHAKE_SENDING if attempting handshake.
68 * return LUDP_NOT_CONFIRMED if handshake is done (we start sending SYNC packets).
69 * return LUDP_ESTABLISHED if we are sending SYNC packets and can send data.
70 * return LUDP_TIMED_OUT if the connection has timed out.
71 */
72 uint8_t status;
73
74 /*
75 * return 0 if connection was not initiated by someone else.
76 * return 1 if incoming_connection() has returned.
77 * return 2 if it has not.
78 */
79 uint8_t inbound;
80
81 uint16_t SYNC_rate; /* Current SYNC packet send rate packets per second. */
82 uint32_t data_rate; /* Current data packet send rate packets per second. */
83
84 uint64_t last_SYNC; /* Time our last SYNC packet was sent. */
85 uint64_t last_sent; /* Time our last data or handshake packet was sent. */
86 uint64_t last_recvSYNC; /* Time we last received a SYNC packet from the other. */
87 uint64_t last_recvdata; /* Time we last received a DATA packet from the other. */
88 uint64_t killat; /* Time to kill the connection. */
89
90 Data *sendbuffer; /* packet send buffer. */
91 uint32_t sendbuffer_length;
92 Data *recvbuffer; /* packet receive buffer. */
93 uint32_t recvbuffer_length;
94 uint32_t handshake_id1;
95 uint32_t handshake_id2;
96
97 /* Number of data packets received (also used as handshake_id1). */
98 uint32_t recv_packetnum;
99
100 /* Number of packets received by the other peer. */
101 uint32_t orecv_packetnum;
102
103 /* Number of data packets sent. */
104 uint32_t sent_packetnum;
105
106 /* Number of packets sent by the other peer. */
107 uint32_t osent_packetnum;
108
109 /* Number of latest packet written onto the sendbuffer. */
110 uint32_t sendbuff_packetnum;
111
112 /* We know all packets before that number were successfully sent. */
113 uint32_t successful_sent;
114
115 /* Packet number of last packet read with the read_packet function. */
116 uint32_t successful_read;
117
118 /* List of currently requested packet numbers(by the other person). */
119 uint32_t req_packets[MAX_REQUESTED_PACKETS];
120
121 /* Total number of currently requested packets(by the other person). */
122 uint16_t num_req_paquets;
123
124 uint8_t recv_counter;
125 uint8_t send_counter;
126 uint8_t timeout; /* connection timeout in seconds. */
127
128 /* Is the connection confirmed or not? 1 if yes, 0 if no */
129 uint8_t confirmed;
130} Connection;
131
132typedef struct {
133 Networking_Core *net;
134
135 tox_array connections;
136
137 /* Table of random numbers used in handshake_id. */
138 /* IPv6 (16) + port (2)*/
139 uint32_t randtable[18][256];
140} Lossless_UDP;
141
142/*
143 * Initialize a new connection to ip_port.
144 *
145 * return an integer corresponding to the connection id.
146 * return -1 if it could not initialize the connection.
147 * return number if there already was an existing connection to that ip_port.
148 */
149int new_connection(Lossless_UDP *ludp, IP_Port ip_port);
150
151/*
152 * Get connection id from IP_Port.
153 *
154 * return -1 if there are no connections like we are looking for.
155 * return id if it found it .
156 */
157int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port);
158
159/*
160 * return an integer corresponding to the next connection in our incoming connection list with at least numpackets in the recieve queue.
161 * return -1 if there are no new incoming connections in the list.
162 */
163int incoming_connection(Lossless_UDP *ludp, uint32_t numpackets);
164
165/* return -1 if it could not kill the connection.
166 * return 0 if killed successfully.
167 */
168int kill_connection(Lossless_UDP *ludp, int connection_id);
169
170/*
171 * timeout connection in seconds seconds.
172 *
173 * return -1 if it can not kill the connection.
174 * return 0 if it will kill it.
175 */
176int timeout_connection_in(Lossless_UDP *ludp, int connection_id, uint32_t seconds);
177
178
179/* Check if connection is confirmed.
180 *
181 * returns 1 if yes.
182 * returns 0 if no.
183 */
184int connection_confirmed(Lossless_UDP *ludp, int connection_id);
185
186/* Confirm an incoming connection.
187 * Also disables the auto kill timeout on incomming connections.
188 *
189 * return 0 on success
190 * return -1 on failure.
191 */
192int confirm_connection(Lossless_UDP *ludp, int connection_id);
193
194/* returns the ip_port of the corresponding connection.
195 * return 0 if there is no such connection.
196 */
197IP_Port connection_ip(Lossless_UDP *ludp, int connection_id);
198
199/* returns the id of the next packet in the queue.
200 * return -1 if no packet in queue.
201 */
202uint8_t id_packet(Lossless_UDP *ludp, int connection_id);
203
204/* return 0 if there is no received data in the buffer.
205 * return length of received packet if successful.
206 */
207int read_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data);
208
209/* Like read_packet() but does leaves the queue as is.
210 * return 0 if there is no received data in the buffer.
211 * return length of received packet if successful.
212 */
213int read_packet_silent(Lossless_UDP *ludp, int connection_id, uint8_t *data);
214
215/* Discard the next packet to be read from the queue
216 * return 0 if success.
217 * return -1 if failure.
218 */
219int discard_packet(Lossless_UDP *ludp, int connection_id);
220
221/* returns the number of packet slots left in the sendbuffer.
222 * return 0 if failure.
223 */
224uint32_t num_free_sendqueue_slots(Lossless_UDP *ludp, int connection_id);
225
226/* return 0 if data could not be put in packet queue.
227 * return 1 if data was put into the queue.
228 */
229int write_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data, uint32_t length);
230
231/* return number of packets in the queue waiting to be successfully sent. */
232uint32_t sendqueue(Lossless_UDP *ludp, int connection_id);
233
234/* return number of packets in all queues waiting to be successfully sent. */
235uint32_t sendqueue_total(Lossless_UDP *ludp);
236
237/*
238 * return number of packets in the queue waiting to be successfully
239 * read with read_packet(...).
240 */
241uint32_t recvqueue(Lossless_UDP *ludp, int connection_id);
242
243/* Check if connection is connected:
244 *
245 * return LUDP_NO_CONNECTION if not.
246 * return LUDP_HANDSHAKE_SENDING if attempting handshake.
247 * return LUDP_NOT_CONFIRMED if handshake is done.
248 * return LUDP_ESTABLISHED if fully connected.
249 * return LUDP_TIMED_OUT if timed out and wating to be killed.
250 */
251int is_connected(Lossless_UDP *ludp, int connection_id);
252
253/* Call this function a couple times per second. It is the main loop. */
254void do_lossless_udp(Lossless_UDP *ludp);
255
256/* This function sets up LosslessUDP packet handling. */
257Lossless_UDP *new_lossless_udp(Networking_Core *net);
258
259void kill_lossless_udp(Lossless_UDP *ludp);
260
261
262#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 \
11 ../toxcore/network.c \ 11 ../toxcore/network.c \
12 ../toxcore/crypto_core.h \ 12 ../toxcore/crypto_core.h \
13 ../toxcore/crypto_core.c \ 13 ../toxcore/crypto_core.c \
14 ../toxcore/Lossless_UDP.h \
15 ../toxcore/Lossless_UDP.c \
16 ../toxcore/net_crypto.h \ 14 ../toxcore/net_crypto.h \
17 ../toxcore/net_crypto.c \ 15 ../toxcore/net_crypto.c \
18 ../toxcore/friend_requests.h \ 16 ../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
406 406
407uint32_t m_sendmessage_withid(Messenger *m, int32_t friendnumber, uint32_t theid, uint8_t *message, uint32_t length) 407uint32_t m_sendmessage_withid(Messenger *m, int32_t friendnumber, uint32_t theid, uint8_t *message, uint32_t length)
408{ 408{
409 if (length >= (MAX_DATA_SIZE - sizeof(theid))) 409 if (length >= (MAX_CRYPTO_DATA_SIZE - sizeof(theid)))
410 return 0; 410 return 0;
411 411
412 uint8_t temp[MAX_DATA_SIZE]; 412 uint8_t temp[MAX_CRYPTO_DATA_SIZE];
413 theid = htonl(theid); 413 theid = htonl(theid);
414 memcpy(temp, &theid, sizeof(theid)); 414 memcpy(temp, &theid, sizeof(theid));
415 memcpy(temp + sizeof(theid), message, length); 415 memcpy(temp + sizeof(theid), message, length);
@@ -440,10 +440,10 @@ uint32_t m_sendaction(Messenger *m, int32_t friendnumber, uint8_t *action, uint3
440 440
441uint32_t m_sendaction_withid(Messenger *m, int32_t friendnumber, uint32_t theid, uint8_t *action, uint32_t length) 441uint32_t m_sendaction_withid(Messenger *m, int32_t friendnumber, uint32_t theid, uint8_t *action, uint32_t length)
442{ 442{
443 if (length >= (MAX_DATA_SIZE - sizeof(theid))) 443 if (length >= (MAX_CRYPTO_DATA_SIZE - sizeof(theid)))
444 return 0; 444 return 0;
445 445
446 uint8_t temp[MAX_DATA_SIZE]; 446 uint8_t temp[MAX_CRYPTO_DATA_SIZE];
447 theid = htonl(theid); 447 theid = htonl(theid);
448 memcpy(temp, &theid, sizeof(theid)); 448 memcpy(temp, &theid, sizeof(theid));
449 memcpy(temp + sizeof(theid), action, length); 449 memcpy(temp + sizeof(theid), action, length);
@@ -840,7 +840,7 @@ int write_cryptpacket_id(Messenger *m, int32_t friendnumber, uint8_t packet_id,
840 if (friend_not_valid(m, friendnumber)) 840 if (friend_not_valid(m, friendnumber))
841 return 0; 841 return 0;
842 842
843 if (length >= MAX_DATA_SIZE || m->friendlist[friendnumber].status != FRIEND_ONLINE) 843 if (length >= MAX_CRYPTO_DATA_SIZE || m->friendlist[friendnumber].status != FRIEND_ONLINE)
844 return 0; 844 return 0;
845 845
846 uint8_t packet[length + 1]; 846 uint8_t packet[length + 1];
@@ -888,7 +888,7 @@ static IP_Port get_friend_ipport(Messenger *m, int32_t friendnumber)
888 if (is_cryptoconnected(m->net_crypto, crypt_id) != CRYPTO_CONN_ESTABLISHED) 888 if (is_cryptoconnected(m->net_crypto, crypt_id) != CRYPTO_CONN_ESTABLISHED)
889 return zero; 889 return zero;
890 890
891 return connection_ip(m->net_crypto->lossless_udp, m->net_crypto->crypto_connections[crypt_id].number); 891 return m->net_crypto->crypto_connections[crypt_id].ip_port;
892} 892}
893 893
894/* returns the group number of the chat with public key group_public_key. 894/* 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_
1395int file_control(Messenger *m, int32_t friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t message_id, 1395int file_control(Messenger *m, int32_t friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t message_id,
1396 uint8_t *data, uint16_t length) 1396 uint8_t *data, uint16_t length)
1397{ 1397{
1398 if (length > MAX_DATA_SIZE - 3) 1398 if (length > MAX_CRYPTO_DATA_SIZE - 3)
1399 return -1; 1399 return -1;
1400 1400
1401 if (friend_not_valid(m, friendnumber)) 1401 if (friend_not_valid(m, friendnumber))
@@ -1412,7 +1412,7 @@ int file_control(Messenger *m, int32_t friendnumber, uint8_t send_receive, uint8
1412 if (send_receive > 1) 1412 if (send_receive > 1)
1413 return -1; 1413 return -1;
1414 1414
1415 uint8_t packet[MAX_DATA_SIZE]; 1415 uint8_t packet[MAX_CRYPTO_DATA_SIZE];
1416 packet[0] = send_receive; 1416 packet[0] = send_receive;
1417 packet[1] = filenumber; 1417 packet[1] = filenumber;
1418 packet[2] = message_id; 1418 packet[2] = message_id;
@@ -1482,7 +1482,7 @@ int file_control(Messenger *m, int32_t friendnumber, uint8_t send_receive, uint8
1482 */ 1482 */
1483int file_data(Messenger *m, int32_t friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length) 1483int file_data(Messenger *m, int32_t friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length)
1484{ 1484{
1485 if (length > MAX_DATA_SIZE - 1) 1485 if (length > MAX_CRYPTO_DATA_SIZE - 1)
1486 return -1; 1486 return -1;
1487 1487
1488 if (friend_not_valid(m, friendnumber)) 1488 if (friend_not_valid(m, friendnumber))
@@ -1495,7 +1495,7 @@ int file_data(Messenger *m, int32_t friendnumber, uint8_t filenumber, uint8_t *d
1495 if (crypto_num_free_sendqueue_slots(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id) < MIN_SLOTS_FREE) 1495 if (crypto_num_free_sendqueue_slots(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id) < MIN_SLOTS_FREE)
1496 return -1; 1496 return -1;
1497 1497
1498 uint8_t packet[MAX_DATA_SIZE]; 1498 uint8_t packet[MAX_CRYPTO_DATA_SIZE];
1499 packet[0] = filenumber; 1499 packet[0] = filenumber;
1500 memcpy(packet + 1, data, length); 1500 memcpy(packet + 1, data, length);
1501 1501
@@ -1738,6 +1738,23 @@ static void LANdiscovery(Messenger *m)
1738 } 1738 }
1739} 1739}
1740 1740
1741int handle_new_connections(void *object, New_Connection *n_c)
1742{
1743 Messenger *m = object;
1744 int friend_id = getfriend_id(m, n_c->public_key);
1745
1746 if (friend_id != -1) {
1747 if (m->friendlist[friend_id].crypt_connection_id != -1)
1748 return -1;
1749
1750 m->friendlist[friend_id].crypt_connection_id = accept_crypto_connection(m->net_crypto, n_c);
1751 set_friend_status(m, friend_id, FRIEND_CONFIRMED);
1752 }
1753
1754 return -1;
1755}
1756
1757
1741/* Run this at startup. */ 1758/* Run this at startup. */
1742Messenger *new_messenger(uint8_t ipv6enabled) 1759Messenger *new_messenger(uint8_t ipv6enabled)
1743{ 1760{
@@ -1772,6 +1789,8 @@ Messenger *new_messenger(uint8_t ipv6enabled)
1772 return NULL; 1789 return NULL;
1773 } 1790 }
1774 1791
1792 new_connection_handler(m->net_crypto, &handle_new_connections, m);
1793
1775 m->onion = new_onion(m->dht); 1794 m->onion = new_onion(m->dht);
1776 m->onion_a = new_onion_announce(m->dht); 1795 m->onion_a = new_onion_announce(m->dht);
1777 m->onion_c = new_onion_client(m->net_crypto); 1796 m->onion_c = new_onion_client(m->net_crypto);
@@ -1843,7 +1862,7 @@ void do_friends(Messenger *m)
1843{ 1862{
1844 uint32_t i; 1863 uint32_t i;
1845 int len; 1864 int len;
1846 uint8_t temp[MAX_DATA_SIZE]; 1865 uint8_t temp[MAX_CRYPTO_DATA_SIZE];
1847 uint64_t temp_time = unix_time(); 1866 uint64_t temp_time = unix_time();
1848 1867
1849 for (i = 0; i < m->numfriends; ++i) { 1868 for (i = 0; i < m->numfriends; ++i) {
@@ -2184,32 +2203,8 @@ void do_friends(Messenger *m)
2184 } 2203 }
2185} 2204}
2186 2205
2187void do_inbound(Messenger *m)
2188{
2189 uint8_t secret_nonce[crypto_box_NONCEBYTES];
2190 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
2191 uint8_t session_key[crypto_box_PUBLICKEYBYTES];
2192 int inconnection = crypto_inbound(m->net_crypto, public_key, secret_nonce, session_key);
2193
2194 if (inconnection != -1) {
2195 int friend_id = getfriend_id(m, public_key);
2196
2197 if (friend_id != -1) {
2198 if (m_get_friend_connectionstatus(m, friend_id) == 1) {
2199 kill_connection(m->net_crypto->lossless_udp, inconnection);
2200 return;
2201 }
2202 2206
2203 crypto_kill(m->net_crypto, m->friendlist[friend_id].crypt_connection_id);
2204 m->friendlist[friend_id].crypt_connection_id =
2205 accept_crypto_inbound(m->net_crypto, inconnection, public_key, secret_nonce, session_key);
2206 2207
2207 set_friend_status(m, friend_id, FRIEND_CONFIRMED);
2208 } else {
2209 kill_connection(m->net_crypto->lossless_udp, inconnection);
2210 }
2211 }
2212}
2213 2208
2214#ifdef LOGGING 2209#ifdef LOGGING
2215#define DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS 60UL 2210#define DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS 60UL
@@ -2238,7 +2233,6 @@ void do_messenger(Messenger *m)
2238 do_net_crypto(m->net_crypto); 2233 do_net_crypto(m->net_crypto);
2239 do_onion_client(m->onion_c); 2234 do_onion_client(m->onion_c);
2240 do_friends(m); 2235 do_friends(m);
2241 do_inbound(m);
2242 do_allgroupchats(m); 2236 do_allgroupchats(m);
2243 LANdiscovery(m); 2237 LANdiscovery(m);
2244 2238
@@ -2381,7 +2375,9 @@ size_t wait_data_size()
2381 2375
2382int wait_prepare_messenger(Messenger *m, uint8_t *data) 2376int wait_prepare_messenger(Messenger *m, uint8_t *data)
2383{ 2377{
2384 return networking_wait_prepare(m->net, sendqueue_total(m->net_crypto->lossless_udp), data); 2378 //TODO
2379 //return networking_wait_prepare(m->net, sendqueue_total(m->net_crypto->lossless_udp), data);
2380 return networking_wait_prepare(m->net, 1024, data);
2385} 2381}
2386 2382
2387int wait_execute_messenger(uint8_t *data, long seconds, long microseconds) 2383int 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 @@
34#include "onion_client.h" 34#include "onion_client.h"
35 35
36#define MAX_NAME_LENGTH 128 36#define MAX_NAME_LENGTH 128
37/* TODO: this must depend on other variable. */
37#define MAX_STATUSMESSAGE_LENGTH 1007 38#define MAX_STATUSMESSAGE_LENGTH 1007
38 39
39#define FRIEND_ADDRESS_SIZE (crypto_box_PUBLICKEYBYTES + sizeof(uint32_t) + sizeof(uint16_t)) 40#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,
705 * 705 *
706 * The set function should return -1 on failure and 0 on success. 706 * The set function should return -1 on failure and 0 on success.
707 * 707 *
708 * n_c is only valid for the duration of this function. 708 * n_c is only valid for the duration of the function call.
709 */ 709 */
710void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void *object, New_Connection *n_c), 710void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void *object, New_Connection *n_c),
711 void *object) 711 void *object)
@@ -968,31 +968,7 @@ static void send_crypto_packets(Net_Crypto *c)
968 */ 968 */
969int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data) 969int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data)
970{ 970{
971 if (crypt_connection_id_not_valid(c, crypt_connection_id))
972 return 0;
973
974 if (c->crypto_connections[crypt_connection_id].status != CRYPTO_CONN_ESTABLISHED)
975 return 0;
976
977 uint8_t temp_data[MAX_DATA_SIZE];
978 int length = read_packet(c->lossless_udp, c->crypto_connections[crypt_connection_id].number, temp_data);
979
980 if (length == 0)
981 return 0;
982
983 if (temp_data[0] != 3)
984 return -1;
985 971
986 int len = decrypt_data_symmetric(c->crypto_connections[crypt_connection_id].shared_key,
987 c->crypto_connections[crypt_connection_id].recv_nonce,
988 temp_data + 1, length - 1, data);
989
990 if (len != -1) {
991 increment_nonce(c->crypto_connections[crypt_connection_id].recv_nonce);
992 return len;
993 }
994
995 return -1;
996} 972}
997 973
998/* returns the number of packet slots left in the sendbuffer. 974/* 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)
1000 */ 976 */
1001uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id) 977uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id)
1002{ 978{
1003 if (crypt_connection_id_not_valid(c, crypt_connection_id))
1004 return 0;
1005 979
1006 return num_free_sendqueue_slots(c->lossless_udp, c->crypto_connections[crypt_connection_id].number);
1007} 980}
1008 981
1009/* return 0 if data could not be put in packet queue. 982/* 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)
1011 */ 984 */
1012int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length) 985int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length)
1013{ 986{
1014 if (crypt_connection_id_not_valid(c, crypt_connection_id))
1015 return 0;
1016
1017 if (length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE - 1)
1018 return 0;
1019
1020 if (c->crypto_connections[crypt_connection_id].status != CRYPTO_CONN_ESTABLISHED)
1021 return 0;
1022
1023 uint8_t temp_data[MAX_DATA_SIZE];
1024 int len = encrypt_data_symmetric(c->crypto_connections[crypt_connection_id].shared_key,
1025 c->crypto_connections[crypt_connection_id].sent_nonce,
1026 data, length, temp_data + 1);
1027
1028 if (len == -1)
1029 return 0;
1030
1031 temp_data[0] = 3;
1032
1033 if (write_packet(c->lossless_udp, c->crypto_connections[crypt_connection_id].number, temp_data, len + 1) == 0)
1034 return 0;
1035 987
1036 increment_nonce(c->crypto_connections[crypt_connection_id].sent_nonce);
1037 return 1;
1038}
1039
1040
1041/* Send a crypto handshake packet containing an encrypted secret nonce and session public key
1042 * to peer with connection_id and public_key.
1043 * The packet is encrypted with a random nonce which is sent in plain text with the packet.
1044 */
1045static int send_cryptohandshake(Net_Crypto *c, int connection_id, uint8_t *public_key, uint8_t *secret_nonce,
1046 uint8_t *session_key)
1047{
1048 uint8_t temp_data[MAX_DATA_SIZE];
1049 uint8_t temp[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES];
1050 uint8_t nonce[crypto_box_NONCEBYTES];
1051
1052 new_nonce(nonce);
1053 memcpy(temp, secret_nonce, crypto_box_NONCEBYTES);
1054 memcpy(temp + crypto_box_NONCEBYTES, session_key, crypto_box_PUBLICKEYBYTES);
1055
1056 int len = encrypt_data(public_key, c->self_secret_key, nonce, temp, crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES,
1057 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + temp_data);
1058
1059 if (len == -1)
1060 return 0;
1061
1062 temp_data[0] = 2;
1063 memcpy(temp_data + 1, c->self_public_key, crypto_box_PUBLICKEYBYTES);
1064 memcpy(temp_data + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES);
1065 return write_packet(c->lossless_udp, connection_id, temp_data,
1066 len + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES);
1067}
1068
1069/* Extract secret nonce, session public key and public_key from a packet(data) with length length.
1070 *
1071 * return 1 if successful.
1072 * return 0 if failure.
1073 */
1074static int handle_cryptohandshake(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce,
1075 uint8_t *session_key, uint8_t *data, uint16_t length)
1076{
1077 int pad = (- crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES);
1078
1079 if (length != 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES
1080 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + pad) {
1081 return 0;
1082 }
1083
1084 if (data[0] != 2)
1085 return 0;
1086
1087 uint8_t temp[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES];
1088
1089 memcpy(public_key, data + 1, crypto_box_PUBLICKEYBYTES);
1090
1091 int len = decrypt_data(public_key, c->self_secret_key, data + 1 + crypto_box_PUBLICKEYBYTES,
1092 data + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES,
1093 crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + pad, temp);
1094
1095 if (len != crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES)
1096 return 0;
1097
1098 memcpy(secret_nonce, temp, crypto_box_NONCEBYTES);
1099 memcpy(session_key, temp + crypto_box_NONCEBYTES, crypto_box_PUBLICKEYBYTES);
1100 return 1;
1101} 988}
1102 989
1103 990
@@ -1108,92 +995,7 @@ static int handle_cryptohandshake(Net_Crypto *c, uint8_t *public_key, uint8_t *s
1108 */ 995 */
1109int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port) 996int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port)
1110{ 997{
1111 uint32_t i;
1112 int id_existing = getcryptconnection_id(c, public_key);
1113
1114 if (id_existing != -1) {
1115 IP_Port c_ip = connection_ip(c->lossless_udp, c->crypto_connections[id_existing].number);
1116 998
1117 if (ipport_equal(&c_ip, &ip_port))
1118 return -1;
1119 }
1120
1121 if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == -1
1122 || c->crypto_connections == NULL)
1123 return -1;
1124
1125 memset(&(c->crypto_connections[c->crypto_connections_length]), 0, sizeof(Crypto_Connection));
1126 c->crypto_connections[c->crypto_connections_length].number = ~0;
1127
1128 for (i = 0; i <= c->crypto_connections_length; ++i) {
1129 if (c->crypto_connections[i].status == CRYPTO_CONN_NO_CONNECTION) {
1130 int id_new = new_connection(c->lossless_udp, ip_port);
1131
1132 if (id_new == -1)
1133 return -1;
1134
1135 c->crypto_connections[i].number = id_new;
1136 c->crypto_connections[i].status = CRYPTO_CONN_HANDSHAKE_SENT;
1137 random_nonce(c->crypto_connections[i].recv_nonce);
1138 memcpy(c->crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES);
1139 crypto_box_keypair(c->crypto_connections[i].sessionpublic_key, c->crypto_connections[i].sessionsecret_key);
1140 c->crypto_connections[i].timeout = unix_time() + CRYPTO_HANDSHAKE_TIMEOUT;
1141
1142 if (c->crypto_connections_length == i)
1143 ++c->crypto_connections_length;
1144
1145 if (send_cryptohandshake(c, id_new, public_key, c->crypto_connections[i].recv_nonce,
1146 c->crypto_connections[i].sessionpublic_key) == 1) {
1147 increment_nonce(c->crypto_connections[i].recv_nonce);
1148 return i;
1149 }
1150
1151 return -1; /* This should never happen. */
1152 }
1153 }
1154
1155 return -1;
1156}
1157
1158/* Handle an incoming connection.
1159 *
1160 * return -1 if no crypto inbound connection.
1161 * return incoming connection id (Lossless_UDP one) if there is an incoming crypto connection.
1162 *
1163 * Put the public key of the peer in public_key, the secret_nonce from the handshake into secret_nonce
1164 * and the session public key for the connection in session_key.
1165 * to accept it see: accept_crypto_inbound(...).
1166 * to refuse it just call kill_connection(...) on the connection id.
1167 */
1168int crypto_inbound(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key)
1169{
1170 while (1) {
1171 int incoming_con = incoming_connection(c->lossless_udp, 1);
1172
1173 if (incoming_con != -1) {
1174 if (is_connected(c->lossless_udp, incoming_con) == LUDP_TIMED_OUT) {
1175 kill_connection(c->lossless_udp, incoming_con);
1176 continue;
1177 }
1178
1179 if (id_packet(c->lossless_udp, incoming_con) == 2) {
1180 uint8_t temp_data[MAX_DATA_SIZE];
1181 uint16_t len = read_packet_silent(c->lossless_udp, incoming_con, temp_data);
1182
1183 if (handle_cryptohandshake(c, public_key, secret_nonce, session_key, temp_data, len)) {
1184 return incoming_con;
1185 } else {
1186 kill_connection(c->lossless_udp, incoming_con);
1187 }
1188 } else {
1189 kill_connection(c->lossless_udp, incoming_con);
1190 }
1191 } else {
1192 break;
1193 }
1194 }
1195
1196 return -1;
1197} 999}
1198 1000
1199/* Kill a crypto connection. 1001/* Kill a crypto connection.
@@ -1203,94 +1005,7 @@ int crypto_inbound(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, ui
1203 */ 1005 */
1204int crypto_kill(Net_Crypto *c, int crypt_connection_id) 1006int crypto_kill(Net_Crypto *c, int crypt_connection_id)
1205{ 1007{
1206 if (crypt_connection_id_not_valid(c, crypt_connection_id))
1207 return 1;
1208
1209 if (c->crypto_connections[crypt_connection_id].status != CRYPTO_CONN_NO_CONNECTION) {
1210 c->crypto_connections[crypt_connection_id].status = CRYPTO_CONN_NO_CONNECTION;
1211 kill_connection(c->lossless_udp, c->crypto_connections[crypt_connection_id].number);
1212 memset(&(c->crypto_connections[crypt_connection_id]), 0 , sizeof(Crypto_Connection));
1213 c->crypto_connections[crypt_connection_id].number = ~0;
1214 uint32_t i;
1215
1216 for (i = c->crypto_connections_length; i != 0; --i) {
1217 if (c->crypto_connections[i - 1].status != CRYPTO_CONN_NO_CONNECTION)
1218 break;
1219 }
1220
1221 if (c->crypto_connections_length != i) {
1222 c->crypto_connections_length = i;
1223 realloc_cryptoconnection(c, c->crypto_connections_length);
1224 }
1225
1226 return 0;
1227 }
1228
1229 return 1;
1230}
1231
1232/* Accept an incoming connection using the parameters provided by crypto_inbound.
1233 *
1234 * return -1 if not successful.
1235 * return the crypt_connection_id if successful.
1236 */
1237int accept_crypto_inbound(Net_Crypto *c, int connection_id, uint8_t *public_key, uint8_t *secret_nonce,
1238 uint8_t *session_key)
1239{
1240 uint32_t i;
1241
1242 if (discard_packet(c->lossless_udp, connection_id) == -1)
1243 return -1;
1244
1245 /*
1246 * if(getcryptconnection_id(public_key) != -1)
1247 * {
1248 * return -1;
1249 * }
1250 */
1251
1252 if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == -1
1253 || c->crypto_connections == NULL)
1254 return -1;
1255
1256 memset(&(c->crypto_connections[c->crypto_connections_length]), 0, sizeof(Crypto_Connection));
1257 c->crypto_connections[c->crypto_connections_length].number = ~0;
1258 1008
1259 for (i = 0; i <= c->crypto_connections_length; ++i) {
1260 if (c->crypto_connections[i].status == CRYPTO_CONN_NO_CONNECTION) {
1261 c->crypto_connections[i].number = connection_id;
1262 c->crypto_connections[i].status = CRYPTO_CONN_NOT_CONFIRMED;
1263 c->crypto_connections[i].timeout = unix_time() + CRYPTO_HANDSHAKE_TIMEOUT;
1264 random_nonce(c->crypto_connections[i].recv_nonce);
1265 memcpy(c->crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES);
1266 memcpy(c->crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES);
1267 increment_nonce(c->crypto_connections[i].sent_nonce);
1268 memcpy(c->crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES);
1269
1270 crypto_box_keypair(c->crypto_connections[i].sessionpublic_key, c->crypto_connections[i].sessionsecret_key);
1271
1272 if (c->crypto_connections_length == i)
1273 ++c->crypto_connections_length;
1274
1275 if (send_cryptohandshake(c, connection_id, public_key, c->crypto_connections[i].recv_nonce,
1276 c->crypto_connections[i].sessionpublic_key) == 1) {
1277 increment_nonce(c->crypto_connections[i].recv_nonce);
1278 uint32_t zero = 0;
1279 encrypt_precompute(c->crypto_connections[i].peersessionpublic_key,
1280 c->crypto_connections[i].sessionsecret_key,
1281 c->crypto_connections[i].shared_key);
1282 c->crypto_connections[i].status =
1283 CRYPTO_CONN_ESTABLISHED; /* Connection status needs to be 3 for write_cryptpacket() to work. */
1284 write_cryptpacket(c, i, ((uint8_t *)&zero), sizeof(zero));
1285 c->crypto_connections[i].status = CRYPTO_CONN_NOT_CONFIRMED; /* Set it to its proper value right after. */
1286 return i;
1287 }
1288
1289 return -1; /* This should never happen. */
1290 }
1291 }
1292
1293 return -1;
1294} 1009}
1295 1010
1296/* return 0 if no connection. 1011/* return 0 if no connection.
@@ -1333,84 +1048,7 @@ void load_keys(Net_Crypto *c, uint8_t *keys)
1333/* Handle received packets for not yet established crypto connections. */ 1048/* Handle received packets for not yet established crypto connections. */
1334static void receive_crypto(Net_Crypto *c) 1049static void receive_crypto(Net_Crypto *c)
1335{ 1050{
1336 uint32_t i;
1337 uint64_t temp_time = unix_time();
1338
1339 for (i = 0; i < c->crypto_connections_length; ++i) {
1340 if (c->crypto_connections[i].status == CRYPTO_CONN_NO_CONNECTION)
1341 continue;
1342
1343 if (c->crypto_connections[i].status == CRYPTO_CONN_HANDSHAKE_SENT) {
1344 uint8_t temp_data[MAX_DATA_SIZE];
1345 uint8_t secret_nonce[crypto_box_NONCEBYTES];
1346 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
1347 uint8_t session_key[crypto_box_PUBLICKEYBYTES];
1348 uint16_t len;
1349
1350 if (id_packet(c->lossless_udp, c->crypto_connections[i].number) == 2) { /* Handle handshake packet. */
1351 len = read_packet(c->lossless_udp, c->crypto_connections[i].number, temp_data);
1352
1353 if (handle_cryptohandshake(c, public_key, secret_nonce, session_key, temp_data, len)) {
1354 if (memcmp(public_key, c->crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) {
1355 memcpy(c->crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES);
1356 memcpy(c->crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES);
1357 increment_nonce(c->crypto_connections[i].sent_nonce);
1358 uint32_t zero = 0;
1359 encrypt_precompute(c->crypto_connections[i].peersessionpublic_key,
1360 c->crypto_connections[i].sessionsecret_key,
1361 c->crypto_connections[i].shared_key);
1362 c->crypto_connections[i].status =
1363 CRYPTO_CONN_ESTABLISHED; /* Connection status needs to be 3 for write_cryptpacket() to work. */
1364 write_cryptpacket(c, i, ((uint8_t *)&zero), sizeof(zero));
1365 c->crypto_connections[i].status = CRYPTO_CONN_NOT_CONFIRMED; /* Set it to its proper value right after. */
1366 } else {
1367 /* This should not happen, timeout the connection if it does. */
1368 c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT;
1369 }
1370 } else {
1371 /* This should not happen, timeout the connection if it does. */
1372 c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT;
1373 }
1374 } else if (id_packet(c->lossless_udp,
1375 c->crypto_connections[i].number) != (uint8_t)~0) {
1376 /* This should not happen, timeout the connection if it does. */
1377 c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT;
1378 }
1379 }
1380 1051
1381 if (c->crypto_connections[i].status == CRYPTO_CONN_NOT_CONFIRMED) {
1382 if (id_packet(c->lossless_udp, c->crypto_connections[i].number) == 3) {
1383 uint8_t temp_data[MAX_DATA_SIZE];
1384 uint8_t data[MAX_DATA_SIZE];
1385 int length = read_packet(c->lossless_udp, c->crypto_connections[i].number, temp_data);
1386 int len = decrypt_data(c->crypto_connections[i].peersessionpublic_key,
1387 c->crypto_connections[i].sessionsecret_key,
1388 c->crypto_connections[i].recv_nonce, temp_data + 1, length - 1, data);
1389 uint32_t zero = 0;
1390
1391 if (len == sizeof(uint32_t) && memcmp(((uint8_t *)&zero), data, sizeof(uint32_t)) == 0) {
1392 increment_nonce(c->crypto_connections[i].recv_nonce);
1393 encrypt_precompute(c->crypto_connections[i].peersessionpublic_key,
1394 c->crypto_connections[i].sessionsecret_key,
1395 c->crypto_connections[i].shared_key);
1396 c->crypto_connections[i].status = CRYPTO_CONN_ESTABLISHED;
1397 c->crypto_connections[i].timeout = ~0;
1398 /* Connection is accepted. */
1399 confirm_connection(c->lossless_udp, c->crypto_connections[i].number);
1400 } else {
1401 /* This should not happen, timeout the connection if it does. */
1402 c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT;
1403 }
1404 } else if (id_packet(c->lossless_udp, c->crypto_connections[i].number) != (uint8_t)~0) {
1405 /* This should not happen, timeout the connection if it does. */
1406 c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT;
1407 }
1408 }
1409
1410 if (temp_time > c->crypto_connections[i].timeout) {
1411 c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT;
1412 }
1413 }
1414} 1052}
1415 1053
1416/* Run this to (re)initialize net_crypto. 1054/* Run this to (re)initialize net_crypto.
@@ -1429,12 +1067,6 @@ Net_Crypto *new_net_crypto(DHT *dht)
1429 return NULL; 1067 return NULL;
1430 1068
1431 temp->dht = dht; 1069 temp->dht = dht;
1432 temp->lossless_udp = new_lossless_udp(dht->net);
1433
1434 if (temp->lossless_udp == NULL) {
1435 free(temp);
1436 return NULL;
1437 }
1438 1070
1439 new_keys(temp); 1071 new_keys(temp);
1440 new_symmetric_key(temp->secret_symmetric_key); 1072 new_symmetric_key(temp->secret_symmetric_key);
@@ -1451,9 +1083,7 @@ static void kill_timedout(Net_Crypto *c)
1451 uint32_t i; 1083 uint32_t i;
1452 1084
1453 for (i = 0; i < c->crypto_connections_length; ++i) { 1085 for (i = 0; i < c->crypto_connections_length; ++i) {
1454 if (c->crypto_connections[i].status != CRYPTO_CONN_NO_CONNECTION 1086//TODO
1455 && is_connected(c->lossless_udp, c->crypto_connections[i].number) == LUDP_TIMED_OUT)
1456 c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT;
1457 } 1087 }
1458} 1088}
1459 1089
@@ -1461,9 +1091,9 @@ static void kill_timedout(Net_Crypto *c)
1461void do_net_crypto(Net_Crypto *c) 1091void do_net_crypto(Net_Crypto *c)
1462{ 1092{
1463 unix_time_update(); 1093 unix_time_update();
1464 do_lossless_udp(c->lossless_udp);
1465 kill_timedout(c); 1094 kill_timedout(c);
1466 receive_crypto(c); 1095 receive_crypto(c);
1096 send_crypto_packets(c);
1467} 1097}
1468 1098
1469void kill_net_crypto(Net_Crypto *c) 1099void kill_net_crypto(Net_Crypto *c)
@@ -1474,7 +1104,10 @@ void kill_net_crypto(Net_Crypto *c)
1474 crypto_kill(c, i); 1104 crypto_kill(c, i);
1475 } 1105 }
1476 1106
1477 kill_lossless_udp(c->lossless_udp); 1107 networking_registerhandler(c->dht->net, NET_PACKET_COOKIE_REQUEST, NULL, NULL);
1108 networking_registerhandler(c->dht->net, NET_PACKET_COOKIE_RESPONSE, NULL, NULL);
1109 networking_registerhandler(c->dht->net, NET_PACKET_CRYPTO_HS, NULL, NULL);
1110 networking_registerhandler(c->dht->net, NET_PACKET_CRYPTO_DATA, NULL, NULL);
1478 memset(c, 0, sizeof(Net_Crypto)); 1111 memset(c, 0, sizeof(Net_Crypto));
1479 free(c); 1112 free(c);
1480} 1113}
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 @@
24#ifndef NET_CRYPTO_H 24#ifndef NET_CRYPTO_H
25#define NET_CRYPTO_H 25#define NET_CRYPTO_H
26 26
27#include "Lossless_UDP.h"
28#include "DHT.h" 27#include "DHT.h"
29 28
30#define CRYPTO_HANDSHAKE_TIMEOUT (CONNECTION_TIMEOUT * 2) 29#define CRYPTO_HANDSHAKE_TIMEOUT (CONNECTION_TIMEOUT * 2)
@@ -39,6 +38,8 @@
39#define CRYPTO_PACKET_BUFFER_SIZE 64 38#define CRYPTO_PACKET_BUFFER_SIZE 64
40 39
41#define MAX_CRYPTO_PACKET_SIZE 1400 40#define MAX_CRYPTO_PACKET_SIZE 1400
41
42/* Max size of data in packets TODO*/
42#define MAX_CRYPTO_DATA_SIZE (MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + crypto_box_MACBYTES)) 43#define MAX_CRYPTO_DATA_SIZE (MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + crypto_box_MACBYTES))
43 44
44/* Interval in ms between sending cookie request/handshake packets. */ 45/* Interval in ms between sending cookie request/handshake packets. */
@@ -58,7 +59,6 @@ typedef struct {
58 * 4 if the connection is established. 59 * 4 if the connection is established.
59 * 5 if the connection is timed out. 60 * 5 if the connection is timed out.
60 */ 61 */
61 uint16_t number; /* Lossless_UDP connection number corresponding to this connection. */
62 uint64_t timeout; 62 uint64_t timeout;
63 63
64 uint64_t cookie_request_number; /* number used in the cookie request packets for this connection */ 64 uint64_t cookie_request_number; /* number used in the cookie request packets for this connection */
@@ -71,7 +71,6 @@ typedef struct {
71 71
72 IP_Port ip_port; /* The ip and port to contact this guy directly.*/ 72 IP_Port ip_port; /* The ip and port to contact this guy directly.*/
73 uint64_t direct_lastrecv_time; /* The Time at which we last receive a direct packet. */ 73 uint64_t direct_lastrecv_time; /* The Time at which we last receive a direct packet. */
74
75} Crypto_Connection; 74} Crypto_Connection;
76 75
77typedef struct { 76typedef struct {
@@ -84,7 +83,6 @@ typedef struct {
84} New_Connection; 83} New_Connection;
85 84
86typedef struct { 85typedef struct {
87 Lossless_UDP *lossless_udp;
88 DHT *dht; 86 DHT *dht;
89 87
90 Crypto_Connection *crypto_connections; 88 Crypto_Connection *crypto_connections;
@@ -103,6 +101,22 @@ typedef struct {
103} Net_Crypto; 101} Net_Crypto;
104 102
105 103
104/* Set function to be called when someone requests a new connection to us.
105 *
106 * The set function should return -1 on failure and 0 on success.
107 *
108 * n_c is only valid for the duration of the function call.
109 */
110void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void *object, New_Connection *n_c),
111 void *object);
112
113/* Accept a crypto connection.
114 *
115 * return -1 on failure.
116 * return connection id on success.
117 */
118int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c);
119
106 120
107/* return 0 if there is no received data in the buffer. 121/* return 0 if there is no received data in the buffer.
108 * return -1 if the packet was discarded. 122 * 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);
134 */ 148 */
135int crypto_kill(Net_Crypto *c, int crypt_connection_id); 149int crypto_kill(Net_Crypto *c, int crypt_connection_id);
136 150
137/* Handle an incoming connection.
138 *
139 * return -1 if no crypto inbound connection.
140 * return incoming connection id (Lossless_UDP one) if there is an incoming crypto connection.
141 *
142 * Put the public key of the peer in public_key, the secret_nonce from the handshake into secret_nonce
143 * and the session public key for the connection in session_key.
144 * to accept it see: accept_crypto_inbound(...).
145 * to refuse it just call kill_connection(...) on the connection id.
146 */
147int crypto_inbound(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key);
148
149/* Accept an incoming connection using the parameters provided by crypto_inbound.
150 *
151 * return -1 if not successful.
152 * return crypt_connection_id if successful.
153 */
154int accept_crypto_inbound(Net_Crypto *c, int connection_id, uint8_t *public_key, uint8_t *secret_nonce,
155 uint8_t *session_key);
156 151
157/* return 0 if no connection. 152/* return 0 if no connection.
158 * return 1 we have sent a handshake 153 * 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
721 */ 721 */
722int tox_file_data_size(Tox *tox, int32_t friendnumber) 722int tox_file_data_size(Tox *tox, int32_t friendnumber)
723{ 723{
724 return MAX_DATA_SIZE - crypto_box_MACBYTES - 3; 724 return MAX_CRYPTO_DATA_SIZE - 3;
725} 725}
726 726
727/* Give the number of bytes left to be sent/received. 727/* Give the number of bytes left to be sent/received.