Major speed/cpu usage/bandwidth improvements to onion.

This commit is contained in:
irungentoo 2014-02-26 12:18:47 -05:00
parent b01c19ce56
commit cebae58ddc
6 changed files with 204 additions and 93 deletions

View File

@ -47,48 +47,81 @@ static void change_symmetric_key(Onion *onion)
} }
} }
/* Create and send a onion packet. /* Create a new onion path.
* *
* nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the data * Create a new onion path out of nodes (nodes is a list of 3 nodes)
* with length length will arrive at 3. *
* new_path must be an empty memory location of atleast Onion_Path size.
* *
* return -1 on failure. * return -1 on failure.
* return 0 on success. * return 0 on success.
*/ */
int send_onion_packet(DHT *dht, Node_format *nodes, uint8_t *data, uint32_t length) int create_onion_path(DHT *dht, Onion_Path *new_path, Node_format *nodes)
{
if (!new_path || !nodes)
return -1;
encrypt_precompute(nodes[0].client_id, dht->self_secret_key, new_path->shared_key1);
memcpy(new_path->public_key1, dht->self_public_key, crypto_box_PUBLICKEYBYTES);
uint8_t random_public_key[crypto_box_PUBLICKEYBYTES];
uint8_t random_secret_key[crypto_box_SECRETKEYBYTES];
crypto_box_keypair(random_public_key, random_secret_key);
encrypt_precompute(nodes[1].client_id, random_secret_key, new_path->shared_key2);
memcpy(new_path->public_key2, random_public_key, crypto_box_PUBLICKEYBYTES);
crypto_box_keypair(random_public_key, random_secret_key);
encrypt_precompute(nodes[2].client_id, random_secret_key, new_path->shared_key3);
memcpy(new_path->public_key3, random_public_key, crypto_box_PUBLICKEYBYTES);
new_path->ip_port1 = nodes[0].ip_port;
new_path->ip_port2 = nodes[1].ip_port;
new_path->ip_port3 = nodes[2].ip_port;
/* to_net_family(&new_path->ip_port1.ip); */
to_net_family(&new_path->ip_port2.ip);
to_net_family(&new_path->ip_port3.ip);
return 0;
}
/* Create and send a onion packet.
*
* Use Onion_Path path to send data of length to dest.
*
* return -1 on failure.
* return 0 on success.
*/
int send_onion_packet(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *data, uint32_t length)
{ {
if (1 + length + SEND_1 > MAX_ONION_SIZE || length == 0) if (1 + length + SEND_1 > MAX_ONION_SIZE || length == 0)
return -1; return -1;
to_net_family(&dest.ip);
uint8_t step1[sizeof(IP_Port) + length]; uint8_t step1[sizeof(IP_Port) + length];
to_net_family(&nodes[3].ip_port.ip);
memcpy(step1, &nodes[3].ip_port, sizeof(IP_Port)); memcpy(step1, &dest, sizeof(IP_Port));
memcpy(step1 + sizeof(IP_Port), data, length); memcpy(step1 + sizeof(IP_Port), data, length);
uint8_t nonce[crypto_box_NONCEBYTES]; uint8_t nonce[crypto_box_NONCEBYTES];
random_nonce(nonce); random_nonce(nonce);
uint8_t random_public_key[crypto_box_PUBLICKEYBYTES];
uint8_t random_secret_key[crypto_box_SECRETKEYBYTES];
crypto_box_keypair(random_public_key, random_secret_key);
uint8_t step2[sizeof(IP_Port) + SEND_BASE + length]; uint8_t step2[sizeof(IP_Port) + SEND_BASE + length];
to_net_family(&nodes[2].ip_port.ip); memcpy(step2, &path->ip_port3, sizeof(IP_Port));
memcpy(step2, &nodes[2].ip_port, sizeof(IP_Port)); memcpy(step2 + sizeof(IP_Port), path->public_key3, crypto_box_PUBLICKEYBYTES);
memcpy(step2 + sizeof(IP_Port), random_public_key, crypto_box_PUBLICKEYBYTES);
int len = encrypt_data(nodes[2].client_id, random_secret_key, nonce, int len = encrypt_data_fast(path->shared_key3, nonce, step1, sizeof(step1),
step1, sizeof(step1), step2 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES); step2 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES);
if ((uint32_t)len != sizeof(IP_Port) + length + crypto_box_MACBYTES) if ((uint32_t)len != sizeof(IP_Port) + length + crypto_box_MACBYTES)
return -1; return -1;
crypto_box_keypair(random_public_key, random_secret_key);
uint8_t step3[sizeof(IP_Port) + SEND_BASE * 2 + length]; uint8_t step3[sizeof(IP_Port) + SEND_BASE * 2 + length];
to_net_family(&nodes[1].ip_port.ip); memcpy(step3, &path->ip_port2, sizeof(IP_Port));
memcpy(step3, &nodes[1].ip_port, sizeof(IP_Port)); memcpy(step3 + sizeof(IP_Port), path->public_key2, crypto_box_PUBLICKEYBYTES);
memcpy(step3 + sizeof(IP_Port), random_public_key, crypto_box_PUBLICKEYBYTES); len = encrypt_data_fast(path->shared_key2, nonce, step2, sizeof(step2),
len = encrypt_data(nodes[1].client_id, random_secret_key, nonce, step3 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES);
step2, sizeof(step2), step3 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES);
if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE + length + crypto_box_MACBYTES) if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE + length + crypto_box_MACBYTES)
return -1; return -1;
@ -96,15 +129,15 @@ int send_onion_packet(DHT *dht, Node_format *nodes, uint8_t *data, uint32_t leng
uint8_t packet[1 + length + SEND_1]; uint8_t packet[1 + length + SEND_1];
packet[0] = NET_PACKET_ONION_SEND_INITIAL; packet[0] = NET_PACKET_ONION_SEND_INITIAL;
memcpy(packet + 1, nonce, crypto_box_NONCEBYTES); memcpy(packet + 1, nonce, crypto_box_NONCEBYTES);
memcpy(packet + 1 + crypto_box_NONCEBYTES, dht->self_public_key, crypto_box_PUBLICKEYBYTES); memcpy(packet + 1 + crypto_box_NONCEBYTES, path->public_key1, crypto_box_PUBLICKEYBYTES);
len = encrypt_data(nodes[0].client_id, dht->self_secret_key, nonce, len = encrypt_data_fast(path->shared_key1, nonce, step3, sizeof(step3),
step3, sizeof(step3), packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES); packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES);
if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE * 2 + length + crypto_box_MACBYTES) if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE * 2 + length + crypto_box_MACBYTES)
return -1; return -1;
if ((uint32_t)sendpacket(dht->c->lossless_udp->net, nodes[0].ip_port, packet, sizeof(packet)) != sizeof(packet)) if ((uint32_t)sendpacket(net, path->ip_port1, packet, sizeof(packet)) != sizeof(packet))
return -1; return -1;
return 0; return 0;

