summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--auto_tests/friends_test.c26
-rw-r--r--core/CMakeLists.txt3
-rw-r--r--core/DHT.c520
-rw-r--r--core/DHT.h93
-rw-r--r--core/LAN_discovery.c16
-rw-r--r--core/LAN_discovery.h4
-rw-r--r--core/Lossless_UDP.c578
-rw-r--r--core/Lossless_UDP.h126
-rw-r--r--core/Messenger.c130
-rw-r--r--core/Messenger.h25
-rw-r--r--core/friend_requests.c81
-rw-r--r--core/friend_requests.h26
-rw-r--r--core/net_crypto.c436
-rw-r--r--core/net_crypto.h99
-rw-r--r--core/network.c92
-rw-r--r--core/network.h23
-rw-r--r--core/ping.c115
-rw-r--r--core/ping.h15
-rw-r--r--other/DHT_bootstrap.c39
-rw-r--r--other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c52
-rw-r--r--other/unused/timer.c (renamed from core/timer.c)0
-rw-r--r--other/unused/timer.h (renamed from core/timer.h)0
-rw-r--r--testing/CMakeLists.txt1
-rw-r--r--testing/DHT_test.c75
-rw-r--r--testing/Lossless_UDP_testclient.c65
-rw-r--r--testing/Lossless_UDP_testserver.c40
-rw-r--r--testing/Messenger_test.c3
-rw-r--r--testing/cmake/timer_test.cmake9
-rw-r--r--testing/nTox.c4
-rw-r--r--testing/timer_test.c68
-rw-r--r--testing/toxic/chat.c4
-rw-r--r--testing/toxic/dhtstatus.c4
-rw-r--r--testing/toxic/friendlist.c2
-rw-r--r--testing/toxic/main.c18
-rw-r--r--testing/toxic/prompt.c6
-rw-r--r--testing/toxic/windows.c48
-rw-r--r--testing/toxic/windows.h2
37 files changed, 1476 insertions, 1372 deletions
diff --git a/auto_tests/friends_test.c b/auto_tests/friends_test.c
index dd2db3e3..b6223489 100644
--- a/auto_tests/friends_test.c
+++ b/auto_tests/friends_test.c
@@ -44,6 +44,8 @@
44#define c_sleep(x) usleep(1000*x) 44#define c_sleep(x) usleep(1000*x)
45#endif 45#endif
46 46
47#define PORT 33445
48
47static Messenger *m; 49static Messenger *m;
48 50
49uint8_t *parent_id = NULL; 51uint8_t *parent_id = NULL;
@@ -52,13 +54,13 @@ uint8_t *child_id = NULL;
52pid_t child_pid = 0; 54pid_t child_pid = 0;
53int request_flags = 0; 55int request_flags = 0;
54 56
55void do_tox(void) 57void do_tox(DHT *dht)
56{ 58{
57 static int dht_on = 0; 59 static int dht_on = 0;
58 60
59 if (!dht_on && DHT_isconnected()) { 61 if (!dht_on && DHT_isconnected(dht)) {
60 dht_on = 1; 62 dht_on = 1;
61 } else if (dht_on && !DHT_isconnected()) { 63 } else if (dht_on && !DHT_isconnected(dht)) {
62 dht_on = 0; 64 dht_on = 0;
63 } 65 }
64 66
@@ -77,7 +79,7 @@ void parent_confirm_status(Messenger *m, int num, uint8_t *data, uint16_t length
77 request_flags |= FIRST_FLAG; 79 request_flags |= FIRST_FLAG;
78} 80}
79 81
80int parent_friend_request(void) 82int parent_friend_request(DHT *dht)
81{ 83{
82 char *message = "Watson, come here, I need you."; 84 char *message = "Watson, come here, I need you.";
83 int len = strlen(message); 85 int len = strlen(message);
@@ -90,7 +92,7 @@ int parent_friend_request(void)
90 92
91 /* wait on the status change */ 93 /* wait on the status change */
92 for (i = 0; i < WAIT_COUNT; i++) { 94 for (i = 0; i < WAIT_COUNT; i++) {
93 do_tox(); 95 do_tox(dht);
94 96
95 if (request_flags & FIRST_FLAG) 97 if (request_flags & FIRST_FLAG)
96 break; 98 break;
@@ -123,7 +125,7 @@ void child_got_statuschange(Messenger *m, int friend_num, uint8_t *string, uint1
123 request_flags |= SECOND_FLAG; 125 request_flags |= SECOND_FLAG;
124} 126}
125 127
126int parent_wait_for_message(void) 128int parent_wait_for_message(DHT *dht)
127{ 129{
128 int i = 0; 130 int i = 0;
129 131
@@ -131,7 +133,7 @@ int parent_wait_for_message(void)
131 fflush(stdout); 133 fflush(stdout);
132 134
133 for (i = 0; i < WAIT_COUNT; i++) { 135 for (i = 0; i < WAIT_COUNT; i++) {
134 do_tox(); 136 do_tox(dht);
135 137
136 if (request_flags & SECOND_FLAG) 138 if (request_flags & SECOND_FLAG)
137 break; 139 break;
@@ -185,16 +187,16 @@ int main(int argc, char *argv[])
185 187
186 /* wait on the friend request */ 188 /* wait on the friend request */
187 while (!(request_flags & FIRST_FLAG)) 189 while (!(request_flags & FIRST_FLAG))
188 do_tox(); 190 do_tox(m->dht);
189 191
190 /* wait for the status change */ 192 /* wait for the status change */
191 while (!(request_flags & SECOND_FLAG)) 193 while (!(request_flags & SECOND_FLAG))
192 do_tox(); 194 do_tox(m->dht);
193 195
194 for (i = 0; i < 6; i++) { 196 for (i = 0; i < 6; i++) {
195 /* send the message six times, just to be sure */ 197 /* send the message six times, just to be sure */
196 m_sendmessage(m, 0, (uint8_t *)message, strlen(message)); 198 m_sendmessage(m, 0, (uint8_t *)message, strlen(message));
197 do_tox(); 199 do_tox(m->dht);
198 } 200 }
199 201
200 cleanupMessenger(m); 202 cleanupMessenger(m);
@@ -220,10 +222,10 @@ int main(int argc, char *argv[])
220 222
221 Messenger_save(m, parent_id); 223 Messenger_save(m, parent_id);
222 224
223 if (parent_friend_request() == -1) 225 if (parent_friend_request(m->dht) == -1)
224 return -1; 226 return -1;
225 227
226 if (parent_wait_for_message() == -1) 228 if (parent_wait_for_message(m->dht) == -1)
227 return -1; 229 return -1;
228 230
229 wait(NULL); 231 wait(NULL);
diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt
index ad6eea01..55a41912 100644
--- a/core/CMakeLists.txt
+++ b/core/CMakeLists.txt
@@ -10,8 +10,7 @@ set(core_sources
10 LAN_discovery.c 10 LAN_discovery.c
11 Messenger.c 11 Messenger.c
12 util.c 12 util.c
13 ping.c 13 ping.c)
14 timer.c)
15 14
16if(SHARED_TOXCORE) 15if(SHARED_TOXCORE)
17 add_library(toxcore SHARED ${core_sources}) 16 add_library(toxcore SHARED ${core_sources})
diff --git a/core/DHT.c b/core/DHT.c
index 924e3216..ab631604 100644
--- a/core/DHT.c
+++ b/core/DHT.c
@@ -27,17 +27,6 @@
27#include "packets.h" 27#include "packets.h"
28#include "ping.h" 28#include "ping.h"
29 29
30/* maximum number of clients stored per friend. */
31#define MAX_FRIEND_CLIENTS 8
32
33/* A list of the clients mathematically closest to ours. */
34#define LCLIENT_LIST 32
35
36/* The list of ip ports along with the ping_id of what we sent them and a timestamp */
37#define LPING_ARRAY 256
38
39#define LSEND_NODES_ARRAY LPING_ARRAY/2
40
41/* the number of seconds for a non responsive node to become bad. */ 30/* the number of seconds for a non responsive node to become bad. */
42#define BAD_NODE_TIMEOUT 70 31#define BAD_NODE_TIMEOUT 70
43 32
@@ -61,59 +50,13 @@
61/*Interval in seconds between punching attempts*/ 50/*Interval in seconds between punching attempts*/
62#define PUNCH_INTERVAL 10 51#define PUNCH_INTERVAL 10
63 52
64/*Maximum newly announced nodes to ping per TIME_TOPING seconds*/ 53/*Ping newly announced nodes to ping per TIME_TOPING seconds*/
65#define MAX_TOPING 16
66
67#define TIME_TOPING 5 54#define TIME_TOPING 5
68/*----------------------------------------------------------------------------------*/
69
70typedef struct {
71 uint8_t client_id[CLIENT_ID_SIZE];
72 Client_data client_list[MAX_FRIEND_CLIENTS];
73
74 /* time at which the last get_nodes request was sent. */
75 uint64_t lastgetnode;
76
77 /* Symetric NAT hole punching stuff */
78
79 /* 1 if currently hole punching, otherwise 0 */
80 uint8_t hole_punching;
81 uint32_t punching_index;
82 uint64_t punching_timestamp;
83 uint64_t recvNATping_timestamp;
84 uint64_t NATping_id;
85 uint64_t NATping_timestamp;
86} Friend;
87
88typedef struct {
89 uint8_t client_id[CLIENT_ID_SIZE];
90 IP_Port ip_port;
91} Node_format;
92
93typedef struct {
94 IP_Port ip_port;
95 uint64_t ping_id;
96 uint64_t timestamp;
97} Pinged;
98
99/*----------------------------------------------------------------------------------*/
100 55
101/* Our client id/public key */
102uint8_t self_public_key[CLIENT_ID_SIZE];
103uint8_t self_secret_key[crypto_box_SECRETKEYBYTES];
104static Client_data close_clientlist[LCLIENT_LIST];
105static Friend *friends_list;
106static uint16_t num_friends;
107static Pinged send_nodes[LSEND_NODES_ARRAY];
108static Node_format toping[MAX_TOPING];
109static uint64_t last_toping;
110 56
111/*----------------------------------------------------------------------------------*/ 57Client_data *DHT_get_close_list(DHT *dht)
112
113
114Client_data *DHT_get_close_list(void)
115{ 58{
116 return close_clientlist; 59 return dht->close_clientlist;
117} 60}
118 61
119/* Compares client_id1 and client_id2 with client_id 62/* Compares client_id1 and client_id2 with client_id
@@ -203,12 +146,12 @@ static int client_in_nodelist(Node_format *list, uint32_t length, uint8_t *clien
203 146
204/* Returns the friend number from the client_id, or -1 if a failure occurs 147/* Returns the friend number from the client_id, or -1 if a failure occurs
205 */ 148 */
206static int friend_number(uint8_t *client_id) 149static int friend_number(DHT *dht, uint8_t *client_id)
207{ 150{
208 uint32_t i; 151 uint32_t i;
209 152
210 for (i = 0; i < num_friends; ++i) { 153 for (i = 0; i < dht->num_friends; ++i) {
211 if (id_equal(friends_list[i].client_id, client_id)) 154 if (id_equal(dht->friends_list[i].client_id, client_id))
212 return i; 155 return i;
213 } 156 }
214 157
@@ -220,15 +163,15 @@ static int friend_number(uint8_t *client_id)
220 * 163 *
221 * TODO: For the love of based Allah make this function cleaner and much more efficient. 164 * TODO: For the love of based Allah make this function cleaner and much more efficient.
222 */ 165 */
223static int get_close_nodes(uint8_t *client_id, Node_format *nodes_list) 166static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list)
224{ 167{
225 uint32_t i, j, k; 168 uint32_t i, j, k;
226 uint64_t temp_time = unix_time(); 169 uint64_t temp_time = unix_time();
227 int num_nodes = 0, closest, tout, inlist; 170 int num_nodes = 0, closest, tout, inlist;
228 171
229 for (i = 0; i < LCLIENT_LIST; ++i) { 172 for (i = 0; i < LCLIENT_LIST; ++i) {
230 tout = is_timeout(temp_time, close_clientlist[i].timestamp, BAD_NODE_TIMEOUT); 173 tout = is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT);
231 inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, close_clientlist[i].client_id); 174 inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, dht->close_clientlist[i].client_id);
232 175
233 /* if node isn't good or is already in list. */ 176 /* if node isn't good or is already in list. */
234 if (tout || inlist) 177 if (tout || inlist)
@@ -237,10 +180,10 @@ static int get_close_nodes(uint8_t *client_id, Node_format *nodes_list)
237 if (num_nodes < MAX_SENT_NODES) { 180 if (num_nodes < MAX_SENT_NODES) {
238 181
239 memcpy( nodes_list[num_nodes].client_id, 182 memcpy( nodes_list[num_nodes].client_id,
240 close_clientlist[i].client_id, 183 dht->close_clientlist[i].client_id,
241 CLIENT_ID_SIZE ); 184 CLIENT_ID_SIZE );
242 185
243 nodes_list[num_nodes].ip_port = close_clientlist[i].ip_port; 186 nodes_list[num_nodes].ip_port = dht->close_clientlist[i].ip_port;
244 num_nodes++; 187 num_nodes++;
245 188
246 } else { 189 } else {
@@ -248,27 +191,27 @@ static int get_close_nodes(uint8_t *client_id, Node_format *nodes_list)
248 for (j = 0; j < MAX_SENT_NODES; ++j) { 191 for (j = 0; j < MAX_SENT_NODES; ++j) {
249 closest = id_closest( client_id, 192 closest = id_closest( client_id,
250 nodes_list[j].client_id, 193 nodes_list[j].client_id,
251 close_clientlist[i].client_id ); 194 dht->close_clientlist[i].client_id );
252 195
253 if (closest == 2) { 196 if (closest == 2) {
254 memcpy( nodes_list[j].client_id, 197 memcpy( nodes_list[j].client_id,
255 close_clientlist[i].client_id, 198 dht->close_clientlist[i].client_id,
256 CLIENT_ID_SIZE); 199 CLIENT_ID_SIZE);
257 200
258 nodes_list[j].ip_port = close_clientlist[i].ip_port; 201 nodes_list[j].ip_port = dht->close_clientlist[i].ip_port;
259 break; 202 break;
260 } 203 }
261 } 204 }
262 } 205 }
263 } 206 }
264 207
265 for (i = 0; i < num_friends; ++i) { 208 for (i = 0; i < dht->num_friends; ++i) {
266 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 209 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
267 210
268 tout = is_timeout(temp_time, friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT); 211 tout = is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT);
269 inlist = client_in_nodelist( nodes_list, 212 inlist = client_in_nodelist( nodes_list,
270 MAX_SENT_NODES, 213 MAX_SENT_NODES,
271 friends_list[i].client_list[j].client_id); 214 dht->friends_list[i].client_list[j].client_id);
272 215
273 /* if node isn't good or is already in list. */ 216 /* if node isn't good or is already in list. */
274 if (tout || inlist) 217 if (tout || inlist)
@@ -277,24 +220,24 @@ static int get_close_nodes(uint8_t *client_id, Node_format *nodes_list)
277 if (num_nodes < MAX_SENT_NODES) { 220 if (num_nodes < MAX_SENT_NODES) {
278 221
279 memcpy( nodes_list[num_nodes].client_id, 222 memcpy( nodes_list[num_nodes].client_id,
280 friends_list[i].client_list[j].client_id, 223 dht->friends_list[i].client_list[j].client_id,
281 CLIENT_ID_SIZE); 224 CLIENT_ID_SIZE);
282 225
283 nodes_list[num_nodes].ip_port = friends_list[i].client_list[j].ip_port; 226 nodes_list[num_nodes].ip_port = dht->friends_list[i].client_list[j].ip_port;
284 num_nodes++; 227 num_nodes++;
285 } else { 228 } else {
286 for (k = 0; k < MAX_SENT_NODES; ++k) { 229 for (k = 0; k < MAX_SENT_NODES; ++k) {
287 230
288 closest = id_closest( client_id, 231 closest = id_closest( client_id,
289 nodes_list[k].client_id, 232 nodes_list[k].client_id,
290 friends_list[i].client_list[j].client_id ); 233 dht->friends_list[i].client_list[j].client_id );
291 234
292 if (closest == 2) { 235 if (closest == 2) {
293 memcpy( nodes_list[k].client_id, 236 memcpy( nodes_list[k].client_id,
294 friends_list[i].client_list[j].client_id, 237 dht->friends_list[i].client_list[j].client_id,
295 CLIENT_ID_SIZE ); 238 CLIENT_ID_SIZE );
296 239
297 nodes_list[k].ip_port = friends_list[i].client_list[j].ip_port; 240 nodes_list[k].ip_port = dht->friends_list[i].client_list[j].ip_port;
298 break; 241 break;
299 } 242 }
300 } 243 }
@@ -387,40 +330,40 @@ static int replace_good( Client_data *list,
387/* Attempt to add client with ip_port and client_id to the friends client list 330/* Attempt to add client with ip_port and client_id to the friends client list
388 * and close_clientlist 331 * and close_clientlist
389 */ 332 */
390void addto_lists(IP_Port ip_port, uint8_t *client_id) 333void addto_lists(DHT *dht, IP_Port ip_port, uint8_t *client_id)
391{ 334{
392 uint32_t i; 335 uint32_t i;
393 336
394 /* NOTE: current behavior if there are two clients with the same id is 337 /* NOTE: current behavior if there are two clients with the same id is
395 * to replace the first ip by the second. 338 * to replace the first ip by the second.
396 */ 339 */
397 if (!client_in_list(close_clientlist, LCLIENT_LIST, client_id, ip_port)) { 340 if (!client_in_list(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) {
398 if (replace_bad(close_clientlist, LCLIENT_LIST, client_id, ip_port)) { 341 if (replace_bad(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) {
399 /* if we can't replace bad nodes we try replacing good ones */ 342 /* if we can't replace bad nodes we try replacing good ones */
400 replace_good( close_clientlist, 343 replace_good( dht->close_clientlist,
401 LCLIENT_LIST, 344 LCLIENT_LIST,
402 client_id, 345 client_id,
403 ip_port, 346 ip_port,
404 self_public_key ); 347 dht->c->self_public_key );
405 } 348 }
406 } 349 }
407 350
408 for (i = 0; i < num_friends; ++i) { 351 for (i = 0; i < dht->num_friends; ++i) {
409 if (!client_in_list( friends_list[i].client_list, 352 if (!client_in_list( dht->friends_list[i].client_list,
410 MAX_FRIEND_CLIENTS, 353 MAX_FRIEND_CLIENTS,
411 client_id, 354 client_id,
412 ip_port )) { 355 ip_port )) {
413 356
414 if (replace_bad( friends_list[i].client_list, 357 if (replace_bad( dht->friends_list[i].client_list,
415 MAX_FRIEND_CLIENTS, 358 MAX_FRIEND_CLIENTS,
416 client_id, 359 client_id,
417 ip_port )) { 360 ip_port )) {
418 /* if we can't replace bad nodes we try replacing good ones. */ 361 /* if we can't replace bad nodes we try replacing good ones. */
419 replace_good( friends_list[i].client_list, 362 replace_good( dht->friends_list[i].client_list,
420 MAX_FRIEND_CLIENTS, 363 MAX_FRIEND_CLIENTS,
421 client_id, 364 client_id,
422 ip_port, 365 ip_port,
423 friends_list[i].client_id ); 366 dht->friends_list[i].client_id );
424 } 367 }
425 } 368 }
426 } 369 }
@@ -429,30 +372,30 @@ void addto_lists(IP_Port ip_port, uint8_t *client_id)
429/* If client_id is a friend or us, update ret_ip_port 372/* If client_id is a friend or us, update ret_ip_port
430 * nodeclient_id is the id of the node that sent us this info 373 * nodeclient_id is the id of the node that sent us this info
431 */ 374 */
432static void returnedip_ports(IP_Port ip_port, uint8_t *client_id, uint8_t *nodeclient_id) 375static void returnedip_ports(DHT *dht, IP_Port ip_port, uint8_t *client_id, uint8_t *nodeclient_id)
433{ 376{
434 uint32_t i, j; 377 uint32_t i, j;
435 uint64_t temp_time = unix_time(); 378 uint64_t temp_time = unix_time();
436 379
437 if (id_equal(client_id, self_public_key)) { 380 if (id_equal(client_id, dht->c->self_public_key)) {
438 381
439 for (i = 0; i < LCLIENT_LIST; ++i) { 382 for (i = 0; i < LCLIENT_LIST; ++i) {
440 if (id_equal(nodeclient_id, close_clientlist[i].client_id)) { 383 if (id_equal(nodeclient_id, dht->close_clientlist[i].client_id)) {
441 close_clientlist[i].ret_ip_port = ip_port; 384 dht->close_clientlist[i].ret_ip_port = ip_port;
442 close_clientlist[i].ret_timestamp = temp_time; 385 dht->close_clientlist[i].ret_timestamp = temp_time;
443 return; 386 return;
444 } 387 }
445 } 388 }
446 389
447 } else { 390 } else {
448 391
449 for (i = 0; i < num_friends; ++i) { 392 for (i = 0; i < dht->num_friends; ++i) {
450 if (id_equal(client_id, friends_list[i].client_id)) { 393 if (id_equal(client_id, dht->friends_list[i].client_id)) {
451 394
452 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 395 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
453 if (id_equal(nodeclient_id, friends_list[i].client_list[j].client_id)) { 396 if (id_equal(nodeclient_id, dht->friends_list[i].client_list[j].client_id)) {
454 friends_list[i].client_list[j].ret_ip_port = ip_port; 397 dht->friends_list[i].client_list[j].ret_ip_port = ip_port;
455 friends_list[i].client_list[j].ret_timestamp = temp_time; 398 dht->friends_list[i].client_list[j].ret_timestamp = temp_time;
456 return; 399 return;
457 } 400 }
458 } 401 }
@@ -463,20 +406,20 @@ static void returnedip_ports(IP_Port ip_port, uint8_t *client_id, uint8_t *nodec
463} 406}
464 407
465/* Same as last function but for get_node requests. */ 408/* Same as last function but for get_node requests. */
466static int is_gettingnodes(IP_Port ip_port, uint64_t ping_id) 409static int is_gettingnodes(DHT *dht, IP_Port ip_port, uint64_t ping_id)
467{ 410{
468 uint32_t i; 411 uint32_t i;
469 uint8_t pinging; 412 uint8_t pinging;
470 uint64_t temp_time = unix_time(); 413 uint64_t temp_time = unix_time();
471 414
472 for (i = 0; i < LSEND_NODES_ARRAY; ++i ) { 415 for (i = 0; i < LSEND_NODES_ARRAY; ++i ) {
473 if (!is_timeout(temp_time, send_nodes[i].timestamp, PING_TIMEOUT)) { 416 if (!is_timeout(temp_time, dht->send_nodes[i].timestamp, PING_TIMEOUT)) {
474 pinging = 0; 417 pinging = 0;
475 418
476 if (ip_port.ip.i != 0 && ipport_equal(send_nodes[i].ip_port, ip_port)) 419 if (ip_port.ip.i != 0 && ipport_equal(dht->send_nodes[i].ip_port, ip_port))
477 ++pinging; 420 ++pinging;
478 421
479 if (ping_id != 0 && send_nodes[i].ping_id == ping_id) 422 if (ping_id != 0 && dht->send_nodes[i].ping_id == ping_id)
480 ++pinging; 423 ++pinging;
481 424
482 if (pinging == (ping_id != 0) + (ip_port.ip.i != 0)) 425 if (pinging == (ping_id != 0) + (ip_port.ip.i != 0))
@@ -488,7 +431,7 @@ static int is_gettingnodes(IP_Port ip_port, uint64_t ping_id)
488} 431}
489 432
490/* Same but for get node requests */ 433/* Same but for get node requests */
491static uint64_t add_gettingnodes(IP_Port ip_port) 434static uint64_t add_gettingnodes(DHT *dht, IP_Port ip_port)
492{ 435{
493 uint32_t i, j; 436 uint32_t i, j;
494 uint64_t ping_id = ((uint64_t)random_int() << 32) + random_int(); 437 uint64_t ping_id = ((uint64_t)random_int() << 32) + random_int();
@@ -496,10 +439,10 @@ static uint64_t add_gettingnodes(IP_Port ip_port)
496 439
497 for (i = 0; i < PING_TIMEOUT; ++i ) { 440 for (i = 0; i < PING_TIMEOUT; ++i ) {
498 for (j = 0; j < LSEND_NODES_ARRAY; ++j ) { 441 for (j = 0; j < LSEND_NODES_ARRAY; ++j ) {
499 if (is_timeout(temp_time, send_nodes[j].timestamp, PING_TIMEOUT - i)) { 442 if (is_timeout(temp_time, dht->send_nodes[j].timestamp, PING_TIMEOUT - i)) {
500 send_nodes[j].timestamp = temp_time; 443 dht->send_nodes[j].timestamp = temp_time;
501 send_nodes[j].ip_port = ip_port; 444 dht->send_nodes[j].ip_port = ip_port;
502 send_nodes[j].ping_id = ping_id; 445 dht->send_nodes[j].ping_id = ping_id;
503 return ping_id; 446 return ping_id;
504 } 447 }
505 } 448 }
@@ -509,13 +452,13 @@ static uint64_t add_gettingnodes(IP_Port ip_port)
509} 452}
510 453
511/* send a getnodes request */ 454/* send a getnodes request */
512static int getnodes(IP_Port ip_port, uint8_t *public_key, uint8_t *client_id) 455static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id)
513{ 456{
514 /* check if packet is gonna be sent to ourself */ 457 /* check if packet is gonna be sent to ourself */
515 if (id_equal(public_key, self_public_key) || is_gettingnodes(ip_port, 0)) 458 if (id_equal(public_key, dht->c->self_public_key) || is_gettingnodes(dht, ip_port, 0))
516 return 1; 459 return 1;
517 460
518 uint64_t ping_id = add_gettingnodes(ip_port); 461 uint64_t ping_id = add_gettingnodes(dht, ip_port);
519 462
520 if (ping_id == 0) 463 if (ping_id == 0)
521 return 1; 464 return 1;
@@ -530,7 +473,7 @@ static int getnodes(IP_Port ip_port, uint8_t *public_key, uint8_t *client_id)
530 memcpy(plain + sizeof(ping_id), client_id, CLIENT_ID_SIZE); 473 memcpy(plain + sizeof(ping_id), client_id, CLIENT_ID_SIZE);
531 474
532 int len = encrypt_data( public_key, 475 int len = encrypt_data( public_key,
533 self_secret_key, 476 dht->c->self_secret_key,
534 nonce, 477 nonce,
535 plain, 478 plain,
536 sizeof(ping_id) + CLIENT_ID_SIZE, 479 sizeof(ping_id) + CLIENT_ID_SIZE,
@@ -540,25 +483,25 @@ static int getnodes(IP_Port ip_port, uint8_t *public_key, uint8_t *client_id)
540 return -1; 483 return -1;
541 484
542 data[0] = 2; 485 data[0] = 2;
543 memcpy(data + 1, self_public_key, CLIENT_ID_SIZE); 486 memcpy(data + 1, dht->c->self_public_key, CLIENT_ID_SIZE);
544 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); 487 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
545 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); 488 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len);
546 489
547 return sendpacket(ip_port, data, sizeof(data)); 490 return sendpacket(dht->c->lossless_udp->net->sock, ip_port, data, sizeof(data));
548} 491}
549 492
550/* send a send nodes response */ 493/* send a send nodes response */
551static int sendnodes(IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id) 494static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id)
552{ 495{
553 /* check if packet is gonna be sent to ourself */ 496 /* check if packet is gonna be sent to ourself */
554 if (id_equal(public_key, self_public_key)) 497 if (id_equal(public_key, dht->c->self_public_key))
555 return 1; 498 return 1;
556 499
557 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) 500 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id)
558 + sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING]; 501 + sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING];
559 502
560 Node_format nodes_list[MAX_SENT_NODES]; 503 Node_format nodes_list[MAX_SENT_NODES];
561 int num_nodes = get_close_nodes(client_id, nodes_list); 504 int num_nodes = get_close_nodes(dht, client_id, nodes_list);
562 505
563 if (num_nodes == 0) 506 if (num_nodes == 0)
564 return 0; 507 return 0;
@@ -572,7 +515,7 @@ static int sendnodes(IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, u
572 memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * sizeof(Node_format)); 515 memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * sizeof(Node_format));
573 516
574 int len = encrypt_data( public_key, 517 int len = encrypt_data( public_key,
575 self_secret_key, 518 dht->c->self_secret_key,
576 nonce, 519 nonce,
577 plain, 520 plain,
578 sizeof(ping_id) + num_nodes * sizeof(Node_format), 521 sizeof(ping_id) + num_nodes * sizeof(Node_format),
@@ -582,15 +525,16 @@ static int sendnodes(IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, u
582 return -1; 525 return -1;
583 526
584 data[0] = 3; 527 data[0] = 3;
585 memcpy(data + 1, self_public_key, CLIENT_ID_SIZE); 528 memcpy(data + 1, dht->c->self_public_key, CLIENT_ID_SIZE);
586 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); 529 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
587 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); 530 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len);
588 531
589 return sendpacket(ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); 532 return sendpacket(dht->c->lossless_udp->net->sock, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len);
590} 533}
591 534
592static int handle_getnodes(IP_Port source, uint8_t *packet, uint32_t length) 535static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length)
593{ 536{
537 DHT *dht = object;
594 uint64_t ping_id; 538 uint64_t ping_id;
595 539
596 if (length != ( 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES 540 if (length != ( 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES
@@ -598,13 +542,13 @@ static int handle_getnodes(IP_Port source, uint8_t *packet, uint32_t length)
598 return 1; 542 return 1;
599 543
600 /* check if packet is from ourself. */ 544 /* check if packet is from ourself. */
601 if (id_equal(packet + 1, self_public_key)) 545 if (id_equal(packet + 1, dht->c->self_public_key))
602 return 1; 546 return 1;
603 547
604 uint8_t plain[sizeof(ping_id) + CLIENT_ID_SIZE]; 548 uint8_t plain[sizeof(ping_id) + CLIENT_ID_SIZE];
605 549
606 int len = decrypt_data( packet + 1, 550 int len = decrypt_data( packet + 1,
607 self_secret_key, 551 dht->c->self_secret_key,
608 packet + 1 + CLIENT_ID_SIZE, 552 packet + 1 + CLIENT_ID_SIZE,
609 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, 553 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
610 sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING, 554 sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING,
@@ -614,15 +558,16 @@ static int handle_getnodes(IP_Port source, uint8_t *packet, uint32_t length)
614 return 1; 558 return 1;
615 559
616 memcpy(&ping_id, plain, sizeof(ping_id)); 560 memcpy(&ping_id, plain, sizeof(ping_id));
617 sendnodes(source, packet + 1, plain + sizeof(ping_id), ping_id); 561 sendnodes(dht, source, packet + 1, plain + sizeof(ping_id), ping_id);
618 562
619 //send_ping_request(source, (clientid_t*) (packet + 1)); /* TODO: make this smarter? */ 563 //send_ping_request(dht, source, (clientid_t*) (packet + 1)); /* TODO: make this smarter? */
620 564
621 return 0; 565 return 0;
622} 566}
623 567
624static int handle_sendnodes(IP_Port source, uint8_t *packet, uint32_t length) 568static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length)
625{ 569{
570 DHT *dht = object;
626 uint64_t ping_id; 571 uint64_t ping_id;
627 uint32_t cid_size = 1 + CLIENT_ID_SIZE; 572 uint32_t cid_size = 1 + CLIENT_ID_SIZE;
628 cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING; 573 cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING;
@@ -637,7 +582,7 @@ static int handle_sendnodes(IP_Port source, uint8_t *packet, uint32_t length)
637 582
638 int len = decrypt_data( 583 int len = decrypt_data(
639 packet + 1, 584 packet + 1,
640 self_secret_key, 585 dht->c->self_secret_key,
641 packet + 1 + CLIENT_ID_SIZE, 586 packet + 1 + CLIENT_ID_SIZE,
642 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, 587 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
643 sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING, plain ); 588 sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING, plain );
@@ -647,19 +592,19 @@ static int handle_sendnodes(IP_Port source, uint8_t *packet, uint32_t length)
647 592
648 memcpy(&ping_id, plain, sizeof(ping_id)); 593 memcpy(&ping_id, plain, sizeof(ping_id));
649 594
650 if (!is_gettingnodes(source, ping_id)) 595 if (!is_gettingnodes(dht, source, ping_id))
651 return 1; 596 return 1;
652 597
653 Node_format nodes_list[MAX_SENT_NODES]; 598 Node_format nodes_list[MAX_SENT_NODES];
654 memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format)); 599 memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format));
655 600
656 addto_lists(source, packet + 1); 601 addto_lists(dht, source, packet + 1);
657 602
658 uint32_t i; 603 uint32_t i;
659 604
660 for (i = 0; i < num_nodes; ++i) { 605 for (i = 0; i < num_nodes; ++i) {
661 send_ping_request(nodes_list[i].ip_port, (clientid_t *) &nodes_list[i].client_id); 606 send_ping_request(dht->ping, dht->c, nodes_list[i].ip_port, (clientid_t *) &nodes_list[i].client_id);
662 returnedip_ports(nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1); 607 returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1);
663 } 608 }
664 609
665 return 0; 610 return 0;
@@ -668,54 +613,54 @@ static int handle_sendnodes(IP_Port source, uint8_t *packet, uint32_t length)
668/*----------------------------------------------------------------------------------*/ 613/*----------------------------------------------------------------------------------*/
669/*------------------------END of packet handling functions--------------------------*/ 614/*------------------------END of packet handling functions--------------------------*/
670 615
671int DHT_addfriend(uint8_t *client_id) 616int DHT_addfriend(DHT *dht, uint8_t *client_id)
672{ 617{
673 if (friend_number(client_id) != -1) /*Is friend already in DHT?*/ 618 if (friend_number(dht, client_id) != -1) /*Is friend already in DHT?*/
674 return 1; 619 return 1;
675 620
676 Friend *temp; 621 DHT_Friend *temp;
677 temp = realloc(friends_list, sizeof(Friend) * (num_friends + 1)); 622 temp = realloc(dht->friends_list, sizeof(DHT_Friend) * (dht->num_friends + 1));
678 623
679 if (temp == NULL) 624 if (temp == NULL)
680 return 1; 625 return 1;
681 626
682 friends_list = temp; 627 dht->friends_list = temp;
683 memset(&friends_list[num_friends], 0, sizeof(Friend)); 628 memset(&dht->friends_list[dht->num_friends], 0, sizeof(DHT_Friend));
684 memcpy(friends_list[num_friends].client_id, client_id, CLIENT_ID_SIZE); 629 memcpy(dht->friends_list[dht->num_friends].client_id, client_id, CLIENT_ID_SIZE);
685 630
686 friends_list[num_friends].NATping_id = ((uint64_t)random_int() << 32) + random_int(); 631 dht->friends_list[dht->num_friends].NATping_id = ((uint64_t)random_int() << 32) + random_int();
687 ++num_friends; 632 ++dht->num_friends;
688 return 0; 633 return 0;
689} 634}
690 635
691int DHT_delfriend(uint8_t *client_id) 636int DHT_delfriend(DHT *dht, uint8_t *client_id)
692{ 637{
693 uint32_t i; 638 uint32_t i;
694 Friend *temp; 639 DHT_Friend *temp;
695 640
696 for (i = 0; i < num_friends; ++i) { 641 for (i = 0; i < dht->num_friends; ++i) {
697 /* Equal */ 642 /* Equal */
698 if (id_equal(friends_list[i].client_id, client_id)) { 643 if (id_equal(dht->friends_list[i].client_id, client_id)) {
699 --num_friends; 644 --dht->num_friends;
700 645
701 if (num_friends != i) { 646 if (dht->num_friends != i) {
702 memcpy( friends_list[i].client_id, 647 memcpy( dht->friends_list[i].client_id,
703 friends_list[num_friends].client_id, 648 dht->friends_list[dht->num_friends].client_id,
704 CLIENT_ID_SIZE ); 649 CLIENT_ID_SIZE );
705 } 650 }
706 651
707 if (num_friends == 0) { 652 if (dht->num_friends == 0) {
708 free(friends_list); 653 free(dht->friends_list);
709 friends_list = NULL; 654 dht->friends_list = NULL;
710 return 0; 655 return 0;
711 } 656 }
712 657
713 temp = realloc(friends_list, sizeof(Friend) * (num_friends)); 658 temp = realloc(dht->friends_list, sizeof(DHT_Friend) * (dht->num_friends));
714 659
715 if (temp == NULL) 660 if (temp == NULL)
716 return 1; 661 return 1;
717 662
718 friends_list = temp; 663 dht->friends_list = temp;
719 return 0; 664 return 0;
720 } 665 }
721 } 666 }
@@ -724,19 +669,19 @@ int DHT_delfriend(uint8_t *client_id)
724} 669}
725 670
726/* TODO: Optimize this. */ 671/* TODO: Optimize this. */
727IP_Port DHT_getfriendip(uint8_t *client_id) 672IP_Port DHT_getfriendip(DHT *dht, uint8_t *client_id)
728{ 673{
729 uint32_t i, j; 674 uint32_t i, j;
730 uint64_t temp_time = unix_time(); 675 uint64_t temp_time = unix_time();
731 IP_Port empty = {{{0}}, 0}; 676 IP_Port empty = {{{0}}, 0};
732 677
733 for (i = 0; i < num_friends; ++i) { 678 for (i = 0; i < dht->num_friends; ++i) {
734 /* Equal */ 679 /* Equal */
735 if (id_equal(friends_list[i].client_id, client_id)) { 680 if (id_equal(dht->friends_list[i].client_id, client_id)) {
736 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 681 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
737 if (id_equal(friends_list[i].client_list[j].client_id, client_id) 682 if (id_equal(dht->friends_list[i].client_list[j].client_id, client_id)
738 && !is_timeout(temp_time, friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) 683 && !is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT))
739 return friends_list[i].client_list[j].ip_port; 684 return dht->friends_list[i].client_list[j].ip_port;
740 } 685 }
741 686
742 return empty; 687 return empty;
@@ -750,49 +695,47 @@ IP_Port DHT_getfriendip(uint8_t *client_id)
750/* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request 695/* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request
751 * every GET_NODE_INTERVAL seconds to a random good node for each "friend" in our "friends" list. 696 * every GET_NODE_INTERVAL seconds to a random good node for each "friend" in our "friends" list.
752 */ 697 */
753static void doDHTFriends(void) 698static void do_DHT_friends(DHT *dht)
754{ 699{
755 uint32_t i, j; 700 uint32_t i, j;
756 uint64_t temp_time = unix_time(); 701 uint64_t temp_time = unix_time();
757 uint32_t rand_node; 702 uint32_t rand_node;
758 uint32_t index[MAX_FRIEND_CLIENTS]; 703 uint32_t index[MAX_FRIEND_CLIENTS];
759 704
760 for (i = 0; i < num_friends; ++i) { 705 for (i = 0; i < dht->num_friends; ++i) {
761 uint32_t num_nodes = 0; 706 uint32_t num_nodes = 0;
762 707
763 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 708 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
764 /* if node is not dead. */ 709 /* if node is not dead. */
765 if (!is_timeout(temp_time, friends_list[i].client_list[j].timestamp, Kill_NODE_TIMEOUT)) { 710 if (!is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, Kill_NODE_TIMEOUT)) {
766 if ((friends_list[i].client_list[j].last_pinged + PING_INTERVAL) <= temp_time) { 711 if ((dht->friends_list[i].client_list[j].last_pinged + PING_INTERVAL) <= temp_time) {
767 send_ping_request( friends_list[i].client_list[j].ip_port, 712 send_ping_request(dht->ping, dht->c, dht->friends_list[i].client_list[j].ip_port,
768 (clientid_t *) &friends_list[i].client_list[j].client_id ); 713 (clientid_t *) &dht->friends_list[i].client_list[j].client_id );
769 friends_list[i].client_list[j].last_pinged = temp_time; 714 dht->friends_list[i].client_list[j].last_pinged = temp_time;
770 } 715 }
771 716
772 /* if node is good. */ 717 /* if node is good. */
773 if (!is_timeout(temp_time, friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) { 718 if (!is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) {
774 index[num_nodes] = j; 719 index[num_nodes] = j;
775 ++num_nodes; 720 ++num_nodes;
776 } 721 }
777 } 722 }
778 } 723 }
779 724
780 if (friends_list[i].lastgetnode + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) { 725 if (dht->friends_list[i].lastgetnode + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) {
781 rand_node = rand() % num_nodes; 726 rand_node = rand() % num_nodes;
782 getnodes( friends_list[i].client_list[index[rand_node]].ip_port, 727 getnodes(dht, dht->friends_list[i].client_list[index[rand_node]].ip_port,
783 friends_list[i].client_list[index[rand_node]].client_id, 728 dht->friends_list[i].client_list[index[rand_node]].client_id,
784 friends_list[i].client_id ); 729 dht->friends_list[i].client_id );
785 friends_list[i].lastgetnode = temp_time; 730 dht->friends_list[i].lastgetnode = temp_time;
786 } 731 }
787 } 732 }
788} 733}
789 734
790static uint64_t close_lastgetnodes;
791
792/* Ping each client in the close nodes list every PING_INTERVAL seconds. 735/* Ping each client in the close nodes list every PING_INTERVAL seconds.
793 * Send a get nodes request every GET_NODE_INTERVAL seconds to a random good node in the list. 736 * Send a get nodes request every GET_NODE_INTERVAL seconds to a random good node in the list.
794 */ 737 */
795static void doClose(void) 738static void do_Close(DHT *dht)
796{ 739{
797 uint32_t i; 740 uint32_t i;
798 uint64_t temp_time = unix_time(); 741 uint64_t temp_time = unix_time();
@@ -802,46 +745,46 @@ static void doClose(void)
802 745
803 for (i = 0; i < LCLIENT_LIST; ++i) { 746 for (i = 0; i < LCLIENT_LIST; ++i) {
804 /* if node is not dead. */ 747 /* if node is not dead. */
805 if (!is_timeout(temp_time, close_clientlist[i].timestamp, Kill_NODE_TIMEOUT)) { 748 if (!is_timeout(temp_time, dht->close_clientlist[i].timestamp, Kill_NODE_TIMEOUT)) {
806 if ((close_clientlist[i].last_pinged + PING_INTERVAL) <= temp_time) { 749 if ((dht->close_clientlist[i].last_pinged + PING_INTERVAL) <= temp_time) {
807 send_ping_request( close_clientlist[i].ip_port, 750 send_ping_request(dht->ping, dht->c, dht->close_clientlist[i].ip_port,
808 (clientid_t *) &close_clientlist[i].client_id ); 751 (clientid_t *) &dht->close_clientlist[i].client_id );
809 close_clientlist[i].last_pinged = temp_time; 752 dht->close_clientlist[i].last_pinged = temp_time;
810 } 753 }
811 754
812 /* if node is good. */ 755 /* if node is good. */
813 if (!is_timeout(temp_time, close_clientlist[i].timestamp, BAD_NODE_TIMEOUT)) { 756 if (!is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT)) {
814 index[num_nodes] = i; 757 index[num_nodes] = i;
815 ++num_nodes; 758 ++num_nodes;
816 } 759 }
817 } 760 }
818 } 761 }
819 762
820 if (close_lastgetnodes + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) { 763 if (dht->close_lastgetnodes + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) {
821 rand_node = rand() % num_nodes; 764 rand_node = rand() % num_nodes;
822 getnodes( close_clientlist[index[rand_node]].ip_port, 765 getnodes(dht, dht->close_clientlist[index[rand_node]].ip_port,
823 close_clientlist[index[rand_node]].client_id, 766 dht->close_clientlist[index[rand_node]].client_id,
824 self_public_key ); 767 dht->c->self_public_key );
825 close_lastgetnodes = temp_time; 768 dht->close_lastgetnodes = temp_time;
826 } 769 }
827} 770}
828 771
829void DHT_bootstrap(IP_Port ip_port, uint8_t *public_key) 772void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key)
830{ 773{
831 getnodes(ip_port, public_key, self_public_key); 774 getnodes(dht, ip_port, public_key, dht->c->self_public_key);
832 send_ping_request(ip_port, (clientid_t *) public_key); 775 send_ping_request(dht->ping, dht->c, ip_port, (clientid_t *) public_key);
833} 776}
834 777
835/* send the given packet to node with client_id 778/* send the given packet to node with client_id
836 * returns -1 if failure 779 * returns -1 if failure
837 */ 780 */
838int route_packet(uint8_t *client_id, uint8_t *packet, uint32_t length) 781int route_packet(DHT *dht, uint8_t *client_id, uint8_t *packet, uint32_t length)
839{ 782{
840 uint32_t i; 783 uint32_t i;
841 784
842 for (i = 0; i < LCLIENT_LIST; ++i) { 785 for (i = 0; i < LCLIENT_LIST; ++i) {
843 if (id_equal(client_id, close_clientlist[i].client_id)) 786 if (id_equal(client_id, dht->close_clientlist[i].client_id))
844 return sendpacket(close_clientlist[i].ip_port, packet, length); 787 return sendpacket(dht->c->lossless_udp->net->sock, dht->close_clientlist[i].ip_port, packet, length);
845 } 788 }
846 789
847 return -1; 790 return -1;
@@ -853,16 +796,16 @@ int route_packet(uint8_t *client_id, uint8_t *packet, uint32_t length)
853 * return 0 if we are connected to friend or if no ips were found. 796 * return 0 if we are connected to friend or if no ips were found.
854 * returns -1 if no such friend 797 * returns -1 if no such friend
855 */ 798 */
856static int friend_iplist(IP_Port *ip_portlist, uint16_t friend_num) 799static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num)
857{ 800{
858 int num_ips = 0; 801 int num_ips = 0;
859 uint32_t i; 802 uint32_t i;
860 uint64_t temp_time = unix_time(); 803 uint64_t temp_time = unix_time();
861 804
862 if (friend_num >= num_friends) 805 if (friend_num >= dht->num_friends)
863 return -1; 806 return -1;
864 807
865 Friend *friend = &friends_list[friend_num]; 808 DHT_Friend *friend = &dht->friends_list[friend_num];
866 Client_data *client; 809 Client_data *client;
867 810
868 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { 811 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
@@ -888,9 +831,9 @@ static int friend_iplist(IP_Port *ip_portlist, uint16_t friend_num)
888 * 831 *
889 * Only works if more than (MAX_FRIEND_CLIENTS / 2) return an ip for friend. 832 * Only works if more than (MAX_FRIEND_CLIENTS / 2) return an ip for friend.
890 */ 833 */
891int route_tofriend(uint8_t *friend_id, uint8_t *packet, uint32_t length) 834int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t length)
892{ 835{
893 int num = friend_number(friend_id); 836 int num = friend_number(dht, friend_id);
894 837
895 if (num == -1) 838 if (num == -1)
896 return 0; 839 return 0;
@@ -898,13 +841,13 @@ int route_tofriend(uint8_t *friend_id, uint8_t *packet, uint32_t length)
898 uint32_t i, sent = 0; 841 uint32_t i, sent = 0;
899 842
900 IP_Port ip_list[MAX_FRIEND_CLIENTS]; 843 IP_Port ip_list[MAX_FRIEND_CLIENTS];
901 int ip_num = friend_iplist(ip_list, num); 844 int ip_num = friend_iplist(dht, ip_list, num);
902 845
903 if (ip_num < (MAX_FRIEND_CLIENTS / 2)) 846 if (ip_num < (MAX_FRIEND_CLIENTS / 2))
904 return 0; 847 return 0;
905 848
906 uint64_t temp_time = unix_time(); 849 uint64_t temp_time = unix_time();
907 Friend *friend = &friends_list[num]; 850 DHT_Friend *friend = &dht->friends_list[num];
908 Client_data *client; 851 Client_data *client;
909 852
910 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { 853 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
@@ -912,7 +855,7 @@ int route_tofriend(uint8_t *friend_id, uint8_t *packet, uint32_t length)
912 855
913 /*If ip is not zero and node is good */ 856 /*If ip is not zero and node is good */
914 if (client->ret_ip_port.ip.i != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { 857 if (client->ret_ip_port.ip.i != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) {
915 if (sendpacket(client->ip_port, packet, length) == length) 858 if (sendpacket(dht->c->lossless_udp->net->sock, client->ip_port, packet, length) == length)
916 ++sent; 859 ++sent;
917 } 860 }
918 } 861 }
@@ -923,14 +866,14 @@ int route_tofriend(uint8_t *friend_id, uint8_t *packet, uint32_t length)
923/* Send the following packet to one random person who tells us they are connected to friend_id 866/* Send the following packet to one random person who tells us they are connected to friend_id
924* returns the number of nodes it sent the packet to 867* returns the number of nodes it sent the packet to
925*/ 868*/
926static int routeone_tofriend(uint8_t *friend_id, uint8_t *packet, uint32_t length) 869static int routeone_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t length)
927{ 870{
928 int num = friend_number(friend_id); 871 int num = friend_number(dht, friend_id);
929 872
930 if (num == -1) 873 if (num == -1)
931 return 0; 874 return 0;
932 875
933 Friend *friend = &friends_list[num]; 876 DHT_Friend *friend = &dht->friends_list[num];
934 Client_data *client; 877 Client_data *client;
935 878
936 IP_Port ip_list[MAX_FRIEND_CLIENTS]; 879 IP_Port ip_list[MAX_FRIEND_CLIENTS];
@@ -951,7 +894,7 @@ static int routeone_tofriend(uint8_t *friend_id, uint8_t *packet, uint32_t lengt
951 if (n < 1) 894 if (n < 1)
952 return 0; 895 return 0;
953 896
954 if (sendpacket(ip_list[rand() % n], packet, length) == length) 897 if (sendpacket(dht->c->lossless_udp->net->sock, ip_list[rand() % n], packet, length) == length)
955 return 1; 898 return 1;
956 899
957 return 0; 900 return 0;
@@ -963,14 +906,14 @@ static int routeone_tofriend(uint8_t *friend_id, uint8_t *packet, uint32_t lengt
963 * return 0 if we are connected to friend or if no ips were found. 906 * return 0 if we are connected to friend or if no ips were found.
964 * returns -1 if no such friend 907 * returns -1 if no such friend
965 */ 908 */
966int friend_ips(IP_Port *ip_portlist, uint8_t *friend_id) 909int friend_ips(DHT *dht, IP_Port *ip_portlist, uint8_t *friend_id)
967{ 910{
968 uint32_t i; 911 uint32_t i;
969 912
970 for (i = 0; i < num_friends; ++i) { 913 for (i = 0; i < dht->num_friends; ++i) {
971 /* Equal */ 914 /* Equal */
972 if (id_equal(friends_list[i].client_id, friend_id)) 915 if (id_equal(dht->friends_list[i].client_id, friend_id))
973 return friend_iplist(ip_portlist, i); 916 return friend_iplist(dht, ip_portlist, i);
974 } 917 }
975 918
976 return -1; 919 return -1;
@@ -979,7 +922,7 @@ int friend_ips(IP_Port *ip_portlist, uint8_t *friend_id)
979/*----------------------------------------------------------------------------------*/ 922/*----------------------------------------------------------------------------------*/
980/*---------------------BEGINNING OF NAT PUNCHING FUNCTIONS--------------------------*/ 923/*---------------------BEGINNING OF NAT PUNCHING FUNCTIONS--------------------------*/
981 924
982static int send_NATping(uint8_t *public_key, uint64_t ping_id, uint8_t type) 925static int send_NATping(DHT *dht, uint8_t *public_key, uint64_t ping_id, uint8_t type)
983{ 926{
984 uint8_t data[sizeof(uint64_t) + 1]; 927 uint8_t data[sizeof(uint64_t) + 1];
985 uint8_t packet[MAX_DATA_SIZE]; 928 uint8_t packet[MAX_DATA_SIZE];
@@ -989,15 +932,16 @@ static int send_NATping(uint8_t *public_key, uint64_t ping_id, uint8_t type)
989 data[0] = type; 932 data[0] = type;
990 memcpy(data + 1, &ping_id, sizeof(uint64_t)); 933 memcpy(data + 1, &ping_id, sizeof(uint64_t));
991 /* 254 is NAT ping request packet id */ 934 /* 254 is NAT ping request packet id */
992 int len = create_request(packet, public_key, data, sizeof(uint64_t) + 1, 254); 935 int len = create_request(dht->c->self_public_key, dht->c->self_secret_key, packet, public_key, data,
936 sizeof(uint64_t) + 1, 254);
993 937
994 if (len == -1) 938 if (len == -1)
995 return -1; 939 return -1;
996 940
997 if (type == 0) /*If packet is request use many people to route it*/ 941 if (type == 0) /*If packet is request use many people to route it*/
998 num = route_tofriend(public_key, packet, len); 942 num = route_tofriend(dht, public_key, packet, len);
999 else if (type == 1) /*If packet is response use only one person to route it*/ 943 else if (type == 1) /*If packet is response use only one person to route it*/
1000 num = routeone_tofriend(public_key, packet, len); 944 num = routeone_tofriend(dht, public_key, packet, len);
1001 945
1002 if (num == 0) 946 if (num == 0)
1003 return -1; 947 return -1;
@@ -1006,21 +950,22 @@ static int send_NATping(uint8_t *public_key, uint64_t ping_id, uint8_t type)
1006} 950}
1007 951
1008/* Handle a received ping request for */ 952/* Handle a received ping request for */
1009static int handle_NATping(IP_Port source, uint8_t *source_pubkey, uint8_t *packet, uint32_t length) 953static int handle_NATping(void *object, IP_Port source, uint8_t *source_pubkey, uint8_t *packet, uint32_t length)
1010{ 954{
955 DHT *dht = object;
1011 uint64_t ping_id; 956 uint64_t ping_id;
1012 memcpy(&ping_id, packet + 1, sizeof(uint64_t)); 957 memcpy(&ping_id, packet + 1, sizeof(uint64_t));
1013 958
1014 int friendnumber = friend_number(source_pubkey); 959 int friendnumber = friend_number(dht, source_pubkey);
1015 960
1016 if (friendnumber == -1) 961 if (friendnumber == -1)
1017 return 1; 962 return 1;
1018 963
1019 Friend *friend = &friends_list[friendnumber]; 964 DHT_Friend *friend = &dht->friends_list[friendnumber];
1020 965
1021 if (packet[0] == 0) { 966 if (packet[0] == 0) {
1022 /* 1 is reply */ 967 /* 1 is reply */
1023 send_NATping(source_pubkey, ping_id, 1); 968 send_NATping(dht, source_pubkey, ping_id, 1);
1024 friend->recvNATping_timestamp = unix_time(); 969 friend->recvNATping_timestamp = unix_time();
1025 return 0; 970 return 0;
1026 } else if (packet[0] == 1) { 971 } else if (packet[0] == 1) {
@@ -1082,45 +1027,45 @@ static uint16_t NAT_getports(uint16_t *portlist, IP_Port *ip_portlist, uint16_t
1082 return num; 1027 return num;
1083} 1028}
1084 1029
1085static void punch_holes(IP ip, uint16_t *port_list, uint16_t numports, uint16_t friend_num) 1030static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports, uint16_t friend_num)
1086{ 1031{
1087 if (numports > MAX_FRIEND_CLIENTS || numports == 0) 1032 if (numports > MAX_FRIEND_CLIENTS || numports == 0)
1088 return; 1033 return;
1089 1034
1090 uint32_t i; 1035 uint32_t i;
1091 uint32_t top = friends_list[friend_num].punching_index + MAX_PUNCHING_PORTS; 1036 uint32_t top = dht->friends_list[friend_num].punching_index + MAX_PUNCHING_PORTS;
1092 1037
1093 for (i = friends_list[friend_num].punching_index; i != top; i++) { 1038 for (i = dht->friends_list[friend_num].punching_index; i != top; i++) {
1094 /*TODO: improve port guessing algorithm*/ 1039 /*TODO: improve port guessing algorithm*/
1095 uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1); 1040 uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1);
1096 IP_Port pinging = {ip, htons(port)}; 1041 IP_Port pinging = {ip, htons(port)};
1097 send_ping_request(pinging, (clientid_t *) &friends_list[friend_num].client_id); 1042 send_ping_request(dht->ping, dht->c, pinging, (clientid_t *) &dht->friends_list[friend_num].client_id);
1098 } 1043 }
1099 1044
1100 friends_list[friend_num].punching_index = i; 1045 dht->friends_list[friend_num].punching_index = i;
1101} 1046}
1102 1047
1103static void doNAT(void) 1048static void do_NAT(DHT *dht)
1104{ 1049{
1105 uint32_t i; 1050 uint32_t i;
1106 uint64_t temp_time = unix_time(); 1051 uint64_t temp_time = unix_time();
1107 1052
1108 for (i = 0; i < num_friends; ++i) { 1053 for (i = 0; i < dht->num_friends; ++i) {
1109 IP_Port ip_list[MAX_FRIEND_CLIENTS]; 1054 IP_Port ip_list[MAX_FRIEND_CLIENTS];
1110 int num = friend_iplist(ip_list, i); 1055 int num = friend_iplist(dht, ip_list, i);
1111 1056
1112 /*If already connected or friend is not online don't try to hole punch*/ 1057 /*If already connected or friend is not online don't try to hole punch*/
1113 if (num < MAX_FRIEND_CLIENTS / 2) 1058 if (num < MAX_FRIEND_CLIENTS / 2)
1114 continue; 1059 continue;
1115 1060
1116 if (friends_list[i].NATping_timestamp + PUNCH_INTERVAL < temp_time) { 1061 if (dht->friends_list[i].NATping_timestamp + PUNCH_INTERVAL < temp_time) {
1117 send_NATping(friends_list[i].client_id, friends_list[i].NATping_id, 0); /*0 is request*/ 1062 send_NATping(dht, dht->friends_list[i].client_id, dht->friends_list[i].NATping_id, 0); /*0 is request*/
1118 friends_list[i].NATping_timestamp = temp_time; 1063 dht->friends_list[i].NATping_timestamp = temp_time;
1119 } 1064 }
1120 1065
1121 if (friends_list[i].hole_punching == 1 && 1066 if (dht->friends_list[i].hole_punching == 1 &&
1122 friends_list[i].punching_timestamp + PUNCH_INTERVAL < temp_time && 1067 dht->friends_list[i].punching_timestamp + PUNCH_INTERVAL < temp_time &&
1123 friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) { 1068 dht->friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) {
1124 1069
1125 IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2); 1070 IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2);
1126 1071
@@ -1129,10 +1074,10 @@ static void doNAT(void)
1129 1074
1130 uint16_t port_list[MAX_FRIEND_CLIENTS]; 1075 uint16_t port_list[MAX_FRIEND_CLIENTS];
1131 uint16_t numports = NAT_getports(port_list, ip_list, num, ip); 1076 uint16_t numports = NAT_getports(port_list, ip_list, num, ip);
1132 punch_holes(ip, port_list, numports, i); 1077 punch_holes(dht, ip, port_list, numports, i);
1133 1078
1134 friends_list[i].punching_timestamp = temp_time; 1079 dht->friends_list[i].punching_timestamp = temp_time;
1135 friends_list[i].hole_punching = 0; 1080 dht->friends_list[i].hole_punching = 0;
1136 } 1081 }
1137 } 1082 }
1138} 1083}
@@ -1149,7 +1094,7 @@ static void doNAT(void)
1149 network while preventing amplification attacks. 1094 network while preventing amplification attacks.
1150 return 0 if node was added 1095 return 0 if node was added
1151 return -1 if node was not added */ 1096 return -1 if node was not added */
1152int add_toping(uint8_t *client_id, IP_Port ip_port) 1097int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port)
1153{ 1098{
1154 if (ip_port.ip.i == 0) 1099 if (ip_port.ip.i == 0)
1155 return -1; 1100 return -1;
@@ -1157,19 +1102,19 @@ int add_toping(uint8_t *client_id, IP_Port ip_port)
1157 uint32_t i; 1102 uint32_t i;
1158 1103
1159 for (i = 0; i < MAX_TOPING; ++i) { 1104 for (i = 0; i < MAX_TOPING; ++i) {
1160 if (toping[i].ip_port.ip.i == 0) { 1105 if (dht->toping[i].ip_port.ip.i == 0) {
1161 memcpy(toping[i].client_id, client_id, CLIENT_ID_SIZE); 1106 memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE);
1162 toping[i].ip_port.ip.i = ip_port.ip.i; 1107 dht->toping[i].ip_port.ip.i = ip_port.ip.i;
1163 toping[i].ip_port.port = ip_port.port; 1108 dht->toping[i].ip_port.port = ip_port.port;
1164 return 0; 1109 return 0;
1165 } 1110 }
1166 } 1111 }
1167 1112
1168 for (i = 0; i < MAX_TOPING; ++i) { 1113 for (i = 0; i < MAX_TOPING; ++i) {
1169 if (id_closest(self_public_key, toping[i].client_id, client_id) == 2) { 1114 if (id_closest(dht->c->self_public_key, dht->toping[i].client_id, client_id) == 2) {
1170 memcpy(toping[i].client_id, client_id, CLIENT_ID_SIZE); 1115 memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE);
1171 toping[i].ip_port.ip.i = ip_port.ip.i; 1116 dht->toping[i].ip_port.ip.i = ip_port.ip.i;
1172 toping[i].ip_port.port = ip_port.port; 1117 dht->toping[i].ip_port.port = ip_port.port;
1173 return 0; 1118 return 0;
1174 } 1119 }
1175 } 1120 }
@@ -1179,68 +1124,89 @@ int add_toping(uint8_t *client_id, IP_Port ip_port)
1179 1124
1180/*Ping all the valid nodes in the toping list every TIME_TOPING seconds 1125/*Ping all the valid nodes in the toping list every TIME_TOPING seconds
1181 this function must be run at least once every TIME_TOPING seconds*/ 1126 this function must be run at least once every TIME_TOPING seconds*/
1182static void do_toping() 1127static void do_toping(DHT *dht)
1183{ 1128{
1184 uint64_t temp_time = unix_time(); 1129 uint64_t temp_time = unix_time();
1185 1130
1186 if (!is_timeout(temp_time, last_toping, TIME_TOPING)) 1131 if (!is_timeout(temp_time, dht->last_toping, TIME_TOPING))
1187 return; 1132 return;
1188 1133
1189 last_toping = temp_time; 1134 dht->last_toping = temp_time;
1190 uint32_t i; 1135 uint32_t i;
1191 1136
1192 for (i = 0; i < MAX_TOPING; ++i) { 1137 for (i = 0; i < MAX_TOPING; ++i) {
1193 if (toping[i].ip_port.ip.i == 0) 1138 if (dht->toping[i].ip_port.ip.i == 0)
1194 return; 1139 return;
1195 1140
1196 send_ping_request(toping[i].ip_port, (clientid_t *) toping[i].client_id); 1141 send_ping_request(dht->ping, dht->c, dht->toping[i].ip_port, (clientid_t *) dht->toping[i].client_id);
1197 toping[i].ip_port.ip.i = 0; 1142 dht->toping[i].ip_port.ip.i = 0;
1198 } 1143 }
1199} 1144}
1200 1145
1201 1146
1202void DHT_init(void) 1147DHT *new_DHT(Net_Crypto *c)
1203{ 1148{
1204 networking_registerhandler(0, &handle_ping_request); 1149 if (c == NULL)
1205 networking_registerhandler(1, &handle_ping_response); 1150 return NULL;
1206 networking_registerhandler(2, &handle_getnodes); 1151
1207 networking_registerhandler(3, &handle_sendnodes); 1152 DHT *temp = calloc(1, sizeof(DHT));
1208 cryptopacket_registerhandler(254, &handle_NATping); 1153
1154 if (temp == NULL)
1155 return NULL;
1156
1157 temp->ping = new_ping();
1158
1159 if (temp->ping == NULL) {
1160 kill_DHT(temp);
1161 return NULL;
1162 }
1163
1164 temp->c = c;
1165 networking_registerhandler(c->lossless_udp->net, 0, &handle_ping_request, temp);
1166 networking_registerhandler(c->lossless_udp->net, 1, &handle_ping_response, temp);
1167 networking_registerhandler(c->lossless_udp->net, 2, &handle_getnodes, temp);
1168 networking_registerhandler(c->lossless_udp->net, 3, &handle_sendnodes, temp);
1169 cryptopacket_registerhandler(c, 254, &handle_NATping, temp);
1170 return temp;
1209} 1171}
1210 1172
1211void doDHT(void) 1173void do_DHT(DHT *dht)
1212{ 1174{
1213 doClose(); 1175 do_Close(dht);
1214 doDHTFriends(); 1176 do_DHT_friends(dht);
1215 doNAT(); 1177 do_NAT(dht);
1216 do_toping(); 1178 do_toping(dht);
1179}
1180void kill_DHT(DHT *dht)
1181{
1182 kill_ping(dht->ping);
1183 free(dht->friends_list);
1184 free(dht);
1217} 1185}
1218 1186
1219/* get the size of the DHT (for saving) */ 1187/* get the size of the DHT (for saving) */
1220uint32_t DHT_size(void) 1188uint32_t DHT_size(DHT *dht)
1221{ 1189{
1222 return sizeof(close_clientlist) + sizeof(Friend) * num_friends; 1190 return sizeof(dht->close_clientlist) + sizeof(DHT_Friend) * dht->num_friends;
1223} 1191}
1224 1192
1225/* save the DHT in data where data is an array of size DHT_size() */ 1193/* save the DHT in data where data is an array of size DHT_size() */
1226void DHT_save(uint8_t *data) 1194void DHT_save(DHT *dht, uint8_t *data)
1227{ 1195{
1228 memcpy(data, close_clientlist, sizeof(close_clientlist)); 1196 memcpy(data, dht->close_clientlist, sizeof(dht->close_clientlist));
1229 memcpy(data + sizeof(close_clientlist), friends_list, sizeof(Friend) * num_friends); 1197 memcpy(data + sizeof(dht->close_clientlist), dht->friends_list, sizeof(DHT_Friend) * dht->num_friends);
1230} 1198}
1231 1199
1232/* load the DHT from data of size size; 1200/* load the DHT from data of size size;
1233 * return -1 if failure 1201 * return -1 if failure
1234 * return 0 if success 1202 * return 0 if success
1235 */ 1203 */
1236int DHT_load(uint8_t *data, uint32_t size) 1204int DHT_load(DHT *dht, uint8_t *data, uint32_t size)
1237{ 1205{
1238 init_ping(); 1206 if (size < sizeof(dht->close_clientlist))
1239
1240 if (size < sizeof(close_clientlist))
1241 return -1; 1207 return -1;
1242 1208
1243 if ((size - sizeof(close_clientlist)) % sizeof(Friend) != 0) 1209 if ((size - sizeof(dht->close_clientlist)) % sizeof(DHT_Friend) != 0)
1244 return -1; 1210 return -1;
1245 1211
1246 uint32_t i, j; 1212 uint32_t i, j;
@@ -1249,19 +1215,19 @@ int DHT_load(uint8_t *data, uint32_t size)
1249 1215
1250 Client_data *client; 1216 Client_data *client;
1251 1217
1252 temp = (size - sizeof(close_clientlist)) / sizeof(Friend); 1218 temp = (size - sizeof(dht->close_clientlist)) / sizeof(DHT_Friend);
1253 1219
1254 if (temp != 0) { 1220 if (temp != 0) {
1255 Friend *tempfriends_list = (Friend *)(data + sizeof(close_clientlist)); 1221 DHT_Friend *tempfriends_list = (DHT_Friend *)(data + sizeof(dht->close_clientlist));
1256 1222
1257 for (i = 0; i < temp; ++i) { 1223 for (i = 0; i < temp; ++i) {
1258 DHT_addfriend(tempfriends_list[i].client_id); 1224 DHT_addfriend(dht, tempfriends_list[i].client_id);
1259 1225
1260 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 1226 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
1261 client = &tempfriends_list[i].client_list[j]; 1227 client = &tempfriends_list[i].client_list[j];
1262 1228
1263 if (client->timestamp != 0) 1229 if (client->timestamp != 0)
1264 getnodes(client->ip_port, client->client_id, tempfriends_list[i].client_id); 1230 getnodes(dht, client->ip_port, client->client_id, tempfriends_list[i].client_id);
1265 } 1231 }
1266 } 1232 }
1267 } 1233 }
@@ -1270,8 +1236,8 @@ int DHT_load(uint8_t *data, uint32_t size)
1270 1236
1271 for (i = 0; i < LCLIENT_LIST; ++i) { 1237 for (i = 0; i < LCLIENT_LIST; ++i) {
1272 if (tempclose_clientlist[i].timestamp != 0) 1238 if (tempclose_clientlist[i].timestamp != 0)
1273 DHT_bootstrap( tempclose_clientlist[i].ip_port, 1239 DHT_bootstrap(dht, tempclose_clientlist[i].ip_port,
1274 tempclose_clientlist[i].client_id ); 1240 tempclose_clientlist[i].client_id );
1275 } 1241 }
1276 1242
1277 return 0; 1243 return 0;
@@ -1280,13 +1246,13 @@ int DHT_load(uint8_t *data, uint32_t size)
1280/* returns 0 if we are not connected to the DHT 1246/* returns 0 if we are not connected to the DHT
1281 * returns 1 if we are 1247 * returns 1 if we are
1282 */ 1248 */
1283int DHT_isconnected(void) 1249int DHT_isconnected(DHT *dht)
1284{ 1250{
1285 uint32_t i; 1251 uint32_t i;
1286 uint64_t temp_time = unix_time(); 1252 uint64_t temp_time = unix_time();
1287 1253
1288 for (i = 0; i < LCLIENT_LIST; ++i) { 1254 for (i = 0; i < LCLIENT_LIST; ++i) {
1289 if (!is_timeout(temp_time, close_clientlist[i].timestamp, BAD_NODE_TIMEOUT)) 1255 if (!is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT))
1290 return 1; 1256 return 1;
1291 } 1257 }
1292 1258
diff --git a/core/DHT.h b/core/DHT.h
index 8cb0436a..6295581b 100644
--- a/core/DHT.h
+++ b/core/DHT.h
@@ -34,6 +34,20 @@ extern "C" {
34/* size of the client_id in bytes */ 34/* size of the client_id in bytes */
35#define CLIENT_ID_SIZE crypto_box_PUBLICKEYBYTES 35#define CLIENT_ID_SIZE crypto_box_PUBLICKEYBYTES
36 36
37/* maximum number of clients stored per friend. */
38#define MAX_FRIEND_CLIENTS 8
39
40/* A list of the clients mathematically closest to ours. */
41#define LCLIENT_LIST 32
42
43/* The list of ip ports along with the ping_id of what we sent them and a timestamp */
44#define LPING_ARRAY 256 //NOTE Deprecated (doesn't do anything)
45
46#define LSEND_NODES_ARRAY LPING_ARRAY/2
47
48/*Maximum newly announced nodes to ping per TIME_TOPING seconds*/
49#define MAX_TOPING 16
50
37typedef struct { 51typedef struct {
38 uint8_t client_id[CLIENT_ID_SIZE]; 52 uint8_t client_id[CLIENT_ID_SIZE];
39 IP_Port ip_port; 53 IP_Port ip_port;
@@ -45,19 +59,64 @@ typedef struct {
45 uint64_t ret_timestamp; 59 uint64_t ret_timestamp;
46} Client_data; 60} Client_data;
47 61
48Client_data *DHT_get_close_list(void); 62/*----------------------------------------------------------------------------------*/
63
64typedef struct {
65 uint8_t client_id[CLIENT_ID_SIZE];
66 Client_data client_list[MAX_FRIEND_CLIENTS];
67
68 /* time at which the last get_nodes request was sent. */
69 uint64_t lastgetnode;
70
71 /* Symetric NAT hole punching stuff */
72
73 /* 1 if currently hole punching, otherwise 0 */
74 uint8_t hole_punching;
75 uint32_t punching_index;
76 uint64_t punching_timestamp;
77 uint64_t recvNATping_timestamp;
78 uint64_t NATping_id;
79 uint64_t NATping_timestamp;
80} DHT_Friend;
81
82typedef struct {
83 uint8_t client_id[CLIENT_ID_SIZE];
84 IP_Port ip_port;
85} Node_format;
86
87typedef struct {
88 IP_Port ip_port;
89 uint64_t ping_id;
90 uint64_t timestamp;
91} Pinged;
92
93/*----------------------------------------------------------------------------------*/
94typedef struct {
95 Net_Crypto *c;
96 Client_data close_clientlist[LCLIENT_LIST];
97 DHT_Friend *friends_list;
98 uint16_t num_friends;
99 Pinged send_nodes[LSEND_NODES_ARRAY];
100 Node_format toping[MAX_TOPING];
101 uint64_t last_toping;
102 uint64_t close_lastgetnodes;
103 void *ping;
104} DHT;
105/*----------------------------------------------------------------------------------*/
106
107Client_data *DHT_get_close_list(DHT *dht);
49 108
50/* Add a new friend to the friends list 109/* Add a new friend to the friends list
51 client_id must be CLIENT_ID_SIZE bytes long. 110 client_id must be CLIENT_ID_SIZE bytes long.
52 returns 0 if success 111 returns 0 if success
53 returns 1 if failure (friends list is full) */ 112 returns 1 if failure (friends list is full) */
54int DHT_addfriend(uint8_t *client_id); 113int DHT_addfriend(DHT *dht, uint8_t *client_id);
55 114
56/* Delete a friend from the friends list 115/* Delete a friend from the friends list
57 client_id must be CLIENT_ID_SIZE bytes long. 116 client_id must be CLIENT_ID_SIZE bytes long.
58 returns 0 if success 117 returns 0 if success
59 returns 1 if failure (client_id not in friends list) */ 118 returns 1 if failure (client_id not in friends list) */
60int DHT_delfriend(uint8_t *client_id); 119int DHT_delfriend(DHT *dht, uint8_t *client_id);
61 120
62/* Get ip of friend 121/* Get ip of friend
63 client_id must be CLIENT_ID_SIZE bytes long. 122 client_id must be CLIENT_ID_SIZE bytes long.
@@ -66,14 +125,14 @@ int DHT_delfriend(uint8_t *client_id);
66 returns ip if success 125 returns ip if success
67 returns ip of 0 if failure (This means the friend is either offline or we have not found him yet.) 126 returns ip of 0 if failure (This means the friend is either offline or we have not found him yet.)
68 returns ip of 1 if friend is not in list. */ 127 returns ip of 1 if friend is not in list. */
69IP_Port DHT_getfriendip(uint8_t *client_id); 128IP_Port DHT_getfriendip(DHT *dht, uint8_t *client_id);
70 129
71/* Run this function at least a couple times per second (It's the main loop) */ 130/* Run this function at least a couple times per second (It's the main loop) */
72void doDHT(void); 131void do_DHT(DHT *dht);
73 132
74/* Use this function to bootstrap the client 133/* Use this function to bootstrap the client
75 Sends a get nodes request to the given node with ip port and public_key */ 134 Sends a get nodes request to the given node with ip port and public_key */
76void DHT_bootstrap(IP_Port ip_port, uint8_t *public_key); 135void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key);
77 136
78/* Add nodes to the toping list 137/* Add nodes to the toping list
79 all nodes in this list are pinged every TIME_TOPING seconds 138 all nodes in this list are pinged every TIME_TOPING seconds
@@ -83,17 +142,17 @@ void DHT_bootstrap(IP_Port ip_port, uint8_t *public_key);
83 network while preventing amplification attacks. 142 network while preventing amplification attacks.
84 return 0 if node was added 143 return 0 if node was added
85 return -1 if node was not added */ 144 return -1 if node was not added */
86int add_toping(uint8_t *client_id, IP_Port ip_port); 145int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port);
87 146
88/* ROUTING FUNCTIONS */ 147/* ROUTING FUNCTIONS */
89 148
90/* send the given packet to node with client_id 149/* send the given packet to node with client_id
91 returns -1 if failure */ 150 returns -1 if failure */
92int route_packet(uint8_t *client_id, uint8_t *packet, uint32_t length); 151int route_packet(DHT *dht, uint8_t *client_id, uint8_t *packet, uint32_t length);
93 152
94/* Send the following packet to everyone who tells us they are connected to friend_id 153/* Send the following packet to everyone who tells us they are connected to friend_id
95 returns the number of nodes it sent the packet to */ 154 returns the number of nodes it sent the packet to */
96int route_tofriend(uint8_t *friend_id, uint8_t *packet, uint32_t length); 155int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t length);
97 156
98/* NAT PUNCHING FUNCTIONS */ 157/* NAT PUNCHING FUNCTIONS */
99 158
@@ -101,29 +160,31 @@ int route_tofriend(uint8_t *friend_id, uint8_t *packet, uint32_t length);
101 ip_portlist must be at least MAX_FRIEND_CLIENTS big 160 ip_portlist must be at least MAX_FRIEND_CLIENTS big
102 returns the number of ips returned 161 returns the number of ips returned
103 returns -1 if no such friend*/ 162 returns -1 if no such friend*/
104int friend_ips(IP_Port *ip_portlist, uint8_t *friend_id); 163int friend_ips(DHT *dht, IP_Port *ip_portlist, uint8_t *friend_id);
105 164
106/* SAVE/LOAD functions */ 165/* SAVE/LOAD functions */
107 166
108/* get the size of the DHT (for saving) */ 167/* get the size of the DHT (for saving) */
109uint32_t DHT_size(void); 168uint32_t DHT_size(DHT *dht);
110 169
111/* save the DHT in data where data is an array of size DHT_size() */ 170/* save the DHT in data where data is an array of size DHT_size() */
112void DHT_save(uint8_t *data); 171void DHT_save(DHT *dht, uint8_t *data);
113 172
114/* init DHT */ 173/* init DHT */
115void DHT_init(void); 174DHT *new_DHT(Net_Crypto *c);
175
176void kill_DHT(DHT *dht);
116 177
117/* load the DHT from data of size size; 178/* load the DHT from data of size size;
118 return -1 if failure 179 return -1 if failure
119 return 0 if success */ 180 return 0 if success */
120int DHT_load(uint8_t *data, uint32_t size); 181int DHT_load(DHT *dht, uint8_t *data, uint32_t size);
121 182
122/* returns 0 if we are not connected to the DHT 183/* returns 0 if we are not connected to the DHT
123 returns 1 if we are */ 184 returns 1 if we are */
124int DHT_isconnected(); 185int DHT_isconnected(DHT *dht);
125 186
126void addto_lists(IP_Port ip_port, uint8_t *client_id); 187void addto_lists(DHT *dht, IP_Port ip_port, uint8_t *client_id);
127 188
128#ifdef __cplusplus 189#ifdef __cplusplus
129} 190}
diff --git a/core/LAN_discovery.c b/core/LAN_discovery.c
index ad1337ef..cbbb384b 100644
--- a/core/LAN_discovery.c
+++ b/core/LAN_discovery.c
@@ -121,30 +121,32 @@ static int LAN_ip(IP ip)
121 return -1; 121 return -1;
122} 122}
123 123
124static int handle_LANdiscovery(IP_Port source, uint8_t *packet, uint32_t length) 124static int handle_LANdiscovery(void *object, IP_Port source, uint8_t *packet, uint32_t length)
125{ 125{
126 DHT *dht = object;
127
126 if (LAN_ip(source.ip) == -1) 128 if (LAN_ip(source.ip) == -1)
127 return 1; 129 return 1;
128 130
129 if (length != crypto_box_PUBLICKEYBYTES + 1) 131 if (length != crypto_box_PUBLICKEYBYTES + 1)
130 return 1; 132 return 1;
131 133
132 DHT_bootstrap(source, packet + 1); 134 DHT_bootstrap(dht, source, packet + 1);
133 return 0; 135 return 0;
134} 136}
135 137
136 138
137int send_LANdiscovery(uint16_t port) 139int send_LANdiscovery(uint16_t port, Net_Crypto *c)
138{ 140{
139 uint8_t data[crypto_box_PUBLICKEYBYTES + 1]; 141 uint8_t data[crypto_box_PUBLICKEYBYTES + 1];
140 data[0] = 33; 142 data[0] = 33;
141 memcpy(data + 1, self_public_key, crypto_box_PUBLICKEYBYTES); 143 memcpy(data + 1, c->self_public_key, crypto_box_PUBLICKEYBYTES);
142 IP_Port ip_port = {broadcast_ip(), port}; 144 IP_Port ip_port = {broadcast_ip(), port};
143 return sendpacket(ip_port, data, 1 + crypto_box_PUBLICKEYBYTES); 145 return sendpacket(c->lossless_udp->net->sock, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES);
144} 146}
145 147
146 148
147void LANdiscovery_init(void) 149void LANdiscovery_init(DHT *dht)
148{ 150{
149 networking_registerhandler(33, &handle_LANdiscovery); 151 networking_registerhandler(dht->c->lossless_udp->net, 33, &handle_LANdiscovery, dht);
150} 152}
diff --git a/core/LAN_discovery.h b/core/LAN_discovery.h
index 6b5b8c75..5a790331 100644
--- a/core/LAN_discovery.h
+++ b/core/LAN_discovery.h
@@ -40,11 +40,11 @@ extern "C" {
40#endif 40#endif
41 41
42/*Send a LAN discovery pcaket to the broadcast address with port port*/ 42/*Send a LAN discovery pcaket to the broadcast address with port port*/
43int send_LANdiscovery(uint16_t port); 43int send_LANdiscovery(uint16_t port, Net_Crypto *c);
44 44
45 45
46/* sets up packet handlers */ 46/* sets up packet handlers */
47void LANdiscovery_init(void); 47void LANdiscovery_init(DHT *dht);
48 48
49 49
50 50
diff --git a/core/Lossless_UDP.c b/core/Lossless_UDP.c
index 506a06eb..15e8dea3 100644
--- a/core/Lossless_UDP.c
+++ b/core/Lossless_UDP.c
@@ -28,97 +28,6 @@
28 28
29#include "Lossless_UDP.h" 29#include "Lossless_UDP.h"
30 30
31/* maximum data packets in sent and receive queues. */
32#define MAX_QUEUE_NUM 16
33
34/* maximum number of data packets in the buffer */
35#define BUFFER_PACKET_NUM (16-1)
36
37/* timeout per connection is randomly set between CONNEXION_TIMEOUT and 2*CONNEXION_TIMEOUT */
38#define CONNEXION_TIMEOUT 5
39
40/* initial amount of sync/hanshake packets to send per second. */
41#define SYNC_RATE 2
42
43/* initial send rate of data. */
44#define DATA_SYNC_RATE 30
45
46typedef struct {
47 uint8_t data[MAX_DATA_SIZE];
48 uint16_t size;
49} Data;
50
51typedef struct {
52 IP_Port ip_port;
53
54 /*
55 * 0 if connection is dead, 1 if attempting handshake,
56 * 2 if handshake is done (we start sending SYNC packets)
57 * 3 if we are sending SYNC packets and can send data
58 * 4 if the connection has timed out.
59 */
60 uint8_t status;
61
62 /*
63 * 1 or 2 if connection was initiated by someone else, 0 if not.
64 * 2 if incoming_connection() has not returned it yet, 1 if it has.
65 */
66 uint8_t inbound;
67
68 uint16_t SYNC_rate; /* current SYNC packet send rate packets per second. */
69 uint16_t data_rate; /* current data packet send rate packets per second. */
70
71 uint64_t last_SYNC; /* time our last SYNC packet was sent. */
72 uint64_t last_sent; /* time our last data or handshake packet was sent. */
73 uint64_t last_recvSYNC; /* time we last received a SYNC packet from the other */
74 uint64_t last_recvdata; /* time we last received a DATA packet from the other */
75 uint64_t killat; /* time to kill the connection */
76
77 Data sendbuffer[MAX_QUEUE_NUM]; /* packet send buffer. */
78 Data recvbuffer[MAX_QUEUE_NUM]; /* packet receive buffer. */
79
80 uint32_t handshake_id1;
81 uint32_t handshake_id2;
82
83 /* number of data packets received (also used as handshake_id1) */
84 uint32_t recv_packetnum;
85
86 /* number of packets received by the other peer */
87 uint32_t orecv_packetnum;
88
89 /* number of data packets sent */
90 uint32_t sent_packetnum;
91
92 /* number of packets sent by the other peer. */
93 uint32_t osent_packetnum;
94
95 /* number of latest packet written onto the sendbuffer */
96 uint32_t sendbuff_packetnum;
97
98 /* we know all packets before that number were successfully sent */
99 uint32_t successful_sent;
100
101 /* packet number of last packet read with the read_packet function */
102 uint32_t successful_read;
103
104 /* list of currently requested packet numbers(by the other person) */
105 uint32_t req_packets[BUFFER_PACKET_NUM];
106
107 /* total number of currently requested packets(by the other person) */
108 uint16_t num_req_paquets;
109
110 uint8_t recv_counter;
111 uint8_t send_counter;
112 uint8_t timeout; /* connection timeout in seconds. */
113} Connection;
114
115
116static Connection *connections;
117
118static uint32_t connections_length; /* Length of connections array */
119static uint32_t connections_number; /* Number of connections in connections array */
120
121#define MAX_CONNECTIONS connections_length
122 31
123/* Functions */ 32/* Functions */
124 33
@@ -127,22 +36,20 @@ static uint32_t connections_number; /* Number of connections in connections arra
127 * Return -1 if there are no connections like we are looking for 36 * Return -1 if there are no connections like we are looking for
128 * Return id if it found it 37 * Return id if it found it
129 */ 38 */
130int getconnection_id(IP_Port ip_port) 39int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port)
131{ 40{
132 uint32_t i; 41 uint32_t i;
133 42
134 for (i = 0; i < MAX_CONNECTIONS; ++i) { 43 for (i = 0; i < ludp->connections_length; ++i) {
135 if (connections[i].ip_port.ip.i == ip_port.ip.i && 44 if (ludp->connections[i].ip_port.ip.i == ip_port.ip.i &&
136 connections[i].ip_port.port == ip_port.port && 45 ludp->connections[i].ip_port.port == ip_port.port &&
137 connections[i].status > 0) 46 ludp->connections[i].status > 0)
138 return i; 47 return i;
139 } 48 }
140 49
141 return -1; 50 return -1;
142} 51}
143 52
144/* table of random numbers used below. */
145static uint32_t randtable[6][256];
146 53
147/* 54/*
148 * Generate a handshake_id which depends on the ip_port. 55 * Generate a handshake_id which depends on the ip_port.
@@ -150,15 +57,15 @@ static uint32_t randtable[6][256];
150 * 57 *
151 * TODO: make this better 58 * TODO: make this better
152 */ 59 */
153static uint32_t handshake_id(IP_Port source) 60static uint32_t handshake_id(Lossless_UDP *ludp, IP_Port source)
154{ 61{
155 uint32_t id = 0, i; 62 uint32_t id = 0, i;
156 63
157 for (i = 0; i < 6; ++i) { 64 for (i = 0; i < 6; ++i) {
158 if (randtable[i][((uint8_t *)&source)[i]] == 0) 65 if (ludp->randtable[i][((uint8_t *)&source)[i]] == 0)
159 randtable[i][((uint8_t *)&source)[i]] = random_int(); 66 ludp->randtable[i][((uint8_t *)&source)[i]] = random_int();
160 67
161 id ^= randtable[i][((uint8_t *)&source)[i]]; 68 id ^= ludp->randtable[i][((uint8_t *)&source)[i]];
162 } 69 }
163 70
164 if (id == 0) /* id can't be zero */ 71 if (id == 0) /* id can't be zero */
@@ -172,10 +79,10 @@ static uint32_t handshake_id(IP_Port source)
172 * 79 *
173 * TODO: make this better 80 * TODO: make this better
174 */ 81 */
175static void change_handshake(IP_Port source) 82static void change_handshake(Lossless_UDP *ludp, IP_Port source)
176{ 83{
177 uint8_t rand = random_int() % 4; 84 uint8_t rand = random_int() % 4;
178 randtable[rand][((uint8_t *)&source)[rand]] = random_int(); 85 ludp->randtable[rand][((uint8_t *)&source)[rand]] = random_int();
179} 86}
180 87
181/* 88/*
@@ -184,33 +91,33 @@ static void change_handshake(IP_Port source)
184 * Return -1 if it could not initialize the connectiont 91 * Return -1 if it could not initialize the connectiont
185 * If there already was an existing connection to that ip_port return its number. 92 * If there already was an existing connection to that ip_port return its number.
186 */ 93 */
187int new_connection(IP_Port ip_port) 94int new_connection(Lossless_UDP *ludp, IP_Port ip_port)
188{ 95{
189 int connect = getconnection_id(ip_port); 96 int connect = getconnection_id(ludp, ip_port);
190 97
191 if (connect != -1) 98 if (connect != -1)
192 return connect; 99 return connect;
193 100
194 if (connections_number == connections_length) { 101 if (ludp->connections_number == ludp->connections_length) {
195 Connection *temp; 102 Connection *temp;
196 temp = realloc(connections, sizeof(Connection) * (connections_length + 1)); 103 temp = realloc(ludp->connections, sizeof(Connection) * (ludp->connections_length + 1));
197 104
198 if (temp == NULL) 105 if (temp == NULL)
199 return -1; 106 return -1;
200 107
201 memset(&temp[connections_length], 0, sizeof(Connection)); 108 memset(&temp[ludp->connections_length], 0, sizeof(Connection));
202 ++connections_length; 109 ++ludp->connections_length;
203 connections = temp; 110 ludp->connections = temp;
204 } 111 }
205 112
206 uint32_t i; 113 uint32_t i;
207 114
208 for (i = 0; i < MAX_CONNECTIONS; ++i) { 115 for (i = 0; i < ludp->connections_length; ++i) {
209 if (connections[i].status == 0) { 116 if (ludp->connections[i].status == 0) {
210 memset(&connections[i], 0, sizeof(Connection)); 117 memset(&ludp->connections[i], 0, sizeof(Connection));
211 uint32_t handshake_id1 = handshake_id(ip_port); 118 uint32_t handshake_id1 = handshake_id(ludp, ip_port);
212 119
213 connections[i] = (Connection) { 120 ludp->connections[i] = (Connection) {
214 .ip_port = ip_port, 121 .ip_port = ip_port,
215 .status = 1, 122 .status = 1,
216 .inbound = 0, 123 .inbound = 0,
@@ -227,7 +134,7 @@ int new_connection(IP_Port ip_port)
227 /* add randomness to timeout to prevent connections getting stuck in a loop. */ 134 /* add randomness to timeout to prevent connections getting stuck in a loop. */
228 .timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT 135 .timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT
229 }; 136 };
230 ++connections_number; 137 ++ludp->connections_number;
231 138
232 return i; 139 return i;
233 } 140 }
@@ -241,31 +148,31 @@ int new_connection(IP_Port ip_port)
241 * Returns an integer corresponding to the connection id. 148 * Returns an integer corresponding to the connection id.
242 * Return -1 if it could not initialize the connection. 149 * Return -1 if it could not initialize the connection.
243 */ 150 */
244static int new_inconnection(IP_Port ip_port) 151static int new_inconnection(Lossless_UDP *ludp, IP_Port ip_port)
245{ 152{
246 if (getconnection_id(ip_port) != -1) 153 if (getconnection_id(ludp, ip_port) != -1)
247 return -1; 154 return -1;
248 155
249 if (connections_number == connections_length) { 156 if (ludp->connections_number == ludp->connections_length) {
250 Connection *temp; 157 Connection *temp;
251 temp = realloc(connections, sizeof(Connection) * (connections_length + 1)); 158 temp = realloc(ludp->connections, sizeof(Connection) * (ludp->connections_length + 1));
252 159
253 if (temp == NULL) 160 if (temp == NULL)
254 return -1; 161 return -1;
255 162
256 memset(&temp[connections_length], 0, sizeof(Connection)); 163 memset(&temp[ludp->connections_length], 0, sizeof(Connection));
257 ++connections_length; 164 ++ludp->connections_length;
258 connections = temp; 165 ludp->connections = temp;
259 } 166 }
260 167
261 uint32_t i; 168 uint32_t i;
262 169
263 for (i = 0; i < MAX_CONNECTIONS; ++i) { 170 for (i = 0; i < ludp->connections_length; ++i) {
264 if (connections[i].status == 0) { 171 if (ludp->connections[i].status == 0) {
265 memset(&connections[i], 0, sizeof(Connection)); 172 memset(&ludp->connections[i], 0, sizeof(Connection));
266 uint64_t timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT; 173 uint64_t timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT;
267 174
268 connections[i] = (Connection) { 175 ludp->connections[i] = (Connection) {
269 .ip_port = ip_port, 176 .ip_port = ip_port,
270 .status = 2, 177 .status = 2,
271 .inbound = 2, 178 .inbound = 2,
@@ -281,7 +188,7 @@ static int new_inconnection(IP_Port ip_port)
281 /* if this connection isn't handled within the timeout kill it. */ 188 /* if this connection isn't handled within the timeout kill it. */
282 .killat = current_time() + 1000000UL * timeout 189 .killat = current_time() + 1000000UL * timeout
283 }; 190 };
284 ++connections_number; 191 ++ludp->connections_number;
285 return i; 192 return i;
286 } 193 }
287 } 194 }
@@ -293,13 +200,13 @@ static int new_inconnection(IP_Port ip_port)
293 * Returns an integer corresponding to the next connection in our incoming connection list. 200 * Returns an integer corresponding to the next connection in our incoming connection list.
294 * Return -1 if there are no new incoming connections in the list. 201 * Return -1 if there are no new incoming connections in the list.
295 */ 202 */
296int incoming_connection(void) 203int incoming_connection(Lossless_UDP *ludp)
297{ 204{
298 uint32_t i; 205 uint32_t i;
299 206
300 for (i = 0; i < MAX_CONNECTIONS; ++i) { 207 for (i = 0; i < ludp->connections_length; ++i) {
301 if (connections[i].inbound == 2) { 208 if (ludp->connections[i].inbound == 2) {
302 connections[i].inbound = 1; 209 ludp->connections[i].inbound = 1;
303 return i; 210 return i;
304 } 211 }
305 } 212 }
@@ -308,46 +215,46 @@ int incoming_connection(void)
308} 215}
309 216
310/* Try to free some memory from the connections array. */ 217/* Try to free some memory from the connections array. */
311static void free_connections(void) 218static void free_connections(Lossless_UDP *ludp)
312{ 219{
313 uint32_t i; 220 uint32_t i;
314 221
315 for (i = connections_length; i != 0; --i) 222 for (i = ludp->connections_length; i != 0; --i)
316 if (connections[i - 1].status != 0) 223 if (ludp->connections[i - 1].status != 0)
317 break; 224 break;
318 225
319 if (connections_length == i) 226 if (ludp->connections_length == i)
320 return; 227 return;
321 228
322 if (i == 0) { 229 if (i == 0) {
323 free(connections); 230 free(ludp->connections);
324 connections = NULL; 231 ludp->connections = NULL;
325 connections_length = i; 232 ludp->connections_length = i;
326 return; 233 return;
327 } 234 }
328 235
329 Connection *temp; 236 Connection *temp;
330 temp = realloc(connections, sizeof(Connection) * i); 237 temp = realloc(ludp->connections, sizeof(Connection) * i);
331 238
332 if (temp == NULL && i != 0) 239 if (temp == NULL && i != 0)
333 return; 240 return;
334 241
335 connections = temp; 242 ludp->connections = temp;
336 connections_length = i; 243 ludp->connections_length = i;
337} 244}
338 245
339/* 246/*
340 * Return -1 if it could not kill the connection. 247 * Return -1 if it could not kill the connection.
341 * Return 0 if killed successfully 248 * Return 0 if killed successfully
342 */ 249 */
343int kill_connection(int connection_id) 250int kill_connection(Lossless_UDP *ludp, int connection_id)
344{ 251{
345 if (connection_id >= 0 && connection_id < MAX_CONNECTIONS) { 252 if (connection_id >= 0 && connection_id < ludp->connections_length) {
346 if (connections[connection_id].status > 0) { 253 if (ludp->connections[connection_id].status > 0) {
347 connections[connection_id].status = 0; 254 ludp->connections[connection_id].status = 0;
348 change_handshake(connections[connection_id].ip_port); 255 change_handshake(ludp, ludp->connections[connection_id].ip_port);
349 --connections_number; 256 --ludp->connections_number;
350 free_connections(); 257 free_connections(ludp);
351 return 0; 258 return 0;
352 } 259 }
353 } 260 }
@@ -360,11 +267,11 @@ int kill_connection(int connection_id)
360 * Return -1 if it can not kill the connection. 267 * Return -1 if it can not kill the connection.
361 * Return 0 if it will kill it. 268 * Return 0 if it will kill it.
362 */ 269 */
363int kill_connection_in(int connection_id, uint32_t seconds) 270int kill_connection_in(Lossless_UDP *ludp, int connection_id, uint32_t seconds)
364{ 271{
365 if (connection_id >= 0 && connection_id < MAX_CONNECTIONS) { 272 if (connection_id >= 0 && connection_id < ludp->connections_length) {
366 if (connections[connection_id].status > 0) { 273 if (ludp->connections[connection_id].status > 0) {
367 connections[connection_id].killat = current_time() + 1000000UL * seconds; 274 ludp->connections[connection_id].killat = current_time() + 1000000UL * seconds;
368 return 0; 275 return 0;
369 } 276 }
370 } 277 }
@@ -380,65 +287,66 @@ int kill_connection_in(int connection_id, uint32_t seconds)
380 * Return 3 if fully connected. 287 * Return 3 if fully connected.
381 * Return 4 if timed out and waiting to be killed. 288 * Return 4 if timed out and waiting to be killed.
382 */ 289 */
383int is_connected(int connection_id) 290int is_connected(Lossless_UDP *ludp, int connection_id)
384{ 291{
385 if (connection_id >= 0 && connection_id < MAX_CONNECTIONS) 292 if (connection_id >= 0 && connection_id < ludp->connections_length)
386 return connections[connection_id].status; 293 return ludp->connections[connection_id].status;
387 294
388 return 0; 295 return 0;
389} 296}
390 297
391/* returns the ip_port of the corresponding connection. */ 298/* returns the ip_port of the corresponding connection. */
392IP_Port connection_ip(int connection_id) 299IP_Port connection_ip(Lossless_UDP *ludp, int connection_id)
393{ 300{
394 if (connection_id >= 0 && connection_id < MAX_CONNECTIONS) 301 if (connection_id >= 0 && connection_id < ludp->connections_length)
395 return connections[connection_id].ip_port; 302 return ludp->connections[connection_id].ip_port;
396 303
397 IP_Port zero = {{{0}}, 0}; 304 IP_Port zero = {{{0}}, 0};
398 return zero; 305 return zero;
399} 306}
400 307
401/* returns the number of packets in the queue waiting to be successfully sent. */ 308/* returns the number of packets in the queue waiting to be successfully sent. */
402uint32_t sendqueue(int connection_id) 309uint32_t sendqueue(Lossless_UDP *ludp, int connection_id)
403{ 310{
404 if (connection_id < 0 || connection_id >= MAX_CONNECTIONS) 311 if (connection_id < 0 || connection_id >= ludp->connections_length)
405 return 0; 312 return 0;
406 313
407 return connections[connection_id].sendbuff_packetnum - connections[connection_id].successful_sent; 314 return ludp->connections[connection_id].sendbuff_packetnum - ludp->connections[connection_id].successful_sent;
408} 315}
409 316
410/* returns the number of packets in the queue waiting to be successfully read with read_packet(...) */ 317/* returns the number of packets in the queue waiting to be successfully read with read_packet(...) */
411uint32_t recvqueue(int connection_id) 318uint32_t recvqueue(Lossless_UDP *ludp, int connection_id)
412{ 319{
413 if (connection_id < 0 || connection_id >= MAX_CONNECTIONS) 320 if (connection_id < 0 || connection_id >= ludp->connections_length)
414 return 0; 321 return 0;
415 322
416 return connections[connection_id].recv_packetnum - connections[connection_id].successful_read; 323 return ludp->connections[connection_id].recv_packetnum - ludp->connections[connection_id].successful_read;
417} 324}
418 325
419/* returns the id of the next packet in the queue 326/* returns the id of the next packet in the queue
420 return -1 if no packet in queue */ 327 return -1 if no packet in queue */
421char id_packet(int connection_id) 328char id_packet(Lossless_UDP *ludp, int connection_id)
422{ 329{
423 if (connection_id < 0 || connection_id >= MAX_CONNECTIONS) 330 if (connection_id < 0 || connection_id >= ludp->connections_length)
424 return -1; 331 return -1;
425 332
426 if (recvqueue(connection_id) != 0 && connections[connection_id].status != 0) 333 if (recvqueue(ludp, connection_id) != 0 && ludp->connections[connection_id].status != 0)
427 return connections[connection_id].recvbuffer[connections[connection_id].successful_read % MAX_QUEUE_NUM].data[0]; 334 return ludp->connections[connection_id].recvbuffer[ludp->connections[connection_id].successful_read %
335 MAX_QUEUE_NUM].data[0];
428 336
429 return -1; 337 return -1;
430} 338}
431 339
432/* return 0 if there is no received data in the buffer. 340/* return 0 if there is no received data in the buffer.
433 return length of received packet if successful */ 341 return length of received packet if successful */
434int read_packet(int connection_id, uint8_t *data) 342int read_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data)
435{ 343{
436 if (recvqueue(connection_id) != 0) { 344 if (recvqueue(ludp, connection_id) != 0) {
437 uint16_t index = connections[connection_id].successful_read % MAX_QUEUE_NUM; 345 uint16_t index = ludp->connections[connection_id].successful_read % MAX_QUEUE_NUM;
438 uint16_t size = connections[connection_id].recvbuffer[index].size; 346 uint16_t size = ludp->connections[connection_id].recvbuffer[index].size;
439 memcpy(data, connections[connection_id].recvbuffer[index].data, size); 347 memcpy(data, ludp->connections[connection_id].recvbuffer[index].data, size);
440 ++connections[connection_id].successful_read; 348 ++ludp->connections[connection_id].successful_read;
441 connections[connection_id].recvbuffer[index].size = 0; 349 ludp->connections[connection_id].recvbuffer[index].size = 0;
442 return size; 350 return size;
443 } 351 }
444 352
@@ -449,16 +357,16 @@ int read_packet(int connection_id, uint8_t *data)
449 * Return 0 if data could not be put in packet queue 357 * Return 0 if data could not be put in packet queue
450 * Return 1 if data was put into the queue 358 * Return 1 if data was put into the queue
451 */ 359 */
452int write_packet(int connection_id, uint8_t *data, uint32_t length) 360int write_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data, uint32_t length)
453{ 361{
454 if (length > MAX_DATA_SIZE || length == 0) 362 if (length > MAX_DATA_SIZE || length == 0)
455 return 0; 363 return 0;
456 364
457 if (sendqueue(connection_id) < BUFFER_PACKET_NUM) { 365 if (sendqueue(ludp, connection_id) < BUFFER_PACKET_NUM) {
458 uint32_t index = connections[connection_id].sendbuff_packetnum % MAX_QUEUE_NUM; 366 uint32_t index = ludp->connections[connection_id].sendbuff_packetnum % MAX_QUEUE_NUM;
459 memcpy(connections[connection_id].sendbuffer[index].data, data, length); 367 memcpy(ludp->connections[connection_id].sendbuffer[index].data, data, length);
460 connections[connection_id].sendbuffer[index].size = length; 368 ludp->connections[connection_id].sendbuffer[index].size = length;
461 connections[connection_id].sendbuff_packetnum++; 369 ludp->connections[connection_id].sendbuff_packetnum++;
462 return 1; 370 return 1;
463 } 371 }
464 372
@@ -466,18 +374,18 @@ int write_packet(int connection_id, uint8_t *data, uint32_t length)
466} 374}
467 375
468/* put the packet numbers the we are missing in requested and return the number */ 376/* put the packet numbers the we are missing in requested and return the number */
469uint32_t missing_packets(int connection_id, uint32_t *requested) 377uint32_t missing_packets(Lossless_UDP *ludp, int connection_id, uint32_t *requested)
470{ 378{
471 uint32_t number = 0; 379 uint32_t number = 0;
472 uint32_t i; 380 uint32_t i;
473 uint32_t temp; 381 uint32_t temp;
474 382
475 /* don't request packets if the buffer is full. */ 383 /* don't request packets if the buffer is full. */
476 if (recvqueue(connection_id) >= (BUFFER_PACKET_NUM - 1)) 384 if (recvqueue(ludp, connection_id) >= (BUFFER_PACKET_NUM - 1))
477 return 0; 385 return 0;
478 386
479 for (i = connections[connection_id].recv_packetnum; i != connections[connection_id].osent_packetnum; i++) { 387 for (i = ludp->connections[connection_id].recv_packetnum; i != ludp->connections[connection_id].osent_packetnum; i++) {
480 if (connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size == 0) { 388 if (ludp->connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size == 0) {
481 temp = htonl(i); 389 temp = htonl(i);
482 memcpy(requested + number, &temp, 4); 390 memcpy(requested + number, &temp, 4);
483 ++number; 391 ++number;
@@ -485,7 +393,7 @@ uint32_t missing_packets(int connection_id, uint32_t *requested)
485 } 393 }
486 394
487 if (number == 0) 395 if (number == 0)
488 connections[connection_id].recv_packetnum = connections[connection_id].osent_packetnum; 396 ludp->connections[connection_id].recv_packetnum = ludp->connections[connection_id].osent_packetnum;
489 397
490 return number; 398 return number;
491} 399}
@@ -496,7 +404,7 @@ uint32_t missing_packets(int connection_id, uint32_t *requested)
496 * see http://wiki.tox.im/index.php/Lossless_UDP for more information. 404 * see http://wiki.tox.im/index.php/Lossless_UDP for more information.
497 */ 405 */
498 406
499static int send_handshake(IP_Port ip_port, uint32_t handshake_id1, uint32_t handshake_id2) 407static int send_handshake(Lossless_UDP *ludp, IP_Port ip_port, uint32_t handshake_id1, uint32_t handshake_id2)
500{ 408{
501 uint8_t packet[1 + 4 + 4]; 409 uint8_t packet[1 + 4 + 4];
502 uint32_t temp; 410 uint32_t temp;
@@ -507,21 +415,21 @@ static int send_handshake(IP_Port ip_port, uint32_t handshake_id1, uint32_t hand
507 temp = htonl(handshake_id2); 415 temp = htonl(handshake_id2);
508 memcpy(packet + 5, &temp, 4); 416 memcpy(packet + 5, &temp, 4);
509 417
510 return sendpacket(ip_port, packet, sizeof(packet)); 418 return sendpacket(ludp->net->sock, ip_port, packet, sizeof(packet));
511} 419}
512 420
513static int send_SYNC(uint32_t connection_id) 421static int send_SYNC(Lossless_UDP *ludp, uint32_t connection_id)
514{ 422{
515 uint8_t packet[(BUFFER_PACKET_NUM * 4 + 4 + 4 + 2)]; 423 uint8_t packet[(BUFFER_PACKET_NUM * 4 + 4 + 4 + 2)];
516 uint16_t index = 0; 424 uint16_t index = 0;
517 425
518 IP_Port ip_port = connections[connection_id].ip_port; 426 IP_Port ip_port = ludp->connections[connection_id].ip_port;
519 uint8_t counter = connections[connection_id].send_counter; 427 uint8_t counter = ludp->connections[connection_id].send_counter;
520 uint32_t recv_packetnum = htonl(connections[connection_id].recv_packetnum); 428 uint32_t recv_packetnum = htonl(ludp->connections[connection_id].recv_packetnum);
521 uint32_t sent_packetnum = htonl(connections[connection_id].sent_packetnum); 429 uint32_t sent_packetnum = htonl(ludp->connections[connection_id].sent_packetnum);
522 430
523 uint32_t requested[BUFFER_PACKET_NUM]; 431 uint32_t requested[BUFFER_PACKET_NUM];
524 uint32_t number = missing_packets(connection_id, requested); 432 uint32_t number = missing_packets(ludp, connection_id, requested);
525 433
526 packet[0] = 17; 434 packet[0] = 17;
527 index += 1; 435 index += 1;
@@ -533,11 +441,11 @@ static int send_SYNC(uint32_t connection_id)
533 index += 4; 441 index += 4;
534 memcpy(packet + index, requested, 4 * number); 442 memcpy(packet + index, requested, 4 * number);
535 443
536 return sendpacket(ip_port, packet, (number * 4 + 4 + 4 + 2)); 444 return sendpacket(ludp->net->sock, ip_port, packet, (number * 4 + 4 + 4 + 2));
537 445
538} 446}
539 447
540static int send_data_packet(uint32_t connection_id, uint32_t packet_num) 448static int send_data_packet(Lossless_UDP *ludp, uint32_t connection_id, uint32_t packet_num)
541{ 449{
542 uint32_t index = packet_num % MAX_QUEUE_NUM; 450 uint32_t index = packet_num % MAX_QUEUE_NUM;
543 uint32_t temp; 451 uint32_t temp;
@@ -545,29 +453,29 @@ static int send_data_packet(uint32_t connection_id, uint32_t packet_num)
545 packet[0] = 18; 453 packet[0] = 18;
546 temp = htonl(packet_num); 454 temp = htonl(packet_num);
547 memcpy(packet + 1, &temp, 4); 455 memcpy(packet + 1, &temp, 4);
548 memcpy(packet + 5, connections[connection_id].sendbuffer[index].data, 456 memcpy(packet + 5, ludp->connections[connection_id].sendbuffer[index].data,
549 connections[connection_id].sendbuffer[index].size); 457 ludp->connections[connection_id].sendbuffer[index].size);
550 return sendpacket(connections[connection_id].ip_port, packet, 458 return sendpacket(ludp->net->sock, ludp->connections[connection_id].ip_port, packet,
551 1 + 4 + connections[connection_id].sendbuffer[index].size); 459 1 + 4 + ludp->connections[connection_id].sendbuffer[index].size);
552} 460}
553 461
554/* sends 1 data packet */ 462/* sends 1 data packet */
555static int send_DATA(uint32_t connection_id) 463static int send_DATA(Lossless_UDP *ludp, uint32_t connection_id)
556{ 464{
557 int ret; 465 int ret;
558 uint32_t buffer[BUFFER_PACKET_NUM]; 466 uint32_t buffer[BUFFER_PACKET_NUM];
559 467
560 if (connections[connection_id].num_req_paquets > 0) { 468 if (ludp->connections[connection_id].num_req_paquets > 0) {
561 ret = send_data_packet(connection_id, connections[connection_id].req_packets[0]); 469 ret = send_data_packet(ludp, connection_id, ludp->connections[connection_id].req_packets[0]);
562 connections[connection_id].num_req_paquets--; 470 ludp->connections[connection_id].num_req_paquets--;
563 memcpy(buffer, connections[connection_id].req_packets + 1, connections[connection_id].num_req_paquets * 4); 471 memcpy(buffer, ludp->connections[connection_id].req_packets + 1, ludp->connections[connection_id].num_req_paquets * 4);
564 memcpy(connections[connection_id].req_packets, buffer, connections[connection_id].num_req_paquets * 4); 472 memcpy(ludp->connections[connection_id].req_packets, buffer, ludp->connections[connection_id].num_req_paquets * 4);
565 return ret; 473 return ret;
566 } 474 }
567 475
568 if (connections[connection_id].sendbuff_packetnum != connections[connection_id].sent_packetnum) { 476 if (ludp->connections[connection_id].sendbuff_packetnum != ludp->connections[connection_id].sent_packetnum) {
569 ret = send_data_packet(connection_id, connections[connection_id].sent_packetnum); 477 ret = send_data_packet(ludp, connection_id, ludp->connections[connection_id].sent_packetnum);
570 connections[connection_id].sent_packetnum++; 478 ludp->connections[connection_id].sent_packetnum++;
571 return ret; 479 return ret;
572 } 480 }
573 481
@@ -584,37 +492,39 @@ static int send_DATA(uint32_t connection_id)
584 492
585 493
586/* Return 0 if handled correctly, 1 if packet is bad. */ 494/* Return 0 if handled correctly, 1 if packet is bad. */
587static int handle_handshake(IP_Port source, uint8_t *packet, uint32_t length) 495static int handle_handshake(void *object, IP_Port source, uint8_t *packet, uint32_t length)
588{ 496{
497 Lossless_UDP *ludp = object;
498
589 if (length != (1 + 4 + 4)) 499 if (length != (1 + 4 + 4))
590 return 1; 500 return 1;
591 501
592 uint32_t temp; 502 uint32_t temp;
593 uint32_t handshake_id1, handshake_id2; 503 uint32_t handshake_id1, handshake_id2;
594 504
595 int connection = getconnection_id(source); 505 int connection = getconnection_id(ludp, source);
596 memcpy(&temp, packet + 1, 4); 506 memcpy(&temp, packet + 1, 4);
597 handshake_id1 = ntohl(temp); 507 handshake_id1 = ntohl(temp);
598 memcpy(&temp, packet + 5, 4); 508 memcpy(&temp, packet + 5, 4);
599 handshake_id2 = ntohl(temp); 509 handshake_id2 = ntohl(temp);
600 510
601 if (handshake_id2 == 0 && is_connected(connection) < 3) { 511 if (handshake_id2 == 0 && is_connected(ludp, connection) < 3) {
602 send_handshake(source, handshake_id(source), handshake_id1); 512 send_handshake(ludp, source, handshake_id(ludp, source), handshake_id1);
603 return 0; 513 return 0;
604 } 514 }
605 515
606 if (is_connected(connection) != 1) 516 if (is_connected(ludp, connection) != 1)
607 return 1; 517 return 1;
608 518
609 /* if handshake_id2 is what we sent previously as handshake_id1 */ 519 /* if handshake_id2 is what we sent previously as handshake_id1 */
610 if (handshake_id2 == connections[connection].handshake_id1) { 520 if (handshake_id2 == ludp->connections[connection].handshake_id1) {
611 connections[connection].status = 2; 521 ludp->connections[connection].status = 2;
612 /* NOTE: is this necessary? 522 /* NOTE: is this necessary?
613 connections[connection].handshake_id2 = handshake_id1; */ 523 ludp->connections[connection].handshake_id2 = handshake_id1; */
614 connections[connection].orecv_packetnum = handshake_id2; 524 ludp->connections[connection].orecv_packetnum = handshake_id2;
615 connections[connection].osent_packetnum = handshake_id1; 525 ludp->connections[connection].osent_packetnum = handshake_id1;
616 connections[connection].recv_packetnum = handshake_id1; 526 ludp->connections[connection].recv_packetnum = handshake_id1;
617 connections[connection].successful_read = handshake_id1; 527 ludp->connections[connection].successful_read = handshake_id1;
618 } 528 }
619 529
620 return 0; 530 return 0;
@@ -634,19 +544,19 @@ static int SYNC_valid(uint32_t length)
634} 544}
635 545
636/* case 1 in handle_SYNC: */ 546/* case 1 in handle_SYNC: */
637static int handle_SYNC1(IP_Port source, uint32_t recv_packetnum, uint32_t sent_packetnum) 547static int handle_SYNC1(Lossless_UDP *ludp, IP_Port source, uint32_t recv_packetnum, uint32_t sent_packetnum)
638{ 548{
639 if (handshake_id(source) == recv_packetnum) { 549 if (handshake_id(ludp, source) == recv_packetnum) {
640 int x = new_inconnection(source); 550 int x = new_inconnection(ludp, source);
641 551
642 if (x != -1) { 552 if (x != -1) {
643 connections[x].orecv_packetnum = recv_packetnum; 553 ludp->connections[x].orecv_packetnum = recv_packetnum;
644 connections[x].sent_packetnum = recv_packetnum; 554 ludp->connections[x].sent_packetnum = recv_packetnum;
645 connections[x].sendbuff_packetnum = recv_packetnum; 555 ludp->connections[x].sendbuff_packetnum = recv_packetnum;
646 connections[x].successful_sent = recv_packetnum; 556 ludp->connections[x].successful_sent = recv_packetnum;
647 connections[x].osent_packetnum = sent_packetnum; 557 ludp->connections[x].osent_packetnum = sent_packetnum;
648 connections[x].recv_packetnum = sent_packetnum; 558 ludp->connections[x].recv_packetnum = sent_packetnum;
649 connections[x].successful_read = sent_packetnum; 559 ludp->connections[x].successful_read = sent_packetnum;
650 560
651 return x; 561 return x;
652 } 562 }
@@ -656,63 +566,66 @@ static int handle_SYNC1(IP_Port source, uint32_t recv_packetnum, uint32_t sent_p
656} 566}
657 567
658/* case 2 in handle_SYNC: */ 568/* case 2 in handle_SYNC: */
659static int handle_SYNC2(int connection_id, uint8_t counter, uint32_t recv_packetnum, uint32_t sent_packetnum) 569static int handle_SYNC2(Lossless_UDP *ludp, int connection_id, uint8_t counter, uint32_t recv_packetnum,
660{ 570 uint32_t sent_packetnum)
661 if (recv_packetnum == connections[connection_id].orecv_packetnum) { 571{
662 /* && sent_packetnum == connections[connection_id].osent_packetnum) */ 572 if (recv_packetnum == ludp->connections[connection_id].orecv_packetnum) {
663 connections[connection_id].status = 3; 573 /* && sent_packetnum == ludp->connections[connection_id].osent_packetnum) */
664 connections[connection_id].recv_counter = counter; 574 ludp->connections[connection_id].status = 3;
665 ++connections[connection_id].send_counter; 575 ludp->connections[connection_id].recv_counter = counter;
666 send_SYNC(connection_id); 576 ++ludp->connections[connection_id].send_counter;
577 send_SYNC(ludp, connection_id);
667 return 0; 578 return 0;
668 } 579 }
669 580
670 return 1; 581 return 1;
671} 582}
672/* case 3 in handle_SYNC: */ 583/* case 3 in handle_SYNC: */
673static int handle_SYNC3(int connection_id, uint8_t counter, uint32_t recv_packetnum, uint32_t sent_packetnum, 584static int handle_SYNC3(Lossless_UDP *ludp, int connection_id, uint8_t counter, uint32_t recv_packetnum,
585 uint32_t sent_packetnum,
674 uint32_t *req_packets, 586 uint32_t *req_packets,
675 uint16_t number) 587 uint16_t number)
676{ 588{
677 uint8_t comp_counter = (counter - connections[connection_id].recv_counter ); 589 uint8_t comp_counter = (counter - ludp->connections[connection_id].recv_counter );
678 uint32_t i, temp; 590 uint32_t i, temp;
679 /* uint32_t comp_1 = (recv_packetnum - connections[connection_id].successful_sent); 591 /* uint32_t comp_1 = (recv_packetnum - ludp->connections[connection_id].successful_sent);
680 uint32_t comp_2 = (sent_packetnum - connections[connection_id].successful_read); */ 592 uint32_t comp_2 = (sent_packetnum - ludp->connections[connection_id].successful_read); */
681 uint32_t comp_1 = (recv_packetnum - connections[connection_id].orecv_packetnum); 593 uint32_t comp_1 = (recv_packetnum - ludp->connections[connection_id].orecv_packetnum);
682 uint32_t comp_2 = (sent_packetnum - connections[connection_id].osent_packetnum); 594 uint32_t comp_2 = (sent_packetnum - ludp->connections[connection_id].osent_packetnum);
683 595
684 /* packet valid */ 596 /* packet valid */
685 if (comp_1 <= BUFFER_PACKET_NUM && 597 if (comp_1 <= BUFFER_PACKET_NUM &&
686 comp_2 <= BUFFER_PACKET_NUM && 598 comp_2 <= BUFFER_PACKET_NUM &&
687 comp_counter < 10 && comp_counter != 0) { 599 comp_counter < 10 && comp_counter != 0) {
688 600
689 connections[connection_id].orecv_packetnum = recv_packetnum; 601 ludp->connections[connection_id].orecv_packetnum = recv_packetnum;
690 connections[connection_id].osent_packetnum = sent_packetnum; 602 ludp->connections[connection_id].osent_packetnum = sent_packetnum;
691 connections[connection_id].successful_sent = recv_packetnum; 603 ludp->connections[connection_id].successful_sent = recv_packetnum;
692 connections[connection_id].last_recvSYNC = current_time(); 604 ludp->connections[connection_id].last_recvSYNC = current_time();
693 connections[connection_id].recv_counter = counter; 605 ludp->connections[connection_id].recv_counter = counter;
694 606
695 ++connections[connection_id].send_counter; 607 ++ludp->connections[connection_id].send_counter;
696 608
697 for (i = 0; i < number; ++i) { 609 for (i = 0; i < number; ++i) {
698 temp = ntohl(req_packets[i]); 610 temp = ntohl(req_packets[i]);
699 memcpy(connections[connection_id].req_packets + i, &temp, 4 * number); 611 memcpy(ludp->connections[connection_id].req_packets + i, &temp, 4 * number);
700 } 612 }
701 613
702 connections[connection_id].num_req_paquets = number; 614 ludp->connections[connection_id].num_req_paquets = number;
703 return 0; 615 return 0;
704 } 616 }
705 617
706 return 1; 618 return 1;
707} 619}
708 620
709static int handle_SYNC(IP_Port source, uint8_t *packet, uint32_t length) 621static int handle_SYNC(void *object, IP_Port source, uint8_t *packet, uint32_t length)
710{ 622{
623 Lossless_UDP *ludp = object;
711 624
712 if (!SYNC_valid(length)) 625 if (!SYNC_valid(length))
713 return 1; 626 return 1;
714 627
715 int connection = getconnection_id(source); 628 int connection = getconnection_id(ludp, source);
716 uint8_t counter; 629 uint8_t counter;
717 uint32_t temp; 630 uint32_t temp;
718 uint32_t recv_packetnum, sent_packetnum; 631 uint32_t recv_packetnum, sent_packetnum;
@@ -729,14 +642,14 @@ static int handle_SYNC(IP_Port source, uint8_t *packet, uint32_t length)
729 memcpy(req_packets, packet + 10, 4 * number); 642 memcpy(req_packets, packet + 10, 4 * number);
730 643
731 if (connection == -1) 644 if (connection == -1)
732 return handle_SYNC1(source, recv_packetnum, sent_packetnum); 645 return handle_SYNC1(ludp, source, recv_packetnum, sent_packetnum);
733 646
734 if (connections[connection].status == 2) 647 if (ludp->connections[connection].status == 2)
735 return handle_SYNC2(connection, counter, 648 return handle_SYNC2(ludp, connection, counter,
736 recv_packetnum, sent_packetnum); 649 recv_packetnum, sent_packetnum);
737 650
738 if (connections[connection].status == 3) 651 if (ludp->connections[connection].status == 3)
739 return handle_SYNC3(connection, counter, recv_packetnum, 652 return handle_SYNC3(ludp, connection, counter, recv_packetnum,
740 sent_packetnum, req_packets, number); 653 sent_packetnum, req_packets, number);
741 654
742 return 0; 655 return 0;
@@ -746,33 +659,33 @@ static int handle_SYNC(IP_Port source, uint8_t *packet, uint32_t length)
746 * Add a packet to the received buffer and set the recv_packetnum of the 659 * Add a packet to the received buffer and set the recv_packetnum of the
747 * connection to its proper value. Return 1 if data was too big, 0 if not. 660 * connection to its proper value. Return 1 if data was too big, 0 if not.
748 */ 661 */
749static int add_recv(int connection_id, uint32_t data_num, uint8_t *data, uint16_t size) 662static int add_recv(Lossless_UDP *ludp, int connection_id, uint32_t data_num, uint8_t *data, uint16_t size)
750{ 663{
751 if (size > MAX_DATA_SIZE) 664 if (size > MAX_DATA_SIZE)
752 return 1; 665 return 1;
753 666
754 uint32_t i; 667 uint32_t i;
755 uint32_t maxnum = connections[connection_id].successful_read + BUFFER_PACKET_NUM; 668 uint32_t maxnum = ludp->connections[connection_id].successful_read + BUFFER_PACKET_NUM;
756 uint32_t sent_packet = data_num - connections[connection_id].osent_packetnum; 669 uint32_t sent_packet = data_num - ludp->connections[connection_id].osent_packetnum;
757 670
758 for (i = connections[connection_id].recv_packetnum; i != maxnum; ++i) { 671 for (i = ludp->connections[connection_id].recv_packetnum; i != maxnum; ++i) {
759 if (i == data_num) { 672 if (i == data_num) {
760 memcpy(connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].data, data, size); 673 memcpy(ludp->connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].data, data, size);
761 674
762 connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size = size; 675 ludp->connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size = size;
763 connections[connection_id].last_recvdata = current_time(); 676 ludp->connections[connection_id].last_recvdata = current_time();
764 677
765 if (sent_packet < BUFFER_PACKET_NUM) { 678 if (sent_packet < BUFFER_PACKET_NUM) {
766 connections[connection_id].osent_packetnum = data_num; 679 ludp->connections[connection_id].osent_packetnum = data_num;
767 } 680 }
768 681
769 break; 682 break;
770 } 683 }
771 } 684 }
772 685
773 for (i = connections[connection_id].recv_packetnum; i != maxnum; ++i) { 686 for (i = ludp->connections[connection_id].recv_packetnum; i != maxnum; ++i) {
774 if (connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size != 0) 687 if (ludp->connections[connection_id].recvbuffer[i % MAX_QUEUE_NUM].size != 0)
775 connections[connection_id].recv_packetnum = i; 688 ludp->connections[connection_id].recv_packetnum = i;
776 else 689 else
777 break; 690 break;
778 } 691 }
@@ -780,15 +693,16 @@ static int add_recv(int connection_id, uint32_t data_num, uint8_t *data, uint16_
780 return 0; 693 return 0;
781} 694}
782 695
783static int handle_data(IP_Port source, uint8_t *packet, uint32_t length) 696static int handle_data(void *object, IP_Port source, uint8_t *packet, uint32_t length)
784{ 697{
785 int connection = getconnection_id(source); 698 Lossless_UDP *ludp = object;
699 int connection = getconnection_id(ludp, source);
786 700
787 if (connection == -1) 701 if (connection == -1)
788 return 1; 702 return 1;
789 703
790 /* Drop the data packet if connection is not connected. */ 704 /* Drop the data packet if connection is not connected. */
791 if (connections[connection].status != 3) 705 if (ludp->connections[connection].status != 3)
792 return 1; 706 return 1;
793 707
794 if (length > 1 + 4 + MAX_DATA_SIZE || length < 1 + 4 + 1) 708 if (length > 1 + 4 + MAX_DATA_SIZE || length < 1 + 4 + 1)
@@ -801,76 +715,86 @@ static int handle_data(IP_Port source, uint8_t *packet, uint32_t length)
801 memcpy(&temp, packet + 1, 4); 715 memcpy(&temp, packet + 1, 4);
802 number = ntohl(temp); 716 number = ntohl(temp);
803 717
804 return add_recv(connection, number, packet + 5, size); 718 return add_recv(ludp, connection, number, packet + 5, size);
805} 719}
806 720
807/* 721/*
808 * END of packet handling functions 722 * END of packet handling functions
809 */ 723 */
810 724
811void LosslessUDP_init(void) 725Lossless_UDP *new_lossless_udp(Networking_Core *net)
812{ 726{
813 networking_registerhandler(16, &handle_handshake); 727 if (net == NULL)
814 networking_registerhandler(17, &handle_SYNC); 728 return NULL;
815 networking_registerhandler(18, &handle_data); 729
730 Lossless_UDP *temp = calloc(1, sizeof(Lossless_UDP));
731
732 if (temp == NULL)
733 return NULL;
734
735 temp->net = net;
736 networking_registerhandler(net, 16, &handle_handshake, temp);
737 networking_registerhandler(net, 17, &handle_SYNC, temp);
738 networking_registerhandler(net, 18, &handle_data, temp);
739 return temp;
816} 740}
817 741
818/* 742/*
819 * Send handshake requests 743 * Send handshake requests
820 * handshake packets are sent at the same rate as SYNC packets 744 * handshake packets are sent at the same rate as SYNC packets
821 */ 745 */
822static void doNew(void) 746static void do_new(Lossless_UDP *ludp)
823{ 747{
824 uint32_t i; 748 uint32_t i;
825 uint64_t temp_time = current_time(); 749 uint64_t temp_time = current_time();
826 750
827 for (i = 0; i < MAX_CONNECTIONS; ++i) { 751 for (i = 0; i < ludp->connections_length; ++i) {
828 if (connections[i].status == 1) 752 if (ludp->connections[i].status == 1)
829 if ((connections[i].last_sent + (1000000UL / connections[i].SYNC_rate)) <= temp_time) { 753 if ((ludp->connections[i].last_sent + (1000000UL / ludp->connections[i].SYNC_rate)) <= temp_time) {
830 send_handshake(connections[i].ip_port, connections[i].handshake_id1, 0); 754 send_handshake(ludp, ludp->connections[i].ip_port, ludp->connections[i].handshake_id1, 0);
831 connections[i].last_sent = temp_time; 755 ludp->connections[i].last_sent = temp_time;
832 } 756 }
833 757
834 /* kill all timed out connections */ 758 /* kill all timed out connections */
835 if (connections[i].status > 0 && 759 if (ludp->connections[i].status > 0 &&
836 (connections[i].last_recvSYNC + connections[i].timeout * 1000000UL) < temp_time && 760 (ludp->connections[i].last_recvSYNC + ludp->connections[i].timeout * 1000000UL) < temp_time &&
837 connections[i].status != 4) { 761 ludp->connections[i].status != 4) {
838 connections[i].status = 4; 762 ludp->connections[i].status = 4;
839 /* kill_connection(i); */ 763 /* kill_connection(i); */
840 } 764 }
841 765
842 if (connections[i].status > 0 && connections[i].killat < temp_time) 766 if (ludp->connections[i].status > 0 && ludp->connections[i].killat < temp_time)
843 kill_connection(i); 767 kill_connection(ludp, i);
844 } 768 }
845} 769}
846 770
847static void doSYNC(void) 771static void do_SYNC(Lossless_UDP *ludp)
848{ 772{
849 uint32_t i; 773 uint32_t i;
850 uint64_t temp_time = current_time(); 774 uint64_t temp_time = current_time();
851 775
852 for (i = 0; i < MAX_CONNECTIONS; ++i) { 776 for (i = 0; i < ludp->connections_length; ++i) {
853 if (connections[i].status == 2 || connections[i].status == 3) 777 if (ludp->connections[i].status == 2 || ludp->connections[i].status == 3)
854 if ((connections[i].last_SYNC + (1000000UL / connections[i].SYNC_rate)) <= temp_time) { 778 if ((ludp->connections[i].last_SYNC + (1000000UL / ludp->connections[i].SYNC_rate)) <= temp_time) {
855 send_SYNC(i); 779 send_SYNC(ludp, i);
856 connections[i].last_SYNC = temp_time; 780 ludp->connections[i].last_SYNC = temp_time;
857 } 781 }
858 } 782 }
859} 783}
860 784
861static void doData(void) 785static void do_data(Lossless_UDP *ludp)
862{ 786{
863 uint32_t i; 787 uint32_t i;
864 uint64_t j; 788 uint64_t j;
865 uint64_t temp_time = current_time(); 789 uint64_t temp_time = current_time();
866 790
867 for (i = 0; i < MAX_CONNECTIONS; ++i) 791 for (i = 0; i < ludp->connections_length; ++i)
868 if (connections[i].status == 3 && sendqueue(i) != 0) 792 if (ludp->connections[i].status == 3 && sendqueue(ludp, i) != 0)
869 if ((connections[i].last_sent + (1000000UL / connections[i].data_rate)) <= temp_time) { 793 if ((ludp->connections[i].last_sent + (1000000UL / ludp->connections[i].data_rate)) <= temp_time) {
870 for (j = connections[i].last_sent; j < temp_time; j += (1000000UL / connections[i].data_rate)) 794 for (j = ludp->connections[i].last_sent; j < temp_time; j += (1000000UL / ludp->connections[i].data_rate))
871 send_DATA(i); 795 send_DATA(ludp, i);
872 796
873 connections[i].last_sent = temp_time; 797 ludp->connections[i].last_sent = temp_time;
874 } 798 }
875} 799}
876 800
@@ -881,32 +805,38 @@ static void doData(void)
881 * 805 *
882 * TODO: flow control. 806 * TODO: flow control.
883 */ 807 */
884static void adjustRates(void) 808static void adjust_rates(Lossless_UDP *ludp)
885{ 809{
886 uint32_t i; 810 uint32_t i;
887 uint64_t temp_time = current_time(); 811 uint64_t temp_time = current_time();
888 812
889 for (i = 0; i < MAX_CONNECTIONS; ++i) { 813 for (i = 0; i < ludp->connections_length; ++i) {
890 if (connections[i].status == 1 || connections[i].status == 2) 814 if (ludp->connections[i].status == 1 || ludp->connections[i].status == 2)
891 connections[i].SYNC_rate = MAX_SYNC_RATE; 815 ludp->connections[i].SYNC_rate = MAX_SYNC_RATE;
892 816
893 if (connections[i].status == 3) { 817 if (ludp->connections[i].status == 3) {
894 if (sendqueue(i) != 0) { 818 if (sendqueue(ludp, i) != 0) {
895 connections[i].data_rate = (BUFFER_PACKET_NUM - connections[i].num_req_paquets) * MAX_SYNC_RATE; 819 ludp->connections[i].data_rate = (BUFFER_PACKET_NUM - ludp->connections[i].num_req_paquets) * MAX_SYNC_RATE;
896 connections[i].SYNC_rate = MAX_SYNC_RATE; 820 ludp->connections[i].SYNC_rate = MAX_SYNC_RATE;
897 } else if (connections[i].last_recvdata + 1000000UL > temp_time) 821 } else if (ludp->connections[i].last_recvdata + 1000000UL > temp_time)
898 connections[i].SYNC_rate = MAX_SYNC_RATE; 822 ludp->connections[i].SYNC_rate = MAX_SYNC_RATE;
899 else 823 else
900 connections[i].SYNC_rate = SYNC_RATE; 824 ludp->connections[i].SYNC_rate = SYNC_RATE;
901 } 825 }
902 } 826 }
903} 827}
904 828
905/* Call this function a couple times per second It's the main loop. */ 829/* Call this function a couple times per second It's the main loop. */
906void doLossless_UDP(void) 830void do_lossless_udp(Lossless_UDP *ludp)
907{ 831{
908 doNew(); 832 do_new(ludp);
909 doSYNC(); 833 do_SYNC(ludp);
910 doData(); 834 do_data(ludp);
911 adjustRates(); 835 adjust_rates(ludp);
912} 836}
837
838void kill_lossless_udp(Lossless_UDP *ludp)
839{
840 free(ludp->connections);
841 free(ludp);
842} \ No newline at end of file
diff --git a/core/Lossless_UDP.h b/core/Lossless_UDP.h
index bd426ee0..176e86ce 100644
--- a/core/Lossless_UDP.h
+++ b/core/Lossless_UDP.h
@@ -33,72 +33,168 @@ extern "C" {
33/* maximum length of the data in the data packets */ 33/* maximum length of the data in the data packets */
34#define MAX_DATA_SIZE 1024 34#define MAX_DATA_SIZE 1024
35 35
36/* maximum data packets in sent and receive queues. */
37#define MAX_QUEUE_NUM 16
38
39/* maximum number of data packets in the buffer */
40#define BUFFER_PACKET_NUM (16-1)
41
42/* timeout per connection is randomly set between CONNEXION_TIMEOUT and 2*CONNEXION_TIMEOUT */
43#define CONNEXION_TIMEOUT 5
44
45/* initial amount of sync/hanshake 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
56typedef struct {
57 IP_Port ip_port;
58
59 /*
60 * 0 if connection is dead, 1 if attempting handshake,
61 * 2 if handshake is done (we start sending SYNC packets)
62 * 3 if we are sending SYNC packets and can send data
63 * 4 if the connection has timed out.
64 */
65 uint8_t status;
66
67 /*
68 * 1 or 2 if connection was initiated by someone else, 0 if not.
69 * 2 if incoming_connection() has not returned it yet, 1 if it has.
70 */
71 uint8_t inbound;
72
73 uint16_t SYNC_rate; /* current SYNC packet send rate packets per second. */
74 uint16_t data_rate; /* current data packet send rate packets per second. */
75
76 uint64_t last_SYNC; /* time our last SYNC packet was sent. */
77 uint64_t last_sent; /* time our last data or handshake packet was sent. */
78 uint64_t last_recvSYNC; /* time we last received a SYNC packet from the other */
79 uint64_t last_recvdata; /* time we last received a DATA packet from the other */
80 uint64_t killat; /* time to kill the connection */
81
82 Data sendbuffer[MAX_QUEUE_NUM]; /* packet send buffer. */
83 Data recvbuffer[MAX_QUEUE_NUM]; /* packet receive buffer. */
84
85 uint32_t handshake_id1;
86 uint32_t handshake_id2;
87
88 /* number of data packets received (also used as handshake_id1) */
89 uint32_t recv_packetnum;
90
91 /* number of packets received by the other peer */
92 uint32_t orecv_packetnum;
93
94 /* number of data packets sent */
95 uint32_t sent_packetnum;
96
97 /* number of packets sent by the other peer. */
98 uint32_t osent_packetnum;
99
100 /* number of latest packet written onto the sendbuffer */
101 uint32_t sendbuff_packetnum;
102
103 /* we know all packets before that number were successfully sent */
104 uint32_t successful_sent;
105
106 /* packet number of last packet read with the read_packet function */
107 uint32_t successful_read;
108
109 /* list of currently requested packet numbers(by the other person) */
110 uint32_t req_packets[BUFFER_PACKET_NUM];
111
112 /* total number of currently requested packets(by the other person) */
113 uint16_t num_req_paquets;
114
115 uint8_t recv_counter;
116 uint8_t send_counter;
117 uint8_t timeout; /* connection timeout in seconds. */
118} Connection;
119
120typedef struct {
121 Networking_Core *net;
122 Connection *connections;
123
124 uint32_t connections_length; /* Length of connections array */
125 uint32_t connections_number; /* Number of connections in connections array */
126
127 /* table of random numbers used in handshake_id. */
128 uint32_t randtable[6][256];
129
130} Lossless_UDP;
131
36/* 132/*
37 * Initialize a new connection to ip_port 133 * Initialize a new connection to ip_port
38 * Returns an integer corresponding to the connection id. 134 * Returns an integer corresponding to the connection id.
39 * Return -1 if it could not initialize the connection. 135 * Return -1 if it could not initialize the connection.
40 * Return number if there already was an existing connection to that ip_port. 136 * Return number if there already was an existing connection to that ip_port.
41 */ 137 */
42int new_connection(IP_Port ip_port); 138int new_connection(Lossless_UDP *ludp, IP_Port ip_port);
43 139
44/* 140/*
45 * Get connection id from IP_Port. 141 * Get connection id from IP_Port.
46 * Return -1 if there are no connections like we are looking for. 142 * Return -1 if there are no connections like we are looking for.
47 * Return id if it found it . 143 * Return id if it found it .
48 */ 144 */
49int getconnection_id(IP_Port ip_port); 145int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port);
50 146
51/* 147/*
52 * Returns an int corresponding to the next connection in our imcoming connection list 148 * Returns an int corresponding to the next connection in our imcoming connection list
53 * Return -1 if there are no new incoming connections in the list. 149 * Return -1 if there are no new incoming connections in the list.
54 */ 150 */
55int incoming_connection(void); 151int incoming_connection(Lossless_UDP *ludp);
56 152
57/* 153/*
58 * Return -1 if it could not kill the connection. 154 * Return -1 if it could not kill the connection.
59 * Return 0 if killed successfully 155 * Return 0 if killed successfully
60 */ 156 */
61int kill_connection(int connection_id); 157int kill_connection(Lossless_UDP *ludp, int connection_id);
62 158
63/* 159/*
64 * Kill connection in seconds seconds. 160 * Kill connection in seconds seconds.
65 * Return -1 if it can not kill the connection. 161 * Return -1 if it can not kill the connection.
66 * Return 0 if it will kill it 162 * Return 0 if it will kill it
67 */ 163 */
68int kill_connection_in(int connection_id, uint32_t seconds); 164int kill_connection_in(Lossless_UDP *ludp, int connection_id, uint32_t seconds);
69 165
70/* 166/*
71 * Returns the ip_port of the corresponding connection. 167 * Returns the ip_port of the corresponding connection.
72 * Return 0 if there is no such connection. 168 * Return 0 if there is no such connection.
73 */ 169 */
74IP_Port connection_ip(int connection_id); 170IP_Port connection_ip(Lossless_UDP *ludp, int connection_id);
75 171
76/* 172/*
77 * Returns the id of the next packet in the queue 173 * Returns the id of the next packet in the queue
78 * Return -1 if no packet in queue 174 * Return -1 if no packet in queue
79 */ 175 */
80char id_packet(int connection_id); 176char id_packet(Lossless_UDP *ludp, int connection_id);
81 177
82/* 178/*
83 * Return 0 if there is no received data in the buffer. 179 * Return 0 if there is no received data in the buffer.
84 * Return length of received packet if successful 180 * Return length of received packet if successful
85 */ 181 */
86int read_packet(int connection_id, uint8_t *data); 182int read_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data);
87 183
88/* 184/*
89 * Return 0 if data could not be put in packet queue 185 * Return 0 if data could not be put in packet queue
90 * Return 1 if data was put into the queue 186 * Return 1 if data was put into the queue
91 */ 187 */
92int write_packet(int connection_id, uint8_t *data, uint32_t length); 188int write_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data, uint32_t length);
93 189
94/* Returns the number of packets in the queue waiting to be successfully sent. */ 190/* Returns the number of packets in the queue waiting to be successfully sent. */
95uint32_t sendqueue(int connection_id); 191uint32_t sendqueue(Lossless_UDP *ludp, int connection_id);
96 192
97/* 193/*
98 * returns the number of packets in the queue waiting to be successfully 194 * returns the number of packets in the queue waiting to be successfully
99 * read with read_packet(...) 195 * read with read_packet(...)
100 */ 196 */
101uint32_t recvqueue(int connection_id); 197uint32_t recvqueue(Lossless_UDP *ludp, int connection_id);
102 198
103/* Check if connection is connected: 199/* Check if connection is connected:
104 * Return 0 no. 200 * Return 0 no.
@@ -107,15 +203,17 @@ uint32_t recvqueue(int connection_id);
107 * Return 3 if fully connected. 203 * Return 3 if fully connected.
108 * Return 4 if timed out and wating to be killed. 204 * Return 4 if timed out and wating to be killed.
109 */ 205 */
110int is_connected(int connection_id); 206int is_connected(Lossless_UDP *ludp, int connection_id);
111 207
112/* Call this function a couple times per second It's the main loop. */ 208/* Call this function a couple times per second It's the main loop. */
113void doLossless_UDP(void); 209void do_lossless_udp(Lossless_UDP *ludp);
114 210
115/* 211/*
116 * This function sets up LosslessUDP packet handling. 212 * This function sets up LosslessUDP packet handling.
117 */ 213 */
118void LosslessUDP_init(void); 214Lossless_UDP *new_lossless_udp(Networking_Core *net);
215
216void kill_lossless_udp(Lossless_UDP *ludp);
119 217
120#ifdef __cplusplus 218#ifdef __cplusplus
121} 219}
diff --git a/core/Messenger.c b/core/Messenger.c
index 7fd6a569..dd24ab09 100644
--- a/core/Messenger.c
+++ b/core/Messenger.c
@@ -22,7 +22,6 @@
22 */ 22 */
23 23
24#include "Messenger.h" 24#include "Messenger.h"
25#include "timer.h"
26 25
27#define MIN(a,b) (((a)<(b))?(a):(b)) 26#define MIN(a,b) (((a)<(b))?(a):(b))
28 27
@@ -108,9 +107,8 @@ static uint16_t address_checksum(uint8_t *address, uint32_t len)
108 */ 107 */
109void getaddress(Messenger *m, uint8_t *address) 108void getaddress(Messenger *m, uint8_t *address)
110{ 109{
111 //memcpy(address, m->public_key, crypto_box_PUBLICKEYBYTES); //TODO 110 memcpy(address, m->net_crypto->self_public_key, crypto_box_PUBLICKEYBYTES);
112 memcpy(address, self_public_key, crypto_box_PUBLICKEYBYTES); 111 uint32_t nospam = get_nospam(&(m->fr));
113 uint32_t nospam = get_nospam();
114 memcpy(address + crypto_box_PUBLICKEYBYTES, &nospam, sizeof(nospam)); 112 memcpy(address + crypto_box_PUBLICKEYBYTES, &nospam, sizeof(nospam));
115 uint16_t checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum)); 113 uint16_t checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum));
116 memcpy(address + crypto_box_PUBLICKEYBYTES + sizeof(nospam), &checksum, sizeof(checksum)); 114 memcpy(address + crypto_box_PUBLICKEYBYTES + sizeof(nospam), &checksum, sizeof(checksum));
@@ -150,7 +148,7 @@ int m_addfriend(Messenger *m, uint8_t *address, uint8_t *data, uint16_t length)
150 if (length < 1) 148 if (length < 1)
151 return FAERR_NOMESSAGE; 149 return FAERR_NOMESSAGE;
152 150
153 if (memcmp(client_id, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) 151 if (memcmp(client_id, m->net_crypto->self_public_key, crypto_box_PUBLICKEYBYTES) == 0)
154 return FAERR_OWNKEY; 152 return FAERR_OWNKEY;
155 153
156 int friend_id = getfriend_id(m, client_id); 154 int friend_id = getfriend_id(m, client_id);
@@ -176,7 +174,7 @@ int m_addfriend(Messenger *m, uint8_t *address, uint8_t *data, uint16_t length)
176 174
177 for (i = 0; i <= m->numfriends; ++i) { 175 for (i = 0; i <= m->numfriends; ++i) {
178 if (m->friendlist[i].status == NOFRIEND) { 176 if (m->friendlist[i].status == NOFRIEND) {
179 DHT_addfriend(client_id); 177 DHT_addfriend(m->dht, client_id);
180 m->friendlist[i].status = FRIEND_ADDED; 178 m->friendlist[i].status = FRIEND_ADDED;
181 m->friendlist[i].crypt_connection_id = -1; 179 m->friendlist[i].crypt_connection_id = -1;
182 m->friendlist[i].friendrequest_lastsent = 0; 180 m->friendlist[i].friendrequest_lastsent = 0;
@@ -216,7 +214,7 @@ int m_addfriend_norequest(Messenger *m, uint8_t *client_id)
216 214
217 for (i = 0; i <= m->numfriends; ++i) { 215 for (i = 0; i <= m->numfriends; ++i) {
218 if (m->friendlist[i].status == NOFRIEND) { 216 if (m->friendlist[i].status == NOFRIEND) {
219 DHT_addfriend(client_id); 217 DHT_addfriend(m->dht, client_id);
220 m->friendlist[i].status = FRIEND_CONFIRMED; 218 m->friendlist[i].status = FRIEND_CONFIRMED;
221 m->friendlist[i].crypt_connection_id = -1; 219 m->friendlist[i].crypt_connection_id = -1;
222 m->friendlist[i].friendrequest_lastsent = 0; 220 m->friendlist[i].friendrequest_lastsent = 0;
@@ -245,8 +243,8 @@ int m_delfriend(Messenger *m, int friendnumber)
245 if (friendnumber >= m->numfriends || friendnumber < 0) 243 if (friendnumber >= m->numfriends || friendnumber < 0)
246 return -1; 244 return -1;
247 245
248 DHT_delfriend(m->friendlist[friendnumber].client_id); 246 DHT_delfriend(m->dht, m->friendlist[friendnumber].client_id);
249 crypto_kill(m->friendlist[friendnumber].crypt_connection_id); 247 crypto_kill(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id);
250 free(m->friendlist[friendnumber].statusmessage); 248 free(m->friendlist[friendnumber].statusmessage);
251 memset(&(m->friendlist[friendnumber]), 0, sizeof(Friend)); 249 memset(&(m->friendlist[friendnumber]), 0, sizeof(Friend));
252 uint32_t i; 250 uint32_t i;
@@ -522,7 +520,7 @@ void m_set_sends_receipts(Messenger *m, int friendnumber, int yesno)
522/* set the function that will be executed when a friend request is received. */ 520/* set the function that will be executed when a friend request is received. */
523void m_callback_friendrequest(Messenger *m, void (*function)(uint8_t *, uint8_t *, uint16_t, void *), void *userdata) 521void m_callback_friendrequest(Messenger *m, void (*function)(uint8_t *, uint8_t *, uint16_t, void *), void *userdata)
524{ 522{
525 callback_friendrequest(function, userdata); 523 callback_friendrequest(&(m->fr), function, userdata);
526} 524}
527 525
528/* set the function that will be executed when a message from a friend is received. */ 526/* set the function that will be executed when a message from a friend is received. */
@@ -606,20 +604,20 @@ int write_cryptpacket_id(Messenger *m, int friendnumber, uint8_t packet_id, uint
606 if (length != 0) 604 if (length != 0)
607 memcpy(packet + 1, data, length); 605 memcpy(packet + 1, data, length);
608 606
609 return write_cryptpacket(m->friendlist[friendnumber].crypt_connection_id, packet, length + 1); 607 return write_cryptpacket(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id, packet, length + 1);
610} 608}
611 609
612
613/*Interval in seconds between LAN discovery packet sending*/ 610/*Interval in seconds between LAN discovery packet sending*/
614#define LAN_DISCOVERY_INTERVAL 60 611#define LAN_DISCOVERY_INTERVAL 60
615#define PORT 33445 612#define PORT 33445
616 613
617/*Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds*/ 614/*Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds*/
618int LANdiscovery(timer *t, void *arg) 615static void LANdiscovery(Messenger *m)
619{ 616{
620 send_LANdiscovery(htons(PORT)); 617 if (m->last_LANdiscovery + LAN_DISCOVERY_INTERVAL < unix_time()) {
621 timer_start(t, LAN_DISCOVERY_INTERVAL); 618 send_LANdiscovery(htons(PORT), m->net_crypto);
622 return 0; 619 m->last_LANdiscovery = unix_time();
620 }
623} 621}
624 622
625/* run this at startup */ 623/* run this at startup */
@@ -628,25 +626,41 @@ Messenger *initMessenger(void)
628 Messenger *m = calloc(1, sizeof(Messenger)); 626 Messenger *m = calloc(1, sizeof(Messenger));
629 627
630 if ( ! m ) 628 if ( ! m )
631 return 0; 629 return NULL;
632 630
633 new_keys();
634 m_set_statusmessage(m, (uint8_t *)"Online", sizeof("Online"));
635 initNetCrypto();
636 IP ip; 631 IP ip;
637 ip.i = 0; 632 ip.i = 0;
633 m->net = new_networking(ip, PORT);
638 634
639 if (init_networking(ip, PORT) == -1) 635 if (m->net == NULL) {
640 return 0; 636 free(m);
637 return NULL;
638 }
639
640 m->net_crypto = new_net_crypto(m->net);
641 641
642 DHT_init(); 642 if (m->net_crypto == NULL) {
643 LosslessUDP_init(); 643 kill_networking(m->net);
644 friendreq_init(); 644 free(m);
645 LANdiscovery_init(); 645 return NULL;
646 set_nospam(random_int()); 646 }
647
648 m->dht = new_DHT(m->net_crypto);
649
650 if (m->dht == NULL) {
651 kill_net_crypto(m->net_crypto);
652 kill_networking(m->net);
653 free(m);
654 return NULL;
655 }
647 656
648 send_LANdiscovery(htons(PORT)); 657 new_keys(m->net_crypto);
649 timer_single(&LANdiscovery, 0, LAN_DISCOVERY_INTERVAL); 658 m_set_statusmessage(m, (uint8_t *)"Online", sizeof("Online"));
659
660 friendreq_init(&(m->fr), m->net_crypto);
661 LANdiscovery_init(m->dht);
662 set_nospam(&(m->fr), random_int());
663 init_cryptopackets(m->dht);
650 664
651 return m; 665 return m;
652} 666}
@@ -657,6 +671,9 @@ void cleanupMessenger(Messenger *m)
657 /* FIXME TODO ideally cleanupMessenger will mirror initMessenger 671 /* FIXME TODO ideally cleanupMessenger will mirror initMessenger
658 * this requires the other modules to expose cleanup functions 672 * this requires the other modules to expose cleanup functions
659 */ 673 */
674 kill_DHT(m->dht);
675 kill_net_crypto(m->net_crypto);
676 kill_networking(m->net);
660 free(m->friendlist); 677 free(m->friendlist);
661 free(m); 678 free(m);
662} 679}
@@ -672,7 +689,8 @@ void doFriends(Messenger *m)
672 689
673 for (i = 0; i < m->numfriends; ++i) { 690 for (i = 0; i < m->numfriends; ++i) {
674 if (m->friendlist[i].status == FRIEND_ADDED) { 691 if (m->friendlist[i].status == FRIEND_ADDED) {
675 int fr = send_friendrequest(m->friendlist[i].client_id, m->friendlist[i].friendrequest_nospam, m->friendlist[i].info, 692 int fr = send_friendrequest(m->dht, m->friendlist[i].client_id, m->friendlist[i].friendrequest_nospam,
693 m->friendlist[i].info,
676 m->friendlist[i].info_size); 694 m->friendlist[i].info_size);
677 695
678 if (fr >= 0) { 696 if (fr >= 0) {
@@ -694,12 +712,12 @@ void doFriends(Messenger *m)
694 } 712 }
695 } 713 }
696 714
697 IP_Port friendip = DHT_getfriendip(m->friendlist[i].client_id); 715 IP_Port friendip = DHT_getfriendip(m->dht, m->friendlist[i].client_id);
698 716
699 switch (is_cryptoconnected(m->friendlist[i].crypt_connection_id)) { 717 switch (is_cryptoconnected(m->net_crypto, m->friendlist[i].crypt_connection_id)) {
700 case 0: 718 case 0:
701 if (friendip.ip.i > 1) 719 if (friendip.ip.i > 1)
702 m->friendlist[i].crypt_connection_id = crypto_connect(m->friendlist[i].client_id, friendip); 720 m->friendlist[i].crypt_connection_id = crypto_connect(m->net_crypto, m->friendlist[i].client_id, friendip);
703 721
704 break; 722 break;
705 723
@@ -712,7 +730,7 @@ void doFriends(Messenger *m)
712 break; 730 break;
713 731
714 case 4: 732 case 4:
715 crypto_kill(m->friendlist[i].crypt_connection_id); 733 crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id);
716 m->friendlist[i].crypt_connection_id = -1; 734 m->friendlist[i].crypt_connection_id = -1;
717 break; 735 break;
718 736
@@ -741,7 +759,7 @@ void doFriends(Messenger *m)
741 send_ping(m, i); 759 send_ping(m, i);
742 } 760 }
743 761
744 len = read_cryptpacket(m->friendlist[i].crypt_connection_id, temp); 762 len = read_cryptpacket(m->net_crypto, m->friendlist[i].crypt_connection_id, temp);
745 uint8_t packet_id = temp[0]; 763 uint8_t packet_id = temp[0];
746 uint8_t *data = temp + 1; 764 uint8_t *data = temp + 1;
747 int data_length = len - 1; 765 int data_length = len - 1;
@@ -833,8 +851,9 @@ void doFriends(Messenger *m)
833 } 851 }
834 } 852 }
835 } else { 853 } else {
836 if (is_cryptoconnected(m->friendlist[i].crypt_connection_id) == 4) { /* if the connection timed out, kill it */ 854 if (is_cryptoconnected(m->net_crypto,
837 crypto_kill(m->friendlist[i].crypt_connection_id); 855 m->friendlist[i].crypt_connection_id) == 4) { /* if the connection timed out, kill it */
856 crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id);
838 m->friendlist[i].crypt_connection_id = -1; 857 m->friendlist[i].crypt_connection_id = -1;
839 set_friend_status(m, i, FRIEND_CONFIRMED); 858 set_friend_status(m, i, FRIEND_CONFIRMED);
840 } 859 }
@@ -844,7 +863,7 @@ void doFriends(Messenger *m)
844 863
845 if (m->friendlist[i].ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) { 864 if (m->friendlist[i].ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) {
846 /* if we stopped recieving ping packets kill it */ 865 /* if we stopped recieving ping packets kill it */
847 crypto_kill(m->friendlist[i].crypt_connection_id); 866 crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id);
848 m->friendlist[i].crypt_connection_id = -1; 867 m->friendlist[i].crypt_connection_id = -1;
849 set_friend_status(m, i, FRIEND_CONFIRMED); 868 set_friend_status(m, i, FRIEND_CONFIRMED);
850 } 869 }
@@ -857,34 +876,31 @@ void doInbound(Messenger *m)
857 uint8_t secret_nonce[crypto_box_NONCEBYTES]; 876 uint8_t secret_nonce[crypto_box_NONCEBYTES];
858 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; 877 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
859 uint8_t session_key[crypto_box_PUBLICKEYBYTES]; 878 uint8_t session_key[crypto_box_PUBLICKEYBYTES];
860 int inconnection = crypto_inbound(public_key, secret_nonce, session_key); 879 int inconnection = crypto_inbound(m->net_crypto, public_key, secret_nonce, session_key);
861 880
862 if (inconnection != -1) { 881 if (inconnection != -1) {
863 int friend_id = getfriend_id(m, public_key); 882 int friend_id = getfriend_id(m, public_key);
864 883
865 if (friend_id != -1) { 884 if (friend_id != -1) {
866 crypto_kill(m->friendlist[friend_id].crypt_connection_id); 885 crypto_kill(m->net_crypto, m->friendlist[friend_id].crypt_connection_id);
867 m->friendlist[friend_id].crypt_connection_id = 886 m->friendlist[friend_id].crypt_connection_id =
868 accept_crypto_inbound(inconnection, public_key, secret_nonce, session_key); 887 accept_crypto_inbound(m->net_crypto, inconnection, public_key, secret_nonce, session_key);
869 888
870 set_friend_status(m, friend_id, FRIEND_CONFIRMED); 889 set_friend_status(m, friend_id, FRIEND_CONFIRMED);
871 } 890 }
872 } 891 }
873} 892}
874 893
875 894/* the main loop that needs to be run at least 20 times per second. */
876/* the main loop that needs to be run at least 200 times per second. */
877void doMessenger(Messenger *m) 895void doMessenger(Messenger *m)
878{ 896{
879 networking_poll(); 897 networking_poll(m->net);
880 898
881 doDHT(); 899 do_DHT(m->dht);
882 doLossless_UDP(); 900 do_net_crypto(m->net_crypto);
883 doNetCrypto();
884 doInbound(m); 901 doInbound(m);
885 doFriends(m); 902 doFriends(m);
886 903 LANdiscovery(m);
887 timer_poll();
888} 904}
889 905
890/* returns the size of the messenger data (for saving) */ 906/* returns the size of the messenger data (for saving) */
@@ -893,7 +909,7 @@ uint32_t Messenger_size(Messenger *m)
893 return crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES 909 return crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES
894 + sizeof(uint32_t) // nospam 910 + sizeof(uint32_t) // nospam
895 + sizeof(uint32_t) // DHT size 911 + sizeof(uint32_t) // DHT size
896 + DHT_size() // DHT itself 912 + DHT_size(m->dht) // DHT itself
897 + sizeof(uint32_t) // Friendlist size 913 + sizeof(uint32_t) // Friendlist size
898 + sizeof(Friend) * m->numfriends // Friendlist itself 914 + sizeof(Friend) * m->numfriends // Friendlist itself
899 + sizeof(uint16_t) // Own nickname length 915 + sizeof(uint16_t) // Own nickname length
@@ -904,15 +920,15 @@ uint32_t Messenger_size(Messenger *m)
904/* save the messenger in data of size Messenger_size() */ 920/* save the messenger in data of size Messenger_size() */
905void Messenger_save(Messenger *m, uint8_t *data) 921void Messenger_save(Messenger *m, uint8_t *data)
906{ 922{
907 save_keys(data); 923 save_keys(m->net_crypto, data);
908 data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; 924 data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES;
909 uint32_t nospam = get_nospam(); 925 uint32_t nospam = get_nospam(&(m->fr));
910 memcpy(data, &nospam, sizeof(nospam)); 926 memcpy(data, &nospam, sizeof(nospam));
911 data += sizeof(nospam); 927 data += sizeof(nospam);
912 uint32_t size = DHT_size(); 928 uint32_t size = DHT_size(m->dht);
913 memcpy(data, &size, sizeof(size)); 929 memcpy(data, &size, sizeof(size));
914 data += sizeof(size); 930 data += sizeof(size);
915 DHT_save(data); 931 DHT_save(m->dht, data);
916 data += size; 932 data += size;
917 size = sizeof(Friend) * m->numfriends; 933 size = sizeof(Friend) * m->numfriends;
918 memcpy(data, &size, sizeof(size)); 934 memcpy(data, &size, sizeof(size));
@@ -935,11 +951,11 @@ int Messenger_load(Messenger *m, uint8_t *data, uint32_t length)
935 return -1; 951 return -1;
936 952
937 length -= crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t) * 3; 953 length -= crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t) * 3;
938 load_keys(data); 954 load_keys(m->net_crypto, data);
939 data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; 955 data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES;
940 uint32_t nospam; 956 uint32_t nospam;
941 memcpy(&nospam, data, sizeof(nospam)); 957 memcpy(&nospam, data, sizeof(nospam));
942 set_nospam(nospam); 958 set_nospam(&(m->fr), nospam);
943 data += sizeof(nospam); 959 data += sizeof(nospam);
944 uint32_t size; 960 uint32_t size;
945 memcpy(&size, data, sizeof(size)); 961 memcpy(&size, data, sizeof(size));
@@ -950,7 +966,7 @@ int Messenger_load(Messenger *m, uint8_t *data, uint32_t length)
950 966
951 length -= size; 967 length -= size;
952 968
953 if (DHT_load(data, size) == -1) 969 if (DHT_load(m->dht, data, size) == -1)
954 return -1; 970 return -1;
955 971
956 data += size; 972 data += size;
diff --git a/core/Messenger.h b/core/Messenger.h
index 9016be93..581c4ba9 100644
--- a/core/Messenger.h
+++ b/core/Messenger.h
@@ -112,8 +112,11 @@ typedef struct {
112} Friend; 112} Friend;
113 113
114typedef struct Messenger { 114typedef struct Messenger {
115 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
116 115
116 Networking_Core *net;
117 Net_Crypto *net_crypto;
118 DHT *dht;
119 Friend_Requests fr;
117 uint8_t name[MAX_NAME_LENGTH]; 120 uint8_t name[MAX_NAME_LENGTH];
118 uint16_t name_length; 121 uint16_t name_length;
119 122
@@ -125,6 +128,8 @@ typedef struct Messenger {
125 Friend *friendlist; 128 Friend *friendlist;
126 uint32_t numfriends; 129 uint32_t numfriends;
127 130
131 uint64_t last_LANdiscovery;
132
128 void (*friend_message)(struct Messenger *m, int, uint8_t *, uint16_t, void *); 133 void (*friend_message)(struct Messenger *m, int, uint8_t *, uint16_t, void *);
129 void *friend_message_userdata; 134 void *friend_message_userdata;
130 void (*friend_action)(struct Messenger *m, int, uint8_t *, uint16_t, void *); 135 void (*friend_action)(struct Messenger *m, int, uint8_t *, uint16_t, void *);
@@ -219,17 +224,13 @@ int m_sendaction(Messenger *m, int friendnumber, uint8_t *action, uint32_t lengt
219 return -1 if failure */ 224 return -1 if failure */
220int setname(Messenger *m, uint8_t *name, uint16_t length); 225int setname(Messenger *m, uint8_t *name, uint16_t length);
221 226
222/** 227/*
223 * @brief Get your nickname. 228 Get your nickname.
224 * 229 m The messanger context to use.
225 * @param[in] m The messanger context to use. 230 name Pointer to a string for the name.
226 * 231 nlen The length of the string buffer.
227 * @param[inout] name Pointer to a string for the name. 232 returns Return the length of the name, 0 on error.
228 * 233*/
229 * @param[in] nlen The length of the string buffer.
230 *
231 * @return Return the length of the name, 0 on error.
232 */
233uint16_t getself_name(Messenger *m, uint8_t *name, uint16_t nlen); 234uint16_t getself_name(Messenger *m, uint8_t *name, uint16_t nlen);
234 235
235/* get name of friendnumber 236/* get name of friendnumber
diff --git a/core/friend_requests.c b/core/friend_requests.c
index 3708f154..ee2da633 100644
--- a/core/friend_requests.c
+++ b/core/friend_requests.c
@@ -23,15 +23,12 @@
23 23
24#include "friend_requests.h" 24#include "friend_requests.h"
25 25
26uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
27
28
29/* Try to send a friendrequest to peer with public_key 26/* Try to send a friendrequest to peer with public_key
30 data is the data in the request and length is the length. 27 data is the data in the request and length is the length.
31 return -1 if failure. 28 return -1 if failure.
32 return 0 if it sent the friend request directly to the friend. 29 return 0 if it sent the friend request directly to the friend.
33 return the number of peers it was routed through if it did not send it directly.*/ 30 return the number of peers it was routed through if it did not send it directly.*/
34int send_friendrequest(uint8_t *public_key, uint32_t nospam_num, uint8_t *data, uint32_t length) 31int send_friendrequest(DHT *dht, uint8_t *public_key, uint32_t nospam_num, uint8_t *data, uint32_t length)
35{ 32{
36 if (length + sizeof(nospam_num) > MAX_DATA_SIZE) 33 if (length + sizeof(nospam_num) > MAX_DATA_SIZE)
37 return -1; 34 return -1;
@@ -40,25 +37,26 @@ int send_friendrequest(uint8_t *public_key, uint32_t nospam_num, uint8_t *data,
40 memcpy(temp, &nospam_num, sizeof(nospam_num)); 37 memcpy(temp, &nospam_num, sizeof(nospam_num));
41 memcpy(temp + sizeof(nospam_num), data, length); 38 memcpy(temp + sizeof(nospam_num), data, length);
42 uint8_t packet[MAX_DATA_SIZE]; 39 uint8_t packet[MAX_DATA_SIZE];
43 int len = create_request(packet, public_key, temp, length + sizeof(nospam_num), 40 int len = create_request(dht->c->self_public_key, dht->c->self_secret_key, packet, public_key, temp,
41 length + sizeof(nospam_num),
44 32); /* 32 is friend request packet id */ 42 32); /* 32 is friend request packet id */
45 43
46 if (len == -1) 44 if (len == -1)
47 return -1; 45 return -1;
48 46
49 IP_Port ip_port = DHT_getfriendip(public_key); 47 IP_Port ip_port = DHT_getfriendip(dht, public_key);
50 48
51 if (ip_port.ip.i == 1) 49 if (ip_port.ip.i == 1)
52 return -1; 50 return -1;
53 51
54 if (ip_port.ip.i != 0) { 52 if (ip_port.ip.i != 0) {
55 if (sendpacket(ip_port, packet, len) != -1) 53 if (sendpacket(dht->c->lossless_udp->net->sock, ip_port, packet, len) != -1)
56 return 0; 54 return 0;
57 55
58 return -1; 56 return -1;
59 } 57 }
60 58
61 int num = route_tofriend(public_key, packet, len); 59 int num = route_tofriend(dht, public_key, packet, len);
62 60
63 if (num == 0) 61 if (num == 0)
64 return -1; 62 return -1;
@@ -66,58 +64,48 @@ int send_friendrequest(uint8_t *public_key, uint32_t nospam_num, uint8_t *data,
66 return num; 64 return num;
67} 65}
68 66
69static uint32_t nospam; 67
70/* 68/*
71 * Set and get the nospam variable used to prevent one type of friend request spam 69 * Set and get the nospam variable used to prevent one type of friend request spam
72 */ 70 */
73void set_nospam(uint32_t num) 71void set_nospam(Friend_Requests *fr, uint32_t num)
74{ 72{
75 nospam = num; 73 fr->nospam = num;
76} 74}
77 75
78uint32_t get_nospam() 76uint32_t get_nospam(Friend_Requests *fr)
79{ 77{
80 return nospam; 78 return fr->nospam;
81} 79}
82 80
83static void (*handle_friendrequest)(uint8_t *, uint8_t *, uint16_t, void *); 81
84static uint8_t handle_friendrequest_isset = 0;
85static void *handle_friendrequest_userdata;
86/* set the function that will be executed when a friend request is received. */ 82/* set the function that will be executed when a friend request is received. */
87void callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t, void *), void *userdata) 83void callback_friendrequest(Friend_Requests *fr, void (*function)(uint8_t *, uint8_t *, uint16_t, void *),
84 void *userdata)
88{ 85{
89 handle_friendrequest = function; 86 fr->handle_friendrequest = function;
90 handle_friendrequest_isset = 1; 87 fr->handle_friendrequest_isset = 1;
91 handle_friendrequest_userdata = userdata; 88 fr->handle_friendrequest_userdata = userdata;
92} 89}
93 90
94
95/*NOTE: the following is just a temporary fix for the multiple friend requests received at the same time problem
96 TODO: Make this better (This will most likely tie in with the way we will handle spam.)*/
97
98#define MAX_RECEIVED_STORED 32
99
100static uint8_t received_requests[MAX_RECEIVED_STORED][crypto_box_PUBLICKEYBYTES];
101static uint16_t received_requests_index;
102
103/*Add to list of received friend requests*/ 91/*Add to list of received friend requests*/
104static void addto_receivedlist(uint8_t *client_id) 92static void addto_receivedlist(Friend_Requests *fr, uint8_t *client_id)
105{ 93{
106 if (received_requests_index >= MAX_RECEIVED_STORED) 94 if (fr->received_requests_index >= MAX_RECEIVED_STORED)
107 received_requests_index = 0; 95 fr->received_requests_index = 0;
108 96
109 memcpy(received_requests[received_requests_index], client_id, crypto_box_PUBLICKEYBYTES); 97 memcpy(fr->received_requests[fr->received_requests_index], client_id, crypto_box_PUBLICKEYBYTES);
110 ++received_requests_index; 98 ++fr->received_requests_index;
111} 99}
112 100
113/* Check if a friend request was already received 101/* Check if a friend request was already received
114 return 0 if not, 1 if we did */ 102 return 0 if not, 1 if we did */
115static int request_received(uint8_t *client_id) 103static int request_received(Friend_Requests *fr, uint8_t *client_id)
116{ 104{
117 uint32_t i; 105 uint32_t i;
118 106
119 for (i = 0; i < MAX_RECEIVED_STORED; ++i) { 107 for (i = 0; i < MAX_RECEIVED_STORED; ++i) {
120 if (memcmp(received_requests[i], client_id, crypto_box_PUBLICKEYBYTES) == 0) 108 if (memcmp(fr->received_requests[i], client_id, crypto_box_PUBLICKEYBYTES) == 0)
121 return 1; 109 return 1;
122 } 110 }
123 111
@@ -125,26 +113,29 @@ static int request_received(uint8_t *client_id)
125} 113}
126 114
127 115
128static int friendreq_handlepacket(IP_Port source, uint8_t *source_pubkey, uint8_t *packet, uint32_t length) 116static int friendreq_handlepacket(void *object, IP_Port source, uint8_t *source_pubkey, uint8_t *packet,
117 uint32_t length)
129{ 118{
130 if (handle_friendrequest_isset == 0) 119 Friend_Requests *fr = object;
120
121 if (fr->handle_friendrequest_isset == 0)
131 return 1; 122 return 1;
132 123
133 if (length <= sizeof(nospam)) 124 if (length <= sizeof(fr->nospam))
134 return 1; 125 return 1;
135 126
136 if (request_received(source_pubkey)) 127 if (request_received(fr, source_pubkey))
137 return 1; 128 return 1;
138 129
139 if (memcmp(packet, &nospam, sizeof(nospam)) != 0) 130 if (memcmp(packet, &fr->nospam, sizeof(fr->nospam)) != 0)
140 return 1; 131 return 1;
141 132
142 addto_receivedlist(source_pubkey); 133 addto_receivedlist(fr, source_pubkey);
143 (*handle_friendrequest)(source_pubkey, packet + 4, length - 4, handle_friendrequest_userdata); 134 (*fr->handle_friendrequest)(source_pubkey, packet + 4, length - 4, fr->handle_friendrequest_userdata);
144 return 0; 135 return 0;
145} 136}
146 137
147void friendreq_init(void) 138void friendreq_init(Friend_Requests *fr, Net_Crypto *c)
148{ 139{
149 cryptopacket_registerhandler(32, &friendreq_handlepacket); 140 cryptopacket_registerhandler(c, 32, &friendreq_handlepacket, fr);
150} 141}
diff --git a/core/friend_requests.h b/core/friend_requests.h
index 3ce0df8c..2ebd557b 100644
--- a/core/friend_requests.h
+++ b/core/friend_requests.h
@@ -31,21 +31,37 @@
31extern "C" { 31extern "C" {
32#endif 32#endif
33 33
34typedef struct {
35 uint32_t nospam;
36 void (*handle_friendrequest)(uint8_t *, uint8_t *, uint16_t, void *);
37 uint8_t handle_friendrequest_isset;
38 void *handle_friendrequest_userdata;
39
40 /*NOTE: the following is just a temporary fix for the multiple friend requests received at the same time problem
41 TODO: Make this better (This will most likely tie in with the way we will handle spam.)*/
42
43#define MAX_RECEIVED_STORED 32
44
45 uint8_t received_requests[MAX_RECEIVED_STORED][crypto_box_PUBLICKEYBYTES];
46 uint16_t received_requests_index;
47} Friend_Requests;
48
34/* Try to send a friendrequest to peer with public_key 49/* Try to send a friendrequest to peer with public_key
35 data is the data in the request and length is the length. */ 50 data is the data in the request and length is the length. */
36int send_friendrequest(uint8_t *public_key, uint32_t nospam_num, uint8_t *data, uint32_t length); 51int send_friendrequest(DHT *dht, uint8_t *public_key, uint32_t nospam_num, uint8_t *data, uint32_t length);
37/* 52/*
38 * Set and get the nospam variable used to prevent one type of friend request spam 53 * Set and get the nospam variable used to prevent one type of friend request spam
39 */ 54 */
40void set_nospam(uint32_t num); 55void set_nospam(Friend_Requests *fr, uint32_t num);
41uint32_t get_nospam(); 56uint32_t get_nospam(Friend_Requests *fr);
42 57
43/* set the function that will be executed when a friend request for us is received. 58/* set the function that will be executed when a friend request for us is received.
44 function format is function(uint8_t * public_key, uint8_t * data, uint16_t length) */ 59 function format is function(uint8_t * public_key, uint8_t * data, uint16_t length) */
45void callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t, void *), void *userdata); 60void callback_friendrequest(Friend_Requests *fr, void (*function)(uint8_t *, uint8_t *, uint16_t, void *),
61 void *userdata);
46 62
47/* sets up friendreq packet handlers */ 63/* sets up friendreq packet handlers */
48void friendreq_init(void); 64void friendreq_init(Friend_Requests *fr, Net_Crypto *c);
49 65
50#ifdef __cplusplus 66#ifdef __cplusplus
51} 67}
diff --git a/core/net_crypto.c b/core/net_crypto.c
index 8fcb62e1..e3757ffb 100644
--- a/core/net_crypto.c
+++ b/core/net_crypto.c
@@ -26,42 +26,12 @@
26 26
27#include "net_crypto.h" 27#include "net_crypto.h"
28 28
29/* Our public and secret keys. */
30uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
31uint8_t self_secret_key[crypto_box_SECRETKEYBYTES];
32
33typedef struct {
34 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* the real public key of the peer. */
35 uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* nonce of received packets */
36 uint8_t sent_nonce[crypto_box_NONCEBYTES]; /* nonce of sent packets. */
37 uint8_t sessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* our public key for this session. */
38 uint8_t sessionsecret_key[crypto_box_SECRETKEYBYTES]; /* our private key for this session. */
39 uint8_t peersessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* The public key of the peer. */
40 uint8_t shared_key[crypto_box_BEFORENMBYTES]; /* the precomputed shared key from encrypt_precompute */
41 uint8_t status; /* 0 if no connection, 1 we have sent a handshake, 2 if connexion is not confirmed yet
42 (we have received a handshake but no empty data packet), 3 if the connection is established.
43 4 if the connection is timed out. */
44 uint16_t number; /* Lossless_UDP connection number corresponding to this connection. */
45
46} Crypto_Connection;
47
48static Crypto_Connection *crypto_connections;
49
50static uint32_t crypto_connections_length; /* Length of connections array */
51
52#define MAX_CRYPTO_CONNECTIONS crypto_connections_length
53
54#define CONN_NO_CONNECTION 0 29#define CONN_NO_CONNECTION 0
55#define CONN_HANDSHAKE_SENT 1 30#define CONN_HANDSHAKE_SENT 1
56#define CONN_NOT_CONFIRMED 2 31#define CONN_NOT_CONFIRMED 2
57#define CONN_ESTABLISHED 3 32#define CONN_ESTABLISHED 3
58#define CONN_TIMED_OUT 4 33#define CONN_TIMED_OUT 4
59 34
60#define MAX_INCOMING 64
61
62/* keeps track of the connection numbers for friends request so we can check later if they were sent */
63static int incoming_connections[MAX_INCOMING];
64
65/* Use this instead of memcmp; not vulnerable to timing attacks. */ 35/* Use this instead of memcmp; not vulnerable to timing attacks. */
66uint8_t crypto_iszero(uint8_t *mem, uint32_t length) 36uint8_t crypto_iszero(uint8_t *mem, uint32_t length)
67{ 37{
@@ -175,16 +145,16 @@ void random_nonce(uint8_t *nonce)
175/* return 0 if there is no received data in the buffer 145/* return 0 if there is no received data in the buffer
176 return -1 if the packet was discarded. 146 return -1 if the packet was discarded.
177 return length of received data if successful */ 147 return length of received data if successful */
178int read_cryptpacket(int crypt_connection_id, uint8_t *data) 148int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data)
179{ 149{
180 if (crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS) 150 if (crypt_connection_id < 0 || crypt_connection_id >= c->crypto_connections_length)
181 return 0; 151 return 0;
182 152
183 if (crypto_connections[crypt_connection_id].status != CONN_ESTABLISHED) 153 if (c->crypto_connections[crypt_connection_id].status != CONN_ESTABLISHED)
184 return 0; 154 return 0;
185 155
186 uint8_t temp_data[MAX_DATA_SIZE]; 156 uint8_t temp_data[MAX_DATA_SIZE];
187 int length = read_packet(crypto_connections[crypt_connection_id].number, temp_data); 157 int length = read_packet(c->lossless_udp, c->crypto_connections[crypt_connection_id].number, temp_data);
188 158
189 if (length == 0) 159 if (length == 0)
190 return 0; 160 return 0;
@@ -192,12 +162,12 @@ int read_cryptpacket(int crypt_connection_id, uint8_t *data)
192 if (temp_data[0] != 3) 162 if (temp_data[0] != 3)
193 return -1; 163 return -1;
194 164
195 int len = decrypt_data_fast(crypto_connections[crypt_connection_id].shared_key, 165 int len = decrypt_data_fast(c->crypto_connections[crypt_connection_id].shared_key,
196 crypto_connections[crypt_connection_id].recv_nonce, 166 c->crypto_connections[crypt_connection_id].recv_nonce,
197 temp_data + 1, length - 1, data); 167 temp_data + 1, length - 1, data);
198 168
199 if (len != -1) { 169 if (len != -1) {
200 increment_nonce(crypto_connections[crypt_connection_id].recv_nonce); 170 increment_nonce(c->crypto_connections[crypt_connection_id].recv_nonce);
201 return len; 171 return len;
202 } 172 }
203 173
@@ -206,20 +176,20 @@ int read_cryptpacket(int crypt_connection_id, uint8_t *data)
206 176
207/* return 0 if data could not be put in packet queue 177/* return 0 if data could not be put in packet queue
208 return 1 if data was put into the queue */ 178 return 1 if data was put into the queue */
209int write_cryptpacket(int crypt_connection_id, uint8_t *data, uint32_t length) 179int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length)
210{ 180{
211 if (crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS) 181 if (crypt_connection_id < 0 || crypt_connection_id >= c->crypto_connections_length)
212 return 0; 182 return 0;
213 183
214 if (length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE - 1) 184 if (length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE - 1)
215 return 0; 185 return 0;
216 186
217 if (crypto_connections[crypt_connection_id].status != CONN_ESTABLISHED) 187 if (c->crypto_connections[crypt_connection_id].status != CONN_ESTABLISHED)
218 return 0; 188 return 0;
219 189
220 uint8_t temp_data[MAX_DATA_SIZE]; 190 uint8_t temp_data[MAX_DATA_SIZE];
221 int len = encrypt_data_fast(crypto_connections[crypt_connection_id].shared_key, 191 int len = encrypt_data_fast(c->crypto_connections[crypt_connection_id].shared_key,
222 crypto_connections[crypt_connection_id].sent_nonce, 192 c->crypto_connections[crypt_connection_id].sent_nonce,
223 data, length, temp_data + 1); 193 data, length, temp_data + 1);
224 194
225 if (len == -1) 195 if (len == -1)
@@ -227,20 +197,23 @@ int write_cryptpacket(int crypt_connection_id, uint8_t *data, uint32_t length)
227 197
228 temp_data[0] = 3; 198 temp_data[0] = 3;
229 199
230 if (write_packet(crypto_connections[crypt_connection_id].number, temp_data, len + 1) == 0) 200 if (write_packet(c->lossless_udp, c->crypto_connections[crypt_connection_id].number, temp_data, len + 1) == 0)
231 return 0; 201 return 0;
232 202
233 increment_nonce(crypto_connections[crypt_connection_id].sent_nonce); 203 increment_nonce(c->crypto_connections[crypt_connection_id].sent_nonce);
234 return 1; 204 return 1;
235} 205}
236 206
237/* create a request to peer with public_key. 207/* create a request to peer.
208 send_public_key and send_secret_key are the pub/secret keys of the sender
209 recv_public_key is public key of reciever
238 packet must be an array of MAX_DATA_SIZE big. 210 packet must be an array of MAX_DATA_SIZE big.
239 Data represents the data we send with the request with length being the length of the data. 211 Data represents the data we send with the request with length being the length of the data.
240 request_id is the id of the request (32 = friend request, 254 = ping request) 212 request_id is the id of the request (32 = friend request, 254 = ping request)
241 returns -1 on failure 213 returns -1 on failure
242 returns the length of the created packet on success */ 214 returns the length of the created packet on success */
243int create_request(uint8_t *packet, uint8_t *public_key, uint8_t *data, uint32_t length, uint8_t request_id) 215int create_request(uint8_t *send_public_key, uint8_t *send_secret_key, uint8_t *packet, uint8_t *recv_public_key,
216 uint8_t *data, uint32_t length, uint8_t request_id)
244{ 217{
245 if (MAX_DATA_SIZE < length + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING) 218 if (MAX_DATA_SIZE < length + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING)
246 return -1; 219 return -1;
@@ -250,15 +223,15 @@ int create_request(uint8_t *packet, uint8_t *public_key, uint8_t *data, uint32_t
250 memcpy(temp + 1, data, length); 223 memcpy(temp + 1, data, length);
251 temp[0] = request_id; 224 temp[0] = request_id;
252 random_nonce(nonce); 225 random_nonce(nonce);
253 int len = encrypt_data(public_key, self_secret_key, nonce, temp, length + 1, 226 int len = encrypt_data(recv_public_key, send_secret_key, nonce, temp, length + 1,
254 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + packet); 227 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + packet);
255 228
256 if (len == -1) 229 if (len == -1)
257 return -1; 230 return -1;
258 231
259 packet[0] = 32; 232 packet[0] = 32;
260 memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES); 233 memcpy(packet + 1, recv_public_key, crypto_box_PUBLICKEYBYTES);
261 memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, self_public_key, crypto_box_PUBLICKEYBYTES); 234 memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, send_public_key, crypto_box_PUBLICKEYBYTES);
262 memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES * 2, nonce, crypto_box_NONCEBYTES); 235 memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES * 2, nonce, crypto_box_NONCEBYTES);
263 236
264 return len + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES; 237 return len + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES;
@@ -268,17 +241,18 @@ int create_request(uint8_t *packet, uint8_t *public_key, uint8_t *data, uint32_t
268 in data if a friend or ping request was sent to us and returns the length of the data. 241 in data if a friend or ping request was sent to us and returns the length of the data.
269 packet is the request packet and length is its length 242 packet is the request packet and length is its length
270 return -1 if not valid request. */ 243 return -1 if not valid request. */
271static int handle_request(uint8_t *public_key, uint8_t *data, uint8_t *request_id, uint8_t *packet, uint16_t length) 244static int handle_request(Net_Crypto *c, uint8_t *public_key, uint8_t *data, uint8_t *request_id, uint8_t *packet,
245 uint16_t length)
272{ 246{
273 247
274 if (length > crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING && 248 if (length > crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING &&
275 length <= MAX_DATA_SIZE + ENCRYPTION_PADDING && 249 length <= MAX_DATA_SIZE + ENCRYPTION_PADDING &&
276 memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { 250 memcmp(packet + 1, c->self_public_key, crypto_box_PUBLICKEYBYTES) == 0) {
277 memcpy(public_key, packet + 1 + crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); 251 memcpy(public_key, packet + 1 + crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES);
278 uint8_t nonce[crypto_box_NONCEBYTES]; 252 uint8_t nonce[crypto_box_NONCEBYTES];
279 uint8_t temp[MAX_DATA_SIZE]; 253 uint8_t temp[MAX_DATA_SIZE];
280 memcpy(nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2, crypto_box_NONCEBYTES); 254 memcpy(nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2, crypto_box_NONCEBYTES);
281 int len1 = decrypt_data(public_key, self_secret_key, nonce, 255 int len1 = decrypt_data(public_key, c->self_secret_key, nonce,
282 packet + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES, 256 packet + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES,
283 length - (crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1), temp); 257 length - (crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1), temp);
284 258
@@ -293,35 +267,37 @@ static int handle_request(uint8_t *public_key, uint8_t *data, uint8_t *request_i
293 return -1; 267 return -1;
294} 268}
295 269
296static cryptopacket_handler_callback cryptopackethandlers[256] = {0}; 270void cryptopacket_registerhandler(Net_Crypto *c, uint8_t byte, cryptopacket_handler_callback cb, void *object)
297
298void cryptopacket_registerhandler(uint8_t byte, cryptopacket_handler_callback cb)
299{ 271{
300 cryptopackethandlers[byte] = cb; 272 c->cryptopackethandlers[byte].function = cb;
273 c->cryptopackethandlers[byte].object = object;
301} 274}
302 275
303static int cryptopacket_handle(IP_Port source, uint8_t *packet, uint32_t length) 276static int cryptopacket_handle(void *object, IP_Port source, uint8_t *packet, uint32_t length)
304{ 277{
278 DHT *dht = object;
279
305 if (packet[0] == 32) { 280 if (packet[0] == 32) {
306 if (length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING || 281 if (length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING ||
307 length > MAX_DATA_SIZE + ENCRYPTION_PADDING) 282 length > MAX_DATA_SIZE + ENCRYPTION_PADDING)
308 return 1; 283 return 1;
309 284
310 if (memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) {// check if request is for us. 285 if (memcmp(packet + 1, dht->c->self_public_key, crypto_box_PUBLICKEYBYTES) == 0) {// check if request is for us.
311 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; 286 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
312 uint8_t data[MAX_DATA_SIZE]; 287 uint8_t data[MAX_DATA_SIZE];
313 uint8_t number; 288 uint8_t number;
314 int len = handle_request(public_key, data, &number, packet, length); 289 int len = handle_request(dht->c, public_key, data, &number, packet, length);
315 290
316 if (len == -1 || len == 0) 291 if (len == -1 || len == 0)
317 return 1; 292 return 1;
318 293
319 if (!cryptopackethandlers[number]) return 1; 294 if (!dht->c->cryptopackethandlers[number].function) return 1;
320 295
321 cryptopackethandlers[number](source, public_key, data, len); 296 dht->c->cryptopackethandlers[number].function(dht->c->cryptopackethandlers[number].object, source, public_key, data,
297 len);
322 298
323 } else { /* if request is not for us, try routing it. */ 299 } else { /* if request is not for us, try routing it. */
324 if (route_packet(packet + 1, packet, length) == length) 300 if (route_packet(dht, packet + 1, packet, length) == length) //NOTE
325 return 0; 301 return 0;
326 } 302 }
327 } 303 }
@@ -332,7 +308,8 @@ static int cryptopacket_handle(IP_Port source, uint8_t *packet, uint32_t length)
332/* Send a crypto handshake packet containing an encrypted secret nonce and session public key 308/* Send a crypto handshake packet containing an encrypted secret nonce and session public key
333 to peer with connection_id and public_key 309 to peer with connection_id and public_key
334 the packet is encrypted with a random nonce which is sent in plain text with the packet */ 310 the packet is encrypted with a random nonce which is sent in plain text with the packet */
335static int send_cryptohandshake(int connection_id, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key) 311static int send_cryptohandshake(Net_Crypto *c, int connection_id, uint8_t *public_key, uint8_t *secret_nonce,
312 uint8_t *session_key)
336{ 313{
337 uint8_t temp_data[MAX_DATA_SIZE]; 314 uint8_t temp_data[MAX_DATA_SIZE];
338 uint8_t temp[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES]; 315 uint8_t temp[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES];
@@ -342,22 +319,23 @@ static int send_cryptohandshake(int connection_id, uint8_t *public_key, uint8_t
342 memcpy(temp, secret_nonce, crypto_box_NONCEBYTES); 319 memcpy(temp, secret_nonce, crypto_box_NONCEBYTES);
343 memcpy(temp + crypto_box_NONCEBYTES, session_key, crypto_box_PUBLICKEYBYTES); 320 memcpy(temp + crypto_box_NONCEBYTES, session_key, crypto_box_PUBLICKEYBYTES);
344 321
345 int len = encrypt_data(public_key, self_secret_key, nonce, temp, crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, 322 int len = encrypt_data(public_key, c->self_secret_key, nonce, temp, crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES,
346 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + temp_data); 323 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + temp_data);
347 324
348 if (len == -1) 325 if (len == -1)
349 return 0; 326 return 0;
350 327
351 temp_data[0] = 2; 328 temp_data[0] = 2;
352 memcpy(temp_data + 1, self_public_key, crypto_box_PUBLICKEYBYTES); 329 memcpy(temp_data + 1, c->self_public_key, crypto_box_PUBLICKEYBYTES);
353 memcpy(temp_data + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES); 330 memcpy(temp_data + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES);
354 return write_packet(connection_id, temp_data, len + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES); 331 return write_packet(c->lossless_udp, connection_id, temp_data,
332 len + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES);
355} 333}
356 334
357/* Extract secret nonce, session public key and public_key from a packet(data) with length length 335/* Extract secret nonce, session public key and public_key from a packet(data) with length length
358 return 1 if successful 336 return 1 if successful
359 return 0 if failure */ 337 return 0 if failure */
360static int handle_cryptohandshake(uint8_t *public_key, uint8_t *secret_nonce, 338static int handle_cryptohandshake(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce,
361 uint8_t *session_key, uint8_t *data, uint16_t length) 339 uint8_t *session_key, uint8_t *data, uint16_t length)
362{ 340{
363 int pad = (- crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES); 341 int pad = (- crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES);
@@ -374,7 +352,7 @@ static int handle_cryptohandshake(uint8_t *public_key, uint8_t *secret_nonce,
374 352
375 memcpy(public_key, data + 1, crypto_box_PUBLICKEYBYTES); 353 memcpy(public_key, data + 1, crypto_box_PUBLICKEYBYTES);
376 354
377 int len = decrypt_data(public_key, self_secret_key, data + 1 + crypto_box_PUBLICKEYBYTES, 355 int len = decrypt_data(public_key, c->self_secret_key, data + 1 + crypto_box_PUBLICKEYBYTES,
378 data + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, 356 data + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES,
379 crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + pad, temp); 357 crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + pad, temp);
380 358
@@ -389,13 +367,13 @@ static int handle_cryptohandshake(uint8_t *public_key, uint8_t *secret_nonce,
389/* get crypto connection id from public key of peer 367/* get crypto connection id from public key of peer
390 return -1 if there are no connections like we are looking for 368 return -1 if there are no connections like we are looking for
391 return id if it found it */ 369 return id if it found it */
392static int getcryptconnection_id(uint8_t *public_key) 370static int getcryptconnection_id(Net_Crypto *c, uint8_t *public_key)
393{ 371{
394 uint32_t i; 372 uint32_t i;
395 373
396 for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) { 374 for (i = 0; i < c->crypto_connections_length; ++i) {
397 if (crypto_connections[i].status != CONN_NO_CONNECTION) 375 if (c->crypto_connections[i].status != CONN_NO_CONNECTION)
398 if (memcmp(public_key, crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) 376 if (memcmp(public_key, c->crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0)
399 return i; 377 return i;
400 } 378 }
401 379
@@ -404,63 +382,63 @@ static int getcryptconnection_id(uint8_t *public_key)
404 382
405/* set the size of the friend list to numfriends 383/* set the size of the friend list to numfriends
406 return -1 if realloc fails */ 384 return -1 if realloc fails */
407int realloc_cryptoconnection(uint32_t num) 385int realloc_cryptoconnection(Net_Crypto *c, uint32_t num)
408{ 386{
409 if (num == 0) { 387 if (num == 0) {
410 free(crypto_connections); 388 free(c->crypto_connections);
411 crypto_connections = NULL; 389 c->crypto_connections = NULL;
412 return 0; 390 return 0;
413 } 391 }
414 392
415 Crypto_Connection *newcrypto_connections = realloc(crypto_connections, num * sizeof(Crypto_Connection)); 393 Crypto_Connection *newcrypto_connections = realloc(c->crypto_connections, num * sizeof(Crypto_Connection));
416 394
417 if (newcrypto_connections == NULL) 395 if (newcrypto_connections == NULL)
418 return -1; 396 return -1;
419 397
420 crypto_connections = newcrypto_connections; 398 c->crypto_connections = newcrypto_connections;
421 return 0; 399 return 0;
422} 400}
423 401
424/* Start a secure connection with other peer who has public_key and ip_port 402/* Start a secure connection with other peer who has public_key and ip_port
425 returns -1 if failure 403 returns -1 if failure
426 returns crypt_connection_id of the initialized connection if everything went well. */ 404 returns crypt_connection_id of the initialized connection if everything went well. */
427int crypto_connect(uint8_t *public_key, IP_Port ip_port) 405int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port)
428{ 406{
429 uint32_t i; 407 uint32_t i;
430 int id = getcryptconnection_id(public_key); 408 int id = getcryptconnection_id(c, public_key);
431 409
432 if (id != -1) { 410 if (id != -1) {
433 IP_Port c_ip = connection_ip(crypto_connections[id].number); 411 IP_Port c_ip = connection_ip(c->lossless_udp, c->crypto_connections[id].number);
434 412
435 if (c_ip.ip.i == ip_port.ip.i && c_ip.port == ip_port.port) 413 if (c_ip.ip.i == ip_port.ip.i && c_ip.port == ip_port.port)
436 return -1; 414 return -1;
437 } 415 }
438 416
439 if (realloc_cryptoconnection(crypto_connections_length + 1) == -1) 417 if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == -1)
440 return -1; 418 return -1;
441 419
442 memset(&crypto_connections[crypto_connections_length], 0, sizeof(Crypto_Connection)); 420 memset(&(c->crypto_connections[c->crypto_connections_length]), 0, sizeof(Crypto_Connection));
443 crypto_connections[crypto_connections_length].number = ~0; 421 c->crypto_connections[c->crypto_connections_length].number = ~0;
444 422
445 for (i = 0; i <= MAX_CRYPTO_CONNECTIONS; ++i) { 423 for (i = 0; i <= c->crypto_connections_length; ++i) {
446 if (crypto_connections[i].status == CONN_NO_CONNECTION) { 424 if (c->crypto_connections[i].status == CONN_NO_CONNECTION) {
447 int id = new_connection(ip_port); 425 int id = new_connection(c->lossless_udp, ip_port);
448 426
449 if (id == -1) 427 if (id == -1)
450 return -1; 428 return -1;
451 429
452 crypto_connections[i].number = id; 430 c->crypto_connections[i].number = id;
453 crypto_connections[i].status = CONN_HANDSHAKE_SENT; 431 c->crypto_connections[i].status = CONN_HANDSHAKE_SENT;
454 random_nonce(crypto_connections[i].recv_nonce); 432 random_nonce(c->crypto_connections[i].recv_nonce);
455 memcpy(crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); 433 memcpy(c->crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES);
456 crypto_box_keypair(crypto_connections[i].sessionpublic_key, crypto_connections[i].sessionsecret_key); 434 crypto_box_keypair(c->crypto_connections[i].sessionpublic_key, c->crypto_connections[i].sessionsecret_key);
457 435
458 if (crypto_connections_length == i) 436 if (c->crypto_connections_length == i)
459 ++crypto_connections_length; 437 ++c->crypto_connections_length;
460 438
461 if (send_cryptohandshake(id, public_key, crypto_connections[i].recv_nonce, 439 if (send_cryptohandshake(c, id, public_key, c->crypto_connections[i].recv_nonce,
462 crypto_connections[i].sessionpublic_key) == 1) { 440 c->crypto_connections[i].sessionpublic_key) == 1) {
463 increment_nonce(crypto_connections[i].recv_nonce); 441 increment_nonce(c->crypto_connections[i].recv_nonce);
464 return i; 442 return i;
465 } 443 }
466 444
@@ -478,25 +456,26 @@ int crypto_connect(uint8_t *public_key, IP_Port ip_port)
478 and the session public key for the connection in session_key 456 and the session public key for the connection in session_key
479 to accept it see: accept_crypto_inbound(...) 457 to accept it see: accept_crypto_inbound(...)
480 to refuse it just call kill_connection(...) on the connection id */ 458 to refuse it just call kill_connection(...) on the connection id */
481int crypto_inbound(uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key) 459int crypto_inbound(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key)
482{ 460{
483 uint32_t i; 461 uint32_t i;
484 462
485 for (i = 0; i < MAX_INCOMING; ++i) { 463 for (i = 0; i < MAX_INCOMING; ++i) {
486 if (incoming_connections[i] != -1) { 464 if (c->incoming_connections[i] != -1) {
487 if (is_connected(incoming_connections[i]) == 4 || is_connected(incoming_connections[i]) == 0) { 465 if (is_connected(c->lossless_udp, c->incoming_connections[i]) == 4
488 kill_connection(incoming_connections[i]); 466 || is_connected(c->lossless_udp, c->incoming_connections[i]) == 0) {
489 incoming_connections[i] = -1; 467 kill_connection(c->lossless_udp, c->incoming_connections[i]);
468 c->incoming_connections[i] = -1;
490 continue; 469 continue;
491 } 470 }
492 471
493 if (id_packet(incoming_connections[i]) == 2) { 472 if (id_packet(c->lossless_udp, c->incoming_connections[i]) == 2) {
494 uint8_t temp_data[MAX_DATA_SIZE]; 473 uint8_t temp_data[MAX_DATA_SIZE];
495 uint16_t len = read_packet(incoming_connections[i], temp_data); 474 uint16_t len = read_packet(c->lossless_udp, c->incoming_connections[i], temp_data);
496 475
497 if (handle_cryptohandshake(public_key, secret_nonce, session_key, temp_data, len)) { 476 if (handle_cryptohandshake(c, public_key, secret_nonce, session_key, temp_data, len)) {
498 int connection_id = incoming_connections[i]; 477 int connection_id = c->incoming_connections[i];
499 incoming_connections[i] = -1; /* remove this connection from the incoming connection list. */ 478 c->incoming_connections[i] = -1; /* remove this connection from the incoming connection list. */
500 return connection_id; 479 return connection_id;
501 } 480 }
502 } 481 }
@@ -509,25 +488,25 @@ int crypto_inbound(uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_
509/* kill a crypto connection 488/* kill a crypto connection
510 return 0 if killed successfully 489 return 0 if killed successfully
511 return 1 if there was a problem. */ 490 return 1 if there was a problem. */
512int crypto_kill(int crypt_connection_id) 491int crypto_kill(Net_Crypto *c, int crypt_connection_id)
513{ 492{
514 if (crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS) 493 if (crypt_connection_id < 0 || crypt_connection_id >= c->crypto_connections_length)
515 return 1; 494 return 1;
516 495
517 if (crypto_connections[crypt_connection_id].status != CONN_NO_CONNECTION) { 496 if (c->crypto_connections[crypt_connection_id].status != CONN_NO_CONNECTION) {
518 crypto_connections[crypt_connection_id].status = CONN_NO_CONNECTION; 497 c->crypto_connections[crypt_connection_id].status = CONN_NO_CONNECTION;
519 kill_connection(crypto_connections[crypt_connection_id].number); 498 kill_connection(c->lossless_udp, c->crypto_connections[crypt_connection_id].number);
520 memset(&crypto_connections[crypt_connection_id], 0 , sizeof(Crypto_Connection)); 499 memset(&(c->crypto_connections[crypt_connection_id]), 0 , sizeof(Crypto_Connection));
521 crypto_connections[crypt_connection_id].number = ~0; 500 c->crypto_connections[crypt_connection_id].number = ~0;
522 uint32_t i; 501 uint32_t i;
523 502
524 for (i = crypto_connections_length; i != 0; --i) { 503 for (i = c->crypto_connections_length; i != 0; --i) {
525 if (crypto_connections[i - 1].status != CONN_NO_CONNECTION) 504 if (c->crypto_connections[i - 1].status != CONN_NO_CONNECTION)
526 break; 505 break;
527 } 506 }
528 507
529 crypto_connections_length = i; 508 c->crypto_connections_length = i;
530 realloc_cryptoconnection(crypto_connections_length); 509 realloc_cryptoconnection(c, c->crypto_connections_length);
531 return 0; 510 return 0;
532 } 511 }
533 512
@@ -537,7 +516,8 @@ int crypto_kill(int crypt_connection_id)
537/* accept an incoming connection using the parameters provided by crypto_inbound 516/* accept an incoming connection using the parameters provided by crypto_inbound
538 return -1 if not successful 517 return -1 if not successful
539 returns the crypt_connection_id if successful */ 518 returns the crypt_connection_id if successful */
540int accept_crypto_inbound(int connection_id, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key) 519int accept_crypto_inbound(Net_Crypto *c, int connection_id, uint8_t *public_key, uint8_t *secret_nonce,
520 uint8_t *session_key)
541{ 521{
542 uint32_t i; 522 uint32_t i;
543 523
@@ -549,37 +529,38 @@ int accept_crypto_inbound(int connection_id, uint8_t *public_key, uint8_t *secre
549 { 529 {
550 return -1; 530 return -1;
551 }*/ 531 }*/
552 if (realloc_cryptoconnection(crypto_connections_length + 1) == -1) 532 if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == -1)
553 return -1; 533 return -1;
554 534
555 memset(&crypto_connections[crypto_connections_length], 0, sizeof(Crypto_Connection)); 535 memset(&(c->crypto_connections[c->crypto_connections_length]), 0, sizeof(Crypto_Connection));
556 crypto_connections[crypto_connections_length].number = ~0; 536 c->crypto_connections[c->crypto_connections_length].number = ~0;
557 537
558 for (i = 0; i <= MAX_CRYPTO_CONNECTIONS; ++i) { 538 for (i = 0; i <= c->crypto_connections_length; ++i) {
559 if (crypto_connections[i].status == CONN_NO_CONNECTION) { 539 if (c->crypto_connections[i].status == CONN_NO_CONNECTION) {
560 crypto_connections[i].number = connection_id; 540 c->crypto_connections[i].number = connection_id;
561 crypto_connections[i].status = CONN_NOT_CONFIRMED; 541 c->crypto_connections[i].status = CONN_NOT_CONFIRMED;
562 random_nonce(crypto_connections[i].recv_nonce); 542 random_nonce(c->crypto_connections[i].recv_nonce);
563 memcpy(crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES); 543 memcpy(c->crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES);
564 memcpy(crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); 544 memcpy(c->crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES);
565 increment_nonce(crypto_connections[i].sent_nonce); 545 increment_nonce(c->crypto_connections[i].sent_nonce);
566 memcpy(crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); 546 memcpy(c->crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES);
567 547
568 crypto_box_keypair(crypto_connections[i].sessionpublic_key, crypto_connections[i].sessionsecret_key); 548 crypto_box_keypair(c->crypto_connections[i].sessionpublic_key, c->crypto_connections[i].sessionsecret_key);
569 549
570 if (crypto_connections_length == i) 550 if (c->crypto_connections_length == i)
571 ++crypto_connections_length; 551 ++c->crypto_connections_length;
572 552
573 if (send_cryptohandshake(connection_id, public_key, crypto_connections[i].recv_nonce, 553 if (send_cryptohandshake(c, connection_id, public_key, c->crypto_connections[i].recv_nonce,
574 crypto_connections[i].sessionpublic_key) == 1) { 554 c->crypto_connections[i].sessionpublic_key) == 1) {
575 increment_nonce(crypto_connections[i].recv_nonce); 555 increment_nonce(c->crypto_connections[i].recv_nonce);
576 uint32_t zero = 0; 556 uint32_t zero = 0;
577 encrypt_precompute(crypto_connections[i].peersessionpublic_key, 557 encrypt_precompute(c->crypto_connections[i].peersessionpublic_key,
578 crypto_connections[i].sessionsecret_key, 558 c->crypto_connections[i].sessionsecret_key,
579 crypto_connections[i].shared_key); 559 c->crypto_connections[i].shared_key);
580 crypto_connections[i].status = CONN_ESTABLISHED; /* connection status needs to be 3 for write_cryptpacket() to work */ 560 c->crypto_connections[i].status =
581 write_cryptpacket(i, ((uint8_t *)&zero), sizeof(zero)); 561 CONN_ESTABLISHED; /* connection status needs to be 3 for write_cryptpacket() to work */
582 crypto_connections[i].status = CONN_NOT_CONFIRMED; /* set it to its proper value right after. */ 562 write_cryptpacket(c, i, ((uint8_t *)&zero), sizeof(zero));
563 c->crypto_connections[i].status = CONN_NOT_CONFIRMED; /* set it to its proper value right after. */
583 return i; 564 return i;
584 } 565 }
585 566
@@ -593,48 +574,46 @@ int accept_crypto_inbound(int connection_id, uint8_t *public_key, uint8_t *secre
593/* return 0 if no connection, 1 we have sent a handshake, 2 if connection is not confirmed yet 574/* return 0 if no connection, 1 we have sent a handshake, 2 if connection is not confirmed yet
594 (we have received a handshake but no empty data packet), 3 if the connection is established. 575 (we have received a handshake but no empty data packet), 3 if the connection is established.
595 4 if the connection is timed out and waiting to be killed */ 576 4 if the connection is timed out and waiting to be killed */
596int is_cryptoconnected(int crypt_connection_id) 577int is_cryptoconnected(Net_Crypto *c, int crypt_connection_id)
597{ 578{
598 if (crypt_connection_id >= 0 && crypt_connection_id < MAX_CRYPTO_CONNECTIONS) 579 if (crypt_connection_id >= 0 && crypt_connection_id < c->crypto_connections_length)
599 return crypto_connections[crypt_connection_id].status; 580 return c->crypto_connections[crypt_connection_id].status;
600 581
601 return CONN_NO_CONNECTION; 582 return CONN_NO_CONNECTION;
602} 583}
603 584
604/* Generate our public and private keys 585void new_keys(Net_Crypto *c)
605 Only call this function the first time the program starts. */
606void new_keys(void)
607{ 586{
608 crypto_box_keypair(self_public_key, self_secret_key); 587 crypto_box_keypair(c->self_public_key, c->self_secret_key);
609} 588}
610 589
611/* save the public and private keys to the keys array 590/* save the public and private keys to the keys array
612 Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES */ 591 Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES */
613void save_keys(uint8_t *keys) 592void save_keys(Net_Crypto *c, uint8_t *keys)
614{ 593{
615 memcpy(keys, self_public_key, crypto_box_PUBLICKEYBYTES); 594 memcpy(keys, c->self_public_key, crypto_box_PUBLICKEYBYTES);
616 memcpy(keys + crypto_box_PUBLICKEYBYTES, self_secret_key, crypto_box_SECRETKEYBYTES); 595 memcpy(keys + crypto_box_PUBLICKEYBYTES, c->self_secret_key, crypto_box_SECRETKEYBYTES);
617} 596}
618 597
619/* load the public and private keys from the keys array 598/* load the public and private keys from the keys array
620 Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES */ 599 Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES */
621void load_keys(uint8_t *keys) 600void load_keys(Net_Crypto *c, uint8_t *keys)
622{ 601{
623 memcpy(self_public_key, keys, crypto_box_PUBLICKEYBYTES); 602 memcpy(c->self_public_key, keys, crypto_box_PUBLICKEYBYTES);
624 memcpy(self_secret_key, keys + crypto_box_PUBLICKEYBYTES, crypto_box_SECRETKEYBYTES); 603 memcpy(c->self_secret_key, keys + crypto_box_PUBLICKEYBYTES, crypto_box_SECRETKEYBYTES);
625} 604}
626 605
627/* TODO: optimize this 606/* TODO: optimize this
628 adds an incoming connection to the incoming_connection list. 607 adds an incoming connection to the incoming_connection list.
629 returns 0 if successful 608 returns 0 if successful
630 returns 1 if failure */ 609 returns 1 if failure */
631static int new_incoming(int id) 610static int new_incoming(Net_Crypto *c, int id)
632{ 611{
633 uint32_t i; 612 uint32_t i;
634 613
635 for (i = 0; i < MAX_INCOMING; ++i) { 614 for (i = 0; i < MAX_INCOMING; ++i) {
636 if (incoming_connections[i] == -1) { 615 if (c->incoming_connections[i] == -1) {
637 incoming_connections[i] = id; 616 c->incoming_connections[i] = id;
638 return 0; 617 return 0;
639 } 618 }
640 } 619 }
@@ -644,81 +623,83 @@ static int new_incoming(int id)
644 623
645/* TODO: optimize this 624/* TODO: optimize this
646 handle all new incoming connections. */ 625 handle all new incoming connections. */
647static void handle_incomings(void) 626static void handle_incomings(Net_Crypto *c)
648{ 627{
649 int income; 628 int income;
650 629
651 while (1) { 630 while (1) {
652 income = incoming_connection(); 631 income = incoming_connection(c->lossless_udp);
653 632
654 if (income == -1 || new_incoming(income) ) 633 if (income == -1 || new_incoming(c, income) )
655 break; 634 break;
656 } 635 }
657} 636}
658 637
659/* handle received packets for not yet established crypto connections. */ 638/* handle received packets for not yet established crypto connections. */
660static void receive_crypto(void) 639static void receive_crypto(Net_Crypto *c)
661{ 640{
662 uint32_t i; 641 uint32_t i;
663 642
664 for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) { 643 for (i = 0; i < c->crypto_connections_length; ++i) {
665 if (crypto_connections[i].status == CONN_HANDSHAKE_SENT) { 644 if (c->crypto_connections[i].status == CONN_HANDSHAKE_SENT) {
666 uint8_t temp_data[MAX_DATA_SIZE]; 645 uint8_t temp_data[MAX_DATA_SIZE];
667 uint8_t secret_nonce[crypto_box_NONCEBYTES]; 646 uint8_t secret_nonce[crypto_box_NONCEBYTES];
668 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; 647 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
669 uint8_t session_key[crypto_box_PUBLICKEYBYTES]; 648 uint8_t session_key[crypto_box_PUBLICKEYBYTES];
670 uint16_t len; 649 uint16_t len;
671 650
672 if (id_packet(crypto_connections[i].number) == 2) { /* handle handshake packet. */ 651 if (id_packet(c->lossless_udp, c->crypto_connections[i].number) == 2) { /* handle handshake packet. */
673 len = read_packet(crypto_connections[i].number, temp_data); 652 len = read_packet(c->lossless_udp, c->crypto_connections[i].number, temp_data);
674 653
675 if (handle_cryptohandshake(public_key, secret_nonce, session_key, temp_data, len)) { 654 if (handle_cryptohandshake(c, public_key, secret_nonce, session_key, temp_data, len)) {
676 if (memcmp(public_key, crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) { 655 if (memcmp(public_key, c->crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) {
677 memcpy(crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES); 656 memcpy(c->crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES);
678 memcpy(crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); 657 memcpy(c->crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES);
679 increment_nonce(crypto_connections[i].sent_nonce); 658 increment_nonce(c->crypto_connections[i].sent_nonce);
680 uint32_t zero = 0; 659 uint32_t zero = 0;
681 encrypt_precompute(crypto_connections[i].peersessionpublic_key, 660 encrypt_precompute(c->crypto_connections[i].peersessionpublic_key,
682 crypto_connections[i].sessionsecret_key, 661 c->crypto_connections[i].sessionsecret_key,
683 crypto_connections[i].shared_key); 662 c->crypto_connections[i].shared_key);
684 crypto_connections[i].status = CONN_ESTABLISHED; /* connection status needs to be 3 for write_cryptpacket() to work */ 663 c->crypto_connections[i].status =
685 write_cryptpacket(i, ((uint8_t *)&zero), sizeof(zero)); 664 CONN_ESTABLISHED; /* connection status needs to be 3 for write_cryptpacket() to work */
686 crypto_connections[i].status = CONN_NOT_CONFIRMED; /* set it to its proper value right after. */ 665 write_cryptpacket(c, i, ((uint8_t *)&zero), sizeof(zero));
666 c->crypto_connections[i].status = CONN_NOT_CONFIRMED; /* set it to its proper value right after. */
687 } 667 }
688 } 668 }
689 } else if (id_packet(crypto_connections[i].number) != -1) { // This should not happen kill the connection if it does 669 } else if (id_packet(c->lossless_udp,
690 crypto_kill(crypto_connections[i].number); 670 c->crypto_connections[i].number) != -1) { // This should not happen kill the connection if it does
671 crypto_kill(c, i);
691 return; 672 return;
692 } 673 }
693 } 674 }
694 675
695 if (crypto_connections[i].status == CONN_NOT_CONFIRMED) { 676 if (c->crypto_connections[i].status == CONN_NOT_CONFIRMED) {
696 if (id_packet(crypto_connections[i].number) == 3) { 677 if (id_packet(c->lossless_udp, c->crypto_connections[i].number) == 3) {
697 uint8_t temp_data[MAX_DATA_SIZE]; 678 uint8_t temp_data[MAX_DATA_SIZE];
698 uint8_t data[MAX_DATA_SIZE]; 679 uint8_t data[MAX_DATA_SIZE];
699 int length = read_packet(crypto_connections[i].number, temp_data); 680 int length = read_packet(c->lossless_udp, c->crypto_connections[i].number, temp_data);
700 int len = decrypt_data(crypto_connections[i].peersessionpublic_key, 681 int len = decrypt_data(c->crypto_connections[i].peersessionpublic_key,
701 crypto_connections[i].sessionsecret_key, 682 c->crypto_connections[i].sessionsecret_key,
702 crypto_connections[i].recv_nonce, temp_data + 1, length - 1, data); 683 c->crypto_connections[i].recv_nonce, temp_data + 1, length - 1, data);
703 uint32_t zero = 0; 684 uint32_t zero = 0;
704 685
705 if (len == sizeof(uint32_t) && memcmp(((uint8_t *)&zero), data, sizeof(uint32_t)) == 0) { 686 if (len == sizeof(uint32_t) && memcmp(((uint8_t *)&zero), data, sizeof(uint32_t)) == 0) {
706 increment_nonce(crypto_connections[i].recv_nonce); 687 increment_nonce(c->crypto_connections[i].recv_nonce);
707 encrypt_precompute(crypto_connections[i].peersessionpublic_key, 688 encrypt_precompute(c->crypto_connections[i].peersessionpublic_key,
708 crypto_connections[i].sessionsecret_key, 689 c->crypto_connections[i].sessionsecret_key,
709 crypto_connections[i].shared_key); 690 c->crypto_connections[i].shared_key);
710 crypto_connections[i].status = CONN_ESTABLISHED; 691 c->crypto_connections[i].status = CONN_ESTABLISHED;
711 692
712 /* connection is accepted so we disable the auto kill by setting it to about 1 month from now. */ 693 /* connection is accepted so we disable the auto kill by setting it to about 1 month from now. */
713 kill_connection_in(crypto_connections[i].number, 3000000); 694 kill_connection_in(c->lossless_udp, c->crypto_connections[i].number, 3000000);
714 } else { 695 } else {
715 crypto_kill(crypto_connections[i].number); // This should not happen kill the connection if it does 696 crypto_kill(c, i); // This should not happen kill the connection if it does
716 return; 697 return;
717 } 698 }
718 } else if (id_packet(crypto_connections[i].number) != -1) 699 } else if (id_packet(c->lossless_udp, c->crypto_connections[i].number) != -1)
719 /* This should not happen 700 /* This should not happen
720 kill the connection if it does */ 701 kill the connection if it does */
721 crypto_kill(crypto_connections[i].number); 702 crypto_kill(c, i);
722 703
723 return; 704 return;
724 } 705 }
@@ -727,33 +708,64 @@ static void receive_crypto(void)
727 708
728/* run this to (re)initialize net_crypto 709/* run this to (re)initialize net_crypto
729 sets all the global connection variables to their default values. */ 710 sets all the global connection variables to their default values. */
730void initNetCrypto(void) 711Net_Crypto *new_net_crypto(Networking_Core *net)
712{
713 if (net == NULL)
714 return NULL;
715
716 Net_Crypto *temp = calloc(1, sizeof(Net_Crypto));
717
718 if (temp == NULL)
719 return NULL;
720
721 temp->lossless_udp = new_lossless_udp(net);
722
723 if (temp->lossless_udp == NULL)
724 return NULL;
725
726 memset(temp->incoming_connections, -1 , sizeof(int) * MAX_INCOMING);
727 return temp;
728}
729
730void init_cryptopackets(void *dht)
731{ 731{
732 memset(incoming_connections, -1 , sizeof(incoming_connections)); 732 DHT *s_dht = dht;
733 networking_registerhandler(32, &cryptopacket_handle); 733 networking_registerhandler(s_dht->c->lossless_udp->net, 32, &cryptopacket_handle, s_dht);
734} 734}
735 735
736static void killTimedout(void) 736static void kill_timedout(Net_Crypto *c)
737{ 737{
738 uint32_t i; 738 uint32_t i;
739 739
740 for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) { 740 for (i = 0; i < c->crypto_connections_length; ++i) {
741 if (crypto_connections[i].status != CONN_NO_CONNECTION && is_connected(crypto_connections[i].number) == 4) 741 if (c->crypto_connections[i].status != CONN_NO_CONNECTION
742 crypto_connections[i].status = CONN_TIMED_OUT; 742 && is_connected(c->lossless_udp, c->crypto_connections[i].number) == 4)
743 else if (is_connected(crypto_connections[i].number) == 4) { 743 c->crypto_connections[i].status = CONN_TIMED_OUT;
744 kill_connection(crypto_connections[i].number); 744 else if (is_connected(c->lossless_udp, c->crypto_connections[i].number) == 4) {
745 crypto_connections[i].number = ~0; 745 kill_connection(c->lossless_udp, c->crypto_connections[i].number);
746 c->crypto_connections[i].number = ~0;
746 } 747 }
747 } 748 }
748} 749}
749 750
750/* main loop */ 751/* main loop */
751void doNetCrypto(void) 752void do_net_crypto(Net_Crypto *c)
752{ 753{
753 /* TODO:check if friend requests were sent correctly 754 do_lossless_udp(c->lossless_udp);
754 handle new incoming connections 755 handle_incomings(c);
755 handle friend requests */ 756 receive_crypto(c);
756 handle_incomings(); 757 kill_timedout(c);
757 receive_crypto(); 758}
758 killTimedout(); 759
760void kill_net_crypto(Net_Crypto *c)
761{
762 uint32_t i;
763
764 for (i = 0; i < c->crypto_connections_length; ++i) {
765 crypto_kill(c, i);
766 }
767
768 kill_lossless_udp(c->lossless_udp);
769 memset(c, 0, sizeof(Net_Crypto));
770 free(c);
759} 771}
diff --git a/core/net_crypto.h b/core/net_crypto.h
index 742d9fdc..46bcf250 100644
--- a/core/net_crypto.h
+++ b/core/net_crypto.h
@@ -25,15 +25,54 @@
25#define NET_CRYPTO_H 25#define NET_CRYPTO_H
26 26
27#include "Lossless_UDP.h" 27#include "Lossless_UDP.h"
28#include "DHT.h"
29 28
30#ifdef __cplusplus 29#ifdef __cplusplus
31extern "C" { 30extern "C" {
32#endif 31#endif
33 32
34/* Our public key. */ 33#define MAX_INCOMING 64
35extern uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; 34
36extern uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; 35typedef struct {
36 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* the real public key of the peer. */
37 uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* nonce of received packets */
38 uint8_t sent_nonce[crypto_box_NONCEBYTES]; /* nonce of sent packets. */
39 uint8_t sessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* our public key for this session. */
40 uint8_t sessionsecret_key[crypto_box_SECRETKEYBYTES]; /* our private key for this session. */
41 uint8_t peersessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* The public key of the peer. */
42 uint8_t shared_key[crypto_box_BEFORENMBYTES]; /* the precomputed shared key from encrypt_precompute */
43 uint8_t status; /* 0 if no connection, 1 we have sent a handshake, 2 if connexion is not confirmed yet
44 (we have received a handshake but no empty data packet), 3 if the connection is established.
45 4 if the connection is timed out. */
46 uint16_t number; /* Lossless_UDP connection number corresponding to this connection. */
47
48} Crypto_Connection;
49
50typedef int (*cryptopacket_handler_callback)(void *object, IP_Port ip_port, uint8_t *source_pubkey, uint8_t *data,
51 uint32_t len);
52
53typedef struct {
54 cryptopacket_handler_callback function;
55 void *object;
56} Cryptopacket_Handles;
57
58typedef struct {
59 Lossless_UDP *lossless_udp;
60
61 Crypto_Connection *crypto_connections;
62
63 uint32_t crypto_connections_length; /* Length of connections array */
64
65 /* Our public and secret keys. */
66 uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
67 uint8_t self_secret_key[crypto_box_SECRETKEYBYTES];
68
69 /* keeps track of the connection numbers for friends request so we can check later if they were sent */
70 int incoming_connections[MAX_INCOMING];
71
72 Cryptopacket_Handles cryptopackethandlers[256];
73} Net_Crypto;
74
75#include "DHT.h"
37 76
38#define ENCRYPTION_PADDING (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES) 77#define ENCRYPTION_PADDING (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES)
39 78
@@ -75,34 +114,36 @@ void random_nonce(uint8_t *nonce);
75/* return 0 if there is no received data in the buffer 114/* return 0 if there is no received data in the buffer
76 return -1 if the packet was discarded. 115 return -1 if the packet was discarded.
77 return length of received data if successful */ 116 return length of received data if successful */
78int read_cryptpacket(int crypt_connection_id, uint8_t *data); 117int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data);
79 118
80/* return 0 if data could not be put in packet queue 119/* return 0 if data could not be put in packet queue
81 return 1 if data was put into the queue */ 120 return 1 if data was put into the queue */
82int write_cryptpacket(int crypt_connection_id, uint8_t *data, uint32_t length); 121int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length);
83 122
84/* create a request to peer with public_key. 123/* create a request to peer.
85 packet must be an array of MAX_DATA_SIZE big. 124 send_public_key and send_secret_key are the pub/secret keys of the sender
86 Data represents the data we send with the request with length being the length of the data. 125 recv_public_key is public key of reciever
87 request_id is the id of the request (32 = friend request, 254 = ping request) 126 packet must be an array of MAX_DATA_SIZE big.
88 returns -1 on failure 127 Data represents the data we send with the request with length being the length of the data.
89 returns the length of the created packet on success */ 128 request_id is the id of the request (32 = friend request, 254 = ping request)
90int create_request(uint8_t *packet, uint8_t *public_key, uint8_t *data, uint32_t length, uint8_t request_id); 129 returns -1 on failure
130 returns the length of the created packet on success */
131int create_request(uint8_t *send_public_key, uint8_t *send_secret_key, uint8_t *packet, uint8_t *recv_public_key,
132 uint8_t *data, uint32_t length, uint8_t request_id);
91 133
92 134
93typedef int (*cryptopacket_handler_callback)(IP_Port ip_port, uint8_t *source_pubkey, uint8_t *data, uint32_t len);
94/* Function to call when request beginning with byte is received */ 135/* Function to call when request beginning with byte is received */
95void cryptopacket_registerhandler(uint8_t byte, cryptopacket_handler_callback cb); 136void cryptopacket_registerhandler(Net_Crypto *c, uint8_t byte, cryptopacket_handler_callback cb, void *object);
96 137
97/* Start a secure connection with other peer who has public_key and ip_port 138/* Start a secure connection with other peer who has public_key and ip_port
98 returns -1 if failure 139 returns -1 if failure
99 returns crypt_connection_id of the initialized connection if everything went well. */ 140 returns crypt_connection_id of the initialized connection if everything went well. */
100int crypto_connect(uint8_t *public_key, IP_Port ip_port); 141int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port);
101 142
102/* kill a crypto connection 143/* kill a crypto connection
103 return 0 if killed successfully 144 return 0 if killed successfully
104 return 1 if there was a problem. */ 145 return 1 if there was a problem. */
105int crypto_kill(int crypt_connection_id); 146int crypto_kill(Net_Crypto *c, int crypt_connection_id);
106 147
107/* handle an incoming connection 148/* handle an incoming connection
108 return -1 if no crypto inbound connection 149 return -1 if no crypto inbound connection
@@ -111,37 +152,43 @@ int crypto_kill(int crypt_connection_id);
111 and the session public key for the connection in session_key 152 and the session public key for the connection in session_key
112 to accept it see: accept_crypto_inbound(...) 153 to accept it see: accept_crypto_inbound(...)
113 to refuse it just call kill_connection(...) on the connection id */ 154 to refuse it just call kill_connection(...) on the connection id */
114int crypto_inbound(uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key); 155int crypto_inbound(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key);
115 156
116/* accept an incoming connection using the parameters provided by crypto_inbound 157/* accept an incoming connection using the parameters provided by crypto_inbound
117 return -1 if not successful 158 return -1 if not successful
118 returns the crypt_connection_id if successful */ 159 returns the crypt_connection_id if successful */
119int accept_crypto_inbound(int connection_id, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key); 160int accept_crypto_inbound(Net_Crypto *c, int connection_id, uint8_t *public_key, uint8_t *secret_nonce,
161 uint8_t *session_key);
120 162
121/* return 0 if no connection, 1 we have sent a handshake, 2 if connexion is not confirmed yet 163/* return 0 if no connection, 1 we have sent a handshake, 2 if connexion is not confirmed yet
122 (we have received a handshake but no empty data packet), 3 if the connection is established. 164 (we have received a handshake but no empty data packet), 3 if the connection is established.
123 4 if the connection is timed out and waiting to be killed */ 165 4 if the connection is timed out and waiting to be killed */
124int is_cryptoconnected(int crypt_connection_id); 166int is_cryptoconnected(Net_Crypto *c, int crypt_connection_id);
125 167
126 168
127/* Generate our public and private keys 169/* Generate our public and private keys
128 Only call this function the first time the program starts. */ 170 Only call this function the first time the program starts. */
129void new_keys(void); 171void new_keys(Net_Crypto *c);
130 172
131/* save the public and private keys to the keys array 173/* save the public and private keys to the keys array
132 Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES */ 174 Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES */
133void save_keys(uint8_t *keys); 175void save_keys(Net_Crypto *c, uint8_t *keys);
134 176
135/* load the public and private keys from the keys array 177/* load the public and private keys from the keys array
136 Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES */ 178 Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES */
137void load_keys(uint8_t *keys); 179void load_keys(Net_Crypto *c, uint8_t *keys);
138 180
139/* run this to (re)initialize net_crypto 181/* create new instance of Net_Crypto
140 sets all the global connection variables to their default values. */ 182 sets all the global connection variables to their default values. */
141void initNetCrypto(void); 183Net_Crypto *new_net_crypto(Networking_Core *net);
142 184
143/* main loop */ 185/* main loop */
144void doNetCrypto(void); 186void do_net_crypto(Net_Crypto *c);
187
188void kill_net_crypto(Net_Crypto *c);
189
190/* Init the cryptopacket handling */
191void init_cryptopackets(void *dht);
145 192
146#ifdef __cplusplus 193#ifdef __cplusplus
147} 194}
diff --git a/core/network.c b/core/network.c
index 1977ce38..849c7e2a 100644
--- a/core/network.c
+++ b/core/network.c
@@ -56,12 +56,9 @@ uint32_t random_int(void)
56#endif 56#endif
57} 57}
58 58
59/* our UDP socket, a global variable. */
60static int sock;
61
62/* Basic network functions: 59/* Basic network functions:
63 Function to send packet(data) of length length to ip_port */ 60 Function to send packet(data) of length length to ip_port */
64int sendpacket(IP_Port ip_port, uint8_t *data, uint32_t length) 61int sendpacket(int sock, IP_Port ip_port, uint8_t *data, uint32_t length)
65{ 62{
66 ADDR addr = {AF_INET, ip_port.port, ip_port.ip}; 63 ADDR addr = {AF_INET, ip_port.port, ip_port.ip};
67 return sendto(sock, (char *) data, length, 0, (struct sockaddr *)&addr, sizeof(addr)); 64 return sendto(sock, (char *) data, length, 0, (struct sockaddr *)&addr, sizeof(addr));
@@ -71,7 +68,7 @@ int sendpacket(IP_Port ip_port, uint8_t *data, uint32_t length)
71 the packet data into data 68 the packet data into data
72 the packet length into length. 69 the packet length into length.
73 dump all empty packets. */ 70 dump all empty packets. */
74static int receivepacket(IP_Port *ip_port, uint8_t *data, uint32_t *length) 71static int receivepacket(int sock, IP_Port *ip_port, uint8_t *data, uint32_t *length)
75{ 72{
76 ADDR addr; 73 ADDR addr;
77#ifdef WIN32 74#ifdef WIN32
@@ -89,36 +86,33 @@ static int receivepacket(IP_Port *ip_port, uint8_t *data, uint32_t *length)
89 return 0; 86 return 0;
90} 87}
91 88
92static packet_handler_callback packethandlers[256] = {0}; 89void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handler_callback cb, void *object)
93
94void networking_registerhandler(uint8_t byte, packet_handler_callback cb)
95{ 90{
96 packethandlers[byte] = cb; 91 net->packethandlers[byte].function = cb;
92 net->packethandlers[byte].object = object;
97} 93}
98 94
99void networking_poll() 95void networking_poll(Networking_Core *net)
100{ 96{
101 IP_Port ip_port; 97 IP_Port ip_port;
102 uint8_t data[MAX_UDP_PACKET_SIZE]; 98 uint8_t data[MAX_UDP_PACKET_SIZE];
103 uint32_t length; 99 uint32_t length;
104 100
105 while (receivepacket(&ip_port, data, &length) != -1) { 101 while (receivepacket(net->sock, &ip_port, data, &length) != -1) {
106 if (length < 1) continue; 102 if (length < 1) continue;
107 103
108 if (!packethandlers[data[0]]) continue; 104 if (!(net->packethandlers[data[0]].function)) continue;
109 105
110 packethandlers[data[0]](ip_port, data, length); 106 net->packethandlers[data[0]].function(net->packethandlers[data[0]].object, ip_port, data, length);
111 } 107 }
112} 108}
113 109
114/* initialize networking 110uint8_t at_startup_ran;
115 bind to ip and port 111static void at_startup(void)
116 ip must be in network order EX: 127.0.0.1 = (7F000001)
117 port is in host byte order (this means don't worry about it)
118 returns 0 if no problems
119 returns -1 if there are problems */
120int init_networking(IP ip, uint16_t port)
121{ 112{
113 if (at_startup_ran != 0)
114 return;
115
122#ifdef WIN32 116#ifdef WIN32
123 WSADATA wsaData; 117 WSADATA wsaData;
124 118
@@ -129,20 +123,49 @@ int init_networking(IP ip, uint16_t port)
129 srandom((uint32_t)current_time()); 123 srandom((uint32_t)current_time());
130#endif 124#endif
131 srand((uint32_t)current_time()); 125 srand((uint32_t)current_time());
126 at_startup_ran = 1;
127}
128
129/* TODO: put this somewhere
130static void at_shutdown(void)
131{
132#ifdef WIN32
133 WSACleanup();
134#endif
135}
136*/
132 137
138/* initialize networking
139 bind to ip and port
140 ip must be in network order EX: 127.0.0.1 = (7F000001)
141 port is in host byte order (this means don't worry about it)
142 returns Networking_Core object if no problems
143 returns NULL if there are problems */
144Networking_Core *new_networking(IP ip, uint16_t port)
145{
146 at_startup();
133 /* initialize our socket */ 147 /* initialize our socket */
134 sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 148 Networking_Core *temp = calloc(1, sizeof(Networking_Core));
149
150 if (temp == NULL)
151 return NULL;
152
153 temp->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
135 154
136 /* Check for socket error */ 155 /* Check for socket error */
137#ifdef WIN32 156#ifdef WIN32
138 157
139 if (sock == INVALID_SOCKET) /* MSDN recommends this */ 158 if (temp->sock == INVALID_SOCKET) { /* MSDN recommends this */
140 return -1; 159 free(temp);
160 return NULL;
161 }
141 162
142#else 163#else
143 164
144 if (sock < 0) 165 if (temp->sock < 0) {
145 return -1; 166 free(temp);
167 return NULL;
168 }
146 169
147#endif 170#endif
148 171
@@ -161,34 +184,33 @@ int init_networking(IP ip, uint16_t port)
161 184
162 /* Enable broadcast on socket */ 185 /* Enable broadcast on socket */
163 int broadcast = 1; 186 int broadcast = 1;
164 setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast, sizeof(broadcast)); 187 setsockopt(temp->sock, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast, sizeof(broadcast));
165 188
166 /* Set socket nonblocking */ 189 /* Set socket nonblocking */
167#ifdef WIN32 190#ifdef WIN32
168 /* I think this works for windows */ 191 /* I think this works for windows */
169 u_long mode = 1; 192 u_long mode = 1;
170 /* ioctl(sock, FIONBIO, &mode); */ 193 /* ioctl(sock, FIONBIO, &mode); */
171 ioctlsocket(sock, FIONBIO, &mode); 194 ioctlsocket(temp->sock, FIONBIO, &mode);
172#else 195#else
173 fcntl(sock, F_SETFL, O_NONBLOCK, 1); 196 fcntl(temp->sock, F_SETFL, O_NONBLOCK, 1);
174#endif 197#endif
175 198
176 /* Bind our socket to port PORT and address 0.0.0.0 */ 199 /* Bind our socket to port PORT and address 0.0.0.0 */
177 ADDR addr = {AF_INET, htons(port), ip}; 200 ADDR addr = {AF_INET, htons(port), ip};
178 bind(sock, (struct sockaddr *)&addr, sizeof(addr)); 201 bind(temp->sock, (struct sockaddr *)&addr, sizeof(addr));
179 202 return temp;
180 return 0;
181} 203}
182 204
183/* function to cleanup networking stuff */ 205/* function to cleanup networking stuff */
184void shutdown_networking(void) 206void kill_networking(Networking_Core *net)
185{ 207{
186#ifdef WIN32 208#ifdef WIN32
187 closesocket(sock); 209 closesocket(net->sock);
188 WSACleanup();
189#else 210#else
190 close(sock); 211 close(net->sock);
191#endif 212#endif
213 free(net);
192 return; 214 return;
193} 215}
194 216
diff --git a/core/network.h b/core/network.h
index 127a55d1..87f45978 100644
--- a/core/network.h
+++ b/core/network.h
@@ -99,7 +99,18 @@ typedef struct {
99/* Function to receive data, ip and port of sender is put into ip_port 99/* Function to receive data, ip and port of sender is put into ip_port
100 the packet data into data 100 the packet data into data
101 the packet length into length. */ 101 the packet length into length. */
102typedef int (*packet_handler_callback)(IP_Port ip_port, uint8_t *data, uint32_t len); 102typedef int (*packet_handler_callback)(void *object, IP_Port ip_port, uint8_t *data, uint32_t len);
103
104typedef struct {
105 packet_handler_callback function;
106 void *object;
107} Packet_Handles;
108
109typedef struct {
110 Packet_Handles packethandlers[256];
111 /* our UDP socket */
112 int sock;
113} Networking_Core;
103 114
104/* returns current time in milleseconds since the epoch. */ 115/* returns current time in milleseconds since the epoch. */
105uint64_t current_time(void); 116uint64_t current_time(void);
@@ -111,13 +122,13 @@ uint32_t random_int(void);
111/* Basic network functions: */ 122/* Basic network functions: */
112 123
113/* Function to send packet(data) of length length to ip_port */ 124/* Function to send packet(data) of length length to ip_port */
114int sendpacket(IP_Port ip_port, uint8_t *data, uint32_t length); 125int sendpacket(int sock, IP_Port ip_port, uint8_t *data, uint32_t length);
115 126
116/* Function to call when packet beginning with byte is received */ 127/* Function to call when packet beginning with byte is received */
117void networking_registerhandler(uint8_t byte, packet_handler_callback cb); 128void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handler_callback cb, void *object);
118 129
119/* call this several times a second */ 130/* call this several times a second */
120void networking_poll(); 131void networking_poll(Networking_Core *net);
121 132
122/* initialize networking 133/* initialize networking
123 bind to ip and port 134 bind to ip and port
@@ -125,10 +136,10 @@ void networking_poll();
125 port is in host byte order (this means don't worry about it) 136 port is in host byte order (this means don't worry about it)
126 returns 0 if no problems 137 returns 0 if no problems
127 returns -1 if there were problems */ 138 returns -1 if there were problems */
128int init_networking(IP ip, uint16_t port); 139Networking_Core *new_networking(IP ip, uint16_t port);
129 140
130/* function to cleanup networking stuff(doesn't do much right now) */ 141/* function to cleanup networking stuff(doesn't do much right now) */
131void shutdown_networking(void); 142void kill_networking(Networking_Core *net);
132 143
133/* 144/*
134 resolve_addr(): 145 resolve_addr():
diff --git a/core/ping.c b/core/ping.c
index 47d6e163..4bb9c38a 100644
--- a/core/ping.c
+++ b/core/ping.c
@@ -23,17 +23,20 @@ typedef struct {
23 uint64_t timestamp; 23 uint64_t timestamp;
24} pinged_t; 24} pinged_t;
25 25
26static pinged_t pings[PING_NUM_MAX]; 26typedef struct {
27static size_t num_pings; 27 pinged_t pings[PING_NUM_MAX];
28static size_t pos_pings; 28 size_t num_pings;
29static clientid_t *self_id = (clientid_t *) &self_public_key; 29 size_t pos_pings;
30} PING;
30 31
31extern uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; // DHT.c 32void *new_ping(void)
33{
34 return calloc(1, sizeof(PING));
35}
32 36
33void init_ping() 37void kill_ping(void *ping)
34{ 38{
35 num_pings = 0; 39 free(ping);
36 pos_pings = 0;
37} 40}
38 41
39static bool is_timeout(uint64_t time) 42static bool is_timeout(uint64_t time)
@@ -41,17 +44,18 @@ static bool is_timeout(uint64_t time)
41 return (time + PING_TIMEOUT) < now(); 44 return (time + PING_TIMEOUT) < now();
42} 45}
43 46
44static void remove_timeouts() // O(n) 47static void remove_timeouts(void *ping) // O(n)
45{ 48{
49 PING *png = ping;
46 size_t i, id; 50 size_t i, id;
47 size_t new_pos = pos_pings; 51 size_t new_pos = png->pos_pings;
48 size_t new_num = num_pings; 52 size_t new_num = png->num_pings;
49 53
50 // Loop through buffer, oldest first 54 // Loop through buffer, oldest first
51 for (i = 0; i < num_pings; i++) { 55 for (i = 0; i < png->num_pings; i++) {
52 id = (pos_pings + i) % PING_NUM_MAX; 56 id = (png->pos_pings + i) % PING_NUM_MAX;
53 57
54 if (is_timeout(pings[id].timestamp)) { 58 if (is_timeout(png->pings[id].timestamp)) {
55 new_pos++; 59 new_pos++;
56 new_num--; 60 new_num--;
57 } 61 }
@@ -61,47 +65,50 @@ static void remove_timeouts() // O(n)
61 } 65 }
62 } 66 }
63 67
64 num_pings = new_num; 68 png->num_pings = new_num;
65 pos_pings = new_pos % PING_NUM_MAX; 69 png->pos_pings = new_pos % PING_NUM_MAX;
66} 70}
67 71
68uint64_t add_ping(IP_Port ipp) // O(n) 72uint64_t add_ping(void *ping, IP_Port ipp) // O(n)
69{ 73{
74 PING *png = ping;
70 size_t p; 75 size_t p;
71 76
72 remove_timeouts(); 77 remove_timeouts(ping);
73 78
74 // Remove oldest ping if full buffer 79 // Remove oldest ping if full buffer
75 if (num_pings == PING_NUM_MAX) { 80 if (png->num_pings == PING_NUM_MAX) {
76 num_pings--; 81 png->num_pings--;
77 pos_pings = (pos_pings + 1) % PING_NUM_MAX; 82 png->pos_pings = (png->pos_pings + 1) % PING_NUM_MAX;
78 } 83 }
79 84
80 // Insert new ping at end of list 85 // Insert new ping at end of list
81 p = (pos_pings + num_pings) % PING_NUM_MAX; 86 p = (png->pos_pings + png->num_pings) % PING_NUM_MAX;
82 87
83 pings[p].ipp = ipp; 88 png->pings[p].ipp = ipp;
84 pings[p].timestamp = now(); 89 png->pings[p].timestamp = now();
85 pings[p].id = random_64b(); 90 png->pings[p].id = random_64b();
86 91
87 num_pings++; 92 png->num_pings++;
88 return pings[p].id; 93 return png->pings[p].id;
89} 94}
90 95
91bool is_pinging(IP_Port ipp, uint64_t ping_id) // O(n) TODO: replace this with something else. 96bool is_pinging(void *ping, IP_Port ipp, uint64_t ping_id) // O(n) TODO: replace this with something else.
92{ 97{
98 PING *png = ping;
99
93 if (ipp.ip.i == 0 && ping_id == 0) 100 if (ipp.ip.i == 0 && ping_id == 0)
94 return false; 101 return false;
95 102
96 size_t i, id; 103 size_t i, id;
97 104
98 remove_timeouts(); 105 remove_timeouts(ping);
99 106
100 for (i = 0; i < num_pings; i++) { 107 for (i = 0; i < png->num_pings; i++) {
101 id = (pos_pings + i) % PING_NUM_MAX; 108 id = (png->pos_pings + i) % PING_NUM_MAX;
102 109
103 // ping_id = 0 means match any id 110 // ping_id = 0 means match any id
104 if ((ipp_eq(pings[id].ipp, ipp) || ipp.ip.i == 0) && (pings[id].id == ping_id || ping_id == 0)) { 111 if ((ipp_eq(png->pings[id].ipp, ipp) || ipp.ip.i == 0) && (png->pings[id].id == ping_id || ping_id == 0)) {
105 return true; 112 return true;
106 } 113 }
107 } 114 }
@@ -109,25 +116,25 @@ bool is_pinging(IP_Port ipp, uint64_t ping_id) // O(n) TODO: replace this with
109 return false; 116 return false;
110} 117}
111 118
112int send_ping_request(IP_Port ipp, clientid_t *client_id) 119int send_ping_request(void *ping, Net_Crypto *c, IP_Port ipp, clientid_t *client_id)
113{ 120{
114 pingreq_t pk; 121 pingreq_t pk;
115 int rc; 122 int rc;
116 uint64_t ping_id; 123 uint64_t ping_id;
117 124
118 if (is_pinging(ipp, 0) || id_eq(client_id, self_id)) 125 if (is_pinging(ping, ipp, 0) || id_eq(client_id, (clientid_t *)c->self_public_key))
119 return 1; 126 return 1;
120 127
121 // Generate random ping_id 128 // Generate random ping_id
122 ping_id = add_ping(ipp); 129 ping_id = add_ping(ping, ipp);
123 130
124 pk.magic = PACKET_PING_REQ; 131 pk.magic = PACKET_PING_REQ;
125 id_cpy(&pk.client_id, self_id); // Our pubkey 132 id_cpy(&pk.client_id, (clientid_t *)c->self_public_key); // Our pubkey
126 random_nonce((uint8_t *) &pk.nonce); // Generate random nonce 133 random_nonce((uint8_t *) &pk.nonce); // Generate random nonce
127 134
128 // Encrypt ping_id using recipient privkey 135 // Encrypt ping_id using recipient privkey
129 rc = encrypt_data((uint8_t *) client_id, 136 rc = encrypt_data((uint8_t *) client_id,
130 self_secret_key, 137 c->self_secret_key,
131 (uint8_t *) &pk.nonce, 138 (uint8_t *) &pk.nonce,
132 (uint8_t *) &ping_id, sizeof(ping_id), 139 (uint8_t *) &ping_id, sizeof(ping_id),
133 (uint8_t *) &pk.ping_id); 140 (uint8_t *) &pk.ping_id);
@@ -135,24 +142,24 @@ int send_ping_request(IP_Port ipp, clientid_t *client_id)
135 if (rc != sizeof(ping_id) + ENCRYPTION_PADDING) 142 if (rc != sizeof(ping_id) + ENCRYPTION_PADDING)
136 return 1; 143 return 1;
137 144
138 return sendpacket(ipp, (uint8_t *) &pk, sizeof(pk)); 145 return sendpacket(c->lossless_udp->net->sock, ipp, (uint8_t *) &pk, sizeof(pk));
139} 146}
140 147
141int send_ping_response(IP_Port ipp, clientid_t *client_id, uint64_t ping_id) 148int send_ping_response(Net_Crypto *c, IP_Port ipp, clientid_t *client_id, uint64_t ping_id)
142{ 149{
143 pingres_t pk; 150 pingres_t pk;
144 int rc; 151 int rc;
145 152
146 if (id_eq(client_id, self_id)) 153 if (id_eq(client_id, (clientid_t *)c->self_public_key))
147 return 1; 154 return 1;
148 155
149 pk.magic = PACKET_PING_RES; 156 pk.magic = PACKET_PING_RES;
150 id_cpy(&pk.client_id, self_id); // Our pubkey 157 id_cpy(&pk.client_id, (clientid_t *)c->self_public_key); // Our pubkey
151 random_nonce((uint8_t *) &pk.nonce); // Generate random nonce 158 random_nonce((uint8_t *) &pk.nonce); // Generate random nonce
152 159
153 // Encrypt ping_id using recipient privkey 160 // Encrypt ping_id using recipient privkey
154 rc = encrypt_data((uint8_t *) client_id, 161 rc = encrypt_data((uint8_t *) client_id,
155 self_secret_key, 162 c->self_secret_key,
156 (uint8_t *) &pk.nonce, 163 (uint8_t *) &pk.nonce,
157 (uint8_t *) &ping_id, sizeof(ping_id), 164 (uint8_t *) &ping_id, sizeof(ping_id),
158 (uint8_t *) &pk.ping_id); 165 (uint8_t *) &pk.ping_id);
@@ -160,21 +167,22 @@ int send_ping_response(IP_Port ipp, clientid_t *client_id, uint64_t ping_id)
160 if (rc != sizeof(ping_id) + ENCRYPTION_PADDING) 167 if (rc != sizeof(ping_id) + ENCRYPTION_PADDING)
161 return 1; 168 return 1;
162 169
163 return sendpacket(ipp, (uint8_t *) &pk, sizeof(pk)); 170 return sendpacket(c->lossless_udp->net->sock, ipp, (uint8_t *) &pk, sizeof(pk));
164} 171}
165 172
166int handle_ping_request(IP_Port source, uint8_t *packet, uint32_t length) 173int handle_ping_request(void *object, IP_Port source, uint8_t *packet, uint32_t length)
167{ 174{
175 DHT *dht = object;
168 pingreq_t *p = (pingreq_t *) packet; 176 pingreq_t *p = (pingreq_t *) packet;
169 int rc; 177 int rc;
170 uint64_t ping_id; 178 uint64_t ping_id;
171 179
172 if (length != sizeof(pingreq_t) || id_eq(&p->client_id, self_id)) 180 if (length != sizeof(pingreq_t) || id_eq(&p->client_id, (clientid_t *)dht->c->self_public_key))
173 return 1; 181 return 1;
174 182
175 // Decrypt ping_id 183 // Decrypt ping_id
176 rc = decrypt_data((uint8_t *) &p->client_id, 184 rc = decrypt_data((uint8_t *) &p->client_id,
177 self_secret_key, 185 dht->c->self_secret_key,
178 (uint8_t *) &p->nonce, 186 (uint8_t *) &p->nonce,
179 (uint8_t *) &p->ping_id, 187 (uint8_t *) &p->ping_id,
180 sizeof(ping_id) + ENCRYPTION_PADDING, 188 sizeof(ping_id) + ENCRYPTION_PADDING,
@@ -184,24 +192,25 @@ int handle_ping_request(IP_Port source, uint8_t *packet, uint32_t length)
184 return 1; 192 return 1;
185 193
186 // Send response 194 // Send response
187 send_ping_response(source, &p->client_id, ping_id); 195 send_ping_response(dht->c, source, &p->client_id, ping_id);
188 add_toping((uint8_t *) &p->client_id, source); 196 add_toping(dht, (uint8_t *) &p->client_id, source);
189 197
190 return 0; 198 return 0;
191} 199}
192 200
193int handle_ping_response(IP_Port source, uint8_t *packet, uint32_t length) 201int handle_ping_response(void *object, IP_Port source, uint8_t *packet, uint32_t length)
194{ 202{
203 DHT *dht = object;
195 pingres_t *p = (pingres_t *) packet; 204 pingres_t *p = (pingres_t *) packet;
196 int rc; 205 int rc;
197 uint64_t ping_id; 206 uint64_t ping_id;
198 207
199 if (length != sizeof(pingres_t) || id_eq(&p->client_id, self_id)) 208 if (length != sizeof(pingres_t) || id_eq(&p->client_id, (clientid_t *)dht->c->self_public_key))
200 return 1; 209 return 1;
201 210
202 // Decrypt ping_id 211 // Decrypt ping_id
203 rc = decrypt_data((uint8_t *) &p->client_id, 212 rc = decrypt_data((uint8_t *) &p->client_id,
204 self_secret_key, 213 dht->c->self_secret_key,
205 (uint8_t *) &p->nonce, 214 (uint8_t *) &p->nonce,
206 (uint8_t *) &p->ping_id, 215 (uint8_t *) &p->ping_id,
207 sizeof(ping_id) + ENCRYPTION_PADDING, 216 sizeof(ping_id) + ENCRYPTION_PADDING,
@@ -211,10 +220,10 @@ int handle_ping_response(IP_Port source, uint8_t *packet, uint32_t length)
211 return 1; 220 return 1;
212 221
213 // Make sure ping_id is correct 222 // Make sure ping_id is correct
214 if (!is_pinging(source, ping_id)) 223 if (!is_pinging(dht->ping, source, ping_id))
215 return 1; 224 return 1;
216 225
217 // Associate source ip with client_id 226 // Associate source ip with client_id
218 addto_lists(source, (uint8_t *) &p->client_id); 227 addto_lists(dht, source, (uint8_t *) &p->client_id);
219 return 0; 228 return 0;
220} 229}
diff --git a/core/ping.h b/core/ping.h
index 0c44874b..c04ec80e 100644
--- a/core/ping.h
+++ b/core/ping.h
@@ -7,10 +7,11 @@
7 7
8#include <stdbool.h> 8#include <stdbool.h>
9 9
10void init_ping(); 10void *new_ping(void);
11uint64_t add_ping(IP_Port ipp); 11void kill_ping(void *ping);
12bool is_pinging(IP_Port ipp, uint64_t ping_id); 12uint64_t add_ping(void *ping, IP_Port ipp);
13int send_ping_request(IP_Port ipp, clientid_t *client_id); 13bool is_pinging(void *ping, IP_Port ipp, uint64_t ping_id);
14int send_ping_response(IP_Port ipp, clientid_t *client_id, uint64_t ping_id); 14int send_ping_request(void *ping, Net_Crypto *c, IP_Port ipp, clientid_t *client_id);
15int handle_ping_request(IP_Port source, uint8_t *packet, uint32_t length); 15int send_ping_response(Net_Crypto *c, IP_Port ipp, clientid_t *client_id, uint64_t ping_id);
16int handle_ping_response(IP_Port source, uint8_t *packet, uint32_t length); 16int handle_ping_request(void *object, IP_Port source, uint8_t *packet, uint32_t length);
17int handle_ping_response(void *object, IP_Port source, uint8_t *packet, uint32_t length);
diff --git a/other/DHT_bootstrap.c b/other/DHT_bootstrap.c
index 299e030c..5d97b37a 100644
--- a/other/DHT_bootstrap.c
+++ b/other/DHT_bootstrap.c
@@ -44,7 +44,7 @@
44 44
45 45
46 46
47void manage_keys() 47void manage_keys(DHT *dht)
48{ 48{
49 const uint32_t KEYS_SIZE = crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; 49 const uint32_t KEYS_SIZE = crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES;
50 uint8_t keys[KEYS_SIZE]; 50 uint8_t keys[KEYS_SIZE];
@@ -60,12 +60,12 @@ void manage_keys()
60 exit(1); 60 exit(1);
61 } 61 }
62 62
63 load_keys(keys); 63 load_keys(dht->c, keys);
64 printf("Keys loaded successfully\n"); 64 printf("Keys loaded successfully\n");
65 } else { 65 } else {
66 //otherwise save new keys 66 //otherwise save new keys
67 new_keys(); 67 new_keys(dht->c);
68 save_keys(keys); 68 save_keys(dht->c, keys);
69 keys_file = fopen("key", "w"); 69 keys_file = fopen("key", "w");
70 70
71 if (fwrite(keys, sizeof(uint8_t), KEYS_SIZE, keys_file) != KEYS_SIZE) { 71 if (fwrite(keys, sizeof(uint8_t), KEYS_SIZE, keys_file) != KEYS_SIZE) {
@@ -81,7 +81,13 @@ void manage_keys()
81 81
82int main(int argc, char *argv[]) 82int main(int argc, char *argv[])
83{ 83{
84 manage_keys(); 84 //initialize networking
85 //bind to ip 0.0.0.0:PORT
86 IP ip;
87 ip.i = 0;
88 DHT *dht = new_DHT(new_net_crypto(new_networking(ip, PORT)));
89 init_cryptopackets(dht);
90 manage_keys(dht);
85 printf("Public key: "); 91 printf("Public key: ");
86 uint32_t i; 92 uint32_t i;
87 93
@@ -89,22 +95,17 @@ int main(int argc, char *argv[])
89 file = fopen("PUBLIC_ID.txt", "w"); 95 file = fopen("PUBLIC_ID.txt", "w");
90 96
91 for (i = 0; i < 32; i++) { 97 for (i = 0; i < 32; i++) {
92 if (self_public_key[i] < 16) 98 if (dht->c->self_public_key[i] < 16)
93 printf("0"); 99 printf("0");
94 100
95 printf("%hhX", self_public_key[i]); 101 printf("%hhX", dht->c->self_public_key[i]);
96 fprintf(file, "%hhX", self_public_key[i]); 102 fprintf(file, "%hhX", dht->c->self_public_key[i]);
97 } 103 }
98 104
99 fclose(file); 105 fclose(file);
100 106
101 printf("\n"); 107 printf("\n");
102 printf("Port: %u\n", PORT); 108 printf("Port: %u\n", PORT);
103 //initialize networking
104 //bind to ip 0.0.0.0:PORT
105 IP ip;
106 ip.i = 0;
107 init_networking(ip, PORT);
108 109
109 perror("Initialization"); 110 perror("Initialization");
110 111
@@ -114,28 +115,24 @@ int main(int argc, char *argv[])
114 bootstrap_info.ip.i = inet_addr(argv[1]); 115 bootstrap_info.ip.i = inet_addr(argv[1]);
115 bootstrap_info.port = htons(atoi(argv[2])); 116 bootstrap_info.port = htons(atoi(argv[2]));
116 uint8_t *bootstrap_key = hex_string_to_bin(argv[3]); 117 uint8_t *bootstrap_key = hex_string_to_bin(argv[3]);
117 DHT_bootstrap(bootstrap_info, bootstrap_key); 118 DHT_bootstrap(dht, bootstrap_info, bootstrap_key);
118 free(bootstrap_key); 119 free(bootstrap_key);
119 } 120 }
120 121
121 DHT_init();
122 friendreq_init();
123
124 int is_waiting_for_dht_connection = 1; 122 int is_waiting_for_dht_connection = 1;
125 123
126 while (1) { 124 while (1) {
127 if (is_waiting_for_dht_connection && DHT_isconnected()) { 125 if (is_waiting_for_dht_connection && DHT_isconnected(dht)) {
128 printf("Connected to other bootstrap server successfully.\n"); 126 printf("Connected to other bootstrap server successfully.\n");
129 is_waiting_for_dht_connection = 0; 127 is_waiting_for_dht_connection = 0;
130 } 128 }
131 129
132 doDHT(); 130 do_DHT(dht);
133 131
134 networking_poll(); 132 networking_poll(dht->c->lossless_udp->net);
135 133
136 c_sleep(1); 134 c_sleep(1);
137 } 135 }
138 136
139 shutdown_networking();
140 return 0; 137 return 0;
141} 138}
diff --git a/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c b/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c
index 896d6a69..81ac538b 100644
--- a/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c
+++ b/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c
@@ -77,7 +77,7 @@ and connect to them.
77returns 1 if the connection to the DHT is up 77returns 1 if the connection to the DHT is up
78returns -1 if all attempts failed 78returns -1 if all attempts failed
79*/ 79*/
80int connect_to_servers(struct server_info_s *info) 80int connect_to_servers(DHT *dht, struct server_info_s *info)
81{ 81{
82 int i; 82 int i;
83 int c; 83 int c;
@@ -86,7 +86,7 @@ int connect_to_servers(struct server_info_s *info)
86 if (info[i].valid) { 86 if (info[i].valid) {
87 /* Actual bootstrapping code goes here */ 87 /* Actual bootstrapping code goes here */
88 //puts("Calling DHT_bootstrap"); 88 //puts("Calling DHT_bootstrap");
89 DHT_bootstrap(info[i].conn, info[i].bs_pk); 89 DHT_bootstrap(dht, info[i].conn, info[i].bs_pk);
90 } 90 }
91 } 91 }
92 92
@@ -94,28 +94,28 @@ int connect_to_servers(struct server_info_s *info)
94 for (c = 0; c != 100; ++c) { 94 for (c = 0; c != 100; ++c) {
95 usleep(10000); 95 usleep(10000);
96 96
97 if (DHT_isconnected()) { 97 if (DHT_isconnected(dht)) {
98 //puts("Connected"); 98 //puts("Connected");
99 return 1; 99 return 1;
100 break; 100 break;
101 } 101 }
102 102
103 if (DHT_isconnected() == 0 && c == 99) { 103 if (DHT_isconnected(dht) == 0 && c == 99) {
104 //puts("Not connected"); 104 //puts("Not connected");
105 return -1; 105 return -1;
106 break; 106 break;
107 } 107 }
108 108
109 doDHT(); 109 do_DHT(dht);
110 110
111 networking_poll(); 111 networking_poll(dht->c->lossless_udp->net);
112 } 112 }
113 113
114 /* This probably never happens */ 114 /* This probably never happens */
115 return 0; 115 return 0;
116} 116}
117 117
118void manage_keys(char *keys_file) 118void manage_keys(DHT *dht, char *keys_file)
119{ 119{
120 const uint32_t KEYS_SIZE = crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; 120 const uint32_t KEYS_SIZE = crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES;
121 uint8_t keys[KEYS_SIZE]; 121 uint8_t keys[KEYS_SIZE];
@@ -134,13 +134,13 @@ void manage_keys(char *keys_file)
134 printf("Keys loaded successfully\n"); 134 printf("Keys loaded successfully\n");
135 } 135 }
136 136
137 load_keys(keys); 137 load_keys(dht->c, keys);
138 138
139 } else { 139 } else {
140 /* otherwise save new keys */ 140 /* otherwise save new keys */
141 /* Silly work-around to ignore any errors coming from new_keys() */ 141 /* Silly work-around to ignore any errors coming from new_keys() */
142 new_keys(); 142 new_keys(dht->c);
143 save_keys(keys); 143 save_keys(dht->c, keys);
144 keysf = fopen(keys_file, "w"); 144 keysf = fopen(keys_file, "w");
145 145
146 if (fwrite(keys, sizeof(uint8_t), KEYS_SIZE, keysf) != KEYS_SIZE) { 146 if (fwrite(keys, sizeof(uint8_t), KEYS_SIZE, keysf) != KEYS_SIZE) {
@@ -294,9 +294,14 @@ int main(int argc, char *argv[])
294 exit(EXIT_FAILURE); 294 exit(EXIT_FAILURE);
295 } 295 }
296 296
297 /* Read the config file */
298 server_conf = configure_server(argv[1]); 297 server_conf = configure_server(argv[1]);
299 298
299 /* initialize networking
300 bind to ip 0.0.0.0:PORT */
301 IP ip;
302 ip.i = 0;
303 DHT *dht = new_DHT(new_net_crypto(new_networking(ip, server_conf.port)));
304 /* Read the config file */
300 printf("PID file: %s\n", server_conf.pid_file); 305 printf("PID file: %s\n", server_conf.pid_file);
301 printf("Key file: %s\n", server_conf.keys_file); 306 printf("Key file: %s\n", server_conf.keys_file);
302 307
@@ -313,38 +318,32 @@ int main(int argc, char *argv[])
313 /* Manage the keys */ 318 /* Manage the keys */
314 /* for now, just ignore any errors after this call. */ 319 /* for now, just ignore any errors after this call. */
315 int tmperr = errno; 320 int tmperr = errno;
316 manage_keys(server_conf.keys_file); 321 manage_keys(dht, server_conf.keys_file);
317 errno = tmperr; 322 errno = tmperr;
318 323
324 init_cryptopackets(dht);
319 /* Public key */ 325 /* Public key */
320 int i; 326 int i;
321 printf("\nPublic Key: "); 327 printf("\nPublic Key: ");
322 328
323 for (i = 0; i < 32; ++i) { 329 for (i = 0; i < 32; ++i) {
324 uint8_t ln, hn; 330 uint8_t ln, hn;
325 ln = 0x0F & self_public_key[i]; 331 ln = 0x0F & dht->c->self_public_key[i];
326 hn = 0xF0 & self_public_key[i]; 332 hn = 0xF0 & dht->c->self_public_key[i];
327 hn = hn >> 4; 333 hn = hn >> 4;
328 printf("%X%X", hn, ln); 334 printf("%X%X", hn, ln);
329 } 335 }
330 336
331 printf("\n"); 337 printf("\n");
332 338
333 /* initialize networking
334 bind to ip 0.0.0.0:PORT */
335 IP ip;
336 ip.i = 0;
337 init_networking(ip, server_conf.port);
338
339 /* Bootstrap the DHT 339 /* Bootstrap the DHT
340 This one throws odd errors, too. Ignore. I assume they come 340 This one throws odd errors, too. Ignore. I assume they come
341 from somewhere in the core. */ 341 from somewhere in the core. */
342 DHT_init();
343 tmperr = errno; 342 tmperr = errno;
344 connect_to_servers(server_conf.info); 343 connect_to_servers(dht, server_conf.info);
345 errno = tmperr; 344 errno = tmperr;
346 345
347 if (!DHT_isconnected()) { 346 if (!DHT_isconnected(dht)) {
348 puts("Could not establish DHT connection. Check server settings.\n"); 347 puts("Could not establish DHT connection. Check server settings.\n");
349 exit(EXIT_FAILURE); 348 exit(EXIT_FAILURE);
350 } else { 349 } else {
@@ -404,13 +403,10 @@ int main(int argc, char *argv[])
404 close(STDIN_FILENO); 403 close(STDIN_FILENO);
405 close(STDERR_FILENO); 404 close(STDERR_FILENO);
406 405
407 /* Main loop */
408 friendreq_init();
409
410 while (1) { 406 while (1) {
411 doDHT(); 407 do_DHT(dht);
412 408
413 networking_poll(); 409 networking_poll(dht->c->lossless_udp->net);
414 usleep(10000); 410 usleep(10000);
415 } 411 }
416 412
diff --git a/core/timer.c b/other/unused/timer.c
index 29190921..29190921 100644
--- a/core/timer.c
+++ b/other/unused/timer.c
diff --git a/core/timer.h b/other/unused/timer.h
index 15491326..15491326 100644
--- a/core/timer.h
+++ b/other/unused/timer.h
diff --git a/testing/CMakeLists.txt b/testing/CMakeLists.txt
index 9e07135c..e3cdc838 100644
--- a/testing/CMakeLists.txt
+++ b/testing/CMakeLists.txt
@@ -9,7 +9,6 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Lossless_UDP_testclient.cmake)
9include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Lossless_UDP_testserver.cmake) 9include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Lossless_UDP_testserver.cmake)
10include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Messenger_test.cmake) 10include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Messenger_test.cmake)
11include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/crypto_speed_test.cmake) 11include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/crypto_speed_test.cmake)
12include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/timer_test.cmake)
13 12
14if(WIN32) 13if(WIN32)
15# include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/nTox_win32.cmake) 14# include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/nTox_win32.cmake)
diff --git a/testing/DHT_test.c b/testing/DHT_test.c
index 3883f3a7..8ab9157e 100644
--- a/testing/DHT_test.c
+++ b/testing/DHT_test.c
@@ -28,8 +28,8 @@
28 */ 28 */
29 29
30//#include "../core/network.h" 30//#include "../core/network.h"
31#include "../core/DHT.c" 31#include "../core/DHT.h"
32#include "../core/friend_requests.c" 32#include "../core/friend_requests.h"
33#include "misc_tools.h" 33#include "misc_tools.h"
34 34
35#include <string.h> 35#include <string.h>
@@ -48,7 +48,7 @@
48 48
49#define PORT 33445 49#define PORT 33445
50 50
51void print_clientlist() 51void print_clientlist(DHT *dht)
52{ 52{
53 uint32_t i, j; 53 uint32_t i, j;
54 IP_Port p_ip; 54 IP_Port p_ip;
@@ -58,34 +58,34 @@ void print_clientlist()
58 printf("ClientID: "); 58 printf("ClientID: ");
59 59
60 for (j = 0; j < 32; j++) { 60 for (j = 0; j < 32; j++) {
61 printf("%02hhX", close_clientlist[i].client_id[j]); 61 printf("%02hhX", dht->close_clientlist[i].client_id[j]);
62 } 62 }
63 63
64 p_ip = close_clientlist[i].ip_port; 64 p_ip = dht->close_clientlist[i].ip_port;
65 printf("\nIP: %u.%u.%u.%u Port: %u", p_ip.ip.c[0], p_ip.ip.c[1], p_ip.ip.c[2], p_ip.ip.c[3], ntohs(p_ip.port)); 65 printf("\nIP: %u.%u.%u.%u Port: %u", p_ip.ip.c[0], p_ip.ip.c[1], p_ip.ip.c[2], p_ip.ip.c[3], ntohs(p_ip.port));
66 printf("\nTimestamp: %llu", (long long unsigned int) close_clientlist[i].timestamp); 66 printf("\nTimestamp: %llu", (long long unsigned int) dht->close_clientlist[i].timestamp);
67 printf("\nLast pinged: %llu\n", (long long unsigned int) close_clientlist[i].last_pinged); 67 printf("\nLast pinged: %llu\n", (long long unsigned int) dht->close_clientlist[i].last_pinged);
68 p_ip = close_clientlist[i].ret_ip_port; 68 p_ip = dht->close_clientlist[i].ret_ip_port;
69 printf("OUR IP: %u.%u.%u.%u Port: %u\n", p_ip.ip.c[0], p_ip.ip.c[1], p_ip.ip.c[2], p_ip.ip.c[3], ntohs(p_ip.port)); 69 printf("OUR IP: %u.%u.%u.%u Port: %u\n", p_ip.ip.c[0], p_ip.ip.c[1], p_ip.ip.c[2], p_ip.ip.c[3], ntohs(p_ip.port));
70 printf("Timestamp: %llu\n", (long long unsigned int) close_clientlist[i].ret_timestamp); 70 printf("Timestamp: %llu\n", (long long unsigned int) dht->close_clientlist[i].ret_timestamp);
71 } 71 }
72} 72}
73 73
74void print_friendlist() 74void print_friendlist(DHT *dht)
75{ 75{
76 uint32_t i, j, k; 76 uint32_t i, j, k;
77 IP_Port p_ip; 77 IP_Port p_ip;
78 printf("_________________FRIENDS__________________________________\n"); 78 printf("_________________FRIENDS__________________________________\n");
79 79
80 for (k = 0; k < num_friends; k++) { 80 for (k = 0; k < dht->num_friends; k++) {
81 printf("FRIEND %u\n", k); 81 printf("FRIEND %u\n", k);
82 printf("ID: "); 82 printf("ID: ");
83 83
84 for (j = 0; j < 32; j++) { 84 for (j = 0; j < 32; j++) {
85 printf("%c", friends_list[k].client_id[j]); 85 printf("%c", dht->friends_list[k].client_id[j]);
86 } 86 }
87 87
88 p_ip = DHT_getfriendip(friends_list[k].client_id); 88 p_ip = DHT_getfriendip(dht, dht->friends_list[k].client_id);
89 printf("\nIP: %u.%u.%u.%u:%u", p_ip.ip.c[0], p_ip.ip.c[1], p_ip.ip.c[2], p_ip.ip.c[3], ntohs(p_ip.port)); 89 printf("\nIP: %u.%u.%u.%u:%u", p_ip.ip.c[0], p_ip.ip.c[1], p_ip.ip.c[2], p_ip.ip.c[3], ntohs(p_ip.port));
90 90
91 printf("\nCLIENTS IN LIST:\n\n"); 91 printf("\nCLIENTS IN LIST:\n\n");
@@ -94,19 +94,19 @@ void print_friendlist()
94 printf("ClientID: "); 94 printf("ClientID: ");
95 95
96 for (j = 0; j < 32; j++) { 96 for (j = 0; j < 32; j++) {
97 if (friends_list[k].client_list[i].client_id[j] < 16) 97 if (dht->friends_list[k].client_list[i].client_id[j] < 16)
98 printf("0"); 98 printf("0");
99 99
100 printf("%hhX", friends_list[k].client_list[i].client_id[j]); 100 printf("%hhX", dht->friends_list[k].client_list[i].client_id[j]);
101 } 101 }
102 102
103 p_ip = friends_list[k].client_list[i].ip_port; 103 p_ip = dht->friends_list[k].client_list[i].ip_port;
104 printf("\nIP: %u.%u.%u.%u:%u", p_ip.ip.c[0], p_ip.ip.c[1], p_ip.ip.c[2], p_ip.ip.c[3], ntohs(p_ip.port)); 104 printf("\nIP: %u.%u.%u.%u:%u", p_ip.ip.c[0], p_ip.ip.c[1], p_ip.ip.c[2], p_ip.ip.c[3], ntohs(p_ip.port));
105 printf("\nTimestamp: %llu", (long long unsigned int) friends_list[k].client_list[i].timestamp); 105 printf("\nTimestamp: %llu", (long long unsigned int) dht->friends_list[k].client_list[i].timestamp);
106 printf("\nLast pinged: %llu\n", (long long unsigned int) friends_list[k].client_list[i].last_pinged); 106 printf("\nLast pinged: %llu\n", (long long unsigned int) dht->friends_list[k].client_list[i].last_pinged);
107 p_ip = friends_list[k].client_list[i].ret_ip_port; 107 p_ip = dht->friends_list[k].client_list[i].ret_ip_port;
108 printf("ret IP: %u.%u.%u.%u:%u\n", p_ip.ip.c[0], p_ip.ip.c[1], p_ip.ip.c[2], p_ip.ip.c[3], ntohs(p_ip.port)); 108 printf("ret IP: %u.%u.%u.%u:%u\n", p_ip.ip.c[0], p_ip.ip.c[1], p_ip.ip.c[2], p_ip.ip.c[3], ntohs(p_ip.port));
109 printf("Timestamp: %llu\n", (long long unsigned int)friends_list[k].client_list[i].ret_timestamp); 109 printf("Timestamp: %llu\n", (long long unsigned int)dht->friends_list[k].client_list[i].ret_timestamp);
110 } 110 }
111 } 111 }
112} 112}
@@ -130,21 +130,28 @@ void printpacket(uint8_t *data, uint32_t length, IP_Port ip_port)
130int main(int argc, char *argv[]) 130int main(int argc, char *argv[])
131{ 131{
132 //memcpy(self_client_id, "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", 32); 132 //memcpy(self_client_id, "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", 32);
133 /* initialize networking */
134 /* bind to ip 0.0.0.0:PORT */
135 IP ip;
136 ip.i = 0;
137
138 DHT *dht = new_DHT(new_net_crypto(new_networking(ip, PORT)));
139 init_cryptopackets(dht);
133 140
134 if (argc < 4) { 141 if (argc < 4) {
135 printf("usage %s ip port public_key\n", argv[0]); 142 printf("usage %s ip port public_key\n", argv[0]);
136 exit(0); 143 exit(0);
137 } 144 }
138 145
139 new_keys(); 146 new_keys(dht->c);
140 printf("OUR ID: "); 147 printf("OUR ID: ");
141 uint32_t i; 148 uint32_t i;
142 149
143 for (i = 0; i < 32; i++) { 150 for (i = 0; i < 32; i++) {
144 if (self_public_key[i] < 16) 151 if (dht->c->self_public_key[i] < 16)
145 printf("0"); 152 printf("0");
146 153
147 printf("%hhX", self_public_key[i]); 154 printf("%hhX", dht->c->self_public_key[i]);
148 } 155 }
149 156
150 char temp_id[128]; 157 char temp_id[128];
@@ -153,13 +160,7 @@ int main(int argc, char *argv[])
153 if (scanf("%s", temp_id) != 1) 160 if (scanf("%s", temp_id) != 1)
154 exit(0); 161 exit(0);
155 162
156 DHT_addfriend(hex_string_to_bin(temp_id)); 163 DHT_addfriend(dht, hex_string_to_bin(temp_id));
157
158 /* initialize networking */
159 /* bind to ip 0.0.0.0:PORT */
160 IP ip;
161 ip.i = 0;
162 init_networking(ip, PORT);
163 164
164 165
165 perror("Initialization"); 166 perror("Initialization");
@@ -170,7 +171,7 @@ int main(int argc, char *argv[])
170 * bootstrap_ip_port.ip.c[2] = 0; 171 * bootstrap_ip_port.ip.c[2] = 0;
171 * bootstrap_ip_port.ip.c[3] = 1; */ 172 * bootstrap_ip_port.ip.c[3] = 1; */
172 bootstrap_ip_port.ip.i = inet_addr(argv[1]); 173 bootstrap_ip_port.ip.i = inet_addr(argv[1]);
173 DHT_bootstrap(bootstrap_ip_port, hex_string_to_bin(argv[3])); 174 DHT_bootstrap(dht, bootstrap_ip_port, hex_string_to_bin(argv[3]));
174 175
175 /* 176 /*
176 IP_Port ip_port; 177 IP_Port ip_port;
@@ -178,12 +179,9 @@ int main(int argc, char *argv[])
178 uint32_t length; 179 uint32_t length;
179 */ 180 */
180 181
181 DHT_init();
182 friendreq_init();
183
184 while (1) { 182 while (1) {
185 183
186 doDHT(); 184 do_DHT(dht);
187 185
188 /* slvrTODO: 186 /* slvrTODO:
189 while(receivepacket(&ip_port, data, &length) != -1) { 187 while(receivepacket(&ip_port, data, &length) != -1) {
@@ -195,13 +193,12 @@ int main(int argc, char *argv[])
195 } 193 }
196 } 194 }
197 */ 195 */
198 networking_poll(); 196 networking_poll(dht->c->lossless_udp->net);
199 197
200 print_clientlist(); 198 print_clientlist(dht);
201 print_friendlist(); 199 print_friendlist(dht);
202 c_sleep(300); 200 c_sleep(300);
203 } 201 }
204 202
205 shutdown_networking();
206 return 0; 203 return 0;
207} 204}
diff --git a/testing/Lossless_UDP_testclient.c b/testing/Lossless_UDP_testclient.c
index 575be2bd..09e9e0a3 100644
--- a/testing/Lossless_UDP_testclient.c
+++ b/testing/Lossless_UDP_testclient.c
@@ -122,29 +122,29 @@ void printconnection(int connection_id)
122 122
123/*( receive packets and send them to the packethandler */ 123/*( receive packets and send them to the packethandler */
124/*run doLossless_UDP(); */ 124/*run doLossless_UDP(); */
125void Lossless_UDP() 125//void Lossless_UDP()
126{ 126//{
127 /* IP_Port ip_port; 127/* IP_Port ip_port;
128 uint8_t data[MAX_UDP_PACKET_SIZE]; 128 uint8_t data[MAX_UDP_PACKET_SIZE];
129 uint32_t length; 129 uint32_t length;
130 while (receivepacket(&ip_port, data, &length) != -1) { 130 while (receivepacket(&ip_port, data, &length) != -1) {
131 printf("packet with length: %u\n", length); */ 131 printf("packet with length: %u\n", length); */
132 /* if(rand() % 3 != 1)//add packet loss 132/* if(rand() % 3 != 1)//add packet loss
133 { */ 133 { */
134 /* 134/*
135 if (LosslessUDP_handlepacket(data, length, ip_port)) 135 if (LosslessUDP_handlepacket(data, length, ip_port))
136 printpacket(data, length, ip_port); 136 printpacket(data, length, ip_port);
137 else 137 else
138 printf("Received handled packet with length: %u\n", length); //printconnection(0); */ 138 printf("Received handled packet with length: %u\n", length); //printconnection(0); */
139
140 /* } */
141 /* }*/
142
143 networking_poll();
144
145 doLossless_UDP();
146 139
147} 140/* } */
141/* }*/
142
143//networking_poll();
144
145//doLossless_UDP();
146
147//}
148 148
149int main(int argc, char *argv[]) 149int main(int argc, char *argv[])
150{ 150{
@@ -166,25 +166,26 @@ int main(int argc, char *argv[])
166 /* bind to ip 0.0.0.0:PORT */ 166 /* bind to ip 0.0.0.0:PORT */
167 IP ip; 167 IP ip;
168 ip.i = 0; 168 ip.i = 0;
169 init_networking(ip, PORT); 169 Lossless_UDP *ludp = new_lossless_udp(new_networking(ip, PORT));
170 perror("Initialization"); 170 perror("Initialization");
171 IP_Port serverip; 171 IP_Port serverip;
172 serverip.ip.i = inet_addr(argv[1]); 172 serverip.ip.i = inet_addr(argv[1]);
173 serverip.port = htons(atoi(argv[2])); 173 serverip.port = htons(atoi(argv[2]));
174 printip(serverip); 174 printip(serverip);
175 int connection = new_connection(serverip); 175 int connection = new_connection(ludp, serverip);
176 uint64_t timer = current_time(); 176 uint64_t timer = current_time();
177 177
178 while (1) { 178 while (1) {
179 /* printconnection(connection); */ 179 /* printconnection(connection); */
180 Lossless_UDP(); 180 networking_poll(ludp->net);
181 do_lossless_udp(ludp);
181 182
182 if (is_connected(connection) == 3) { 183 if (is_connected(ludp, connection) == 3) {
183 printf("Connecting took: %llu us\n", (unsigned long long)(current_time() - timer)); 184 printf("Connecting took: %llu us\n", (unsigned long long)(current_time() - timer));
184 break; 185 break;
185 } 186 }
186 187
187 if (is_connected(connection) == 0) { 188 if (is_connected(ludp, connection) == 0) {
188 printf("Connection timeout after: %llu us\n", (unsigned long long)(current_time() - timer)); 189 printf("Connection timeout after: %llu us\n", (unsigned long long)(current_time() - timer));
189 return 1; 190 return 1;
190 } 191 }
@@ -194,25 +195,25 @@ int main(int argc, char *argv[])
194 195
195 timer = current_time(); 196 timer = current_time();
196 197
197 LosslessUDP_init();
198 198
199 /*read first part of file */ 199 /*read first part of file */
200 read = fread(buffer, 1, 512, file); 200 read = fread(buffer, 1, 512, file);
201 201
202 while (1) { 202 while (1) {
203 /* printconnection(connection); */ 203 /* printconnection(connection); */
204 Lossless_UDP(); 204 networking_poll(ludp->net);
205 do_lossless_udp(ludp);
205 206
206 if (is_connected(connection) == 3) { 207 if (is_connected(ludp, connection) == 3) {
207 208
208 if (write_packet(connection, buffer, read)) { 209 if (write_packet(ludp, connection, buffer, read)) {
209 /* printf("Wrote data.\n"); */ 210 /* printf("Wrote data.\n"); */
210 read = fread(buffer, 1, 512, file); 211 read = fread(buffer, 1, 512, file);
211 212
212 } 213 }
213 214
214 /* printf("%u\n", sendqueue(connection)); */ 215 /* printf("%u\n", sendqueue(connection)); */
215 if (sendqueue(connection) == 0) { 216 if (sendqueue(ludp, connection) == 0) {
216 if (read == 0) { 217 if (read == 0) {
217 printf("Sent file successfully in: %llu us\n", (unsigned long long)(current_time() - timer)); 218 printf("Sent file successfully in: %llu us\n", (unsigned long long)(current_time() - timer));
218 break; 219 break;
diff --git a/testing/Lossless_UDP_testserver.c b/testing/Lossless_UDP_testserver.c
index dec50d7f..a82b787a 100644
--- a/testing/Lossless_UDP_testserver.c
+++ b/testing/Lossless_UDP_testserver.c
@@ -118,27 +118,27 @@ void printconnection(int connection_id)
118 118
119/* receive packets and send them to the packethandler 119/* receive packets and send them to the packethandler
120 * run doLossless_UDP(); */ 120 * run doLossless_UDP(); */
121void Lossless_UDP() 121//void Lossless_UDP()
122{ 122//{
123// IP_Port ip_port; 123// IP_Port ip_port;
124// uint8_t data[MAX_UDP_PACKET_SIZE]; 124// uint8_t data[MAX_UDP_PACKET_SIZE];
125// uint32_t length; 125// uint32_t length;
126// while (receivepacket(&ip_port, data, &length) != -1) { 126// while (receivepacket(&ip_port, data, &length) != -1) {
127 //if(rand() % 3 != 1)//add packet loss 127//if(rand() % 3 != 1)//add packet loss
128 //{ 128//{
129// if (LosslessUDP_handlepacket(data, length, ip_port)) { 129// if (LosslessUDP_handlepacket(data, length, ip_port)) {
130// printpacket(data, length, ip_port); 130// printpacket(data, length, ip_port);
131// } else { 131// } else {
132 //printconnection(0); 132//printconnection(0);
133// printf("Received handled packet with length: %u\n", length); 133// printf("Received handled packet with length: %u\n", length);
134// } 134// }
135 //} 135//}
136// } 136// }
137 137
138 networking_poll(); 138// networking_poll();
139 139
140 doLossless_UDP(); 140//doLossless_UDP();
141} 141//}
142 142
143 143
144int main(int argc, char *argv[]) 144int main(int argc, char *argv[])
@@ -161,20 +161,19 @@ int main(int argc, char *argv[])
161 //bind to ip 0.0.0.0:PORT 161 //bind to ip 0.0.0.0:PORT
162 IP ip; 162 IP ip;
163 ip.i = 0; 163 ip.i = 0;
164 init_networking(ip, PORT); 164 Lossless_UDP *ludp = new_lossless_udp(new_networking(ip, PORT));
165 perror("Initialization"); 165 perror("Initialization");
166 166
167 int connection; 167 int connection;
168 uint64_t timer = current_time(); 168 uint64_t timer = current_time();
169 169
170 LosslessUDP_init();
171
172 while (1) { 170 while (1) {
173 Lossless_UDP(); 171 networking_poll(ludp->net);
174 connection = incoming_connection(); 172 do_lossless_udp(ludp);
173 connection = incoming_connection(ludp);
175 174
176 if (connection != -1) { 175 if (connection != -1) {
177 if (is_connected(connection) == 2) { 176 if (is_connected(ludp, connection) == 2) {
178 printf("Received the connection.\n"); 177 printf("Received the connection.\n");
179 178
180 } 179 }
@@ -189,11 +188,12 @@ int main(int argc, char *argv[])
189 188
190 while (1) { 189 while (1) {
191 //printconnection(0); 190 //printconnection(0);
192 Lossless_UDP(); 191 networking_poll(ludp->net);
192 do_lossless_udp(ludp);
193 193
194 if (is_connected(connection) >= 2) { 194 if (is_connected(ludp, connection) >= 2) {
195 kill_connection_in(connection, 3000000); 195 kill_connection_in(ludp, connection, 3000000);
196 read = read_packet(connection, buffer); 196 read = read_packet(ludp, connection, buffer);
197 197
198 if (read != 0) { 198 if (read != 0) {
199 // printf("Received data.\n"); 199 // printf("Received data.\n");
@@ -202,7 +202,7 @@ int main(int argc, char *argv[])
202 } 202 }
203 } 203 }
204 204
205 if (is_connected(connection) == 4) { 205 if (is_connected(ludp, connection) == 4) {
206 printf("Connecting Lost after: %llu us\n", (unsigned long long)(current_time() - timer)); 206 printf("Connecting Lost after: %llu us\n", (unsigned long long)(current_time() - timer));
207 fclose(file); 207 fclose(file);
208 return 1; 208 return 1;
diff --git a/testing/Messenger_test.c b/testing/Messenger_test.c
index f8685b39..c76584d7 100644
--- a/testing/Messenger_test.c
+++ b/testing/Messenger_test.c
@@ -48,6 +48,7 @@
48#include <unistd.h> 48#include <unistd.h>
49#include <arpa/inet.h> 49#include <arpa/inet.h>
50#define c_sleep(x) usleep(1000*x) 50#define c_sleep(x) usleep(1000*x)
51#define PORT 33445
51 52
52#endif 53#endif
53 54
@@ -106,7 +107,7 @@ int main(int argc, char *argv[])
106 IP_Port bootstrap_ip_port; 107 IP_Port bootstrap_ip_port;
107 bootstrap_ip_port.port = htons(atoi(argv[2])); 108 bootstrap_ip_port.port = htons(atoi(argv[2]));
108 bootstrap_ip_port.ip.i = inet_addr(argv[1]); 109 bootstrap_ip_port.ip.i = inet_addr(argv[1]);
109 DHT_bootstrap(bootstrap_ip_port, hex_string_to_bin(argv[3])); 110 DHT_bootstrap(m->dht, bootstrap_ip_port, hex_string_to_bin(argv[3]));
110 } else { 111 } else {
111 FILE *file = fopen(argv[1], "rb"); 112 FILE *file = fopen(argv[1], "rb");
112 113
diff --git a/testing/cmake/timer_test.cmake b/testing/cmake/timer_test.cmake
deleted file mode 100644
index a5f8c5ec..00000000
--- a/testing/cmake/timer_test.cmake
+++ /dev/null
@@ -1,9 +0,0 @@
1cmake_minimum_required(VERSION 2.6.0)
2project(timer_test C)
3
4set(exe_name timer_test)
5
6add_executable(${exe_name}
7 timer_test.c)
8
9linkCoreLibraries(${exe_name})
diff --git a/testing/nTox.c b/testing/nTox.c
index 8813f305..a476cc19 100644
--- a/testing/nTox.c
+++ b/testing/nTox.c
@@ -521,12 +521,12 @@ int main(int argc, char *argv[])
521 exit(1); 521 exit(1);
522 522
523 unsigned char *binary_string = hex_string_to_bin(argv[3]); 523 unsigned char *binary_string = hex_string_to_bin(argv[3]);
524 DHT_bootstrap(bootstrap_ip_port, binary_string); 524 DHT_bootstrap(m->dht, bootstrap_ip_port, binary_string);
525 free(binary_string); 525 free(binary_string);
526 nodelay(stdscr, TRUE); 526 nodelay(stdscr, TRUE);
527 527
528 while (true) { 528 while (true) {
529 if (on == 0 && DHT_isconnected()) { 529 if (on == 0 && DHT_isconnected(m->dht)) {
530 new_lines("[i] connected to DHT\n[i] define username with /n"); 530 new_lines("[i] connected to DHT\n[i] define username with /n");
531 on = 1; 531 on = 1;
532 } 532 }
diff --git a/testing/timer_test.c b/testing/timer_test.c
deleted file mode 100644
index f47d4878..00000000
--- a/testing/timer_test.c
+++ /dev/null
@@ -1,68 +0,0 @@
1#include "../core/timer.h"
2#include <stdio.h>
3
4#ifdef WINDOWS
5#include <windows.h>
6#else
7#include <unistd.h>
8#endif
9
10void mssleep(int ms)
11{
12#ifdef WINDOWS
13 Sleep(ms);
14#else
15 usleep(ms * 1000);
16#endif
17}
18
19int callback(timer *t, void *arg)
20{
21 printf("%s\n", (char *)arg);
22 return 1;
23}
24
25int repeating(timer *t, void *arg)
26{
27 printf("%s\n", (char *)arg);
28 timer_start(t, 3);
29 return 0;
30}
31
32extern void timer_debug_print();
33
34int main(int argc, char **argv)
35{
36 timer_init();
37 timer_debug_print();
38
39 timer *t = new_timer();
40 timer_setup(t, &callback, "Long setup method, 4 seconds");
41 timer_start(t, 4);
42 timer_debug_print();
43
44 timer_single(&repeating, (void *)"This repeats every 3 seconds", 3);
45 timer_debug_print();
46
47 timer_single(&callback, "Short method, 4 seconds", 4);
48 timer_debug_print();
49
50 timer_single(&callback, "1 second", 1);
51 timer_debug_print();
52
53 timer_single(&callback, "15 seconds", 15);
54 timer_debug_print();
55
56 timer_single(&callback, "10 seconds", 10);
57 timer_debug_print();
58
59 timer_us(&callback, "100000us", 100000);
60 timer_us(&callback, "13s", 13 * US_PER_SECOND);
61
62 while (true) {
63 timer_poll();
64 mssleep(10);
65 }
66
67 return 0;
68}
diff --git a/testing/toxic/chat.c b/testing/toxic/chat.c
index 57404a59..c7979843 100644
--- a/testing/toxic/chat.c
+++ b/testing/toxic/chat.c
@@ -123,7 +123,7 @@ static void chat_onStatusChange(ToxWindow *self, int num, uint8_t *status, uint1
123 123
124 status[len - 1] = '\0'; 124 status[len - 1] = '\0';
125 fix_name(status); 125 fix_name(status);
126 126
127 wattron(ctx->history, COLOR_PAIR(3)); 127 wattron(ctx->history, COLOR_PAIR(3));
128 wprintw(ctx->history, "* Your partner changed status to '%s'\n", status); 128 wprintw(ctx->history, "* Your partner changed status to '%s'\n", status);
129 wattroff(ctx->history, COLOR_PAIR(3)); 129 wattroff(ctx->history, COLOR_PAIR(3));
@@ -342,7 +342,7 @@ void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd)
342 wprintw(ctx->history, "Invalid command.\n"); 342 wprintw(ctx->history, "Invalid command.\n");
343} 343}
344 344
345static void chat_onDraw(ToxWindow *self) 345static void chat_onDraw(ToxWindow *self, Messenger *m)
346{ 346{
347 curs_set(1); 347 curs_set(1);
348 int x, y; 348 int x, y;
diff --git a/testing/toxic/dhtstatus.c b/testing/toxic/dhtstatus.c
index a11dc616..6c9f2a80 100644
--- a/testing/toxic/dhtstatus.c
+++ b/testing/toxic/dhtstatus.c
@@ -34,9 +34,9 @@ static void dhtstatus_onKey(ToxWindow *self, Messenger *m, int key)
34 } 34 }
35} 35}
36 36
37static void dhtstatus_onDraw(ToxWindow *self) 37static void dhtstatus_onDraw(ToxWindow *self, Messenger *m)
38{ 38{
39 Client_data *close_clientlist = DHT_get_close_list(); 39 Client_data *close_clientlist = DHT_get_close_list(m->dht);
40 curs_set(0); 40 curs_set(0);
41 werase(self->window); 41 werase(self->window);
42 42
diff --git a/testing/toxic/friendlist.c b/testing/toxic/friendlist.c
index 0a58bc54..2e46f124 100644
--- a/testing/toxic/friendlist.c
+++ b/testing/toxic/friendlist.c
@@ -102,7 +102,7 @@ static void friendlist_onKey(ToxWindow *self, Messenger *m, int key)
102 } 102 }
103} 103}
104 104
105static void friendlist_onDraw(ToxWindow *self) 105static void friendlist_onDraw(ToxWindow *self, Messenger *m)
106{ 106{
107 curs_set(0); 107 curs_set(0);
108 werase(self->window); 108 werase(self->window);
diff --git a/testing/toxic/main.c b/testing/toxic/main.c
index 9abe8de4..e5525e94 100644
--- a/testing/toxic/main.c
+++ b/testing/toxic/main.c
@@ -90,11 +90,11 @@ static Messenger *init_tox()
90#define MAXSERVERS 50 90#define MAXSERVERS 50
91 91
92/* Connects to a random DHT server listed in the DHTservers file */ 92/* Connects to a random DHT server listed in the DHTservers file */
93int init_connection(void) 93int init_connection(Messenger *m)
94{ 94{
95 FILE *fp = NULL; 95 FILE *fp = NULL;
96 96
97 if (DHT_isconnected()) 97 if (DHT_isconnected(m->dht))
98 return 0; 98 return 0;
99 99
100 fp = fopen(SRVLIST_FILE, "r"); 100 fp = fopen(SRVLIST_FILE, "r");
@@ -135,7 +135,7 @@ int init_connection(void)
135 135
136 dht.ip.i = resolved_address; 136 dht.ip.i = resolved_address;
137 unsigned char *binary_string = hex_string_to_bin(key); 137 unsigned char *binary_string = hex_string_to_bin(key);
138 DHT_bootstrap(dht, binary_string); 138 DHT_bootstrap(m->dht, dht, binary_string);
139 free(binary_string); 139 free(binary_string);
140 return 0; 140 return 0;
141} 141}
@@ -146,18 +146,18 @@ static void do_tox(Messenger *m, ToxWindow *prompt)
146 static int conn_err = 0; 146 static int conn_err = 0;
147 static bool dht_on = false; 147 static bool dht_on = false;
148 148
149 if (!dht_on && !DHT_isconnected() && !(conn_try++ % 100)) { 149 if (!dht_on && !DHT_isconnected(m->dht) && !(conn_try++ % 100)) {
150 if (!conn_err) { 150 if (!conn_err) {
151 conn_err = init_connection(); 151 conn_err = init_connection(m);
152 wprintw(prompt->window, "\nEstablishing connection...\n"); 152 wprintw(prompt->window, "\nEstablishing connection...\n");
153 153
154 if (conn_err) 154 if (conn_err)
155 wprintw(prompt->window, "\nAuto-connect failed with error code %d\n", conn_err); 155 wprintw(prompt->window, "\nAuto-connect failed with error code %d\n", conn_err);
156 } 156 }
157 } else if (!dht_on && DHT_isconnected()) { 157 } else if (!dht_on && DHT_isconnected(m->dht)) {
158 dht_on = true; 158 dht_on = true;
159 wprintw(prompt->window, "\nDHT connected.\n"); 159 wprintw(prompt->window, "\nDHT connected.\n");
160 } else if (dht_on && !DHT_isconnected()) { 160 } else if (dht_on && !DHT_isconnected(m->dht)) {
161 dht_on = false; 161 dht_on = false;
162 wprintw(prompt->window, "\nDHT disconnected. Attempting to reconnect.\n"); 162 wprintw(prompt->window, "\nDHT disconnected. Attempting to reconnect.\n");
163 } 163 }
@@ -297,7 +297,7 @@ int main(int argc, char *argv[])
297 strcpy(DATA_FILE, user_config_dir); 297 strcpy(DATA_FILE, user_config_dir);
298 strcat(DATA_FILE, CONFIGDIR); 298 strcat(DATA_FILE, CONFIGDIR);
299 strcat(DATA_FILE, "data"); 299 strcat(DATA_FILE, "data");
300 300
301 SRVLIST_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("DHTservers") + 1); 301 SRVLIST_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("DHTservers") + 1);
302 strcpy(SRVLIST_FILE, user_config_dir); 302 strcpy(SRVLIST_FILE, user_config_dir);
303 strcat(SRVLIST_FILE, CONFIGDIR); 303 strcat(SRVLIST_FILE, CONFIGDIR);
diff --git a/testing/toxic/prompt.c b/testing/toxic/prompt.c
index 81f00bce..e194a90e 100644
--- a/testing/toxic/prompt.c
+++ b/testing/toxic/prompt.c
@@ -204,7 +204,7 @@ void cmd_connect(ToxWindow *self, Messenger *m, char **args)
204 204
205 dht.ip.i = resolved_address; 205 dht.ip.i = resolved_address;
206 unsigned char *binary_string = hex_string_to_bin(key); 206 unsigned char *binary_string = hex_string_to_bin(key);
207 DHT_bootstrap(dht, binary_string); 207 DHT_bootstrap(m->dht, dht, binary_string);
208 free(binary_string); 208 free(binary_string);
209} 209}
210 210
@@ -365,7 +365,9 @@ static void execute(ToxWindow *self, Messenger *m, char *u_cmd)
365 cmd[i] = '\0'; 365 cmd[i] = '\0';
366 366
367 int j = i; 367 int j = i;
368
368 while (++j < MAX_STR_SIZE && isspace(cmd[j])); 369 while (++j < MAX_STR_SIZE && isspace(cmd[j]));
370
369 i = j - 1; 371 i = j - 1;
370 372
371 numargs++; 373 numargs++;
@@ -460,7 +462,7 @@ static void prompt_onKey(ToxWindow *self, Messenger *m, int key)
460 } 462 }
461} 463}
462 464
463static void prompt_onDraw(ToxWindow *self) 465static void prompt_onDraw(ToxWindow *self, Messenger *m)
464{ 466{
465 curs_set(1); 467 curs_set(1);
466 int x, y; 468 int x, y;
diff --git a/testing/toxic/windows.c b/testing/toxic/windows.c
index c0ff3026..8fdf4e19 100644
--- a/testing/toxic/windows.c
+++ b/testing/toxic/windows.c
@@ -88,23 +88,25 @@ int add_window(Messenger *m, ToxWindow w)
88{ 88{
89 if (LINES < 2) 89 if (LINES < 2)
90 return -1; 90 return -1;
91 91
92 int i; 92 int i;
93 for(i = 0; i < MAX_WINDOWS_NUM; i++) { 93
94 if (windows[i].window) 94 for (i = 0; i < MAX_WINDOWS_NUM; i++) {
95 if (windows[i].window)
95 continue; 96 continue;
96 97
97 w.window = newwin(LINES - 2, COLS, 0, 0); 98 w.window = newwin(LINES - 2, COLS, 0, 0);
99
98 if (w.window == NULL) 100 if (w.window == NULL)
99 return -1; 101 return -1;
100 102
101 windows[i] = w; 103 windows[i] = w;
102 w.onInit(&w, m); 104 w.onInit(&w, m);
103 105
104 active_window = windows+i; 106 active_window = windows + i;
105 return i; 107 return i;
106 } 108 }
107 109
108 return -1; 110 return -1;
109} 111}
110 112
@@ -113,8 +115,10 @@ void del_window(ToxWindow *w)
113{ 115{
114 active_window = windows; // Go to prompt screen 116 active_window = windows; // Go to prompt screen
115 delwin(w->window); 117 delwin(w->window);
118
116 if (w->x) 119 if (w->x)
117 free(w->x); 120 free(w->x);
121
118 w->window = NULL; 122 w->window = NULL;
119 memset(w, 0, sizeof(ToxWindow)); 123 memset(w, 0, sizeof(ToxWindow));
120 clear(); 124 clear();
@@ -124,19 +128,19 @@ void del_window(ToxWindow *w)
124/* Shows next window when tab or back-tab is pressed */ 128/* Shows next window when tab or back-tab is pressed */
125void set_next_window(int ch) 129void set_next_window(int ch)
126{ 130{
127 ToxWindow *end = windows+MAX_WINDOWS_NUM-1; 131 ToxWindow *end = windows + MAX_WINDOWS_NUM - 1;
128 ToxWindow *inf = active_window; 132 ToxWindow *inf = active_window;
129 while(true) { 133
134 while (true) {
130 if (ch == '\t') { 135 if (ch == '\t') {
131 if (++active_window > end) 136 if (++active_window > end)
132 active_window = windows; 137 active_window = windows;
133 } else 138 } else if (--active_window < windows)
134 if (--active_window < windows) 139 active_window = end;
135 active_window = end; 140
136
137 if (active_window->window) 141 if (active_window->window)
138 return; 142 return;
139 143
140 if (active_window == inf) { // infinite loop check 144 if (active_window == inf) { // infinite loop check
141 endwin(); 145 endwin();
142 exit(2); 146 exit(2);
@@ -148,14 +152,14 @@ void set_active_window(int index)
148{ 152{
149 if (index < 0 || index >= MAX_WINDOWS_NUM) 153 if (index < 0 || index >= MAX_WINDOWS_NUM)
150 return; 154 return;
151 155
152 active_window = windows+index; 156 active_window = windows + index;
153} 157}
154 158
155ToxWindow *init_windows() 159ToxWindow *init_windows()
156{ 160{
157 int n_prompt = add_window(m, new_prompt()); 161 int n_prompt = add_window(m, new_prompt());
158 162
159 if (n_prompt == -1 163 if (n_prompt == -1
160 || add_window(m, new_friendlist()) == -1 164 || add_window(m, new_friendlist()) == -1
161 || add_window(m, new_dhtstatus()) == -1) { 165 || add_window(m, new_dhtstatus()) == -1) {
@@ -166,7 +170,7 @@ ToxWindow *init_windows()
166 170
167 prompt = &windows[n_prompt]; 171 prompt = &windows[n_prompt];
168 active_window = prompt; 172 active_window = prompt;
169 173
170 return prompt; 174 return prompt;
171} 175}
172 176
@@ -189,7 +193,7 @@ static void draw_bar()
189 193
190 for (i = 0; i < (MAX_WINDOWS_NUM); ++i) { 194 for (i = 0; i < (MAX_WINDOWS_NUM); ++i) {
191 if (windows[i].window) { 195 if (windows[i].window) {
192 if (windows+i == active_window) 196 if (windows + i == active_window)
193 attron(A_BOLD); 197 attron(A_BOLD);
194 198
195 odd = (odd + 1) % blinkrate; 199 odd = (odd + 1) % blinkrate;
@@ -197,13 +201,13 @@ static void draw_bar()
197 if (windows[i].blink && (odd < (blinkrate / 2))) 201 if (windows[i].blink && (odd < (blinkrate / 2)))
198 attron(COLOR_PAIR(3)); 202 attron(COLOR_PAIR(3));
199 203
200 clrtoeol(); 204 clrtoeol();
201 printw(" %s", windows[i].title); 205 printw(" %s", windows[i].title);
202 206
203 if (windows[i].blink && (odd < (blinkrate / 2))) 207 if (windows[i].blink && (odd < (blinkrate / 2)))
204 attroff(COLOR_PAIR(3)); 208 attroff(COLOR_PAIR(3));
205 209
206 if (windows+i == active_window) { 210 if (windows + i == active_window) {
207 attroff(A_BOLD); 211 attroff(A_BOLD);
208 } 212 }
209 } 213 }
@@ -225,7 +229,7 @@ void draw_active_window(Messenger *m)
225 prepare_window(a->window); 229 prepare_window(a->window);
226 a->blink = false; 230 a->blink = false;
227 draw_bar(); 231 draw_bar();
228 a->onDraw(a); 232 a->onDraw(a, m);
229 233
230 /* Handle input */ 234 /* Handle input */
231 int ch = getch(); 235 int ch = getch();
diff --git a/testing/toxic/windows.h b/testing/toxic/windows.h
index be5557e9..86917dbe 100644
--- a/testing/toxic/windows.h
+++ b/testing/toxic/windows.h
@@ -24,7 +24,7 @@ typedef struct ToxWindow_ ToxWindow;
24 24
25struct ToxWindow_ { 25struct ToxWindow_ {
26 void(*onKey)(ToxWindow *, Messenger *, int); 26 void(*onKey)(ToxWindow *, Messenger *, int);
27 void(*onDraw)(ToxWindow *); 27 void(*onDraw)(ToxWindow *, Messenger *);
28 void(*onInit)(ToxWindow *, Messenger *); 28 void(*onInit)(ToxWindow *, Messenger *);
29 void(*onFriendRequest)(ToxWindow *, uint8_t *, uint8_t *, uint16_t); 29 void(*onFriendRequest)(ToxWindow *, uint8_t *, uint8_t *, uint16_t);
30 void(*onMessage)(ToxWindow *, Messenger *, int, uint8_t *, uint16_t); 30 void(*onMessage)(ToxWindow *, Messenger *, int, uint8_t *, uint16_t);