summaryrefslogtreecommitdiff
path: root/toxcore/DHT.c
diff options
context:
space:
mode:
Diffstat (limited to 'toxcore/DHT.c')
-rw-r--r--toxcore/DHT.c132
1 files changed, 129 insertions, 3 deletions
diff --git a/toxcore/DHT.c b/toxcore/DHT.c
index a11f1aad..0b866940 100644
--- a/toxcore/DHT.c
+++ b/toxcore/DHT.c
@@ -1236,13 +1236,13 @@ void kill_DHT(DHT *dht)
1236} 1236}
1237 1237
1238/* Get the size of the DHT (for saving). */ 1238/* Get the size of the DHT (for saving). */
1239uint32_t DHT_size(DHT *dht) 1239uint32_t DHT_size_old(DHT *dht)
1240{ 1240{
1241 return sizeof(dht->close_clientlist) + sizeof(DHT_Friend) * dht->num_friends; 1241 return sizeof(dht->close_clientlist) + sizeof(DHT_Friend) * dht->num_friends;
1242} 1242}
1243 1243
1244/* Save the DHT in data where data is an array of size DHT_size(). */ 1244/* Save the DHT in data where data is an array of size DHT_size(). */
1245void DHT_save(DHT *dht, uint8_t *data) 1245void DHT_save_old(DHT *dht, uint8_t *data)
1246{ 1246{
1247 memcpy(data, dht->close_clientlist, sizeof(dht->close_clientlist)); 1247 memcpy(data, dht->close_clientlist, sizeof(dht->close_clientlist));
1248 memcpy(data + sizeof(dht->close_clientlist), dht->friends_list, sizeof(DHT_Friend) * dht->num_friends); 1248 memcpy(data + sizeof(dht->close_clientlist), dht->friends_list, sizeof(DHT_Friend) * dht->num_friends);
@@ -1253,7 +1253,7 @@ void DHT_save(DHT *dht, uint8_t *data)
1253 * return -1 if failure. 1253 * return -1 if failure.
1254 * return 0 if success. 1254 * return 0 if success.
1255 */ 1255 */
1256int DHT_load(DHT *dht, uint8_t *data, uint32_t size) 1256int DHT_load_old(DHT *dht, uint8_t *data, uint32_t size)
1257{ 1257{
1258 if (size < sizeof(dht->close_clientlist)) 1258 if (size < sizeof(dht->close_clientlist))
1259 return -1; 1259 return -1;
@@ -1295,6 +1295,132 @@ int DHT_load(DHT *dht, uint8_t *data, uint32_t size)
1295 return 0; 1295 return 0;
1296} 1296}
1297 1297
1298
1299/* new DHT format for load/save, more robust and forward compatible */
1300
1301#define DHT_STATE_COOKIE_GLOBAL 0x159000d
1302
1303#define DHT_STATE_COOKIE_TYPE 0x11ce
1304#define DHT_STATE_TYPE_FRIENDS 1
1305#define DHT_STATE_TYPE_CLIENTS 2
1306
1307typedef uint16_t statelensub_t;
1308
1309/* Get the size of the DHT (for saving). */
1310uint32_t DHT_size(DHT *dht)
1311{
1312 uint32_t num = 0, i;
1313 for (i = 0; i < LCLIENT_LIST; ++i)
1314 if (dht->close_clientlist[i].timestamp != 0)
1315 num++;
1316
1317 uint32_t size32 = sizeof(uint32_t), lengthsublen = sizeof(statelensub_t);
1318 uint32_t sizesubhead = lengthsublen + size32;
1319 return size32
1320 + sizesubhead + sizeof(DHT_Friend) * dht->num_friends
1321 + sizesubhead + sizeof(Client_data) * num;
1322}
1323
1324static uint8_t *z_state_save_subheader(uint8_t *data, statelensub_t len, uint16_t type)
1325{
1326 *(statelensub_t *)data = len;
1327 data += sizeof(statelensub_t);
1328 *(uint32_t *)data = (DHT_STATE_COOKIE_TYPE << 16) | type;
1329 data += sizeof(uint32_t);
1330 return data;
1331}
1332
1333/* Save the DHT in data where data is an array of size DHT_size(). */
1334void DHT_save(DHT *dht, uint8_t *data)
1335{
1336 statelensub_t len;
1337 uint16_t type;
1338 *(uint32_t *)data = DHT_STATE_COOKIE_GLOBAL;
1339 data += sizeof(uint32_t);
1340
1341 len = sizeof(DHT_Friend) * dht->num_friends;
1342 type = DHT_STATE_TYPE_FRIENDS;
1343 data = z_state_save_subheader(data, len, type);
1344 memcpy(data, dht->friends_list, len);
1345 data += len;
1346
1347 uint32_t num = 0, i;
1348 for (i = 0; i < LCLIENT_LIST; ++i)
1349 if (dht->close_clientlist[i].timestamp != 0)
1350 num++;
1351
1352 if (!num)
1353 return;
1354
1355 len = num * sizeof(Client_data);
1356 type = DHT_STATE_TYPE_CLIENTS;
1357 data = z_state_save_subheader(data, len, type);
1358 Client_data *clients = (Client_data *)data;
1359 for (num = 0, i = 0; i < LCLIENT_LIST; ++i)
1360 if (dht->close_clientlist[i].timestamp != 0)
1361 memcpy(&clients[num++], &dht->close_clientlist[i], sizeof(Client_data));
1362 data += len;
1363}
1364
1365static int dht_load_state_callback(void *outer, uint8_t *data, uint32_t length, uint16_t type)
1366{
1367 DHT *dht = outer;
1368 uint32_t num, i, j;
1369 switch(type) {
1370 case DHT_STATE_TYPE_FRIENDS:
1371 if (length % sizeof(DHT_Friend) != 0)
1372 break;
1373
1374 DHT_Friend *friend_list = (DHT_Friend *)data;
1375 num = length / sizeof(DHT_Friend);
1376 for (i = 0; i < num; ++i) {
1377 DHT_addfriend(dht, friend_list[i].client_id);
1378 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
1379 Client_data *client = &friend_list[i].client_list[j];
1380 if (client->timestamp != 0)
1381 getnodes(dht, client->ip_port, client->client_id, friend_list[i].client_id);
1382 }
1383 }
1384
1385 break;
1386
1387 case DHT_STATE_TYPE_CLIENTS:
1388 if ((length % sizeof(Client_data)) != 0)
1389 break;
1390
1391 num = length / sizeof(Client_data);
1392 Client_data *client_list = (Client_data *)data;
1393 for (i = 0; i < num; ++i)
1394 if (client_list[i].timestamp != 0)
1395 DHT_bootstrap(dht, client_list[i].ip_port, client_list[i].client_id);
1396
1397 break;
1398
1399 default:
1400 fprintf(stderr, "Load state (DHT): contains unrecognized part (len %u, type %u)\n",
1401 length, type);
1402 }
1403
1404 return 0;
1405}
1406
1407/* Load the DHT from data of size size.
1408 *
1409 * return -1 if failure.
1410 * return 0 if success.
1411 */
1412int DHT_load_new(DHT *dht, uint8_t *data, uint32_t length)
1413{
1414 uint32_t cookie_len = sizeof(uint32_t);
1415 if (length > cookie_len) {
1416 uint32_t *data32 = (uint32_t *)data;
1417 if (data32[0] == DHT_STATE_COOKIE_GLOBAL)
1418 return load_state(dht_load_state_callback, dht, data + cookie_len,
1419 length - cookie_len, DHT_STATE_COOKIE_TYPE);
1420 }
1421
1422 return DHT_load_old(dht, data, length);
1423}
1298/* return 0 if we are not connected to the DHT. 1424/* return 0 if we are not connected to the DHT.
1299 * return 1 if we are. 1425 * return 1 if we are.
1300 */ 1426 */