View File

@ -41,16 +41,39 @@ typedef struct {
#define ONION_SEND_2 (crypto_box_NONCEBYTES + ONION_SEND_BASE*2 + ONION_RETURN_1) #define ONION_SEND_2 (crypto_box_NONCEBYTES + ONION_SEND_BASE*2 + ONION_RETURN_1)
#define ONION_SEND_1 (crypto_box_NONCEBYTES + ONION_SEND_BASE*3) #define ONION_SEND_1 (crypto_box_NONCEBYTES + ONION_SEND_BASE*3)
typedef struct {
uint8_t shared_key1[crypto_box_BEFORENMBYTES];
uint8_t shared_key2[crypto_box_BEFORENMBYTES];
uint8_t shared_key3[crypto_box_BEFORENMBYTES];
/* Create and send a onion packet. uint8_t public_key1[crypto_box_PUBLICKEYBYTES];
uint8_t public_key2[crypto_box_PUBLICKEYBYTES];
uint8_t public_key3[crypto_box_PUBLICKEYBYTES];
IP_Port ip_port1;
IP_Port ip_port2;
IP_Port ip_port3;
} Onion_Path;
/* Create a new onion path.
* *
* nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the data * Create a new onion path out of nodes (nodes is a list of 3 nodes)
* with length length will arrive at 3. *
* new_path must be an empty memory location of atleast Onion_Path size.
* *
* return -1 on failure. * return -1 on failure.
* return 0 on success. * return 0 on success.
*/ */
int send_onion_packet(DHT *dht, Node_format *nodes, uint8_t *data, uint32_t length); int create_onion_path(DHT *dht, Onion_Path *new_path, Node_format *nodes);
/* Create and send a onion packet.
*
* Use Onion_Path path to send data of length to dest.
*
* return -1 on failure.
* return 0 on success.
*/
int send_onion_packet(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *data, uint32_t length);
/* Create and send a onion response sent initially to dest with. /* Create and send a onion response sent initially to dest with.
* *

View File

@ -37,8 +37,7 @@
/* Create and send an onion announce request packet. /* Create and send an onion announce request packet.
* *
* nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the announe * path is the path the request will take before it is sent to dest.
* request will be sent to 3.
* *
* public_key and secret_key is the kepair which will be used to encrypt the request. * public_key and secret_key is the kepair which will be used to encrypt the request.
* ping_id is the ping id that will be sent in the request. * ping_id is the ping id that will be sent in the request.
@ -50,8 +49,8 @@
* return -1 on failure. * return -1 on failure.
* return 0 on success. * return 0 on success.
*/ */
int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *secret_key, uint8_t *ping_id, int send_announce_request(Networking_Core *net, Onion_Path *path, Node_format dest, uint8_t *public_key,
uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data) uint8_t *secret_key, uint8_t *ping_id, uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data)
{ {
uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH]; uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];
memcpy(plain, ping_id, ONION_PING_ID_SIZE); memcpy(plain, ping_id, ONION_PING_ID_SIZE);
@ -63,7 +62,7 @@ int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uin
packet[0] = NET_PACKET_ANNOUNCE_REQUEST; packet[0] = NET_PACKET_ANNOUNCE_REQUEST;
random_nonce(packet + 1); random_nonce(packet + 1);
int len = encrypt_data(nodes[3].client_id, secret_key, packet + 1, plain, sizeof(plain), int len = encrypt_data(dest.client_id, secret_key, packet + 1, plain, sizeof(plain),
packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES); packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES);
if ((uint32_t)len + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES != ANNOUNCE_REQUEST_SIZE) if ((uint32_t)len + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES != ANNOUNCE_REQUEST_SIZE)
@ -71,13 +70,13 @@ int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uin
memcpy(packet + 1 + crypto_box_NONCEBYTES, public_key, crypto_box_PUBLICKEYBYTES); memcpy(packet + 1 + crypto_box_NONCEBYTES, public_key, crypto_box_PUBLICKEYBYTES);
return send_onion_packet(dht, nodes, packet, sizeof(packet)); return send_onion_packet(net, path, dest.ip_port, packet, sizeof(packet));
} }
/* Create and send an onion data request packet. /* Create and send an onion data request packet.
* *
* nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the data * path is the path the request will take before it is sent to dest.
* request packet will arrive at 3. (if 3 knows the person with the public_key they should * (if dest knows the person with the public_key they should
* send the packet to that person in the form of a response) * send the packet to that person in the form of a response)
* *
* public_key is the real public key of the node which we want to send the data of length length to. * public_key is the real public key of the node which we want to send the data of length length to.
@ -88,8 +87,8 @@ int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uin
* return -1 on failure. * return -1 on failure.
* return 0 on success. * return 0 on success.
*/ */
int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *encrypt_public_key, uint8_t *nonce, int send_data_request(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *public_key,
uint8_t *data, uint16_t length) uint8_t *encrypt_public_key, uint8_t *nonce, uint8_t *data, uint16_t length)
{ {
uint8_t packet[DATA_REQUEST_MIN_SIZE + length]; uint8_t packet[DATA_REQUEST_MIN_SIZE + length];
packet[0] = NET_PACKET_ONION_DATA_REQUEST; packet[0] = NET_PACKET_ONION_DATA_REQUEST;
@ -108,7 +107,7 @@ int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t
if (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + (uint32_t)len != sizeof(packet)) if (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + (uint32_t)len != sizeof(packet))
return -1; return -1;
return send_onion_packet(dht, nodes, packet, sizeof(packet)); return send_onion_packet(net, path, dest, packet, sizeof(packet));
} }
/* Generate a ping_id and put it in ping_id */ /* Generate a ping_id and put it in ping_id */

