int handle_ping_request(uint8_t* packet, uint32_t length, IP_Port source) { pingreq_t* p = (pingreq_t*) packet; int rc; uint64_t ping_id; if (length != sizeof(pingreq_t) || id_eq(&p->client_id, self_id)) return 1; // Decrypt ping_id rc = decrypt_data((uint8_t*) &p->client_id, self_secret_key, (uint8_t*) &p->nonce, (uint8_t*) &p->ping_id, sizeof(ping_id) + ENCRYPTION_PADDING, (uint8_t*) &ping_id); if (rc != sizeof(ping_id)) return 1; // Send response send_ping_response(source, &p->client_id, ping_id); send_ping_request(source, &p->client_id); // Make this smarter? return 0; }
static int handle_ping_request(void *_dht, IP_Port source, size_t *packet, size_t length) { DHT *dht = _dht; int rc; size_t ping_id; if (length != DHT_PING_SIZE) return 1; PING *ping = dht->ping; if (id_equal(packet + 1, ping->dht->self_public_key)) return 1; // Decrypt ping_id rc = decrypt_data(packet + 1, ping->dht->self_secret_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, sizeof(ping_id) + crypto_box_MACBYTES, (size_t *) &ping_id); if (rc != sizeof(ping_id)) return 1; // Send response send_ping_response(ping, source, packet + 1, ping_id); add_toping(ping, packet + 1, source); return 0; }
/* return 1 on success. * return 0 if could not send packet. * return -1 on failure. */ int send_data(TCP_Client_Connection *con, uint8_t con_id, const uint8_t *data, uint16_t length) { if (con_id >= NUM_CLIENT_CONNECTIONS) { return -1; } if (con->connections[con_id].status != 2) { return -1; } if (send_ping_response(con) == 0 || send_ping_request(con) == 0) { return 0; } VLA(uint8_t, packet, 1 + length); packet[0] = con_id + NUM_RESERVED_PORTS; memcpy(packet + 1, data, length); return write_packet_TCP_secure_connection(con, packet, SIZEOF_VLA(packet), 0); }
static int handle_ping_request(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata) { DHT *dht = (DHT *)object; int rc; if (length != DHT_PING_SIZE) { return 1; } PING *ping = dht->ping; if (id_equal(packet + 1, ping->dht->self_public_key)) { return 1; } uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; uint8_t ping_plain[PING_PLAIN_SIZE]; // Decrypt ping_id DHT_get_shared_key_recv(dht, shared_key, packet + 1); rc = decrypt_data_symmetric(shared_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, PING_PLAIN_SIZE + CRYPTO_MAC_SIZE, ping_plain); if (rc != sizeof(ping_plain)) { return 1; } if (ping_plain[0] != NET_PACKET_PING_REQUEST) { return 1; } uint64_t ping_id; memcpy(&ping_id, ping_plain + 1, sizeof(ping_id)); // Send response send_ping_response(ping, source, packet + 1, ping_id, shared_key); add_to_ping(ping, packet + 1, source); return 0; }
static int do_confirmed_TCP(TCP_Client_Connection *conn, void *userdata) { send_pending_data(conn); send_ping_response(conn); send_ping_request(conn); uint8_t packet[MAX_PACKET_SIZE]; int len; if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY)) { uint64_t ping_id = random_64b(); if (!ping_id) { ++ping_id; } conn->ping_request_id = conn->ping_id = ping_id; send_ping_request(conn); conn->last_pinged = unix_time(); } if (conn->ping_id && is_timeout(conn->last_pinged, TCP_PING_TIMEOUT)) { conn->status = TCP_CLIENT_DISCONNECTED; return 0; } while ((len = read_packet_TCP_secure_connection(conn->sock, &conn->next_packet_length, conn->shared_key, conn->recv_nonce, packet, sizeof(packet)))) { if (len == -1) { conn->status = TCP_CLIENT_DISCONNECTED; break; } if (handle_TCP_packet(conn, packet, len, userdata) == -1) { conn->status = TCP_CLIENT_DISCONNECTED; break; } } return 0; }
static int handle_ping_request(void *_dht, IP_Port source, const uint8_t *packet, uint16_t length) { DHT *dht = _dht; int rc; if (length != DHT_PING_SIZE) return 1; PING *ping = dht->ping; if (id_equal(packet + 1, ping->dht->self_public_key)) return 1; uint8_t shared_key[crypto_box_BEFORENMBYTES]; uint8_t ping_plain[PING_PLAIN_SIZE]; // Decrypt ping_id DHT_get_shared_key_recv(dht, shared_key, packet + 1); rc = decrypt_data_symmetric(shared_key, packet + 1 + crypto_box_PUBLICKEYBYTES, packet + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, PING_PLAIN_SIZE + crypto_box_MACBYTES, ping_plain ); if (rc != sizeof(ping_plain)) return 1; if (ping_plain[0] != NET_PACKET_PING_REQUEST) return 1; uint64_t ping_id; memcpy(&ping_id, ping_plain + 1, sizeof(ping_id)); // Send response send_ping_response(ping, source, packet + 1, ping_id, shared_key); add_to_ping(ping, packet + 1, source); return 0; }
/* return 0 on success * return -1 on failure */ static int handle_TCP_packet(TCP_Client_Connection *conn, const uint8_t *data, uint16_t length, void *userdata) { if (length <= 1) { return -1; } switch (data[0]) { case TCP_PACKET_ROUTING_RESPONSE: { if (length != 1 + 1 + CRYPTO_PUBLIC_KEY_SIZE) { return -1; } if (data[1] < NUM_RESERVED_PORTS) { return 0; } uint8_t con_id = data[1] - NUM_RESERVED_PORTS; if (conn->connections[con_id].status != 0) { return 0; } conn->connections[con_id].status = 1; conn->connections[con_id].number = ~0; memcpy(conn->connections[con_id].public_key, data + 2, CRYPTO_PUBLIC_KEY_SIZE); if (conn->response_callback) { conn->response_callback(conn->response_callback_object, con_id, conn->connections[con_id].public_key); } return 0; } case TCP_PACKET_CONNECTION_NOTIFICATION: { if (length != 1 + 1) { return -1; } if (data[1] < NUM_RESERVED_PORTS) { return -1; } uint8_t con_id = data[1] - NUM_RESERVED_PORTS; if (conn->connections[con_id].status != 1) { return 0; } conn->connections[con_id].status = 2; if (conn->status_callback) { conn->status_callback(conn->status_callback_object, conn->connections[con_id].number, con_id, conn->connections[con_id].status); } return 0; } case TCP_PACKET_DISCONNECT_NOTIFICATION: { if (length != 1 + 1) { return -1; } if (data[1] < NUM_RESERVED_PORTS) { return -1; } uint8_t con_id = data[1] - NUM_RESERVED_PORTS; if (conn->connections[con_id].status == 0) { return 0; } if (conn->connections[con_id].status != 2) { return 0; } conn->connections[con_id].status = 1; if (conn->status_callback) { conn->status_callback(conn->status_callback_object, conn->connections[con_id].number, con_id, conn->connections[con_id].status); } return 0; } case TCP_PACKET_PING: { if (length != 1 + sizeof(uint64_t)) { return -1; } uint64_t ping_id; memcpy(&ping_id, data + 1, sizeof(uint64_t)); conn->ping_response_id = ping_id; send_ping_response(conn); return 0; } case TCP_PACKET_PONG: { if (length != 1 + sizeof(uint64_t)) { return -1; } uint64_t ping_id; memcpy(&ping_id, data + 1, sizeof(uint64_t)); if (ping_id) { if (ping_id == conn->ping_id) { conn->ping_id = 0; } return 0; } return -1; } case TCP_PACKET_OOB_RECV: { if (length <= 1 + CRYPTO_PUBLIC_KEY_SIZE) { return -1; } if (conn->oob_data_callback) { conn->oob_data_callback(conn->oob_data_callback_object, data + 1, data + 1 + CRYPTO_PUBLIC_KEY_SIZE, length - (1 + CRYPTO_PUBLIC_KEY_SIZE), userdata); } return 0; } case TCP_PACKET_ONION_RESPONSE: { conn->onion_callback(conn->onion_callback_object, data + 1, length - 1, userdata); return 0; } default: { if (data[0] < NUM_RESERVED_PORTS) { return -1; } uint8_t con_id = data[0] - NUM_RESERVED_PORTS; if (conn->data_callback) { conn->data_callback(conn->data_callback_object, conn->connections[con_id].number, con_id, data + 1, length - 1, userdata); } } } return 0; }