diff options
Diffstat (limited to 'toxcore/DHT.c')
-rw-r--r-- | toxcore/DHT.c | 132 |
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). */ |
1239 | uint32_t DHT_size(DHT *dht) | 1239 | uint32_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(). */ |
1245 | void DHT_save(DHT *dht, uint8_t *data) | 1245 | void 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 | */ |
1256 | int DHT_load(DHT *dht, uint8_t *data, uint32_t size) | 1256 | int 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 | |||
1307 | typedef uint16_t statelensub_t; | ||
1308 | |||
1309 | /* Get the size of the DHT (for saving). */ | ||
1310 | uint32_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 | |||
1324 | static 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(). */ | ||
1334 | void 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 | |||
1365 | static 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 | */ | ||
1412 | int 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 | */ |