diff options
Diffstat (limited to 'toxcore/DHT.c')
-rw-r--r-- | toxcore/DHT.c | 129 |
1 files changed, 126 insertions, 3 deletions
diff --git a/toxcore/DHT.c b/toxcore/DHT.c index db9bfe3c..bb746fb0 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c | |||
@@ -1457,13 +1457,13 @@ void kill_DHT(DHT *dht) | |||
1457 | } | 1457 | } |
1458 | 1458 | ||
1459 | /* Get the size of the DHT (for saving). */ | 1459 | /* Get the size of the DHT (for saving). */ |
1460 | uint32_t DHT_size(DHT *dht) | 1460 | uint32_t DHT_size_old(DHT *dht) |
1461 | { | 1461 | { |
1462 | return sizeof(dht->close_clientlist) + sizeof(DHT_Friend) * dht->num_friends; | 1462 | return sizeof(dht->close_clientlist) + sizeof(DHT_Friend) * dht->num_friends; |
1463 | } | 1463 | } |
1464 | 1464 | ||
1465 | /* Save the DHT in data where data is an array of size DHT_size(). */ | 1465 | /* Save the DHT in data where data is an array of size DHT_size(). */ |
1466 | void DHT_save(DHT *dht, uint8_t *data) | 1466 | void DHT_save_old(DHT *dht, uint8_t *data) |
1467 | { | 1467 | { |
1468 | memcpy(data, dht->close_clientlist, sizeof(dht->close_clientlist)); | 1468 | memcpy(data, dht->close_clientlist, sizeof(dht->close_clientlist)); |
1469 | memcpy(data + sizeof(dht->close_clientlist), dht->friends_list, sizeof(DHT_Friend) * dht->num_friends); | 1469 | memcpy(data + sizeof(dht->close_clientlist), dht->friends_list, sizeof(DHT_Friend) * dht->num_friends); |
@@ -1474,7 +1474,7 @@ void DHT_save(DHT *dht, uint8_t *data) | |||
1474 | * return -1 if failure. | 1474 | * return -1 if failure. |
1475 | * return 0 if success. | 1475 | * return 0 if success. |
1476 | */ | 1476 | */ |
1477 | int DHT_load(DHT *dht, uint8_t *data, uint32_t size) | 1477 | int DHT_load_old(DHT *dht, uint8_t *data, uint32_t size) |
1478 | { | 1478 | { |
1479 | if (size < sizeof(dht->close_clientlist)) { | 1479 | if (size < sizeof(dht->close_clientlist)) { |
1480 | fprintf(stderr, "DHT_load: Expected at least %u bytes, got %u.\n", sizeof(dht->close_clientlist), size); | 1480 | fprintf(stderr, "DHT_load: Expected at least %u bytes, got %u.\n", sizeof(dht->close_clientlist), size); |
@@ -1518,6 +1518,129 @@ int DHT_load(DHT *dht, uint8_t *data, uint32_t size) | |||
1518 | return 0; | 1518 | return 0; |
1519 | } | 1519 | } |
1520 | 1520 | ||
1521 | |||
1522 | /* new DHT format for load/save, more robust and forward compatible */ | ||
1523 | |||
1524 | #define DHT_STATE_COOKIE_GLOBAL 0x159000d | ||
1525 | |||
1526 | #define DHT_STATE_COOKIE_TYPE 0x11ce | ||
1527 | #define DHT_STATE_TYPE_FRIENDS 1 | ||
1528 | #define DHT_STATE_TYPE_CLIENTS 2 | ||
1529 | |||
1530 | /* Get the size of the DHT (for saving). */ | ||
1531 | uint32_t DHT_size(DHT *dht) | ||
1532 | { | ||
1533 | uint32_t num = 0, i; | ||
1534 | for (i = 0; i < LCLIENT_LIST; ++i) | ||
1535 | if (dht->close_clientlist[i].timestamp != 0) | ||
1536 | num++; | ||
1537 | |||
1538 | uint32_t size32 = sizeof(uint32_t), sizesubhead = size32 * 2; | ||
1539 | return size32 | ||
1540 | + sizesubhead + sizeof(DHT_Friend) * dht->num_friends | ||
1541 | + sizesubhead + sizeof(Client_data) * num; | ||
1542 | } | ||
1543 | |||
1544 | static uint8_t *z_state_save_subheader(uint8_t *data, uint32_t len, uint16_t type) | ||
1545 | { | ||
1546 | uint32_t *data32 = (uint32_t *)data; | ||
1547 | data32[0] = len; | ||
1548 | data32[1] = (DHT_STATE_COOKIE_TYPE << 16) | type; | ||
1549 | data += sizeof(uint32_t) * 2; | ||
1550 | return data; | ||
1551 | } | ||
1552 | |||
1553 | /* Save the DHT in data where data is an array of size DHT_size(). */ | ||
1554 | void DHT_save(DHT *dht, uint8_t *data) | ||
1555 | { | ||
1556 | uint32_t len; | ||
1557 | uint16_t type; | ||
1558 | *(uint32_t *)data = DHT_STATE_COOKIE_GLOBAL; | ||
1559 | data += sizeof(uint32_t); | ||
1560 | |||
1561 | len = sizeof(DHT_Friend) * dht->num_friends; | ||
1562 | type = DHT_STATE_TYPE_FRIENDS; | ||
1563 | data = z_state_save_subheader(data, len, type); | ||
1564 | memcpy(data, dht->friends_list, len); | ||
1565 | data += len; | ||
1566 | |||
1567 | uint32_t num = 0, i; | ||
1568 | for (i = 0; i < LCLIENT_LIST; ++i) | ||
1569 | if (dht->close_clientlist[i].timestamp != 0) | ||
1570 | num++; | ||
1571 | |||
1572 | if (!num) | ||
1573 | return; | ||
1574 | |||
1575 | len = num * sizeof(Client_data); | ||
1576 | type = DHT_STATE_TYPE_CLIENTS; | ||
1577 | data = z_state_save_subheader(data, len, type); | ||
1578 | Client_data *clients = (Client_data *)data; | ||
1579 | for (num = 0, i = 0; i < LCLIENT_LIST; ++i) | ||
1580 | if (dht->close_clientlist[i].timestamp != 0) | ||
1581 | memcpy(&clients[num++], &dht->close_clientlist[i], sizeof(Client_data)); | ||
1582 | data += len; | ||
1583 | } | ||
1584 | |||
1585 | static int dht_load_state_callback(void *outer, uint8_t *data, uint32_t length, uint16_t type) | ||
1586 | { | ||
1587 | DHT *dht = outer; | ||
1588 | uint32_t num, i, j; | ||
1589 | switch(type) { | ||
1590 | case DHT_STATE_TYPE_FRIENDS: | ||
1591 | if (length % sizeof(DHT_Friend) != 0) | ||
1592 | break; | ||
1593 | |||
1594 | DHT_Friend *friend_list = (DHT_Friend *)data; | ||
1595 | num = length / sizeof(DHT_Friend); | ||
1596 | for (i = 0; i < num; ++i) { | ||
1597 | DHT_addfriend(dht, friend_list[i].client_id); | ||
1598 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { | ||
1599 | Client_data *client = &friend_list[i].client_list[j]; | ||
1600 | if (client->timestamp != 0) | ||
1601 | getnodes(dht, client->ip_port, client->client_id, friend_list[i].client_id); | ||
1602 | } | ||
1603 | } | ||
1604 | |||
1605 | break; | ||
1606 | |||
1607 | case DHT_STATE_TYPE_CLIENTS: | ||
1608 | if ((length % sizeof(Client_data)) != 0) | ||
1609 | break; | ||
1610 | |||
1611 | num = length / sizeof(Client_data); | ||
1612 | Client_data *client_list = (Client_data *)data; | ||
1613 | for (i = 0; i < num; ++i) | ||
1614 | if (client_list[i].timestamp != 0) | ||
1615 | DHT_bootstrap(dht, client_list[i].ip_port, client_list[i].client_id); | ||
1616 | |||
1617 | break; | ||
1618 | |||
1619 | default: | ||
1620 | fprintf(stderr, "Load state (DHT): contains unrecognized part (len %u, type %u)\n", | ||
1621 | length, type); | ||
1622 | } | ||
1623 | |||
1624 | return 0; | ||
1625 | } | ||
1626 | |||
1627 | /* Load the DHT from data of size size. | ||
1628 | * | ||
1629 | * return -1 if failure. | ||
1630 | * return 0 if success. | ||
1631 | */ | ||
1632 | int DHT_load_new(DHT *dht, uint8_t *data, uint32_t length) | ||
1633 | { | ||
1634 | uint32_t cookie_len = sizeof(uint32_t); | ||
1635 | if (length > cookie_len) { | ||
1636 | uint32_t *data32 = (uint32_t *)data; | ||
1637 | if (data32[0] == DHT_STATE_COOKIE_GLOBAL) | ||
1638 | return load_state(dht_load_state_callback, dht, data + cookie_len, | ||
1639 | length - cookie_len, DHT_STATE_COOKIE_TYPE); | ||
1640 | } | ||
1641 | |||
1642 | return DHT_load_old(dht, data, length); | ||
1643 | } | ||
1521 | /* return 0 if we are not connected to the DHT. | 1644 | /* return 0 if we are not connected to the DHT. |
1522 | * return 1 if we are. | 1645 | * return 1 if we are. |
1523 | */ | 1646 | */ |