View File

@ -58,8 +58,7 @@ typedef struct {
/* Create and send an onion announce request packet. /* Create and send an onion announce request packet.
* *
* nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the announe * path is the path the request will take before it is sent to dest.
* request will be sent to 3.
* *
* public_key and secret_key is the kepair which will be used to encrypt the request. * public_key and secret_key is the kepair which will be used to encrypt the request.
* ping_id is the ping id that will be sent in the request. * ping_id is the ping id that will be sent in the request.
@ -71,13 +70,13 @@ typedef struct {
* return -1 on failure. * return -1 on failure.
* return 0 on success. * return 0 on success.
*/ */
int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *secret_key, uint8_t *ping_id, int send_announce_request(Networking_Core *net, Onion_Path *path, Node_format dest, uint8_t *public_key,
uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data); uint8_t *secret_key, uint8_t *ping_id, uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data);
/* Create and send an onion data request packet. /* Create and send an onion data request packet.
* *
* nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the data * path is the path the request will take before it is sent to dest.
* request packet will arrive at 3. (if 3 knows the person with the public_key they should * (if dest knows the person with the public_key they should
* send the packet to that person in the form of a response) * send the packet to that person in the form of a response)
* *
* public_key is the real public key of the node which we want to send the data of length length to. * public_key is the real public key of the node which we want to send the data of length length to.
@ -88,8 +87,8 @@ int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uin
* return -1 on failure. * return -1 on failure.
* return 0 on success. * return 0 on success.
*/ */
int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *encrypt_public_key, uint8_t *nonce, int send_data_request(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *public_key,
uint8_t *data, uint16_t length); uint8_t *encrypt_public_key, uint8_t *nonce, uint8_t *data, uint16_t length);
Onion_Announce *new_onion_announce(DHT *dht); Onion_Announce *new_onion_announce(DHT *dht);

