summaryrefslogtreecommitdiff
path: root/toxcore
diff options
context:
space:
mode:
Diffstat (limited to 'toxcore')
-rw-r--r--toxcore/DHT.c157
-rw-r--r--toxcore/Lossless_UDP.c292
-rw-r--r--toxcore/Lossless_UDP.h52
-rw-r--r--toxcore/Messenger.c88
-rw-r--r--toxcore/Messenger.h22
-rw-r--r--toxcore/net_crypto.c69
-rw-r--r--toxcore/net_crypto.h5
-rw-r--r--toxcore/network.c68
-rw-r--r--toxcore/network.h9
-rw-r--r--toxcore/tox.c38
-rw-r--r--toxcore/tox.h35
11 files changed, 661 insertions, 174 deletions
diff --git a/toxcore/DHT.c b/toxcore/DHT.c
index 1761f50b..ad4c8a1d 100644
--- a/toxcore/DHT.c
+++ b/toxcore/DHT.c
@@ -131,14 +131,32 @@ static int is_timeout(uint64_t time_now, uint64_t timestamp, uint64_t timeout)
131 * 131 *
132 * return True(1) or False(0) 132 * return True(1) or False(0)
133 */ 133 */
134static int client_in_list(Client_data *list, uint32_t length, uint8_t *client_id, IP_Port ip_port) 134static int client_or_ip_port_in_list(Client_data *list, uint32_t length, uint8_t *client_id, IP_Port ip_port)
135{ 135{
136 uint32_t i; 136 uint32_t i;
137 uint64_t temp_time = unix_time(); 137 uint64_t temp_time = unix_time();
138 138
139 uint8_t candropipv4 = 1;
140 if (ip_port.ip.family == AF_INET6) {
141 uint8_t ipv6cnt = 0;
142
143 /* ipv6: count how many spots are used */
144 for(i = 0; i < length; i++)
145 if (list[i].ip_port.ip.family == AF_INET6)
146 ipv6cnt++;
147
148 /* more than half the list filled with ipv6: block ipv4->ipv6 overwrite */
149 if (ipv6cnt > length / 2)
150 candropipv4 = 0;
151 }
152
139 /* if client_id is in list, find it and maybe overwrite ip_port */ 153 /* if client_id is in list, find it and maybe overwrite ip_port */
140 for (i = 0; i < length; ++i) 154 for (i = 0; i < length; ++i)
141 if (id_equal(list[i].client_id, client_id)) { 155 if (id_equal(list[i].client_id, client_id)) {
156 /* if we got "too many" ipv6 addresses already, keep the ipv4 address */
157 if (!candropipv4 && (list[i].ip_port.ip.family == AF_INET))
158 return 1;
159
142 /* Refresh the client timestamp. */ 160 /* Refresh the client timestamp. */
143 list[i].timestamp = temp_time; 161 list[i].timestamp = temp_time;
144 list[i].ip_port = ip_port; 162 list[i].ip_port = ip_port;
@@ -299,15 +317,31 @@ static int replace_bad( Client_data *list,
299 uint32_t i; 317 uint32_t i;
300 uint64_t temp_time = unix_time(); 318 uint64_t temp_time = unix_time();
301 319
320 uint8_t candropipv4 = 1;
321 if (ip_port.ip.family == AF_INET6) {
322 uint32_t ipv6cnt = 0;
323
324 /* ipv6: count how many spots are used */
325 for(i = 0; i < length; i++)
326 if (list[i].ip_port.ip.family == AF_INET6)
327 ipv6cnt++;
328
329 /* more than half the list filled with ipv6: block ipv4->ipv6 overwrite */
330 if (ipv6cnt > length / 2)
331 candropipv4 = 0;
332 }
333
302 for (i = 0; i < length; ++i) { 334 for (i = 0; i < length; ++i) {
303 /* If node is bad */ 335 /* If node is bad */
304 if (is_timeout(temp_time, list[i].timestamp, BAD_NODE_TIMEOUT)) { 336 Client_data *client = &list[i];
305 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); 337 if ((candropipv4 || (client->ip_port.ip.family == AF_INET6)) &&
306 list[i].ip_port = ip_port; 338 is_timeout(temp_time, client->timestamp, BAD_NODE_TIMEOUT)) {
307 list[i].timestamp = temp_time; 339 memcpy(client->client_id, client_id, CLIENT_ID_SIZE);
308 ip_reset(&list[i].ret_ip_port.ip); 340 client->ip_port = ip_port;
309 list[i].ret_ip_port.port = 0; 341 client->timestamp = temp_time;
310 list[i].ret_timestamp = 0; 342 ip_reset(&client->ret_ip_port.ip);
343 client->ret_ip_port.port = 0;
344 client->ret_timestamp = 0;
311 return 0; 345 return 0;
312 } 346 }
313 } 347 }
@@ -344,20 +378,69 @@ static int replace_good( Client_data *list,
344 IP_Port ip_port, 378 IP_Port ip_port,
345 uint8_t *comp_client_id ) 379 uint8_t *comp_client_id )
346{ 380{
347 uint32_t i;
348 uint64_t temp_time = unix_time();
349 sort_list(list, length, comp_client_id); 381 sort_list(list, length, comp_client_id);
350 382
351 for (i = 0; i < length; ++i) 383 uint8_t candropipv4 = 1;
352 if (id_closest(comp_client_id, list[i].client_id, client_id) == 2) { 384 if (ip_port.ip.family == AF_INET6) {
353 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); 385 uint32_t i, ipv6cnt = 0;
354 list[i].ip_port = ip_port; 386
355 list[i].timestamp = temp_time; 387 /* ipv6: count how many spots are used */
356 ip_reset(&list[i].ret_ip_port.ip); 388 for(i = 0; i < length; i++)
357 list[i].ret_ip_port.port = 0; 389 if (list[i].ip_port.ip.family == AF_INET6)
358 list[i].ret_timestamp = 0; 390 ipv6cnt++;
359 return 0; 391
392 /* more than half the list filled with ipv6: block ipv4->ipv6 overwrite */
393 if (ipv6cnt > length / 2)
394 candropipv4 = 0;
395 }
396
397 int8_t replace = -1;
398 uint32_t i;
399
400 if (candropipv4) {
401 /* either we got an ipv4 address, or we're "allowed" to push out an ipv4
402 * address in favor of an ipv6 one
403 *
404 * because the list is sorted, we can simply check the client_id at the
405 * border, either it is closer, then every other one is as well, or it is
406 * further, then it gets pushed out in favor of the new address, which
407 * will with the next sort() move to its "rightful" position
408 *
409 * CAVEAT: weirdly enough, the list is sorted DESCENDING in distance
410 * so the furthest element is the first, NOT the last (at least that's
411 * what the comment above sort_list() claims)
412 */
413 if (id_closest(comp_client_id, list[0].client_id, client_id) == 2)
414 replace = 0;
415 } else {
416 /* ipv6 case without a right to push out an ipv4: only look for ipv6
417 * addresses, the first one we find is either closer (then we can skip
418 * out like above) or further (then we can replace it, like above)
419 */
420 for (i = 0; i < length; i++) {
421 Client_data *client = &list[i];
422 if (client->ip_port.ip.family == AF_INET6) {
423 if (id_closest(comp_client_id, list[i].client_id, client_id) == 2)
424 replace = i;
425
426 break;
427 }
360 } 428 }
429 }
430
431 if (replace != -1) {
432#ifdef DEBUG
433 assert(replace >= 0 && replace < length);
434#endif
435 Client_data *client = &list[replace];
436 memcpy(client->client_id, client_id, CLIENT_ID_SIZE);
437 client->ip_port = ip_port;
438 client->timestamp = unix_time();
439 ip_reset(&client->ret_ip_port.ip);
440 client->ret_ip_port.port = 0;
441 client->ret_timestamp = 0;
442 return 0;
443 }
361 444
362 return 1; 445 return 1;
363} 446}
@@ -369,36 +452,32 @@ void addto_lists(DHT *dht, IP_Port ip_port, uint8_t *client_id)
369{ 452{
370 uint32_t i; 453 uint32_t i;
371 454
455 /* convert IPv4-in-IPv6 to IPv4 */
456 if ((ip_port.ip.family == AF_INET6) && IN6_IS_ADDR_V4MAPPED(&ip_port.ip.ip6.in6_addr)) {
457 ip_port.ip.family = AF_INET;
458 ip_port.ip.ip4.uint32 = ip_port.ip.ip6.uint32[3];
459 }
460
372 /* NOTE: Current behavior if there are two clients with the same id is 461 /* NOTE: Current behavior if there are two clients with the same id is
373 * to replace the first ip by the second. 462 * to replace the first ip by the second.
374 */ 463 */
375 if (!client_in_list(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) { 464 if (!client_or_ip_port_in_list(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) {
376 if (replace_bad(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) { 465 if (replace_bad(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) {
377 /* If we can't replace bad nodes we try replacing good ones. */ 466 /* If we can't replace bad nodes we try replacing good ones. */
378 replace_good( dht->close_clientlist, 467 replace_good(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port,
379 LCLIENT_LIST, 468 dht->c->self_public_key);
380 client_id,
381 ip_port,
382 dht->c->self_public_key );
383 } 469 }
384 } 470 }
385 471
386 for (i = 0; i < dht->num_friends; ++i) { 472 for (i = 0; i < dht->num_friends; ++i) {
387 if (!client_in_list( dht->friends_list[i].client_list, 473 if (!client_or_ip_port_in_list(dht->friends_list[i].client_list,
388 MAX_FRIEND_CLIENTS, 474 MAX_FRIEND_CLIENTS, client_id, ip_port)) {
389 client_id, 475
390 ip_port )) { 476 if (replace_bad(dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
391 477 client_id, ip_port)) {
392 if (replace_bad( dht->friends_list[i].client_list,
393 MAX_FRIEND_CLIENTS,
394 client_id,
395 ip_port )) {
396 /* If we can't replace bad nodes we try replacing good ones. */ 478 /* If we can't replace bad nodes we try replacing good ones. */
397 replace_good( dht->friends_list[i].client_list, 479 replace_good(dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
398 MAX_FRIEND_CLIENTS, 480 client_id, ip_port, dht->friends_list[i].client_id);
399 client_id,
400 ip_port,
401 dht->friends_list[i].client_id );
402 } 481 }
403 } 482 }
404 } 483 }
diff --git a/toxcore/Lossless_UDP.c b/toxcore/Lossless_UDP.c
index 83a5b338..8d447534 100644
--- a/toxcore/Lossless_UDP.c
+++ b/toxcore/Lossless_UDP.c
@@ -52,6 +52,43 @@ int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port)
52 return -1; 52 return -1;
53} 53}
54 54
55/* Resize a queue
56 * return length of queue on success.
57 * return ~0 on failure.
58 */
59uint32_t resize_queue(Data **buffer, uint32_t length, uint32_t new_length, uint32_t min_packetnum,
60 uint32_t max_packetnum)
61{
62 if (MAX_QUEUE_NUM < new_length)
63 new_length = MAX_QUEUE_NUM;
64
65 if (max_packetnum - min_packetnum > new_length)
66 return ~0;
67
68 if (length == new_length)
69 return new_length;
70
71 Data *temp = calloc(1, sizeof(Data) * new_length);
72
73 if (temp == NULL)
74 return ~0;
75
76 if (*buffer == NULL) {
77 *buffer = temp;
78 return new_length;
79 }
80
81 uint32_t i;
82
83 for (i = min_packetnum; i != max_packetnum; ++i)
84 memcpy(temp + (i % new_length), *buffer + (i % length), sizeof(Data));
85
86 free(*buffer);
87 *buffer = temp;
88 return new_length;
89}
90
91
55 92
56/* 93/*
57 * Generate a handshake_id which depends on the ip_port. 94 * Generate a handshake_id which depends on the ip_port.
@@ -148,8 +185,10 @@ int new_connection(Lossless_UDP *ludp, IP_Port ip_port)
148{ 185{
149 int connection_id = getconnection_id(ludp, ip_port); 186 int connection_id = getconnection_id(ludp, ip_port);
150 187
151 if (connection_id != -1) 188 if (connection_id != -1) {
189 confirm_connection(ludp, connection_id);
152 return connection_id; 190 return connection_id;
191 }
153 192
154 tox_array_for_each(&ludp->connections, Connection, tmp) { 193 tox_array_for_each(&ludp->connections, Connection, tmp) {
155 if (tmp->status == 0) { 194 if (tmp->status == 0) {
@@ -170,7 +209,8 @@ int new_connection(Lossless_UDP *ludp, IP_Port ip_port)
170 memset(connection, 0, sizeof(Connection)); 209 memset(connection, 0, sizeof(Connection));
171 210
172 uint32_t handshake_id1 = handshake_id(ludp, ip_port); 211 uint32_t handshake_id1 = handshake_id(ludp, ip_port);
173 uint64_t timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT; 212 /* add randomness to timeout to prevent connections getting stuck in a loop. */
213 uint8_t timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT;
174 214
175 *connection = (Connection) { 215 *connection = (Connection) {
176 .ip_port = ip_port, 216 .ip_port = ip_port,
@@ -186,9 +226,18 @@ int new_connection(Lossless_UDP *ludp, IP_Port ip_port)
186 .last_sent = current_time(), 226 .last_sent = current_time(),
187 .killat = ~0, 227 .killat = ~0,
188 .send_counter = 0, 228 .send_counter = 0,
189 /* add randomness to timeout to prevent connections getting stuck in a loop. */ 229 .timeout = timeout,
190 .timeout = timeout 230 .confirmed = 1
191 }; 231 };
232 connection->sendbuffer_length = resize_queue(&connection->sendbuffer, 0, DEFAULT_QUEUE_NUM, 0, 0);
233 connection->recvbuffer_length = resize_queue(&connection->recvbuffer, 0, DEFAULT_QUEUE_NUM, 0, 0);
234
235 if (connection->sendbuffer_length == (uint32_t)~0 || connection->recvbuffer_length == (uint32_t)~0) {
236 free(connection->sendbuffer);
237 free(connection->recvbuffer);
238 memset(connection, 0, sizeof(Connection));
239 return -1;
240 }
192 241
193 return connection_id; 242 return connection_id;
194} 243}
@@ -221,8 +270,8 @@ static int new_inconnection(Lossless_UDP *ludp, IP_Port ip_port)
221 270
222 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); 271 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
223 memset(connection, 0, sizeof(Connection)); 272 memset(connection, 0, sizeof(Connection));
224 273 /* Add randomness to timeout to prevent connections getting stuck in a loop. */
225 uint64_t timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT; 274 uint8_t timeout = CONNEXION_TIMEOUT + rand() % CONNEXION_TIMEOUT;
226 275
227 *connection = (Connection) { 276 *connection = (Connection) {
228 .ip_port = ip_port, 277 .ip_port = ip_port,
@@ -234,24 +283,33 @@ static int new_inconnection(Lossless_UDP *ludp, IP_Port ip_port)
234 .last_sent = current_time(), 283 .last_sent = current_time(),
235 .send_counter = 127, 284 .send_counter = 127,
236 285
237 /* Add randomness to timeout to prevent connections getting stuck in a loop. */
238 .timeout = timeout, 286 .timeout = timeout,
239 287
240 /* If this connection isn't handled within the timeout kill it. */ 288 /* If this connection isn't handled within the timeout kill it. */
241 .killat = current_time() + 1000000UL * timeout 289 .killat = current_time() + 1000000UL * timeout,
290 .confirmed = 0
242 }; 291 };
292 connection->sendbuffer_length = resize_queue(&connection->sendbuffer, 0, DEFAULT_QUEUE_NUM, 0, 0);
293 connection->recvbuffer_length = resize_queue(&connection->recvbuffer, 0, DEFAULT_QUEUE_NUM, 0, 0);
294
295 if (connection->sendbuffer_length == (uint32_t)~0 || connection->recvbuffer_length == (uint32_t)~0) {
296 free(connection->sendbuffer);
297 free(connection->recvbuffer);
298 memset(connection, 0, sizeof(Connection));
299 return -1;
300 }
243 301
244 return connection_id; 302 return connection_id;
245} 303}
246 304
247/* 305/*
248 * return an integer corresponding to the next connection in our incoming connection list. 306 * return an integer corresponding to the next connection in our incoming connection list with at least numpackets in the recieve queue.
249 * return -1 if there are no new incoming connections in the list. 307 * return -1 if there are no new incoming connections in the list.
250 */ 308 */
251int incoming_connection(Lossless_UDP *ludp) 309int incoming_connection(Lossless_UDP *ludp, uint32_t numpackets)
252{ 310{
253 tox_array_for_each(&ludp->connections, Connection, tmp) { 311 tox_array_for_each(&ludp->connections, Connection, tmp) {
254 if (tmp->inbound == 2) { 312 if (tmp->inbound == 2 && tmp->recv_packetnum - tmp->successful_read >= numpackets) {
255 tmp->inbound = 1; 313 tmp->inbound = 1;
256 return tmp_i; 314 return tmp_i;
257 } 315 }
@@ -286,6 +344,8 @@ int kill_connection(Lossless_UDP *ludp, int connection_id)
286 if (connection->status > 0) { 344 if (connection->status > 0) {
287 connection->status = 0; 345 connection->status = 0;
288 change_handshake(ludp, connection->ip_port); 346 change_handshake(ludp, connection->ip_port);
347 free(connection->sendbuffer);
348 free(connection->recvbuffer);
289 memset(connection, 0, sizeof(Connection)); 349 memset(connection, 0, sizeof(Connection));
290 free_connections(ludp); 350 free_connections(ludp);
291 return 0; 351 return 0;
@@ -332,6 +392,49 @@ int is_connected(Lossless_UDP *ludp, int connection_id)
332 return 0; 392 return 0;
333} 393}
334 394
395/* Check if connection is confirmed.
396 *
397 * returns 1 if yes.
398 * returns 0 if no/failure.
399 */
400int connection_confirmed(Lossless_UDP *ludp, int connection_id)
401{
402 if ((unsigned int)connection_id >= ludp->connections.len)
403 return 0;
404
405 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
406
407 if (connection->status == 0)
408 return 0;
409
410 if (connection->confirmed == 1)
411 return 1;
412
413 return 0;
414}
415
416/* Confirm an incoming connection.
417 * Also disables the auto kill timeout on incomming connections.
418 *
419 * return 0 on success
420 * return -1 on failure.
421 */
422int confirm_connection(Lossless_UDP *ludp, int connection_id)
423{
424 if ((unsigned int)connection_id >= ludp->connections.len)
425 return -1;
426
427 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
428
429 if (connection->status == 0)
430 return -1;
431
432 connection->killat = ~0;
433 connection->confirmed = 1;
434 connection->inbound = 0;
435 return 0;
436}
437
335/* return the ip_port of the corresponding connection. */ 438/* return the ip_port of the corresponding connection. */
336IP_Port connection_ip(Lossless_UDP *ludp, int connection_id) 439IP_Port connection_ip(Lossless_UDP *ludp, int connection_id)
337{ 440{
@@ -383,7 +486,7 @@ char id_packet(Lossless_UDP *ludp, int connection_id)
383 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); 486 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
384 487
385 if (connection->status != 0) 488 if (connection->status != 0)
386 return connection->recvbuffer[connection->successful_read % MAX_QUEUE_NUM].data[0]; 489 return connection->recvbuffer[connection->successful_read % connection->recvbuffer_length].data[0];
387 490
388 return -1; 491 return -1;
389} 492}
@@ -401,13 +504,47 @@ int read_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data)
401 if (connection->status == 0) 504 if (connection->status == 0)
402 return 0; 505 return 0;
403 506
404 uint16_t index = connection->successful_read % MAX_QUEUE_NUM; 507 uint16_t index = connection->successful_read % connection->recvbuffer_length;
405 uint16_t size = connection->recvbuffer[index].size; 508 uint16_t size = connection->recvbuffer[index].size;
406 memcpy(data, connection->recvbuffer[index].data, size); 509 memcpy(data, connection->recvbuffer[index].data, size);
407 ++connection->successful_read; 510 ++connection->successful_read;
408 connection->recvbuffer[index].size = 0; 511 connection->recvbuffer[index].size = 0;
409 return size; 512 return size;
513}
514
515/* Like read_packet() but does leaves the queue as is.
516 * return 0 if there is no received data in the buffer.
517 * return length of received packet if successful.
518 */
519int read_packet_silent(Lossless_UDP *ludp, int connection_id, uint8_t *data)
520{
521 if (recvqueue(ludp, connection_id) == 0)
522 return 0;
523
524 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
525
526 if (connection->status == 0)
527 return 0;
528
529 uint16_t index = connection->successful_read % connection->recvbuffer_length;
530 uint16_t size = connection->recvbuffer[index].size;
531 memcpy(data, connection->recvbuffer[index].data, size);
532 return size;
533}
534/* Discard the next packet to be read from the queue
535 * return 0 if success.
536 * return -1 if failure.
537 */
538int discard_packet(Lossless_UDP *ludp, int connection_id)
539{
540 if (recvqueue(ludp, connection_id) == 0)
541 return -1;
410 542
543 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
544 uint16_t index = connection->successful_read % connection->recvbuffer_length;
545 ++connection->successful_read;
546 connection->recvbuffer[index].size = 0;
547 return 0;
411} 548}
412 549
413/* return 0 if data could not be put in packet queue. 550/* return 0 if data could not be put in packet queue.
@@ -418,15 +555,27 @@ int write_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data, uint32_t
418 if ((unsigned int)connection_id >= ludp->connections.len) 555 if ((unsigned int)connection_id >= ludp->connections.len)
419 return 0; 556 return 0;
420 557
421 if (length > MAX_DATA_SIZE || length == 0 || sendqueue(ludp, connection_id) >= BUFFER_PACKET_NUM)
422 return 0;
423
424 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); 558 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
425 559
426 if (connection->status == 0) 560 if (connection->status == 0)
427 return 0; 561 return 0;
428 562
429 uint32_t index = connection->sendbuff_packetnum % MAX_QUEUE_NUM; 563 if (length > MAX_DATA_SIZE || length == 0 || sendqueue(ludp, connection_id) >= MAX_QUEUE_NUM)
564 return 0;
565
566 if (sendqueue(ludp, connection_id) >= connection->sendbuffer_length && connection->sendbuffer_length != 0) {
567 uint32_t newlen = connection->sendbuffer_length = resize_queue(&connection->sendbuffer, connection->sendbuffer_length,
568 connection->sendbuffer_length * 2, connection->successful_sent, connection->sendbuff_packetnum);
569
570 if (newlen == (uint32_t)~0)
571 return 0;
572
573 connection->sendbuffer_length = newlen;
574 return write_packet(ludp, connection_id, data, length);
575 }
576
577
578 uint32_t index = connection->sendbuff_packetnum % connection->sendbuffer_length;
430 memcpy(connection->sendbuffer[index].data, data, length); 579 memcpy(connection->sendbuffer[index].data, data, length);
431 connection->sendbuffer[index].size = length; 580 connection->sendbuffer[index].size = length;
432 connection->sendbuff_packetnum++; 581 connection->sendbuff_packetnum++;
@@ -434,26 +583,32 @@ int write_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data, uint32_t
434} 583}
435 584
436/* Put the packet numbers the we are missing in requested and return the number. */ 585/* Put the packet numbers the we are missing in requested and return the number. */
437uint32_t missing_packets(Lossless_UDP *ludp, int connection_id, uint32_t *requested) 586static uint32_t missing_packets(Lossless_UDP *ludp, int connection_id, uint32_t *requested)
438{ 587{
588 if ((unsigned int)connection_id >= ludp->connections.len)
589 return 0;
590
591 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
592
439 /* Don't request packets if the buffer is full. */ 593 /* Don't request packets if the buffer is full. */
440 if (recvqueue(ludp, connection_id) >= (BUFFER_PACKET_NUM - 1)) 594 if (recvqueue(ludp, connection_id) >= (connection->recvbuffer_length - 1))
441 return 0; 595 return 0;
442 596
443 uint32_t number = 0; 597 uint32_t number = 0;
444 uint32_t i; 598 uint32_t i;
445 uint32_t temp; 599 uint32_t temp;
446 600
447 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
448
449 for (i = connection->recv_packetnum; 601 for (i = connection->recv_packetnum;
450 i != connection->osent_packetnum; 602 i != connection->osent_packetnum;
451 i++) { 603 i++) {
452 if (connection->recvbuffer[i % MAX_QUEUE_NUM].size == 0) { 604 if (connection->recvbuffer[i % connection->recvbuffer_length].size == 0) {
453 temp = htonl(i); 605 temp = htonl(i);
454 memcpy(requested + number, &temp, 4); 606 memcpy(requested + number, &temp, 4);
455 ++number; 607 ++number;
456 } 608 }
609
610 if (number >= MAX_REQUESTED_PACKETS)
611 return number;
457 } 612 }
458 613
459 if (number == 0) 614 if (number == 0)
@@ -485,7 +640,7 @@ static int send_handshake(Lossless_UDP *ludp, IP_Port ip_port, uint32_t handshak
485static int send_SYNC(Lossless_UDP *ludp, int connection_id) 640static int send_SYNC(Lossless_UDP *ludp, int connection_id)
486{ 641{
487 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); 642 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
488 uint8_t packet[(BUFFER_PACKET_NUM * 4 + 4 + 4 + 2)]; 643 uint8_t packet[(MAX_REQUESTED_PACKETS * 4 + 4 + 4 + 2)];
489 uint16_t index = 0; 644 uint16_t index = 0;
490 645
491 IP_Port ip_port = connection->ip_port; 646 IP_Port ip_port = connection->ip_port;
@@ -493,7 +648,7 @@ static int send_SYNC(Lossless_UDP *ludp, int connection_id)
493 uint32_t recv_packetnum = htonl(connection->recv_packetnum); 648 uint32_t recv_packetnum = htonl(connection->recv_packetnum);
494 uint32_t sent_packetnum = htonl(connection->sent_packetnum); 649 uint32_t sent_packetnum = htonl(connection->sent_packetnum);
495 650
496 uint32_t requested[BUFFER_PACKET_NUM]; 651 uint32_t requested[MAX_REQUESTED_PACKETS];
497 uint32_t number = missing_packets(ludp, connection_id, requested); 652 uint32_t number = missing_packets(ludp, connection_id, requested);
498 653
499 packet[0] = NET_PACKET_SYNC; 654 packet[0] = NET_PACKET_SYNC;
@@ -514,7 +669,7 @@ static int send_data_packet(Lossless_UDP *ludp, int connection_id, uint32_t pack
514{ 669{
515 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); 670 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
516 671
517 uint32_t index = packet_num % MAX_QUEUE_NUM; 672 uint32_t index = packet_num % connection->sendbuffer_length;
518 uint32_t temp; 673 uint32_t temp;
519 uint8_t packet[1 + 4 + MAX_DATA_SIZE]; 674 uint8_t packet[1 + 4 + MAX_DATA_SIZE];
520 packet[0] = NET_PACKET_DATA; 675 packet[0] = NET_PACKET_DATA;
@@ -529,7 +684,7 @@ static int send_DATA(Lossless_UDP *ludp, int connection_id)
529{ 684{
530 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); 685 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
531 int ret; 686 int ret;
532 uint32_t buffer[BUFFER_PACKET_NUM]; 687 uint32_t buffer[MAX_REQUESTED_PACKETS];
533 688
534 if (connection->num_req_paquets > 0) { 689 if (connection->num_req_paquets > 0) {
535 ret = send_data_packet(ludp, connection_id, connection->req_packets[0]); 690 ret = send_data_packet(ludp, connection_id, connection->req_packets[0]);
@@ -609,7 +764,7 @@ static int SYNC_valid(uint32_t length)
609 if (length < 4 + 4 + 2) 764 if (length < 4 + 4 + 2)
610 return 0; 765 return 0;
611 766
612 if (length > (BUFFER_PACKET_NUM * 4 + 4 + 4 + 2) || 767 if (length > (MAX_REQUESTED_PACKETS * 4 + 4 + 4 + 2) ||
613 ((length - 4 - 4 - 2) % 4) != 0) 768 ((length - 4 - 4 - 2) % 4) != 0)
614 return 0; 769 return 0;
615 770
@@ -656,6 +811,35 @@ static int handle_SYNC2(Lossless_UDP *ludp, int connection_id, uint8_t counter,
656 811
657 return 1; 812 return 1;
658} 813}
814
815/*
816 * Automatically adjusts send rates of data packets for optimal transmission.
817 *
818 * TODO: Impove this.
819 */
820static void adjust_datasendspeed(Connection *connection, uint32_t req_packets)
821{
822 /* if there are no packets in send buffer */
823 if (connection->sendbuff_packetnum - connection->successful_sent == 0) {
824 connection->data_rate -= connection->data_rate / 8;
825
826 if (connection->data_rate < DATA_SYNC_RATE)
827 connection->data_rate = DATA_SYNC_RATE;
828
829 return;
830 }
831
832 if (req_packets <= (connection->data_rate / connection->SYNC_rate) / 20 || req_packets <= 1) {
833 connection->data_rate += connection->data_rate / 8;
834
835 if (connection->data_rate > connection->sendbuffer_length * connection->SYNC_rate)
836 connection->data_rate = connection->sendbuffer_length * connection->SYNC_rate;
837 } else {
838 connection->data_rate -= connection->data_rate / 8;
839 }
840}
841
842
659/* case 3 in handle_SYNC: */ 843/* case 3 in handle_SYNC: */
660static int handle_SYNC3(Lossless_UDP *ludp, int connection_id, uint8_t counter, uint32_t recv_packetnum, 844static int handle_SYNC3(Lossless_UDP *ludp, int connection_id, uint8_t counter, uint32_t recv_packetnum,
661 uint32_t sent_packetnum, 845 uint32_t sent_packetnum,
@@ -672,13 +856,14 @@ static int handle_SYNC3(Lossless_UDP *ludp, int connection_id, uint8_t counter,
672 uint32_t comp_2 = (sent_packetnum - connection->osent_packetnum); 856 uint32_t comp_2 = (sent_packetnum - connection->osent_packetnum);
673 857
674 /* Packet valid. */ 858 /* Packet valid. */
675 if (comp_1 <= BUFFER_PACKET_NUM && 859 if (comp_1 <= connection->sendbuffer_length &&
676 comp_2 <= BUFFER_PACKET_NUM && 860 comp_2 <= MAX_QUEUE_NUM &&
677 comp_counter == 1) { 861 comp_counter != 0 && comp_counter < 4) {
678 connection->orecv_packetnum = recv_packetnum; 862 connection->orecv_packetnum = recv_packetnum;
679 connection->osent_packetnum = sent_packetnum; 863 connection->osent_packetnum = sent_packetnum;
680 connection->successful_sent = recv_packetnum; 864 connection->successful_sent = recv_packetnum;
681 connection->last_recvSYNC = current_time(); 865 connection->last_recvSYNC = current_time();
866
682 connection->recv_counter = counter; 867 connection->recv_counter = counter;
683 868
684 ++connection->send_counter; 869 ++connection->send_counter;
@@ -689,6 +874,7 @@ static int handle_SYNC3(Lossless_UDP *ludp, int connection_id, uint8_t counter,
689 } 874 }
690 875
691 connection->num_req_paquets = number; 876 connection->num_req_paquets = number;
877 adjust_datasendspeed(connection, number);
692 return 0; 878 return 0;
693 } 879 }
694 880
@@ -705,8 +891,8 @@ static int handle_SYNC(void *object, IP_Port source, uint8_t *packet, uint32_t l
705 uint8_t counter; 891 uint8_t counter;
706 uint32_t temp; 892 uint32_t temp;
707 uint32_t recv_packetnum, sent_packetnum; 893 uint32_t recv_packetnum, sent_packetnum;
708 uint32_t req_packets[BUFFER_PACKET_NUM];
709 uint16_t number = (length - 4 - 4 - 2) / 4; 894 uint16_t number = (length - 4 - 4 - 2) / 4;
895 uint32_t req_packets[number];
710 896
711 memcpy(&counter, packet + 1, 1); 897 memcpy(&counter, packet + 1, 1);
712 memcpy(&temp, packet + 2, 4); 898 memcpy(&temp, packet + 2, 4);
@@ -749,17 +935,35 @@ static int add_recv(Lossless_UDP *ludp, int connection_id, uint32_t data_num, ui
749 935
750 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); 936 Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection);
751 uint32_t i; 937 uint32_t i;
752 uint32_t maxnum = connection->successful_read + BUFFER_PACKET_NUM; 938 uint32_t test = data_num - connection->recv_packetnum;
939
940 if (test > MAX_QUEUE_NUM)
941 return 0;
942
943 if (test > connection->recvbuffer_length) {
944 if (connection->confirmed == 0)
945 return 0;
946
947 uint32_t len = resize_queue(&connection->recvbuffer, connection->recvbuffer_length, test * 2,
948 connection->successful_read, connection->successful_read + connection->recvbuffer_length);
949
950 if (len == (uint32_t)~0)
951 return 0;
952
953 connection->recvbuffer_length = len;
954 }
955
956 uint32_t maxnum = connection->successful_read + connection->recvbuffer_length;
753 uint32_t sent_packet = data_num - connection->osent_packetnum; 957 uint32_t sent_packet = data_num - connection->osent_packetnum;
754 958
755 for (i = connection->recv_packetnum; i != maxnum; ++i) { 959 for (i = connection->recv_packetnum; i != maxnum; ++i) {
756 if (i == data_num) { 960 if (i == data_num) {
757 memcpy(connection->recvbuffer[i % MAX_QUEUE_NUM].data, data, size); 961 memcpy(connection->recvbuffer[data_num % connection->recvbuffer_length].data, data, size);
758 962
759 connection->recvbuffer[i % MAX_QUEUE_NUM].size = size; 963 connection->recvbuffer[data_num % connection->recvbuffer_length].size = size;
760 connection->last_recvdata = current_time(); 964 connection->last_recvdata = current_time();
761 965
762 if (sent_packet < BUFFER_PACKET_NUM) 966 if (sent_packet < connection->recvbuffer_length)
763 connection->osent_packetnum = data_num; 967 connection->osent_packetnum = data_num;
764 968
765 break; 969 break;
@@ -767,7 +971,7 @@ static int add_recv(Lossless_UDP *ludp, int connection_id, uint32_t data_num, ui
767 } 971 }
768 972
769 for (i = connection->recv_packetnum; i != maxnum; ++i) { 973 for (i = connection->recv_packetnum; i != maxnum; ++i) {
770 if (connection->recvbuffer[i % MAX_QUEUE_NUM].size != 0) 974 if (connection->recvbuffer[i % connection->recvbuffer_length].size != 0)
771 connection->recv_packetnum = i; 975 connection->recv_packetnum = i;
772 else 976 else
773 break; 977 break;
@@ -871,7 +1075,8 @@ static void do_data(Lossless_UDP *ludp)
871 if (tmp->status == 3 && sendqueue(ludp, tmp_i) != 0 && 1075 if (tmp->status == 3 && sendqueue(ludp, tmp_i) != 0 &&
872 (tmp->last_sent + (1000000UL / tmp->data_rate)) <= temp_time) { 1076 (tmp->last_sent + (1000000UL / tmp->data_rate)) <= temp_time) {
873 for (j = tmp->last_sent; j < temp_time; j += (1000000UL / tmp->data_rate)) 1077 for (j = tmp->last_sent; j < temp_time; j += (1000000UL / tmp->data_rate))
874 send_DATA(ludp, tmp_i); 1078 if (send_DATA(ludp, tmp_i) <= 0)
1079 break;
875 1080
876 tmp->last_sent = temp_time; 1081 tmp->last_sent = temp_time;
877 1082
@@ -879,7 +1084,7 @@ static void do_data(Lossless_UDP *ludp)
879 } 1084 }
880} 1085}
881 1086
882#define MAX_SYNC_RATE 10 1087#define MAX_SYNC_RATE 20
883 1088
884/* 1089/*
885 * Automatically adjusts send rates of packets for optimal transmission. 1090 * Automatically adjusts send rates of packets for optimal transmission.
@@ -896,12 +1101,12 @@ static void adjust_rates(Lossless_UDP *ludp)
896 1101
897 if (tmp->status == 3) { 1102 if (tmp->status == 3) {
898 if (sendqueue(ludp, tmp_i) != 0) { 1103 if (sendqueue(ludp, tmp_i) != 0) {
899 tmp->data_rate = (BUFFER_PACKET_NUM - tmp->num_req_paquets) * MAX_SYNC_RATE;
900 tmp->SYNC_rate = MAX_SYNC_RATE; 1104 tmp->SYNC_rate = MAX_SYNC_RATE;
901 } else if (tmp->last_recvdata + 1000000UL > temp_time) 1105 } else if (tmp->last_recvdata + 200000UL > temp_time) { /* 200 ms */
902 tmp->SYNC_rate = MAX_SYNC_RATE; 1106 tmp->SYNC_rate = MAX_SYNC_RATE;
903 else 1107 } else {
904 tmp->SYNC_rate = SYNC_RATE; 1108 tmp->SYNC_rate = SYNC_RATE;
1109 }
905 } 1110 }
906 } 1111 }
907} 1112}
@@ -917,6 +1122,11 @@ void do_lossless_udp(Lossless_UDP *ludp)
917 1122
918void kill_lossless_udp(Lossless_UDP *ludp) 1123void kill_lossless_udp(Lossless_UDP *ludp)
919{ 1124{
1125 uint32_t i;
1126
1127 for (i = 0; i < ludp->connections.len; ++i)
1128 kill_connection(ludp, i);
1129
920 tox_array_delete(&ludp->connections); 1130 tox_array_delete(&ludp->connections);
921 free(ludp); 1131 free(ludp);
922} 1132}
diff --git a/toxcore/Lossless_UDP.h b/toxcore/Lossless_UDP.h
index f0ce0e87..2ef6f4d9 100644
--- a/toxcore/Lossless_UDP.h
+++ b/toxcore/Lossless_UDP.h
@@ -32,10 +32,11 @@
32#define MAX_DATA_SIZE 1024 32#define MAX_DATA_SIZE 1024
33 33
34/* Maximum data packets in sent and receive queues. */ 34/* Maximum data packets in sent and receive queues. */
35#define MAX_QUEUE_NUM 16 35#define MAX_QUEUE_NUM 1024
36#define DEFAULT_QUEUE_NUM 4
36 37
37/* Maximum number of data packets in the buffer. */ 38/* Maximum number of data packets in the buffer. */
38#define BUFFER_PACKET_NUM (16-1) 39#define MAX_REQUESTED_PACKETS 256
39 40
40/* Timeout per connection is randomly set between CONNEXION_TIMEOUT and 2*CONNEXION_TIMEOUT. */ 41/* Timeout per connection is randomly set between CONNEXION_TIMEOUT and 2*CONNEXION_TIMEOUT. */
41#define CONNEXION_TIMEOUT 5 42#define CONNEXION_TIMEOUT 5
@@ -71,7 +72,7 @@ typedef struct {
71 uint8_t inbound; 72 uint8_t inbound;
72 73
73 uint16_t SYNC_rate; /* Current SYNC packet send rate packets per second. */ 74 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 uint32_t data_rate; /* Current data packet send rate packets per second. */
75 76
76 uint64_t last_SYNC; /* Time our last SYNC packet was sent. */ 77 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_sent; /* Time our last data or handshake packet was sent. */
@@ -79,9 +80,10 @@ typedef struct {
79 uint64_t last_recvdata; /* Time we last received a DATA packet from the other. */ 80 uint64_t last_recvdata; /* Time we last received a DATA packet from the other. */
80 uint64_t killat; /* Time to kill the connection. */ 81 uint64_t killat; /* Time to kill the connection. */
81 82
82 Data sendbuffer[MAX_QUEUE_NUM]; /* packet send buffer. */ 83 Data *sendbuffer; /* packet send buffer. */
83 Data recvbuffer[MAX_QUEUE_NUM]; /* packet receive buffer. */ 84 uint32_t sendbuffer_length;
84 85 Data *recvbuffer; /* packet receive buffer. */
86 uint32_t recvbuffer_length;
85 uint32_t handshake_id1; 87 uint32_t handshake_id1;
86 uint32_t handshake_id2; 88 uint32_t handshake_id2;
87 89
@@ -107,7 +109,7 @@ typedef struct {
107 uint32_t successful_read; 109 uint32_t successful_read;
108 110
109 /* List of currently requested packet numbers(by the other person). */ 111 /* List of currently requested packet numbers(by the other person). */
110 uint32_t req_packets[BUFFER_PACKET_NUM]; 112 uint32_t req_packets[MAX_REQUESTED_PACKETS];
111 113
112 /* Total number of currently requested packets(by the other person). */ 114 /* Total number of currently requested packets(by the other person). */
113 uint16_t num_req_paquets; 115 uint16_t num_req_paquets;
@@ -115,6 +117,9 @@ typedef struct {
115 uint8_t recv_counter; 117 uint8_t recv_counter;
116 uint8_t send_counter; 118 uint8_t send_counter;
117 uint8_t timeout; /* connection timeout in seconds. */ 119 uint8_t timeout; /* connection timeout in seconds. */
120
121 /* is the connection confirmed or not 1 if yes, 0 if no */
122 uint8_t confirmed;
118} Connection; 123} Connection;
119 124
120typedef struct { 125typedef struct {
@@ -150,10 +155,11 @@ int new_connection(Lossless_UDP *ludp, IP_Port ip_port);
150 */ 155 */
151int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port); 156int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port);
152 157
153/* return an integer corresponding to the next connection in our imcoming connection list. 158/*
159 * return an integer corresponding to the next connection in our incoming connection list with at least numpackets in the recieve queue.
154 * return -1 if there are no new incoming connections in the list. 160 * return -1 if there are no new incoming connections in the list.
155 */ 161 */
156int incoming_connection(Lossless_UDP *ludp); 162int incoming_connection(Lossless_UDP *ludp, uint32_t numpackets);
157 163
158/* return -1 if it could not kill the connection. 164/* return -1 if it could not kill the connection.
159 * return 0 if killed successfully. 165 * return 0 if killed successfully.
@@ -168,6 +174,22 @@ int kill_connection(Lossless_UDP *ludp, int connection_id);
168 */ 174 */
169int kill_connection_in(Lossless_UDP *ludp, int connection_id, uint32_t seconds); 175int kill_connection_in(Lossless_UDP *ludp, int connection_id, uint32_t seconds);
170 176
177
178/* Check if connection is confirmed.
179 *
180 * returns 1 if yes.
181 * returns 0 if no.
182 */
183int connection_confirmed(Lossless_UDP *ludp, int connection_id);
184
185/* Confirm an incoming connection.
186 * Also disables the auto kill timeout on incomming connections.
187 *
188 * return 0 on success
189 * return -1 on failure.
190 */
191int confirm_connection(Lossless_UDP *ludp, int connection_id);
192
171/* returns the ip_port of the corresponding connection. 193/* returns the ip_port of the corresponding connection.
172 * return 0 if there is no such connection. 194 * return 0 if there is no such connection.
173 */ 195 */
@@ -183,6 +205,18 @@ char id_packet(Lossless_UDP *ludp, int connection_id);
183 */ 205 */
184int read_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data); 206int read_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data);
185 207
208/* Like read_packet() but does leaves the queue as is.
209 * return 0 if there is no received data in the buffer.
210 * return length of received packet if successful.
211 */
212int read_packet_silent(Lossless_UDP *ludp, int connection_id, uint8_t *data);
213
214/* Discard the next packet to be read from the queue
215 * return 0 if success.
216 * return -1 if failure.
217 */
218int discard_packet(Lossless_UDP *ludp, int connection_id);
219
186/* return 0 if data could not be put in packet queue. 220/* return 0 if data could not be put in packet queue.
187 * return 1 if data was put into the queue. 221 * return 1 if data was put into the queue.
188 */ 222 */
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index dbbfa58c..f22a8d57 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -352,13 +352,16 @@ static int m_sendname(Messenger *m, int friendnumber, uint8_t *name, uint16_t le
352 * return 0 if success. 352 * return 0 if success.
353 * return -1 if failure. 353 * return -1 if failure.
354 */ 354 */
355static int setfriendname(Messenger *m, int friendnumber, uint8_t *name, uint16_t len) 355int setfriendname(Messenger *m, int friendnumber, uint8_t *name, uint16_t length)
356{ 356{
357 if (friend_not_valid(m, friendnumber)) 357 if (friend_not_valid(m, friendnumber))
358 return -1; 358 return -1;
359 359
360 m->friendlist[friendnumber].name_length = len; 360 if (length > MAX_NAME_LENGTH || length == 0)
361 memcpy(m->friendlist[friendnumber].name, name, len); 361 return -1;
362
363 m->friendlist[friendnumber].name_length = length;
364 memcpy(m->friendlist[friendnumber].name, name, length);
362 return 0; 365 return 0;
363} 366}
364 367
@@ -513,8 +516,10 @@ static int send_userstatus(Messenger *m, int friendnumber, USERSTATUS status)
513 516
514static int send_ping(Messenger *m, int friendnumber) 517static int send_ping(Messenger *m, int friendnumber)
515{ 518{
516 m->friendlist[friendnumber].ping_lastsent = unix_time(); 519 int ret = write_cryptpacket_id(m, friendnumber, PACKET_ID_PING, 0, 0);
517 return write_cryptpacket_id(m, friendnumber, PACKET_ID_PING, 0, 0); 520 if (ret == 1)
521 m->friendlist[friendnumber].ping_lastsent = unix_time();
522 return ret;
518} 523}
519 524
520static int set_friend_statusmessage(Messenger *m, int friendnumber, uint8_t *status, uint16_t length) 525static int set_friend_statusmessage(Messenger *m, int friendnumber, uint8_t *status, uint16_t length)
@@ -538,7 +543,7 @@ static void set_friend_userstatus(Messenger *m, int friendnumber, USERSTATUS sta
538/* Sets whether we send read receipts for friendnumber. */ 543/* Sets whether we send read receipts for friendnumber. */
539void m_set_sends_receipts(Messenger *m, int friendnumber, int yesno) 544void m_set_sends_receipts(Messenger *m, int friendnumber, int yesno)
540{ 545{
541 if (yesno != 0 || yesno != 1) 546 if (yesno != 0 && yesno != 1)
542 return; 547 return;
543 548
544 if (friend_not_valid(m, friendnumber)) 549 if (friend_not_valid(m, friendnumber))
@@ -705,7 +710,7 @@ static void group_message_function(Group_Chat *chat, int peer_number, uint8_t *m
705 } 710 }
706 711
707 if (m->group_message) 712 if (m->group_message)
708 (*m->group_message)(m, i, peer_number, message, length, m->group_invite_userdata); 713 (*m->group_message)(m, i, peer_number, message, length, m->group_message_userdata);
709} 714}
710 715
711/* Creates a new groupchat and puts it in the chats array. 716/* Creates a new groupchat and puts it in the chats array.
@@ -1182,6 +1187,8 @@ void doFriends(Messenger *m)
1182 1187
1183 if (m->group_invite) 1188 if (m->group_invite)
1184 (*m->group_invite)(m, i, data, m->group_invite_userdata); 1189 (*m->group_invite)(m, i, data, m->group_invite_userdata);
1190
1191 break;
1185 } 1192 }
1186 1193
1187 case PACKET_ID_JOIN_GROUPCHAT: { 1194 case PACKET_ID_JOIN_GROUPCHAT: {
@@ -1197,6 +1204,12 @@ void doFriends(Messenger *m)
1197 break; 1204 break;
1198 1205
1199 group_newpeer(m->chats[groupnum], data + crypto_box_PUBLICKEYBYTES); 1206 group_newpeer(m->chats[groupnum], data + crypto_box_PUBLICKEYBYTES);
1207
1208 break;
1209 }
1210
1211 default: {
1212 break;
1200 } 1213 }
1201 } 1214 }
1202 } else { 1215 } else {
@@ -1231,6 +1244,11 @@ void doInbound(Messenger *m)
1231 int friend_id = getfriend_id(m, public_key); 1244 int friend_id = getfriend_id(m, public_key);
1232 1245
1233 if (friend_id != -1) { 1246 if (friend_id != -1) {
1247 if (m_get_friend_connectionstatus(m, friend_id) == 1) {
1248 kill_connection(m->net_crypto->lossless_udp, inconnection);
1249 return;
1250 }
1251
1234 crypto_kill(m->net_crypto, m->friendlist[friend_id].crypt_connection_id); 1252 crypto_kill(m->net_crypto, m->friendlist[friend_id].crypt_connection_id);
1235 m->friendlist[friend_id].crypt_connection_id = 1253 m->friendlist[friend_id].crypt_connection_id =
1236 accept_crypto_inbound(m->net_crypto, inconnection, public_key, secret_nonce, session_key); 1254 accept_crypto_inbound(m->net_crypto, inconnection, public_key, secret_nonce, session_key);
@@ -1263,8 +1281,8 @@ void doMessenger(Messenger *m)
1263 1281
1264 do_DHT(m->dht); 1282 do_DHT(m->dht);
1265 do_net_crypto(m->net_crypto); 1283 do_net_crypto(m->net_crypto);
1266 doInbound(m);
1267 doFriends(m); 1284 doFriends(m);
1285 doInbound(m);
1268 do_allgroupchats(m); 1286 do_allgroupchats(m);
1269 LANdiscovery(m); 1287 LANdiscovery(m);
1270 1288
@@ -1425,12 +1443,12 @@ static int Messenger_load_old(Messenger *m, uint8_t *data, uint32_t length)
1425 if (length < size) 1443 if (length < size)
1426 return -1; 1444 return -1;
1427 1445
1428 if (DHT_load_old(m->dht, data, size) == -1) 1446 if (DHT_load_old(m->dht, data, size) == -1) {
1429#ifdef DEBUG 1447#ifdef DEBUG
1430 fprintf(stderr, "Data file: Something wicked happened to the stored connections...\n"); 1448 fprintf(stderr, "Data file: Something wicked happened to the stored connections...\n");
1431 1449 /* DO go on, friends/name still might be intact */
1432#endif 1450#endif
1433 /* DO go on, friends/name still might be intact */ 1451 }
1434 1452
1435 data += size; 1453 data += size;
1436 length -= size; 1454 length -= size;
@@ -1640,6 +1658,54 @@ int Messenger_load(Messenger *m, uint8_t *data, uint32_t length)
1640 return Messenger_load_old(m, data, length); 1658 return Messenger_load_old(m, data, length);
1641} 1659}
1642 1660
1661/* Return the number of friends in the instance m.
1662 * You should use this to determine how much memory to allocate
1663 * for copy_friendlist. */
1664uint32_t count_friendlist(Messenger *m)
1665{
1666 uint32_t ret = 0;
1667 uint32_t i;
1668
1669 for (i = 0; i < m->numfriends; i++) {
1670 if (m->friendlist[i].status > 0) {
1671 ret++;
1672 }
1673 }
1674
1675 return ret;
1676}
1677
1678/* Copy a list of valid friend IDs into the array out_list.
1679 * If out_list is NULL, returns 0.
1680 * Otherwise, returns the number of elements copied.
1681 * If the array was too small, the contents
1682 * of out_list will be truncated to list_size. */
1683uint32_t copy_friendlist(Messenger *m, int *out_list, uint32_t list_size)
1684{
1685 if (!out_list)
1686 return 0;
1687
1688 if (m->numfriends == 0) {
1689 return 0;
1690 }
1691
1692 uint32_t i;
1693 uint32_t ret = 0;
1694
1695 for (i = 0; i < m->numfriends; i++) {
1696 if (i >= list_size) {
1697 break; /* Abandon ship */
1698 }
1699
1700 if (m->friendlist[i].status > 0) {
1701 out_list[i] = i;
1702 ret++;
1703 }
1704 }
1705
1706 return ret;
1707}
1708
1643/* Allocate and return a list of valid friend id's. List must be freed by the 1709/* Allocate and return a list of valid friend id's. List must be freed by the
1644 * caller. 1710 * caller.
1645 * 1711 *
diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h
index 78580dc0..0ff14de4 100644
--- a/toxcore/Messenger.h
+++ b/toxcore/Messenger.h
@@ -246,6 +246,16 @@ uint32_t m_sendmessage_withid(Messenger *m, int friendnumber, uint32_t theid, ui
246 */ 246 */
247int m_sendaction(Messenger *m, int friendnumber, uint8_t *action, uint32_t length); 247int m_sendaction(Messenger *m, int friendnumber, uint8_t *action, uint32_t length);
248 248
249/* Set the name and name_length of a friend.
250 * name must be a string of maximum MAX_NAME_LENGTH length.
251 * length must be at least 1 byte.
252 * length is the length of name with the NULL terminator.
253 *
254 * return 0 if success.
255 * return -1 if failure.
256 */
257int setfriendname(Messenger *m, int friendnumber, uint8_t *name, uint16_t length);
258
249/* Set our nickname. 259/* Set our nickname.
250 * name must be a string of maximum MAX_NAME_LENGTH length. 260 * name must be a string of maximum MAX_NAME_LENGTH length.
251 * length must be at least 1 byte. 261 * length must be at least 1 byte.
@@ -456,6 +466,18 @@ void Messenger_save(Messenger *m, uint8_t *data);
456/* Load the messenger from data of size length. */ 466/* Load the messenger from data of size length. */
457int Messenger_load(Messenger *m, uint8_t *data, uint32_t length); 467int Messenger_load(Messenger *m, uint8_t *data, uint32_t length);
458 468
469/* Return the number of friends in the instance m.
470 * You should use this to determine how much memory to allocate
471 * for copy_friendlist. */
472uint32_t count_friendlist(Messenger *m);
473
474/* Copy a list of valid friend IDs into the array out_list.
475 * If out_list is NULL, returns 0.
476 * Otherwise, returns the number of elements copied.
477 * If the array was too small, the contents
478 * of out_list will be truncated to list_size. */
479uint32_t copy_friendlist(Messenger *m, int *out_list, uint32_t list_size);
480
459/* Allocate and return a list of valid friend id's. List must be freed by the 481/* Allocate and return a list of valid friend id's. List must be freed by the
460 * caller. 482 * caller.
461 * 483 *
diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c
index a2e42557..98571ce7 100644
--- a/toxcore/net_crypto.c
+++ b/toxcore/net_crypto.c
@@ -503,27 +503,26 @@ int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port)
503 */ 503 */
504int crypto_inbound(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key) 504int crypto_inbound(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key)
505{ 505{
506 uint32_t i; 506 while (1) {
507 int incoming_con = incoming_connection(c->lossless_udp, 1);
507 508
508 for (i = 0; i < MAX_INCOMING; ++i) { 509 if (incoming_con != -1) {
509 if (c->incoming_connections[i] != -1) { 510 if (is_connected(c->lossless_udp, incoming_con) == 4
510 if (is_connected(c->lossless_udp, c->incoming_connections[i]) == 4 511 || is_connected(c->lossless_udp, incoming_con) == 0) {
511 || is_connected(c->lossless_udp, c->incoming_connections[i]) == 0) { 512 kill_connection(c->lossless_udp, incoming_con);
512 kill_connection(c->lossless_udp, c->incoming_connections[i]);
513 c->incoming_connections[i] = -1;
514 continue; 513 continue;
515 } 514 }
516 515
517 if (id_packet(c->lossless_udp, c->incoming_connections[i]) == 2) { 516 if (id_packet(c->lossless_udp, incoming_con) == 2) {
518 uint8_t temp_data[MAX_DATA_SIZE]; 517 uint8_t temp_data[MAX_DATA_SIZE];
519 uint16_t len = read_packet(c->lossless_udp, c->incoming_connections[i], temp_data); 518 uint16_t len = read_packet_silent(c->lossless_udp, incoming_con, temp_data);
520 519
521 if (handle_cryptohandshake(c, public_key, secret_nonce, session_key, temp_data, len)) { 520 if (handle_cryptohandshake(c, public_key, secret_nonce, session_key, temp_data, len)) {
522 int connection_id = c->incoming_connections[i]; 521 return incoming_con;
523 c->incoming_connections[i] = -1; /* Remove this connection from the incoming connection list. */
524 return connection_id;
525 } 522 }
526 } 523 }
524 } else {
525 break;
527 } 526 }
528 } 527 }
529 528
@@ -570,7 +569,7 @@ int accept_crypto_inbound(Net_Crypto *c, int connection_id, uint8_t *public_key,
570{ 569{
571 uint32_t i; 570 uint32_t i;
572 571
573 if (connection_id == -1) 572 if (discard_packet(c->lossless_udp, connection_id) == -1)
574 return -1; 573 return -1;
575 574
576 /* 575 /*
@@ -579,6 +578,10 @@ int accept_crypto_inbound(Net_Crypto *c, int connection_id, uint8_t *public_key,
579 * return -1; 578 * return -1;
580 * } 579 * }
581 */ 580 */
581
582 /* Connection is accepted. */
583 confirm_connection(c->lossless_udp, connection_id);
584
582 if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == -1 585 if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == -1
583 || c->crypto_connections == NULL) 586 || c->crypto_connections == NULL)
584 return -1; 587 return -1;
@@ -659,41 +662,6 @@ void load_keys(Net_Crypto *c, uint8_t *keys)
659 memcpy(c->self_secret_key, keys + crypto_box_PUBLICKEYBYTES, crypto_box_SECRETKEYBYTES); 662 memcpy(c->self_secret_key, keys + crypto_box_PUBLICKEYBYTES, crypto_box_SECRETKEYBYTES);
660} 663}
661 664
662/* Adds an incoming connection to the incoming_connection list.
663 * TODO: Optimize this.
664 *
665 * returns 0 if successful
666 * returns 1 if failure.
667 */
668static int new_incoming(Net_Crypto *c, int id)
669{
670 uint32_t i;
671
672 for (i = 0; i < MAX_INCOMING; ++i) {
673 if (c->incoming_connections[i] == -1) {
674 c->incoming_connections[i] = id;
675 return 0;
676 }
677 }
678
679 return 1;
680}
681
682/* Handle all new incoming connections.
683 * TODO: Optimize this.
684 */
685static void handle_incomings(Net_Crypto *c)
686{
687 int income;
688
689 while (1) {
690 income = incoming_connection(c->lossless_udp);
691
692 if (income == -1 || new_incoming(c, income) )
693 break;
694 }
695}
696
697/* Handle received packets for not yet established crypto connections. */ 665/* Handle received packets for not yet established crypto connections. */
698static void receive_crypto(Net_Crypto *c) 666static void receive_crypto(Net_Crypto *c)
699{ 667{
@@ -748,9 +716,6 @@ static void receive_crypto(Net_Crypto *c)
748 c->crypto_connections[i].sessionsecret_key, 716 c->crypto_connections[i].sessionsecret_key,
749 c->crypto_connections[i].shared_key); 717 c->crypto_connections[i].shared_key);
750 c->crypto_connections[i].status = CONN_ESTABLISHED; 718 c->crypto_connections[i].status = CONN_ESTABLISHED;
751
752 /* Connection is accepted so we disable the auto kill by setting it to about 1 month from now. */
753 kill_connection_in(c->lossless_udp, c->crypto_connections[i].number, 3000000);
754 } else { 719 } else {
755 /* This should not happen, kill the connection if it does. */ 720 /* This should not happen, kill the connection if it does. */
756 crypto_kill(c, i); 721 crypto_kill(c, i);
@@ -785,7 +750,6 @@ Net_Crypto *new_net_crypto(Networking_Core *net)
785 return NULL; 750 return NULL;
786 } 751 }
787 752
788 memset(temp->incoming_connections, -1 , sizeof(int) * MAX_INCOMING);
789 return temp; 753 return temp;
790} 754}
791 755
@@ -810,7 +774,6 @@ static void kill_timedout(Net_Crypto *c)
810void do_net_crypto(Net_Crypto *c) 774void do_net_crypto(Net_Crypto *c)
811{ 775{
812 do_lossless_udp(c->lossless_udp); 776 do_lossless_udp(c->lossless_udp);
813 handle_incomings(c);
814 kill_timedout(c); 777 kill_timedout(c);
815 receive_crypto(c); 778 receive_crypto(c);
816} 779}
diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h
index 55c1e3e3..f8eeb424 100644
--- a/toxcore/net_crypto.h
+++ b/toxcore/net_crypto.h
@@ -26,8 +26,6 @@
26 26
27#include "Lossless_UDP.h" 27#include "Lossless_UDP.h"
28 28
29#define MAX_INCOMING 64
30
31#define CRYPTO_PACKET_FRIEND_REQ 32 /* Friend request crypto packet ID. */ 29#define CRYPTO_PACKET_FRIEND_REQ 32 /* Friend request crypto packet ID. */
32#define CRYPTO_PACKET_NAT_PING 254 /* NAT ping crypto packet ID. */ 30#define CRYPTO_PACKET_NAT_PING 254 /* NAT ping crypto packet ID. */
33 31
@@ -66,9 +64,6 @@ typedef struct {
66 uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; 64 uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
67 uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; 65 uint8_t self_secret_key[crypto_box_SECRETKEYBYTES];
68 66
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]; 67 Cryptopacket_Handles cryptopackethandlers[256];
73} Net_Crypto; 68} Net_Crypto;
74 69
diff --git a/toxcore/network.c b/toxcore/network.c
index 49e1726c..619248d8 100644
--- a/toxcore/network.c
+++ b/toxcore/network.c
@@ -28,6 +28,72 @@
28#include "network.h" 28#include "network.h"
29#include "util.h" 29#include "util.h"
30 30
31#ifndef IPV6_V6ONLY
32#define IPV6_V6ONLY 27
33#endif
34
35#ifdef WIN32
36
37static const char *inet_ntop(sa_family_t family, void *addr, char *buf, size_t bufsize)
38{
39 if (family == AF_INET) {
40 struct sockaddr_in saddr = { 0 };
41 saddr.sin_family = AF_INET;
42 saddr.sin_addr = *(struct in_addr *)addr;
43
44 DWORD len = bufsize;
45
46 if (WSAAddressToString((LPSOCKADDR)&saddr, sizeof(saddr), NULL, buf, &len))
47 return NULL;
48
49 return buf;
50 } else if (family == AF_INET6) {
51 struct sockaddr_in6 saddr = { 0 };
52 saddr.sin6_family = AF_INET6;
53 saddr.sin6_addr = *(struct in6_addr *)addr;
54
55 DWORD len = bufsize;
56
57 if (WSAAddressToString((LPSOCKADDR)&saddr, sizeof(saddr), NULL, buf, &len))
58 return NULL;
59
60 return buf;
61 }
62
63 return NULL;
64}
65
66static int inet_pton(sa_family_t family, const char *addrString, void *addrbuf)
67{
68 if (family == AF_INET) {
69 struct sockaddr_in saddr = { 0 };
70
71 INT len = sizeof(saddr);
72
73 if (WSAStringToAddress((LPTSTR)addrString, AF_INET, NULL, (LPSOCKADDR)&saddr, &len))
74 return 0;
75
76 *(struct in_addr *)addrbuf = saddr.sin_addr;
77
78 return 1;
79 } else if (family == AF_INET6) {
80 struct sockaddr_in6 saddr = { 0 };
81
82 INT len = sizeof(saddr);
83
84 if (WSAStringToAddress((LPTSTR)addrString, AF_INET6, NULL, (LPSOCKADDR)&saddr, &len))
85 return 0;
86
87 *(struct in6_addr *)addrbuf = saddr.sin6_addr;
88
89 return 1;
90 }
91
92 return 0;
93}
94
95#endif
96
31/* return current UNIX time in microseconds (us). */ 97/* return current UNIX time in microseconds (us). */
32uint64_t current_time(void) 98uint64_t current_time(void)
33{ 99{
@@ -407,7 +473,7 @@ Networking_Core *new_networking(IP ip, uint16_t port)
407#ifdef LOGGING 473#ifdef LOGGING
408 res = 474 res =
409#endif 475#endif
410 setsockopt(temp->sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); 476 setsockopt(temp->sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq));
411#ifdef LOGGING 477#ifdef LOGGING
412 478
413 if (res < 0) { 479 if (res < 0) {
diff --git a/toxcore/network.h b/toxcore/network.h
index 4432baed..0d2b5786 100644
--- a/toxcore/network.h
+++ b/toxcore/network.h
@@ -40,6 +40,15 @@
40#include <ws2tcpip.h> 40#include <ws2tcpip.h>
41 41
42typedef unsigned int sock_t; 42typedef unsigned int sock_t;
43typedef INT sa_family_t;
44
45#ifndef IN6_ARE_ADDR_EQUAL
46#define IN6_ARE_ADDR_EQUAL(a,b) \
47 ((((__const uint32_t *) (a))[0] == ((__const uint32_t *) (b))[0]) \
48 && (((__const uint32_t *) (a))[1] == ((__const uint32_t *) (b))[1]) \
49 && (((__const uint32_t *) (a))[2] == ((__const uint32_t *) (b))[2]) \
50 && (((__const uint32_t *) (a))[3] == ((__const uint32_t *) (b))[3]))
51#endif
43 52
44#else // Linux includes 53#else // Linux includes
45 54
diff --git a/toxcore/tox.c b/toxcore/tox.c
index 4fba360b..1d7118be 100644
--- a/toxcore/tox.c
+++ b/toxcore/tox.c
@@ -153,6 +153,20 @@ int tox_sendaction(void *tox, int friendnumber, uint8_t *action, uint32_t length
153 return m_sendaction(m, friendnumber, action, length); 153 return m_sendaction(m, friendnumber, action, length);
154} 154}
155 155
156/* Set friendnumber's nickname.
157 * name must be a string of maximum MAX_NAME_LENGTH length.
158 * length must be at least 1 byte.
159 * length is the length of name with the NULL terminator.
160 *
161 * return 0 if success.
162 * return -1 if failure.
163 */
164int tox_setfriendname(void *tox, int friendnumber, uint8_t *name, uint16_t length)
165{
166 Messenger *m = tox;
167 return setfriendname(m, friendnumber, name, length);
168}
169
156/* Set our nickname. 170/* Set our nickname.
157 * name must be a string of maximum MAX_NAME_LENGTH length. 171 * name must be a string of maximum MAX_NAME_LENGTH length.
158 * length must be at least 1 byte. 172 * length must be at least 1 byte.
@@ -262,16 +276,24 @@ void tox_set_sends_receipts(void *tox, int friendnumber, int yesno)
262 m_set_sends_receipts(m, friendnumber, yesno); 276 m_set_sends_receipts(m, friendnumber, yesno);
263} 277}
264 278
265/* Allocate and return a list of valid friend id's. List must be freed by the 279/* Return the number of friends in the instance m.
266 * caller. 280 * You should use this to determine how much memory to allocate
267 * 281 * for copy_friendlist. */
268 * retun 0 if success. 282uint32_t tox_count_friendlist(void *tox)
269 * return -1 if failure. 283{
270 */ 284 Messenger *m = tox;
271int tox_get_friendlist(void *tox, int **out_list, uint32_t *out_list_length) 285 return count_friendlist(m);
286}
287
288/* Copy a list of valid friend IDs into the array out_list.
289 * If out_list is NULL, returns 0.
290 * Otherwise, returns the number of elements copied.
291 * If the array was too small, the contents
292 * of out_list will be truncated to list_size. */
293uint32_t tox_copy_friendlist(void *tox, int *out_list, uint32_t list_size)
272{ 294{
273 Messenger *m = tox; 295 Messenger *m = tox;
274 return get_friendlist(m, out_list, out_list_length); 296 return copy_friendlist(m, out_list, list_size);
275} 297}
276 298
277/* Set the function that will be executed when a friend request is received. 299/* Set the function that will be executed when a friend request is received.
diff --git a/toxcore/tox.h b/toxcore/tox.h
index b39008fe..eabbb1af 100644
--- a/toxcore/tox.h
+++ b/toxcore/tox.h
@@ -36,6 +36,13 @@
36#include <windows.h> 36#include <windows.h>
37#include <ws2tcpip.h> 37#include <ws2tcpip.h>
38 38
39typedef INT sa_family_t;
40#ifndef true
41#define true 1
42#endif
43#ifndef false
44#define false 0
45#endif
39#else 46#else
40 47
41#include <netinet/ip.h> 48#include <netinet/ip.h>
@@ -214,6 +221,16 @@ uint32_t tox_sendmessage_withid(Tox *tox, int friendnumber, uint32_t theid, uint
214 */ 221 */
215int tox_sendaction(Tox *tox, int friendnumber, uint8_t *action, uint32_t length); 222int tox_sendaction(Tox *tox, int friendnumber, uint8_t *action, uint32_t length);
216 223
224/* Set friendnumber's nickname.
225 * name must be a string of maximum MAX_NAME_LENGTH length.
226 * length must be at least 1 byte.
227 * length is the length of name with the NULL terminator.
228 *
229 * return 0 if success.
230 * return -1 if failure.
231 */
232int tox_setfriendname(void *tox, int friendnumber, uint8_t *name, uint16_t length);
233
217/* Set our nickname. 234/* Set our nickname.
218 * name must be a string of maximum MAX_NAME_LENGTH length. 235 * name must be a string of maximum MAX_NAME_LENGTH length.
219 * length must be at least 1 byte. 236 * length must be at least 1 byte.
@@ -280,13 +297,17 @@ TOX_USERSTATUS tox_get_selfuserstatus(Tox *tox);
280 */ 297 */
281void tox_set_sends_receipts(Tox *tox, int friendnumber, int yesno); 298void tox_set_sends_receipts(Tox *tox, int friendnumber, int yesno);
282 299
283/* Allocate and return a list of valid friend id's. List must be freed by the 300/* Return the number of friends in the instance m.
284 * caller. 301 * You should use this to determine how much memory to allocate
285 * 302 * for copy_friendlist. */
286 * retun 0 if success. 303uint32_t tox_count_friendlist(void *tox);
287 * return -1 if failure. 304
288 */ 305/* Copy a list of valid friend IDs into the array out_list.
289int tox_get_friendlist(void *tox, int **out_list, uint32_t *out_list_length); 306 * If out_list is NULL, returns 0.
307 * Otherwise, returns the number of elements copied.
308 * If the array was too small, the contents
309 * of out_list will be truncated to list_size. */
310uint32_t tox_copy_friendlist(void *tox, int *out_list, uint32_t list_size);
290 311
291/* Set the function that will be executed when a friend request is received. 312/* Set the function that will be executed when a friend request is received.
292 * Function format is function(uint8_t * public_key, uint8_t * data, uint16_t length) 313 * Function format is function(uint8_t * public_key, uint8_t * data, uint16_t length)