static int handle_announce_response(void *object, IP_Port source, const uint8_t *packet, uint16_t length) { Onion_Client *onion_c = object; if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE) return 1; uint16_t len_nodes = length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE; uint8_t public_key[crypto_box_PUBLICKEYBYTES]; IP_Port ip_port; uint32_t path_num; uint32_t num = check_sendback(onion_c, packet + 1, public_key, &ip_port, &path_num); if (num > onion_c->num_friends) return 1; uint8_t plain[1 + ONION_PING_ID_SIZE + len_nodes]; int len = -1; if (num == 0) { len = decrypt_data(public_key, onion_c->c->self_secret_key, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES, length - (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES), plain); } else { if (onion_c->friends_list[num - 1].status == 0) return 1; len = decrypt_data(public_key, onion_c->friends_list[num - 1].temp_secret_key, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES, length - (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES), plain); } if ((uint32_t)len != sizeof(plain)) return 1; if (client_add_to_list(onion_c, num, public_key, ip_port, plain[0], plain + 1, path_num) == -1) return 1; if (len_nodes != 0) { Node_format nodes[MAX_SENT_NODES]; int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, plain + 1 + ONION_PING_ID_SIZE, len_nodes, 0); if (num_nodes <= 0) return 1; if (client_ping_nodes(onion_c, num, nodes, num_nodes, source) == -1) return 1; } //TODO: LAN vs non LAN ips?, if we are connected only to LAN, are we offline? onion_c->last_packet_recv = unix_time(); return 0; }
static int handle_announce_response(void *object, IP_Port source, uint8_t *packet, uint32_t length) { Onion_Client *onion_c = object; if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE) return 1; if ((length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE) % sizeof(Node_format) != 0) return 1; uint16_t num_nodes = (length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE) / sizeof(Node_format); uint8_t public_key[crypto_box_PUBLICKEYBYTES]; IP_Port ip_port; uint32_t num = check_sendback(onion_c, packet + 1, public_key, &ip_port); if (num > onion_c->num_friends) return 1; uint8_t plain[1 + ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format)]; int len = -1; if (num == 0) { len = decrypt_data(public_key, onion_c->dht->c->self_secret_key, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES, length - (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES), plain); } else { if (onion_c->friends_list[num - 1].status == 0) return 1; len = decrypt_data(public_key, onion_c->friends_list[num - 1].temp_secret_key, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES, length - (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES), plain); } if ((uint32_t)len != sizeof(plain)) return 1; if (client_add_to_list(onion_c, num, public_key, ip_port, plain[0], plain + 1, source) == -1) return 1; Node_format nodes[MAX_SENT_NODES]; memcpy(nodes, plain + 1 + ONION_PING_ID_SIZE, num_nodes * sizeof(Node_format)); if (client_ping_nodes(onion_c, num, nodes, num_nodes, source) == -1) return 1; return 0; }