summaryrefslogtreecommitdiff
path: root/toxcore
diff options
context:
space:
mode:
Diffstat (limited to 'toxcore')
-rw-r--r--toxcore/DHT.c129
-rw-r--r--toxcore/DHT.h4
-rw-r--r--toxcore/Messenger.c180
-rw-r--r--toxcore/util.c41
-rw-r--r--toxcore/util.h4
5 files changed, 335 insertions, 23 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). */
1460uint32_t DHT_size(DHT *dht) 1460uint32_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(). */
1466void DHT_save(DHT *dht, uint8_t *data) 1466void 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 */
1477int DHT_load(DHT *dht, uint8_t *data, uint32_t size) 1477int 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). */
1531uint32_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
1544static 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(). */
1554void 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
1585static 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 */
1632int 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 */
diff --git a/toxcore/DHT.h b/toxcore/DHT.h
index ff20c892..e6f227f7 100644
--- a/toxcore/DHT.h
+++ b/toxcore/DHT.h
@@ -226,11 +226,13 @@ DHT *new_DHT(Net_Crypto *c);
226void kill_DHT(DHT *dht); 226void kill_DHT(DHT *dht);
227 227
228/* Load the DHT from data of size size. 228/* Load the DHT from data of size size.
229 * old/new: version of config file
229 * 230 *
230 * return -1 if failure. 231 * return -1 if failure.
231 * return 0 if success. 232 * return 0 if success.
232 */ 233 */
233int DHT_load(DHT *dht, uint8_t *data, uint32_t size); 234int DHT_load_old(DHT *dht, uint8_t *data, uint32_t size);
235int DHT_load_new(DHT *dht, uint8_t *data, uint32_t size);
234 236
235/* return 0 if we are not connected to the DHT. 237/* return 0 if we are not connected to the DHT.
236 * return 1 if we are. 238 * return 1 if we are.
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 *
diff --git a/toxcore/util.c b/toxcore/util.c
index e1c46ee5..28f7d26e 100644
--- a/toxcore/util.c
+++ b/toxcore/util.c
@@ -43,6 +43,47 @@ void id_cpy(uint8_t *dest, uint8_t *src)
43 memcpy(dest, src, CLIENT_ID_SIZE); 43 memcpy(dest, src, CLIENT_ID_SIZE);
44} 44}
45 45
46int load_state(load_state_callback_func load_state_callback, void *outer,
47 uint8_t *data, uint32_t length, uint16_t cookie_inner)
48{
49 if (!load_state_callback || !data) {
50 fprintf(stderr, "load_state() called with invalid args.\n");
51 return -1;
52 }
53
54
55 uint16_t type;
56 uint32_t length_sub, cookie_type;
57 uint32_t size32 = sizeof(uint32_t), size_head = size32 * 2;
58 while (length > size_head) {
59 length_sub = *(uint32_t *)data;
60 cookie_type = *(uint32_t *)(data + size32);
61 data += size_head;
62 length -= size_head;
63
64 if (length < length_sub) {
65 /* file truncated */
66 fprintf(stderr, "state file too short: %u < %u\n", length, length_sub);
67 return -1;
68 }
69
70 if ((cookie_type >> 16) != cookie_inner) {
71 /* something is not matching up in a bad way, give up */
72 fprintf(stderr, "state file garbeled: %04hx != %04hx\n", (cookie_type >> 16), cookie_inner);
73 return -1;
74 }
75
76 type = cookie_type & 0xFFFF;
77 if (-1 == load_state_callback(outer, data, length_sub, type))
78 return -1;
79
80 data += length_sub;
81 length -= length_sub;
82 }
83
84 return length == 0 ? 0 : - 1;
85};
86
46#ifdef LOGGING 87#ifdef LOGGING
47time_t starttime = 0; 88time_t starttime = 0;
48char logbuffer[512]; 89char logbuffer[512];
diff --git a/toxcore/util.h b/toxcore/util.h
index 71be84ca..6937f7d4 100644
--- a/toxcore/util.h
+++ b/toxcore/util.h
@@ -16,6 +16,10 @@ uint64_t random_64b();
16bool id_eq(uint8_t *dest, uint8_t *src); 16bool id_eq(uint8_t *dest, uint8_t *src);
17void id_cpy(uint8_t *dest, uint8_t *src); 17void id_cpy(uint8_t *dest, uint8_t *src);
18 18
19typedef int (*load_state_callback_func)(void *outer, uint8_t *data, uint32_t len, uint16_t type);
20int load_state(load_state_callback_func load_state_callback, void *outer,
21 uint8_t *data, uint32_t length, uint16_t cookie_inner);
22
19#undef LOGGING 23#undef LOGGING
20/* #define LOGGING */ 24/* #define LOGGING */
21#ifdef LOGGING 25#ifdef LOGGING