summaryrefslogtreecommitdiff
path: root/toxcore
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2014-03-06 09:55:50 -0500
committerirungentoo <irungentoo@gmail.com>2014-03-06 09:55:50 -0500
commit51393e62224f397c7c670e11327b5528088744d9 (patch)
tree536674fd3de1e3601f7233460616ea2503ab1967 /toxcore
parent3bcc6e2ae547ae77f14d7d140a363cc2cc01f01a (diff)
Made save more portable.
This should fix the issue of the friends list getting cleared when something in it changes.
Diffstat (limited to 'toxcore')
-rw-r--r--toxcore/Messenger.c145
1 files changed, 140 insertions, 5 deletions
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index 31b82fa1..02c4a362 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -1940,6 +1940,7 @@ void do_friends(Messenger *m)
1940 1940
1941 if (m->friend_typingchange) 1941 if (m->friend_typingchange)
1942 m->friend_typingchange(m, i, typing, m->friend_typingchange_userdata); 1942 m->friend_typingchange(m, i, typing, m->friend_typingchange_userdata);
1943
1943 break; 1944 break;
1944 } 1945 }
1945 1946
@@ -2321,7 +2322,8 @@ void wait_cleanup_messenger(Messenger *m, uint8_t *data, uint16_t len)
2321 2322
2322/* new messenger format for load/save, more robust and forward compatible */ 2323/* new messenger format for load/save, more robust and forward compatible */
2323 2324
2324#define MESSENGER_STATE_COOKIE_GLOBAL 0x15ed1b1e 2325#define MESSENGER_STATE_COOKIE_GLOBAL_OLD 0x15ed1b1e
2326#define MESSENGER_STATE_COOKIE_GLOBAL 0x15ed1b1f
2325 2327
2326#define MESSENGER_STATE_COOKIE_TYPE 0x01ce 2328#define MESSENGER_STATE_COOKIE_TYPE 0x01ce
2327#define MESSENGER_STATE_TYPE_NOSPAMKEYS 1 2329#define MESSENGER_STATE_TYPE_NOSPAMKEYS 1
@@ -2329,6 +2331,87 @@ void wait_cleanup_messenger(Messenger *m, uint8_t *data, uint16_t len)
2329#define MESSENGER_STATE_TYPE_FRIENDS 3 2331#define MESSENGER_STATE_TYPE_FRIENDS 3
2330#define MESSENGER_STATE_TYPE_NAME 4 2332#define MESSENGER_STATE_TYPE_NAME 4
2331 2333
2334struct SAVED_FRIEND {
2335 uint8_t status;
2336 uint8_t client_id[CLIENT_ID_SIZE];
2337 uint8_t info[MAX_DATA_SIZE]; // the data that is sent during the friend requests we do.
2338 uint16_t info_size; // Length of the info.
2339 uint8_t name[MAX_NAME_LENGTH];
2340 uint16_t name_length;
2341 uint8_t statusmessage[MAX_STATUSMESSAGE_LENGTH];
2342 uint16_t statusmessage_length;
2343 uint8_t userstatus;
2344 uint32_t friendrequest_nospam;
2345};
2346
2347static uint32_t saved_friendslist_size(Messenger *m)
2348{
2349 return count_friendlist(m) * sizeof(struct SAVED_FRIEND);
2350}
2351
2352static uint32_t friends_list_save(Messenger *m, uint8_t *data)
2353{
2354 uint32_t i;
2355 uint32_t num = 0;
2356
2357 for (i = 0; i < m->numfriends; i++) {
2358 if (m->friendlist[i].status > 0) {
2359 struct SAVED_FRIEND temp;
2360 memset(&temp, 0, sizeof(struct SAVED_FRIEND));
2361 temp.status = m->friendlist[i].status;
2362 memcpy(temp.client_id, m->friendlist[i].client_id, CLIENT_ID_SIZE);
2363
2364 if (temp.status < 3) {
2365 memcpy(temp.info, m->friendlist[i].info, m->friendlist[i].info_size);
2366 temp.info_size = htons(m->friendlist[i].info_size);
2367 temp.friendrequest_nospam = m->friendlist[i].friendrequest_nospam;
2368 } else {
2369 memcpy(temp.name, m->friendlist[i].name, m->friendlist[i].name_length);
2370 temp.name_length = htons(m->friendlist[i].name_length);
2371 memcpy(temp.statusmessage, m->friendlist[i].statusmessage, m->friendlist[i].statusmessage_length);
2372 temp.statusmessage_length = htons(m->friendlist[i].statusmessage_length);
2373 temp.userstatus = m->friendlist[i].userstatus;
2374 }
2375
2376 memcpy(data + num * sizeof(struct SAVED_FRIEND), &temp, sizeof(struct SAVED_FRIEND));
2377 num++;
2378 }
2379 }
2380
2381 return num * sizeof(struct SAVED_FRIEND);
2382}
2383
2384static int friends_list_load(Messenger *m, uint8_t *data, uint32_t length)
2385{
2386 if (length % sizeof(struct SAVED_FRIEND) != 0)
2387 return -1;
2388
2389 uint32_t num = length / sizeof(struct SAVED_FRIEND);
2390 uint32_t i;
2391
2392 for (i = 0; i < num; ++i) {
2393 struct SAVED_FRIEND temp;
2394 memcpy(&temp, data + i * sizeof(struct SAVED_FRIEND), sizeof(struct SAVED_FRIEND));
2395
2396 if (temp.status >= 3) {
2397 int fnum = m_addfriend_norequest(m, temp.client_id);
2398 setfriendname(m, fnum, temp.name, ntohs(temp.name_length));
2399 set_friend_statusmessage(m, fnum, temp.statusmessage, ntohs(temp.statusmessage_length));
2400 set_friend_userstatus(m, fnum, temp.userstatus);
2401 } else if (temp.status != 0) {
2402 /* TODO: This is not a good way to do this. */
2403 uint8_t address[FRIEND_ADDRESS_SIZE];
2404 id_copy(address, temp.client_id);
2405 memcpy(address + crypto_box_PUBLICKEYBYTES, &(temp.friendrequest_nospam), sizeof(uint32_t));
2406 uint16_t checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum));
2407 memcpy(address + crypto_box_PUBLICKEYBYTES + sizeof(uint32_t), &checksum, sizeof(checksum));
2408 m_addfriend(m, address, temp.info, temp.info_size);
2409 }
2410 }
2411
2412 return num;
2413}
2414
2332/* return size of the messenger data (for saving) */ 2415/* return size of the messenger data (for saving) */
2333uint32_t messenger_size(Messenger *m) 2416uint32_t messenger_size(Messenger *m)
2334{ 2417{
@@ -2336,7 +2419,7 @@ uint32_t messenger_size(Messenger *m)
2336 return size32 * 2 // global cookie 2419 return size32 * 2 // global cookie
2337 + sizesubhead + sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES 2420 + sizesubhead + sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES
2338 + sizesubhead + DHT_size(m->dht) // DHT 2421 + sizesubhead + DHT_size(m->dht) // DHT
2339 + sizesubhead + sizeof(Friend) * m->numfriends // Friendlist itself. 2422 + sizesubhead + saved_friendslist_size(m) // Friendlist itself.
2340 + sizesubhead + m->name_length // Own nickname. 2423 + sizesubhead + m->name_length // Own nickname.
2341 ; 2424 ;
2342} 2425}
@@ -2350,6 +2433,7 @@ static uint8_t *z_state_save_subheader(uint8_t *data, uint32_t len, uint16_t typ
2350 return data; 2433 return data;
2351} 2434}
2352 2435
2436
2353/* Save the messenger in data of size Messenger_size(). */ 2437/* Save the messenger in data of size Messenger_size(). */
2354void messenger_save(Messenger *m, uint8_t *data) 2438void messenger_save(Messenger *m, uint8_t *data)
2355{ 2439{
@@ -2378,10 +2462,10 @@ void messenger_save(Messenger *m, uint8_t *data)
2378 DHT_save(m->dht, data); 2462 DHT_save(m->dht, data);
2379 data += len; 2463 data += len;
2380 2464
2381 len = sizeof(Friend) * m->numfriends; 2465 len = saved_friendslist_size(m);
2382 type = MESSENGER_STATE_TYPE_FRIENDS; 2466 type = MESSENGER_STATE_TYPE_FRIENDS;
2383 data = z_state_save_subheader(data, len, type); 2467 data = z_state_save_subheader(data, len, type);
2384 memcpy(data, m->friendlist, len); 2468 friends_list_save(m, data);
2385 data += len; 2469 data += len;
2386 2470
2387 len = m->name_length; 2471 len = m->name_length;
@@ -2391,7 +2475,7 @@ void messenger_save(Messenger *m, uint8_t *data)
2391 data += len; 2475 data += len;
2392} 2476}
2393 2477
2394static int messenger_load_state_callback(void *outer, uint8_t *data, uint32_t length, uint16_t type) 2478static int messenger_load_state_callback_old(void *outer, uint8_t *data, uint32_t length, uint16_t type)
2395{ 2479{
2396 Messenger *m = outer; 2480 Messenger *m = outer;
2397 2481
@@ -2459,6 +2543,53 @@ static int messenger_load_state_callback(void *outer, uint8_t *data, uint32_t le
2459 return 0; 2543 return 0;
2460} 2544}
2461 2545
2546static int messenger_load_state_callback(void *outer, uint8_t *data, uint32_t length, uint16_t type)
2547{
2548 Messenger *m = outer;
2549
2550 switch (type) {
2551 case MESSENGER_STATE_TYPE_NOSPAMKEYS:
2552 if (length == crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t)) {
2553 set_nospam(&(m->fr), *(uint32_t *)data);
2554 load_keys(m->net_crypto, &data[sizeof(uint32_t)]);
2555#ifdef ENABLE_ASSOC_DHT
2556
2557 if (m->dht->assoc)
2558 Assoc_self_client_id_changed(m->dht->assoc, m->net_crypto->self_public_key);
2559
2560#endif
2561 } else
2562 return -1; /* critical */
2563
2564 break;
2565
2566 case MESSENGER_STATE_TYPE_DHT:
2567 DHT_load(m->dht, data, length);
2568 break;
2569
2570 case MESSENGER_STATE_TYPE_FRIENDS:
2571 friends_list_load(m, data, length);
2572 break;
2573
2574 case MESSENGER_STATE_TYPE_NAME:
2575 if ((length > 0) && (length < MAX_NAME_LENGTH)) {
2576 setname(m, data, length);
2577 }
2578
2579 break;
2580
2581#ifdef DEBUG
2582
2583 default:
2584 fprintf(stderr, "Load state: contains unrecognized part (len %u, type %u)\n",
2585 length, type);
2586 break;
2587#endif
2588 }
2589
2590 return 0;
2591}
2592
2462/* Load the messenger from data of size length. */ 2593/* Load the messenger from data of size length. */
2463int messenger_load(Messenger *m, uint8_t *data, uint32_t length) 2594int messenger_load(Messenger *m, uint8_t *data, uint32_t length)
2464{ 2595{
@@ -2472,6 +2603,10 @@ int messenger_load(Messenger *m, uint8_t *data, uint32_t length)
2472 if (!data32[0] && (data32[1] == MESSENGER_STATE_COOKIE_GLOBAL)) 2603 if (!data32[0] && (data32[1] == MESSENGER_STATE_COOKIE_GLOBAL))
2473 return load_state(messenger_load_state_callback, m, data + cookie_len, 2604 return load_state(messenger_load_state_callback, m, data + cookie_len,
2474 length - cookie_len, MESSENGER_STATE_COOKIE_TYPE); 2605 length - cookie_len, MESSENGER_STATE_COOKIE_TYPE);
2606
2607 else if (!data32[0] && (data32[1] == MESSENGER_STATE_COOKIE_GLOBAL_OLD))
2608 return load_state(messenger_load_state_callback_old, m, data + cookie_len,
2609 length - cookie_len, MESSENGER_STATE_COOKIE_TYPE);
2475 else /* old state file */ 2610 else /* old state file */
2476 return -1; 2611 return -1;
2477} 2612}