View File

@ -30,6 +30,63 @@
#define ANNOUNCE_TIMEOUT 10 #define ANNOUNCE_TIMEOUT 10
/* Create a new path or use an old suitable one (if pathnum is valid)
* or a rondom one from onion_paths.
*
* return -1 on failure
* return 0 on success
*
* TODO: Make this function better, it currently probably is vulnerable to some attacks that
* could de anonimize us.
*/
static int random_path(DHT *dht, Onion_Client_Paths *onion_paths, uint32_t pathnum, Onion_Path *path)
{
if (pathnum >= NUMBER_ONION_PATHS)
pathnum = rand() % NUMBER_ONION_PATHS;
if (is_timeout(onion_paths->last_path_success[pathnum], ONION_PATH_TIMEOUT)) {
Node_format nodes[3];
if (random_nodes_path(dht, nodes, 3) != 3)
return -1;
if (create_onion_path(dht, &onion_paths->paths[pathnum], nodes) == -1)
return -1;
onion_paths->last_path_success[pathnum] = unix_time() + ONION_PATH_FIRST_TIMEOUT - ONION_PATH_TIMEOUT;
}
memcpy(path, &onion_paths->paths[pathnum], sizeof(Onion_Path));
return 0;
}
/* Set path timeouts, return the path number.
*
*/
static uint32_t set_path_timeouts(Onion_Client *onion_c, uint32_t num, IP_Port source)
{
if (num > onion_c->num_friends)
return -1;
Onion_Client_Paths *onion_paths;
if (num == 0) {
onion_paths = &onion_c->onion_paths;
} else {
onion_paths = &onion_c->friends_list[num - 1].onion_paths;
}
uint32_t i;
for (i = 0; i < NUMBER_ONION_PATHS; ++i) {
if (ipport_equal(&onion_paths->paths[i].ip_port1, &source)) {
onion_paths->last_path_success[i] = unix_time();
return i;
}
}
return ~0;
}
/* Creates a sendback for use in an announce request. /* Creates a sendback for use in an announce request.
* *
@ -99,7 +156,7 @@ static uint32_t check_sendback(Onion_Client *onion_c, uint8_t *sendback, uint8_t
} }
static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_Port dest, uint8_t *dest_pubkey, static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_Port dest, uint8_t *dest_pubkey,
uint8_t *ping_id) uint8_t *ping_id, uint32_t pathnum)
{ {
if (num > onion_c->num_friends) if (num > onion_c->num_friends)
return -1; return -1;
@ -114,20 +171,24 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_
if (ping_id == NULL) if (ping_id == NULL)
ping_id = zero_ping_id; ping_id = zero_ping_id;
Node_format nodes[4]; Onion_Path path;
if (random_path(onion_c, nodes) == -1) Node_format dest_node;
return -1; dest_node.ip_port = dest;
memcpy(dest_node.client_id, dest_pubkey, crypto_box_PUBLICKEYBYTES);
nodes[3].ip_port = dest;
memcpy(nodes[3].client_id, dest_pubkey, crypto_box_PUBLICKEYBYTES);
if (num == 0) { if (num == 0) {
return send_announce_request(onion_c->dht, nodes, onion_c->dht->c->self_public_key, if (random_path(onion_c->dht, &onion_c->onion_paths, pathnum, &path) == -1)
return -1;
return send_announce_request(onion_c->net, &path, dest_node, onion_c->dht->c->self_public_key,
onion_c->dht->c->self_secret_key, ping_id, onion_c->dht->c->self_secret_key, ping_id,
onion_c->dht->c->self_public_key, onion_c->temp_public_key, sendback); onion_c->dht->c->self_public_key, onion_c->temp_public_key, sendback);
} else { } else {
return send_announce_request(onion_c->dht, nodes, onion_c->friends_list[num - 1].temp_public_key, if (random_path(onion_c->dht, &onion_c->friends_list[num - 1].onion_paths, pathnum, &path) == -1)
return -1;
return send_announce_request(onion_c->net, &path, dest_node, onion_c->friends_list[num - 1].temp_public_key,
onion_c->friends_list[num - 1].temp_secret_key, ping_id, onion_c->friends_list[num - 1].temp_secret_key, ping_id,
onion_c->friends_list[num - 1].real_client_id, zero_ping_id, sendback); onion_c->friends_list[num - 1].real_client_id, zero_ping_id, sendback);
} }
@ -163,7 +224,7 @@ static int cmp_entry(const void *a, const void *b)
} }
static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *public_key, IP_Port ip_port, static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *public_key, IP_Port ip_port,
uint8_t is_stored, uint8_t *pingid_or_key) uint8_t is_stored, uint8_t *pingid_or_key, IP_Port source)
{ {
if (num > onion_c->num_friends) if (num > onion_c->num_friends)
return -1; return -1;
@ -223,7 +284,8 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *publ
list_nodes[index].is_stored = is_stored; list_nodes[index].is_stored = is_stored;
list_nodes[index].timestamp = unix_time(); list_nodes[index].timestamp = unix_time();
list_nodes[index].last_pinged = 0; list_nodes[index].last_pinged = unix_time();
list_nodes[index].path_used = set_path_timeouts(onion_c, num, source);
return 0; return 0;
} }
@ -267,7 +329,7 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *n
} }
if (j == MAX_ONION_CLIENTS) { if (j == MAX_ONION_CLIENTS) {
client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].client_id, NULL); client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].client_id, NULL, ~0);
} }
} }
} }
@ -315,7 +377,7 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe
return 1; return 1;
if (client_add_to_list(onion_c, num, public_key, ip_port, plain[0], plain + 1) == -1) if (client_add_to_list(onion_c, num, public_key, ip_port, plain[0], plain + 1, source) == -1)
return 1; return 1;
Node_format nodes[MAX_SENT_NODES]; Node_format nodes[MAX_SENT_NODES];
@ -457,13 +519,15 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, uint8_t *data, uint32
if (list_nodes[i].is_stored) { if (list_nodes[i].is_stored) {
Node_format nodes[4]; Node_format nodes[4];
if (random_path(onion_c, nodes) == -1) Onion_Path path;
if (random_path(onion_c->dht, &onion_c->friends_list[friend_num].onion_paths, ~0, &path) == -1)
continue; continue;
memcpy(nodes[3].client_id, list_nodes[i].client_id, crypto_box_PUBLICKEYBYTES); memcpy(nodes[3].client_id, list_nodes[i].client_id, crypto_box_PUBLICKEYBYTES);
nodes[3].ip_port = list_nodes[i].ip_port; nodes[3].ip_port = list_nodes[i].ip_port;
if (send_data_request(onion_c->dht, nodes, onion_c->friends_list[friend_num].real_client_id, if (send_data_request(onion_c->net, &path, list_nodes[i].ip_port, onion_c->friends_list[friend_num].real_client_id,
list_nodes[i].data_public_key, nonce, packet, sizeof(packet)) == 0) list_nodes[i].data_public_key, nonce, packet, sizeof(packet)) == 0)
++good; ++good;
} }
@ -731,23 +795,6 @@ int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_on
return 0; return 0;
} }
/* Takes 3 random nodes that we know and puts them in nodes
*
* nodes must be longer than 3.
*
* return -1 on failure
* return 0 on success
*
* TODO: Make this function better, it currently might be vulnerable to some attacks that
* could de anonimize us.
*/
int random_path(Onion_Client *onion_c, Node_format *nodes)
{
if (random_nodes_path(onion_c->dht, nodes, 3) != 3)
return -1;
return 0;
}
#define ANNOUNCE_FRIEND 30 #define ANNOUNCE_FRIEND 30
@ -770,7 +817,7 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
++count; ++count;
if (is_timeout(list_nodes[i].last_pinged, ANNOUNCE_FRIEND)) { if (is_timeout(list_nodes[i].last_pinged, ANNOUNCE_FRIEND)) {
if (client_send_announce_request(onion_c, friendnum + 1, list_nodes[i].ip_port, list_nodes[i].client_id, 0) == 0) { if (client_send_announce_request(onion_c, friendnum + 1, list_nodes[i].ip_port, list_nodes[i].client_id, 0, ~0) == 0) {
list_nodes[i].last_pinged = unix_time(); list_nodes[i].last_pinged = unix_time();
} }
} }
@ -783,7 +830,7 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
rand() % 2 ? AF_INET : AF_INET6, 1, 0); rand() % 2 ? AF_INET : AF_INET6, 1, 0);
for (i = 0; i < num_nodes; ++i) for (i = 0; i < num_nodes; ++i)
client_send_announce_request(onion_c, friendnum + 1, nodes_list[i].ip_port, nodes_list[i].client_id, 0); client_send_announce_request(onion_c, friendnum + 1, nodes_list[i].ip_port, nodes_list[i].client_id, 0, ~0);
} }
} }
@ -845,7 +892,7 @@ static void do_announce(Onion_Client *onion_c)
if (is_timeout(list_nodes[i].last_pinged, interval)) { if (is_timeout(list_nodes[i].last_pinged, interval)) {
if (client_send_announce_request(onion_c, 0, list_nodes[i].ip_port, list_nodes[i].client_id, if (client_send_announce_request(onion_c, 0, list_nodes[i].ip_port, list_nodes[i].client_id,
list_nodes[i].ping_id) == 0) { list_nodes[i].ping_id, list_nodes[i].path_used) == 0) {
list_nodes[i].last_pinged = unix_time(); list_nodes[i].last_pinged = unix_time();
} }
} }
@ -857,8 +904,9 @@ static void do_announce(Onion_Client *onion_c)
uint32_t num_nodes = get_close_nodes(onion_c->dht, onion_c->dht->c->self_public_key, nodes_list, uint32_t num_nodes = get_close_nodes(onion_c->dht, onion_c->dht->c->self_public_key, nodes_list,
rand() % 2 ? AF_INET : AF_INET6, 1, 0); rand() % 2 ? AF_INET : AF_INET6, 1, 0);
for (i = 0; i < num_nodes; ++i) for (i = 0; i < num_nodes; ++i) {
client_send_announce_request(onion_c, 0, nodes_list[i].ip_port, nodes_list[i].client_id, 0); client_send_announce_request(onion_c, 0, nodes_list[i].ip_port, nodes_list[i].client_id, 0, ~0);
}
} }
} }
} }

