diff options
author | irungentoo <irungentoo@gmail.com> | 2014-03-06 09:55:50 -0500 |
---|---|---|
committer | irungentoo <irungentoo@gmail.com> | 2014-03-06 09:55:50 -0500 |
commit | 51393e62224f397c7c670e11327b5528088744d9 (patch) | |
tree | 536674fd3de1e3601f7233460616ea2503ab1967 /toxcore | |
parent | 3bcc6e2ae547ae77f14d7d140a363cc2cc01f01a (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.c | 145 |
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 | ||
2334 | struct 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 | |||
2347 | static uint32_t saved_friendslist_size(Messenger *m) | ||
2348 | { | ||
2349 | return count_friendlist(m) * sizeof(struct SAVED_FRIEND); | ||
2350 | } | ||
2351 | |||
2352 | static 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 | |||
2384 | static 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) */ |
2333 | uint32_t messenger_size(Messenger *m) | 2416 | uint32_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(). */ |
2354 | void messenger_save(Messenger *m, uint8_t *data) | 2438 | void 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 | ||
2394 | static int messenger_load_state_callback(void *outer, uint8_t *data, uint32_t length, uint16_t type) | 2478 | static 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 | ||
2546 | static 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. */ |
2463 | int messenger_load(Messenger *m, uint8_t *data, uint32_t length) | 2594 | int 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 | } |