diff options
Diffstat (limited to 'toxcore/Messenger.c')
-rw-r--r-- | toxcore/Messenger.c | 180 |
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) */ |
1334 | uint32_t Messenger_size(Messenger *m) | 1334 | uint32_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. */ |
1348 | void Messenger_save(Messenger *m, uint8_t *data) | 1348 | static 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. */ |
1376 | int Messenger_load(Messenger *m, uint8_t *data, uint32_t length) | 1376 | static 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) */ | ||
1477 | uint32_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 | |||
1488 | static 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(). */ | ||
1498 | void 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 | |||
1538 | static 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. */ | ||
1593 | int 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 | * |