View File

@ -33,6 +33,13 @@
#define ONION_FAKEID_INTERVAL 30 #define ONION_FAKEID_INTERVAL 30
#define DHT_FAKEID_INTERVAL 20 #define DHT_FAKEID_INTERVAL 20
#define NUMBER_ONION_PATHS 3
/* The timeout the first time the path is added and
then for all the next consecutive times */
#define ONION_PATH_FIRST_TIMEOUT 5
#define ONION_PATH_TIMEOUT 30
typedef struct { typedef struct {
uint8_t client_id[CLIENT_ID_SIZE]; uint8_t client_id[CLIENT_ID_SIZE];
IP_Port ip_port; IP_Port ip_port;
@ -43,8 +50,15 @@ typedef struct {
uint64_t timestamp; uint64_t timestamp;
uint64_t last_pinged; uint64_t last_pinged;
uint32_t path_used;
} Onion_Node; } Onion_Node;
typedef struct {
Onion_Path paths[NUMBER_ONION_PATHS];
uint64_t last_path_success[NUMBER_ONION_PATHS];
} Onion_Client_Paths;
typedef struct { typedef struct {
uint8_t status; /* 0 if friend is not valid, 1 if friend is valid.*/ uint8_t status; /* 0 if friend is not valid, 1 if friend is valid.*/
uint8_t is_online; /* Set by the onion_set_friend_status function. */ uint8_t is_online; /* Set by the onion_set_friend_status function. */
@ -63,6 +77,8 @@ typedef struct {
uint64_t last_noreplay; uint64_t last_noreplay;
uint64_t last_seen; uint64_t last_seen;
Onion_Client_Paths onion_paths;
} Onion_Friend; } Onion_Friend;
typedef int (*oniondata_handler_callback)(void *object, uint8_t *source_pubkey, uint8_t *data, uint32_t len); typedef int (*oniondata_handler_callback)(void *object, uint8_t *source_pubkey, uint8_t *data, uint32_t len);
@ -75,6 +91,8 @@ typedef struct {
Onion_Node clients_announce_list[MAX_ONION_CLIENTS]; Onion_Node clients_announce_list[MAX_ONION_CLIENTS];
Onion_Client_Paths onion_paths;
uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES]; uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES];
uint64_t last_run; uint64_t last_run;
@ -127,15 +145,6 @@ int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_on
*/ */
int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port); int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port);
/* Takes 3 random nodes that we know and puts them in nodes
*
* nodes must be longer than 3.
*
* return -1 on failure
* return 0 on success
*
*/
int random_path(Onion_Client *onion_c, Node_format *nodes);
/* Send data of length length to friendnum. /* Send data of length length to friendnum.
* This data will be recieved by the friend using the Onion_Data_Handlers callbacks. * This data will be recieved by the friend using the Onion_Data_Handlers callbacks.