summaryrefslogtreecommitdiff
path: root/toxcore/Messenger.c
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2013-09-16 08:11:56 -0700
committerirungentoo <irungentoo@gmail.com>2013-09-16 08:11:56 -0700
commit98fb06c1b75a3bd5ad674daf5c0496a712bc0551 (patch)
treee36833b55b522251b3cc5d0734d62196eb6ac0b0 /toxcore/Messenger.c
parentd17249a65d64c90c79ba6e2a7bcf914d1441cb4e (diff)
parenta069f67ab30c24d9ab0df61814941a12e5e0da34 (diff)
Merge pull request #576 from FullName/MessengerLoadSave
State loading/saving: Instead of a blob, segment into sections marked with tags.
Diffstat (limited to 'toxcore/Messenger.c')
-rw-r--r--toxcore/Messenger.c180
1 files changed, 161 insertions, 19 deletions
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index c46e3938..f2be6008 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -1331,7 +1331,7 @@ void doMessenger(Messenger *m)
1331} 1331}
1332 1332
1333/* return size of the messenger data (for saving) */ 1333/* return size of the messenger data (for saving) */
1334uint32_t Messenger_size(Messenger *m) 1334uint32_t Messenger_size_old(Messenger *m)
1335{ 1335{
1336 return crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES 1336 return crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES
1337 + sizeof(uint32_t) // nospam. 1337 + sizeof(uint32_t) // nospam.
@@ -1344,8 +1344,8 @@ uint32_t Messenger_size(Messenger *m)
1344 ; 1344 ;
1345} 1345}
1346 1346
1347/* Save the messenger in data of size Messenger_size(). */ 1347/* Save the messenger in data of size Messenger_size(). Old version without cookies. */
1348void Messenger_save(Messenger *m, uint8_t *data) 1348static void Messenger_save_old(Messenger *m, uint8_t *data)
1349{ 1349{
1350 save_keys(m->net_crypto, data); 1350 save_keys(m->net_crypto, data);
1351 data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; 1351 data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES;
@@ -1372,8 +1372,8 @@ void Messenger_save(Messenger *m, uint8_t *data)
1372 memcpy(data, m->name, small_size); 1372 memcpy(data, m->name, small_size);
1373} 1373}
1374 1374
1375/* Load the messenger from data of size length. */ 1375/* Load the messenger from data of size length. Old version without cookies. */
1376int Messenger_load(Messenger *m, uint8_t *data, uint32_t length) 1376static int Messenger_load_old(Messenger *m, uint8_t *data, uint32_t length)
1377{ 1377{
1378 if (length == ~((uint32_t)0)) 1378 if (length == ~((uint32_t)0))
1379 return -1; 1379 return -1;
@@ -1393,6 +1393,9 @@ int Messenger_load(Messenger *m, uint8_t *data, uint32_t length)
1393 length -= sizeof(nospam); 1393 length -= sizeof(nospam);
1394 1394
1395 uint32_t size; 1395 uint32_t size;
1396 if (length < sizeof(size))
1397 return -1;
1398
1396 memcpy(&size, data, sizeof(size)); 1399 memcpy(&size, data, sizeof(size));
1397 data += sizeof(size); 1400 data += sizeof(size);
1398 length -= sizeof(size); 1401 length -= sizeof(size);
@@ -1400,10 +1403,9 @@ int Messenger_load(Messenger *m, uint8_t *data, uint32_t length)
1400 if (length < size) 1403 if (length < size)
1401 return -1; 1404 return -1;
1402 1405
1403 if (DHT_load(m->dht, data, size) == -1) 1406 if (DHT_load_old(m->dht, data, size) == -1)
1404 fprintf(stderr, "Data file: Something wicked happened to the stored connections...\n"); 1407 fprintf(stderr, "Data file: Something wicked happened to the stored connections...\n");
1405 1408 /* DO go on, friends/name still might be intact */
1406 /* go on, friends still might be intact */
1407 1409
1408 data += size; 1410 data += size;
1409 length -= size; 1411 length -= size;
@@ -1420,24 +1422,22 @@ int Messenger_load(Messenger *m, uint8_t *data, uint32_t length)
1420 1422
1421 if (!(size % sizeof(Friend))) { 1423 if (!(size % sizeof(Friend))) {
1422 uint16_t num = size / sizeof(Friend); 1424 uint16_t num = size / sizeof(Friend);
1423 Friend temp[num]; 1425 Friend *friend_list = (Friend *)data;
1424 memcpy(temp, data, size);
1425 1426
1426 uint32_t i; 1427 uint32_t i;
1427
1428 for (i = 0; i < num; ++i) { 1428 for (i = 0; i < num; ++i) {
1429 if (temp[i].status >= 3) { 1429 if (friend_list[i].status >= 3) {
1430 int fnum = m_addfriend_norequest(m, temp[i].client_id); 1430 int fnum = m_addfriend_norequest(m, friend_list[i].client_id);
1431 setfriendname(m, fnum, temp[i].name, temp[i].name_length); 1431 setfriendname(m, fnum, friend_list[i].name, friend_list[i].name_length);
1432 /* set_friend_statusmessage(fnum, temp[i].statusmessage, temp[i].statusmessage_length); */ 1432 /* set_friend_statusmessage(fnum, temp[i].statusmessage, temp[i].statusmessage_length); */
1433 } else if (temp[i].status != 0) { 1433 } else if (friend_list[i].status != 0) {
1434 /* TODO: This is not a good way to do this. */ 1434 /* TODO: This is not a good way to do this. */
1435 uint8_t address[FRIEND_ADDRESS_SIZE]; 1435 uint8_t address[FRIEND_ADDRESS_SIZE];
1436 memcpy(address, temp[i].client_id, crypto_box_PUBLICKEYBYTES); 1436 memcpy(address, friend_list[i].client_id, crypto_box_PUBLICKEYBYTES);
1437 memcpy(address + crypto_box_PUBLICKEYBYTES, &(temp[i].friendrequest_nospam), sizeof(uint32_t)); 1437 memcpy(address + crypto_box_PUBLICKEYBYTES, &(friend_list[i].friendrequest_nospam), sizeof(uint32_t));
1438 uint16_t checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum)); 1438 uint16_t checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum));
1439 memcpy(address + crypto_box_PUBLICKEYBYTES + sizeof(uint32_t), &checksum, sizeof(checksum)); 1439 memcpy(address + crypto_box_PUBLICKEYBYTES + sizeof(uint32_t), &checksum, sizeof(checksum));
1440 m_addfriend(m, address, temp[i].info, temp[i].info_size); 1440 m_addfriend(m, address, friend_list[i].info, friend_list[i].info_size);
1441 } 1441 }
1442 } 1442 }
1443 } 1443 }
@@ -1454,7 +1454,7 @@ int Messenger_load(Messenger *m, uint8_t *data, uint32_t length)
1454 data += sizeof(small_size); 1454 data += sizeof(small_size);
1455 length -= sizeof(small_size); 1455 length -= sizeof(small_size);
1456 1456
1457 if (length != small_size) 1457 if (length < small_size)
1458 return -1; 1458 return -1;
1459 1459
1460 setname(m, data, small_size); 1460 setname(m, data, small_size);
@@ -1462,6 +1462,148 @@ int Messenger_load(Messenger *m, uint8_t *data, uint32_t length)
1462 return 0; 1462 return 0;
1463} 1463}
1464 1464
1465
1466/* new messenger format for load/save, more robust and forward compatible */
1467
1468#define MESSENGER_STATE_COOKIE_GLOBAL 0x15ed1b1e
1469
1470#define MESSENGER_STATE_COOKIE_TYPE 0x01ce
1471#define MESSENGER_STATE_TYPE_NOSPAMKEYS 1
1472#define MESSENGER_STATE_TYPE_DHT 2
1473#define MESSENGER_STATE_TYPE_FRIENDS 3
1474#define MESSENGER_STATE_TYPE_NAME 4
1475
1476/* return size of the messenger data (for saving) */
1477uint32_t Messenger_size(Messenger *m)
1478{
1479 uint32_t size32 = sizeof(uint32_t), sizesubhead = size32 * 2;
1480 return size32 * 2 // global cookie
1481 + sizesubhead + sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES
1482 + sizesubhead + DHT_size(m->dht) // DHT
1483 + sizesubhead + sizeof(Friend) * m->numfriends // Friendlist itself.
1484 + sizesubhead + m->name_length // Own nickname.
1485 ;
1486}
1487
1488static uint8_t *z_state_save_subheader(uint8_t *data, uint32_t len, uint16_t type)
1489{
1490 uint32_t *data32 = (uint32_t *)data;
1491 data32[0] = len;
1492 data32[1] = (MESSENGER_STATE_COOKIE_TYPE << 16) | type;
1493 data += sizeof(uint32_t) * 2;
1494 return data;
1495}
1496
1497/* Save the messenger in data of size Messenger_size(). */
1498void Messenger_save(Messenger *m, uint8_t *data)
1499{
1500 uint32_t len;
1501 uint16_t type;
1502 uint32_t *data32, size32 = sizeof(uint32_t);
1503
1504 data32 = (uint32_t *)data;
1505 data32[0] = 0;
1506 data32[1] = MESSENGER_STATE_COOKIE_GLOBAL;
1507 data += size32 * 2;
1508
1509#ifdef DEBUG
1510 assert(sizeof(get_nospam(&(m->fr))) == sizeof(uint32_t));
1511#endif
1512 len = size32 + crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES;
1513 type = MESSENGER_STATE_TYPE_NOSPAMKEYS;
1514 data = z_state_save_subheader(data, len, type);
1515 *(uint32_t *)data = get_nospam(&(m->fr));
1516 save_keys(m->net_crypto, data + size32);
1517 data += len;
1518
1519 len = DHT_size(m->dht);
1520 type = MESSENGER_STATE_TYPE_DHT;
1521 data = z_state_save_subheader(data, len, type);
1522 DHT_save(m->dht, data);
1523 data += len;
1524
1525 len = sizeof(Friend) * m->numfriends;
1526 type = MESSENGER_STATE_TYPE_FRIENDS;
1527 data = z_state_save_subheader(data, len, type);
1528 memcpy(data, m->friendlist, len);
1529 data += len;
1530
1531 len = m->name_length;
1532 type = MESSENGER_STATE_TYPE_NAME;
1533 data = z_state_save_subheader(data, len, type);
1534 memcpy(data, m->name, len);
1535 data += len;
1536}
1537
1538static int messenger_load_state_callback(void *outer, uint8_t *data, uint32_t length, uint16_t type)
1539{
1540 Messenger *m = outer;
1541 switch(type) {
1542 case MESSENGER_STATE_TYPE_NOSPAMKEYS:
1543 if (length == crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t)) {
1544 set_nospam(&(m->fr), *(uint32_t *)data);
1545 load_keys(m->net_crypto, &data[sizeof(uint32_t)]);
1546 }
1547 else
1548 return -1; /* critical */
1549 break;
1550
1551 case MESSENGER_STATE_TYPE_DHT:
1552 DHT_load_new(m->dht, data, length);
1553 break;
1554
1555 case MESSENGER_STATE_TYPE_FRIENDS:
1556 if (!(length % sizeof(Friend))) {
1557 uint16_t num = length / sizeof(Friend);
1558 Friend *friends = (Friend *)data;
1559 uint32_t i;
1560 for (i = 0; i < num; ++i) {
1561 if (friends[i].status >= 3) {
1562 int fnum = m_addfriend_norequest(m, friends[i].client_id);
1563 setfriendname(m, fnum, friends[i].name, friends[i].name_length);
1564 /* set_friend_statusmessage(fnum, temp[i].statusmessage, temp[i].statusmessage_length); */
1565 } else if (friends[i].status != 0) {
1566 /* TODO: This is not a good way to do this. */
1567 uint8_t address[FRIEND_ADDRESS_SIZE];
1568 memcpy(address, friends[i].client_id, crypto_box_PUBLICKEYBYTES);
1569 memcpy(address + crypto_box_PUBLICKEYBYTES, &(friends[i].friendrequest_nospam), sizeof(uint32_t));
1570 uint16_t checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum));
1571 memcpy(address + crypto_box_PUBLICKEYBYTES + sizeof(uint32_t), &checksum, sizeof(checksum));
1572 m_addfriend(m, address, friends[i].info, friends[i].info_size);
1573 }
1574 }
1575 }
1576 break;
1577
1578 case MESSENGER_STATE_TYPE_NAME:
1579 if ((length > 0) && (length < MAX_NAME_LENGTH)) {
1580 setname(m, data, length);
1581 }
1582 break;
1583
1584 default:
1585 fprintf(stderr, "Load state: contains unrecognized part (len %u, type %u)\n",
1586 length, type);
1587 }
1588
1589 return 0;
1590}
1591
1592/* Load the messenger from data of size length. */
1593int Messenger_load(Messenger *m, uint8_t *data, uint32_t length)
1594{
1595 uint32_t cookie_len = 2 * sizeof(uint32_t);
1596 if (length < cookie_len)
1597 return -1;
1598
1599 uint32_t *data32 = (uint32_t *)data;
1600 if (!data32[0] && (data32[1] == MESSENGER_STATE_COOKIE_GLOBAL))
1601 return load_state(messenger_load_state_callback, m, data + cookie_len,
1602 length - cookie_len, MESSENGER_STATE_COOKIE_TYPE);
1603 else /* old state file */
1604 return Messenger_load_old(m, data, length);
1605}
1606
1465/* Allocate and return a list of valid friend id's. List must be freed by the 1607/* Allocate and return a list of valid friend id's. List must be freed by the
1466 * caller. 1608 * caller.
1467 * 1609 *