static int send_getnodes(const Group_Chat *chat, IP_Port ip_port, int peernum) { if ((uint32_t)peernum >= chat->numpeers) return -1; if (!is_timeout(chat->group[peernum].last_pinged, GROUP_PING_TIMEOUT)) return -1; getnodes_data contents; contents.pingid = random_64b(); chat->group[peernum].last_pinged = unix_time(); chat->group[peernum].pingid = contents.pingid; chat->group[peernum].ping_via = ip_port; if (chat->assoc) { IPPTs ippts; ippts.timestamp = unix_time(); ippts.ip_port = ip_port; Assoc_add_entry(chat->assoc, chat->group[peernum].client_id, &ippts, NULL, 1); } return send_groupchatpacket(chat, ip_port, chat->group[peernum].client_id, (uint8_t *)&contents, sizeof(contents), CRYPTO_PACKET_GROUP_CHAT_GET_NODES); }
static int handle_sendnodes(Group_Chat *chat, IP_Port source, int peernum, const uint8_t *data, uint32_t len) { if ((uint32_t)peernum >= chat->numpeers) return 1; if (len > sizeof(sendnodes_data) || len < sizeof(uint64_t)) return 1; if ((len - sizeof(uint64_t)) % sizeof(groupchat_nodes) != 0) return 1; if (is_timeout(chat->group[peernum].last_pinged, GROUP_PING_TIMEOUT)) return 1; sendnodes_data contents; memcpy(&contents, data, len); if (contents.pingid != chat->group[peernum].pingid) return 1; uint16_t numnodes = (len - sizeof(contents.pingid)) / sizeof(groupchat_nodes); uint32_t i; IPPTs ippts_send; ippts_send.timestamp = unix_time(); for (i = 0; i < numnodes; ++i) { if (peer_okping(chat, contents.nodes[i].client_id) > 0) { int peern = peer_in_chat(chat, contents.nodes[i].client_id); if (peern == -1) { /*NOTE: This is just for testing and will be removed later.*/ peern = addpeer(chat, contents.nodes[i].client_id); } if (peern == -1) continue; to_host_family(&contents.nodes[i].ip_port.ip); send_getnodes(chat, contents.nodes[i].ip_port, peern); if (chat->assoc) { ippts_send.ip_port = contents.nodes[i].ip_port; Assoc_add_entry(chat->assoc, contents.nodes[i].client_id, &ippts_send, NULL, 0); } } } int ok = add_closepeer(chat, chat->group[peernum].client_id, source); return 0; }
END_TEST START_TEST(test_fillup) { /* TODO: real test */ int i, j; uint8_t id[CLIENT_ID_SIZE]; //uint32_t a = current_time(); uint32_t a = 2710106197; srand(a); for(i = 0; i < CLIENT_ID_SIZE; ++i) { id[i] = rand(); } Assoc *assoc = new_Assoc(6, 15, id); ck_assert_msg(assoc != NULL, "failed to create default assoc"); struct entry { uint8_t id[CLIENT_ID_SIZE]; IPPTs ippts_send; IP_Port ipp_recv; }; unsigned int fail = 0; struct entry entries[128]; struct entry closest[8]; for(j = 0; j < 128; ++j) { for(i = 0; i < CLIENT_ID_SIZE; ++i) { entries[j].id[i] = rand(); } IP_Port ipp; ipp.ip.family = AF_INET; ipp.ip.ip4.uint32 = rand(); ipp.port = rand(); entries[j].ippts_send.ip_port = ipp; entries[j].ippts_send.timestamp = unix_time(); ipp.ip.ip4.uint32 = rand(); ipp.port = rand(); entries[j].ipp_recv = ipp; if (j % 16 == 0) { memcpy(entries[j].id, id, CLIENT_ID_SIZE - 30); memcpy(&closest[j/16], &entries[j], sizeof(struct entry)); } uint8_t res = Assoc_add_entry(assoc, entries[j].id, &entries[j].ippts_send, &entries[j].ipp_recv, 1); ck_assert_msg(res == 1, "failed to store entry: expected %u, got %u, j = %u", 1, res, j); } int good = 0; Assoc_close_entries close_entries; memset(&close_entries, 0, sizeof(close_entries)); close_entries.count = 8; close_entries.count_good = 8; close_entries.wanted_id = id; Client_data *entri[close_entries.count]; close_entries.result = entri; uint8_t found = Assoc_get_close_entries(assoc, &close_entries); ck_assert_msg(found == 8, "get_close_entries(): expected %u, got %u", 1, found); for (i = 0; i < 8; ++i) { for (j = 0; j < 8; ++j) { if (id_equal(entri[j]->client_id, closest[i].id)) ++good; } }ck_assert_msg(good == 8, "Entries found were not the closest ones. Only %u/8 were.", good); //printf("good: %u %u %u\n", good, a, ((uint32_t)current_time() - a)); }