summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--auto_tests/tox_test.c30
-rw-r--r--toxcore/DHT.c191
-rw-r--r--toxcore/DHT.h10
3 files changed, 111 insertions, 120 deletions
diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c
index 501c93dc..72bc27ee 100644
--- a/auto_tests/tox_test.c
+++ b/auto_tests/tox_test.c
@@ -286,6 +286,16 @@ void tox_connection_status(Tox *tox, TOX_CONNECTION connection_status, void *use
286 286
287START_TEST(test_one) 287START_TEST(test_one)
288{ 288{
289 {
290 TOX_ERR_OPTIONS_NEW o_err;
291 struct Tox_Options *o1 = tox_options_new(&o_err);
292 struct Tox_Options o2;
293 tox_options_default(&o2);
294 ck_assert_msg(o_err == TOX_ERR_OPTIONS_NEW_OK, "tox_options_new wrong error");
295 ck_assert_msg(memcmp(o1, &o2, sizeof(struct Tox_Options)) == 0, "tox_options_new error");
296 tox_options_free(o1);
297 }
298
289 Tox *tox1 = tox_new(0, 0); 299 Tox *tox1 = tox_new(0, 0);
290 Tox *tox2 = tox_new(0, 0); 300 Tox *tox2 = tox_new(0, 0);
291 301
@@ -468,6 +478,12 @@ START_TEST(test_few_clients)
468 478
469 printf("tox clients messaging succeeded\n"); 479 printf("tox clients messaging succeeded\n");
470 480
481 unsigned int save_size1 = tox_get_savedata_size(tox2);
482 ck_assert_msg(save_size1 != 0 && save_size1 < 4096, "save is invalid size %u", save_size1);
483 printf("%u\n", save_size1);
484 uint8_t save1[save_size1];
485 tox_get_savedata(tox2, save1);
486
471 tox_callback_friend_name(tox3, print_nickchange, &to_compare); 487 tox_callback_friend_name(tox3, print_nickchange, &to_compare);
472 TOX_ERR_SET_INFO err_n; 488 TOX_ERR_SET_INFO err_n;
473 bool succ = tox_self_set_name(tox2, (uint8_t *)"Gentoo", sizeof("Gentoo"), &err_n); 489 bool succ = tox_self_set_name(tox2, (uint8_t *)"Gentoo", sizeof("Gentoo"), &err_n);
@@ -785,6 +801,14 @@ START_TEST(test_many_clients)
785 801
786 uint8_t address[TOX_ADDRESS_SIZE]; 802 uint8_t address[TOX_ADDRESS_SIZE];
787 803
804 unsigned int num_f = 0;
805
806 for (i = 0; i < NUM_TOXES; ++i) {
807 num_f += tox_self_get_friend_list_size(toxes[i]);
808 }
809
810 ck_assert_msg(num_f == 0, "bad num friends: %u", num_f);
811
788 for (i = 0; i < NUM_FRIENDS; ++i) { 812 for (i = 0; i < NUM_FRIENDS; ++i) {
789loop_top: 813loop_top:
790 pairs[i].tox1 = rand() % NUM_TOXES; 814 pairs[i].tox1 = rand() % NUM_TOXES;
@@ -807,6 +831,12 @@ loop_top:
807 ck_assert_msg(num != UINT32_MAX && test == TOX_ERR_FRIEND_ADD_OK, "Failed to add friend error code: %i", test); 831 ck_assert_msg(num != UINT32_MAX && test == TOX_ERR_FRIEND_ADD_OK, "Failed to add friend error code: %i", test);
808 } 832 }
809 833
834 for (i = 0; i < NUM_TOXES; ++i) {
835 num_f += tox_self_get_friend_list_size(toxes[i]);
836 }
837
838 ck_assert_msg(num_f == NUM_FRIENDS, "bad num friends: %u", num_f);
839
810 while (1) { 840 while (1) {
811 uint16_t counter = 0; 841 uint16_t counter = 0;
812 842
diff --git a/toxcore/DHT.c b/toxcore/DHT.c
index 8cd8852c..ca87ad90 100644
--- a/toxcore/DHT.c
+++ b/toxcore/DHT.c
@@ -2244,18 +2244,17 @@ DHT *new_DHT(Networking_Core *net)
2244 2244
2245void do_DHT(DHT *dht) 2245void do_DHT(DHT *dht)
2246{ 2246{
2247 // Load friends/clients if first call to do_DHT
2248 if (dht->has_loaded_friends_clients == 0) {
2249 dht->has_loaded_friends_clients = 1;
2250 DHT_connect_after_load(dht);
2251 }
2252
2253 unix_time_update(); 2247 unix_time_update();
2254 2248
2255 if (dht->last_run == unix_time()) { 2249 if (dht->last_run == unix_time()) {
2256 return; 2250 return;
2257 } 2251 }
2258 2252
2253 // Load friends/clients if first call to do_DHT
2254 if (dht->loaded_num_nodes) {
2255 DHT_connect_after_load(dht);
2256 }
2257
2259 do_Close(dht); 2258 do_Close(dht);
2260 do_DHT_friends(dht); 2259 do_DHT_friends(dht);
2261 do_NAT(dht); 2260 do_NAT(dht);
@@ -2282,33 +2281,37 @@ void kill_DHT(DHT *dht)
2282 ping_array_free_all(&dht->dht_harden_ping_array); 2281 ping_array_free_all(&dht->dht_harden_ping_array);
2283 kill_ping(dht->ping); 2282 kill_ping(dht->ping);
2284 free(dht->friends_list); 2283 free(dht->friends_list);
2285 free(dht->loaded_friends_list); 2284 free(dht->loaded_nodes_list);
2286 free(dht->loaded_clients_list);
2287 free(dht); 2285 free(dht);
2288} 2286}
2289 2287
2290/* new DHT format for load/save, more robust and forward compatible */ 2288/* new DHT format for load/save, more robust and forward compatible */
2291 2289//TODO: Move this closer to Messenger.
2292#define DHT_STATE_COOKIE_GLOBAL 0x159000d 2290#define DHT_STATE_COOKIE_GLOBAL 0x159000d
2293 2291
2294#define DHT_STATE_COOKIE_TYPE 0x11ce 2292#define DHT_STATE_COOKIE_TYPE 0x11ce
2295#define DHT_STATE_TYPE_FRIENDS_ASSOC46 3 2293#define DHT_STATE_TYPE_NODES 4
2296#define DHT_STATE_TYPE_CLIENTS_ASSOC46 4
2297 2294
2298/* Get the size of the DHT (for saving). */ 2295/* Get the size of the DHT (for saving). */
2299uint32_t DHT_size(const DHT *dht) 2296uint32_t DHT_size(const DHT *dht)
2300{ 2297{
2301 uint32_t num = 0, i; 2298 uint32_t num = 0, i, j;
2299
2300 for (i = 0; i < LCLIENT_LIST; ++i) {
2301 num += (dht->close_clientlist[i].assoc4.timestamp != 0) + (dht->close_clientlist[i].assoc6.timestamp != 0);
2302 }
2302 2303
2303 for (i = 0; i < LCLIENT_LIST; ++i) 2304 for (i = 0; i < DHT_FAKE_FRIEND_NUMBER && i < dht->num_friends; ++i) {
2304 if ((dht->close_clientlist[i].assoc4.timestamp != 0) || 2305 DHT_Friend *fr = &dht->friends_list[i];
2305 (dht->close_clientlist[i].assoc6.timestamp != 0)) 2306
2306 num++; 2307 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
2308 num += (fr->client_list[j].assoc4.timestamp != 0) + (fr->client_list[j].assoc6.timestamp != 0);
2309 }
2310 }
2307 2311
2308 uint32_t size32 = sizeof(uint32_t), sizesubhead = size32 * 2; 2312 uint32_t size32 = sizeof(uint32_t), sizesubhead = size32 * 2;
2309 return size32 2313 return size32
2310 + sizesubhead + sizeof(DHT_Friend) * dht->num_friends 2314 + sizesubhead + sizeof(Node_format) * num;
2311 + sizesubhead + sizeof(Client_data) * num;
2312} 2315}
2313 2316
2314static uint8_t *z_state_save_subheader(uint8_t *data, uint32_t len, uint16_t type) 2317static uint8_t *z_state_save_subheader(uint8_t *data, uint32_t len, uint16_t type)
@@ -2328,92 +2331,77 @@ void DHT_save(DHT *dht, uint8_t *data)
2328 *(uint32_t *)data = DHT_STATE_COOKIE_GLOBAL; 2331 *(uint32_t *)data = DHT_STATE_COOKIE_GLOBAL;
2329 data += sizeof(uint32_t); 2332 data += sizeof(uint32_t);
2330 2333
2331 len = sizeof(DHT_Friend) * dht->num_friends; 2334 uint32_t num, i, j;
2332 type = DHT_STATE_TYPE_FRIENDS_ASSOC46;
2333 data = z_state_save_subheader(data, len, type);
2334 memcpy(data, dht->friends_list, len);
2335 data += len;
2336 2335
2337 uint32_t num = 0, i; 2336 uint8_t *old_data = data;
2338 2337
2339 for (i = 0; i < LCLIENT_LIST; ++i) 2338 /* get right offset. we write the actual header later. */
2340 if ((dht->close_clientlist[i].assoc4.timestamp != 0) || 2339 data = z_state_save_subheader(data, 0, 0);
2341 (dht->close_clientlist[i].assoc6.timestamp != 0))
2342 num++;
2343 2340
2344 len = num * sizeof(Client_data); 2341 Node_format *clients = (Node_format *)data;
2345 type = DHT_STATE_TYPE_CLIENTS_ASSOC46;
2346 data = z_state_save_subheader(data, len, type);
2347 2342
2348 if (num) { 2343 for (num = 0, i = 0; i < LCLIENT_LIST; ++i) {
2349 Client_data *clients = (Client_data *)data; 2344 if (dht->close_clientlist[i].assoc4.timestamp != 0) {
2345 memcpy(clients[num].public_key, dht->close_clientlist[i].client_id, crypto_box_PUBLICKEYBYTES);
2346 clients[num].ip_port = dht->close_clientlist[i].assoc4.ip_port;
2347 ++num;
2348 }
2350 2349
2351 for (num = 0, i = 0; i < LCLIENT_LIST; ++i) 2350 if (dht->close_clientlist[i].assoc6.timestamp != 0) {
2352 if ((dht->close_clientlist[i].assoc4.timestamp != 0) || 2351 memcpy(clients[num].public_key, dht->close_clientlist[i].client_id, crypto_box_PUBLICKEYBYTES);
2353 (dht->close_clientlist[i].assoc6.timestamp != 0)) 2352 clients[num].ip_port = dht->close_clientlist[i].assoc6.ip_port;
2354 memcpy(&clients[num++], &dht->close_clientlist[i], sizeof(Client_data)); 2353 ++num;
2354 }
2355 } 2355 }
2356}
2357 2356
2358static void DHT_bootstrap_loaded_clients(DHT *dht) 2357 for (i = 0; i < DHT_FAKE_FRIEND_NUMBER && i < dht->num_friends; ++i) {
2359{ 2358 DHT_Friend *fr = &dht->friends_list[i];
2360 if (!dht->loaded_clients_list)
2361 return;
2362 2359
2363 uint32_t i;
2364
2365 Client_data *client_list = dht->loaded_clients_list;
2366 uint32_t client_count = dht->loaded_num_clients;
2367
2368 for (i = 0; i < client_count; ++i) {
2369 if (client_list[i].assoc4.timestamp != 0)
2370 DHT_bootstrap(dht, client_list[i].assoc4.ip_port, client_list[i].client_id);
2371
2372 if (client_list[i].assoc6.timestamp != 0)
2373 DHT_bootstrap(dht, client_list[i].assoc6.ip_port, client_list[i].client_id);
2374 }
2375}
2376
2377static void getnodes_of_loaded_friend_clients(DHT *dht)
2378{
2379 if (!dht->loaded_friends_list)
2380 return;
2381
2382 uint32_t i, j;
2383
2384 DHT_Friend *friend_list = dht->loaded_friends_list;
2385 uint32_t friend_count = dht->loaded_num_friends;
2386
2387 for (i = 0; i < friend_count; ++i) {
2388 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 2360 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
2389 Client_data *client = &friend_list[i].client_list[j]; 2361 if (fr->client_list[j].assoc4.timestamp != 0) {
2390 2362 memcpy(clients[num].public_key, fr->client_list[j].client_id, crypto_box_PUBLICKEYBYTES);
2391 if (client->assoc4.timestamp != 0) 2363 clients[num].ip_port = fr->client_list[j].assoc4.ip_port;
2392 getnodes(dht, client->assoc4.ip_port, client->client_id, friend_list[i].client_id, NULL); 2364 ++num;
2365 }
2393 2366
2394 if (client->assoc6.timestamp != 0) 2367 if (fr->client_list[j].assoc6.timestamp != 0) {
2395 getnodes(dht, client->assoc6.ip_port, client->client_id, friend_list[i].client_id, NULL); 2368 memcpy(clients[num].public_key, fr->client_list[j].client_id, crypto_box_PUBLICKEYBYTES);
2369 clients[num].ip_port = fr->client_list[j].assoc6.ip_port;
2370 ++num;
2371 }
2396 } 2372 }
2397 } 2373 }
2374
2375 z_state_save_subheader(old_data, num * sizeof(Node_format), DHT_STATE_TYPE_NODES);
2398} 2376}
2399 2377
2378/* Bootstrap from this number of nodes every time DHT_connect_after_load() is called */
2379#define SAVE_BOOTSTAP_FREQUENCY 8
2380
2400/* Start sending packets after DHT loaded_friends_list and loaded_clients_list are set */ 2381/* Start sending packets after DHT loaded_friends_list and loaded_clients_list are set */
2401int DHT_connect_after_load(DHT *dht) 2382int DHT_connect_after_load(DHT *dht)
2402{ 2383{
2403 if (dht == NULL) 2384 if (dht == NULL)
2404 return -1; 2385 return -1;
2405 2386
2406 getnodes_of_loaded_friend_clients(dht); 2387 if (!dht->loaded_nodes_list)
2407 DHT_bootstrap_loaded_clients(dht); 2388 return -1;
2389
2390 /* DHT is connected, stop. */
2391 if (DHT_non_lan_connected(dht)) {
2392 free(dht->loaded_nodes_list);
2393 dht->loaded_nodes_list = NULL;
2394 dht->loaded_num_nodes = 0;
2395 return 0;
2396 }
2408 2397
2409 // Loaded lists were allocd, free them 2398 unsigned int i;
2410 free(dht->loaded_friends_list);
2411 dht->loaded_friends_list = NULL;
2412 dht->loaded_num_friends = 0;
2413 2399
2414 free(dht->loaded_clients_list); 2400 for (i = 0; i < dht->loaded_num_nodes && i < SAVE_BOOTSTAP_FREQUENCY; ++i) {
2415 dht->loaded_clients_list = NULL; 2401 unsigned int index = dht->loaded_nodes_index % dht->loaded_num_nodes;
2416 dht->loaded_num_clients = 0; 2402 DHT_bootstrap(dht, dht->loaded_nodes_list[index].ip_port, dht->loaded_nodes_list[index].public_key);
2403 ++dht->loaded_nodes_index;
2404 }
2417 2405
2418 return 0; 2406 return 0;
2419} 2407}
@@ -2424,46 +2412,23 @@ static int dht_load_state_callback(void *outer, const uint8_t *data, uint32_t le
2424 uint32_t num, i; 2412 uint32_t num, i;
2425 2413
2426 switch (type) { 2414 switch (type) {
2427 case DHT_STATE_TYPE_FRIENDS_ASSOC46: 2415 case DHT_STATE_TYPE_NODES:
2428 if (length % sizeof(DHT_Friend) != 0) 2416 if ((length % sizeof(Node_format)) != 0)
2429 break;
2430
2431 { /* localize declarations */
2432 DHT_Friend *friend_list = (DHT_Friend *)data;
2433 num = length / sizeof(DHT_Friend);
2434
2435 free(dht->loaded_friends_list);
2436 // Copy to loaded_friends_list
2437 dht->loaded_friends_list = calloc(num, sizeof(DHT_Friend));
2438
2439 for (i = 0; i < num; i++)
2440 memcpy(&(dht->loaded_friends_list[i]), &(friend_list[i]), sizeof(DHT_Friend));
2441
2442 dht->loaded_num_friends = num;
2443
2444 dht->has_loaded_friends_clients = 1;
2445 } /* localize declarations */
2446
2447 break;
2448
2449 case DHT_STATE_TYPE_CLIENTS_ASSOC46:
2450 if ((length % sizeof(Client_data)) != 0)
2451 break; 2417 break;
2452 2418
2453 { /* localize declarations */ 2419 { /* localize declarations */
2454 num = length / sizeof(Client_data); 2420 num = length / sizeof(Node_format);
2455 Client_data *client_list = (Client_data *)data; 2421 Node_format *client_list = (Node_format *)data;
2456 2422
2457 free(dht->loaded_clients_list); 2423 free(dht->loaded_nodes_list);
2458 // Copy to loaded_clients_list 2424 // Copy to loaded_clients_list
2459 dht->loaded_clients_list = calloc(num, sizeof(Client_data)); 2425 dht->loaded_nodes_list = calloc(num, sizeof(Node_format));
2460 2426
2461 for (i = 0; i < num; i++) 2427 for (i = 0; i < num; i++)
2462 memcpy(&(dht->loaded_clients_list[i]), &(client_list[i]), sizeof(Client_data)); 2428 memcpy(&(dht->loaded_nodes_list[i]), &(client_list[i]), sizeof(Node_format));
2463 2429
2464 dht->loaded_num_clients = num; 2430 dht->loaded_num_nodes = num;
2465 2431
2466 dht->has_loaded_friends_clients = 1;
2467 } /* localize declarations */ 2432 } /* localize declarations */
2468 2433
2469 break; 2434 break;
diff --git a/toxcore/DHT.h b/toxcore/DHT.h
index 318a6002..c612c287 100644
--- a/toxcore/DHT.h
+++ b/toxcore/DHT.h
@@ -211,13 +211,9 @@ typedef struct {
211 DHT_Friend *friends_list; 211 DHT_Friend *friends_list;
212 uint16_t num_friends; 212 uint16_t num_friends;
213 213
214 // Used after loading of file (tox_load), but no longer needed after connect (tox_connect) 214 Node_format *loaded_nodes_list;
215 // Unsure if friends_list and num_friends could just be used instead? 215 uint32_t loaded_num_nodes;
216 int has_loaded_friends_clients; // Whether or not we have loaded on the first do_DHT 216 unsigned int loaded_nodes_index;
217 DHT_Friend *loaded_friends_list;
218 uint32_t loaded_num_friends;
219 Client_data *loaded_clients_list;
220 uint32_t loaded_num_clients;
221 217
222 Shared_Keys shared_keys_recv; 218 Shared_Keys shared_keys_recv;
223 Shared_Keys shared_keys_sent; 219 Shared_Keys shared_keys_sent;