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
* with length length will arrive at 3.
* Create a new onion path out of nodes (nodes is a list of 3 nodes)
*
* new_path must be an empty memory location of atleast Onion_Path size.
*
* return -1 on failure.
* 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)
return -1;
to_net_family(&dest.ip);
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);
uint8_t nonce[crypto_box_NONCEBYTES];
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];
to_net_family(&nodes[2].ip_port.ip);
memcpy(step2, &nodes[2].ip_port, sizeof(IP_Port));
memcpy(step2 + sizeof(IP_Port), random_public_key, crypto_box_PUBLICKEYBYTES);
memcpy(step2, &path->ip_port3, sizeof(IP_Port));
memcpy(step2 + sizeof(IP_Port), path->public_key3, crypto_box_PUBLICKEYBYTES);
int len = encrypt_data(nodes[2].client_id, random_secret_key, nonce,
step1, sizeof(step1), step2 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES);
int len = encrypt_data_fast(path->shared_key3, nonce, step1, sizeof(step1),
step2 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES);
if ((uint32_t)len != sizeof(IP_Port) + length + crypto_box_MACBYTES)
return -1;
crypto_box_keypair(random_public_key, random_secret_key);
uint8_t step3[sizeof(IP_Port) + SEND_BASE * 2 + length];
to_net_family(&nodes[1].ip_port.ip);
memcpy(step3, &nodes[1].ip_port, sizeof(IP_Port));
memcpy(step3 + sizeof(IP_Port), random_public_key, crypto_box_PUBLICKEYBYTES);
len = encrypt_data(nodes[1].client_id, random_secret_key, nonce,
step2, sizeof(step2), step3 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES);
memcpy(step3, &path->ip_port2, sizeof(IP_Port));
memcpy(step3 + sizeof(IP_Port), path->public_key2, crypto_box_PUBLICKEYBYTES);
len = encrypt_data_fast(path->shared_key2, nonce, step2, sizeof(step2),
step3 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES);
if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE + length + crypto_box_MACBYTES)
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];
packet[0] = NET_PACKET_ONION_SEND_INITIAL;
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,
step3, sizeof(step3), packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES);
len = encrypt_data_fast(path->shared_key1, nonce, step3, sizeof(step3),
packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES);
if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE * 2 + length + crypto_box_MACBYTES)
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 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_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
* with length length will arrive at 3.
* Create a new onion path out of nodes (nodes is a list of 3 nodes)
*
* new_path must be an empty memory location of atleast Onion_Path size.
*
* return -1 on failure.
* 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.
*

View File

@ -37,8 +37,7 @@
/* 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
* request will be sent to 3.
* path is the path the request will take before it is sent to dest.
*
* 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.
@ -50,8 +49,8 @@
* return -1 on failure.
* 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,
uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data)
int send_announce_request(Networking_Core *net, Onion_Path *path, Node_format dest, uint8_t *public_key,
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];
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;
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);
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);
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.
*
* nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the data
* request packet will arrive at 3. (if 3 knows the person with the public_key they should
* path is the path the request will take before it is sent to dest.
* (if dest knows the person with the public_key they should
* 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.
@ -88,8 +87,8 @@ int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uin
* return -1 on failure.
* 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,
uint8_t *data, uint16_t length)
int send_data_request(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *public_key,
uint8_t *encrypt_public_key, uint8_t *nonce, uint8_t *data, uint16_t length)
{
uint8_t packet[DATA_REQUEST_MIN_SIZE + length];
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))
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 */

View File

@ -58,8 +58,7 @@ typedef struct {
/* 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
* request will be sent to 3.
* path is the path the request will take before it is sent to dest.
*
* 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.
@ -71,13 +70,13 @@ typedef struct {
* return -1 on failure.
* 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,
uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data);
int send_announce_request(Networking_Core *net, Onion_Path *path, Node_format dest, uint8_t *public_key,
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.
*
* nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the data
* request packet will arrive at 3. (if 3 knows the person with the public_key they should
* path is the path the request will take before it is sent to dest.
* (if dest knows the person with the public_key they should
* 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.
@ -88,8 +87,8 @@ int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uin
* return -1 on failure.
* 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,
uint8_t *data, uint16_t length);
int send_data_request(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *public_key,
uint8_t *encrypt_public_key, uint8_t *nonce, uint8_t *data, uint16_t length);
Onion_Announce *new_onion_announce(DHT *dht);

View File

@ -30,6 +30,63 @@
#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.
*
@ -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,
uint8_t *ping_id)
uint8_t *ping_id, uint32_t pathnum)
{
if (num > onion_c->num_friends)
return -1;
@ -114,20 +171,24 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_
if (ping_id == NULL)
ping_id = zero_ping_id;
Node_format nodes[4];
Onion_Path path;
if (random_path(onion_c, nodes) == -1)
return -1;
nodes[3].ip_port = dest;
memcpy(nodes[3].client_id, dest_pubkey, crypto_box_PUBLICKEYBYTES);
Node_format dest_node;
dest_node.ip_port = dest;
memcpy(dest_node.client_id, dest_pubkey, crypto_box_PUBLICKEYBYTES);
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_public_key, onion_c->temp_public_key, sendback);
} 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].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,
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)
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].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;
}
@ -267,7 +329,7 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *n
}
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;
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;
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) {
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;
memcpy(nodes[3].client_id, list_nodes[i].client_id, crypto_box_PUBLICKEYBYTES);
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)
++good;
}
@ -731,23 +795,6 @@ int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_on
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
@ -770,7 +817,7 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
++count;
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();
}
}
@ -783,7 +830,7 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
rand() % 2 ? AF_INET : AF_INET6, 1, 0);
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 (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();
}
}
@ -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,
rand() % 2 ? AF_INET : AF_INET6, 1, 0);
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);
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, ~0);
}
}
}
}

View File

@ -33,6 +33,13 @@
#define ONION_FAKEID_INTERVAL 30
#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 {
uint8_t client_id[CLIENT_ID_SIZE];
IP_Port ip_port;
@ -43,8 +50,15 @@ typedef struct {
uint64_t timestamp;
uint64_t last_pinged;
uint32_t path_used;
} Onion_Node;
typedef struct {
Onion_Path paths[NUMBER_ONION_PATHS];
uint64_t last_path_success[NUMBER_ONION_PATHS];
} Onion_Client_Paths;
typedef struct {
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. */
@ -63,6 +77,8 @@ typedef struct {
uint64_t last_noreplay;
uint64_t last_seen;
Onion_Client_Paths onion_paths;
} Onion_Friend;
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_Client_Paths onion_paths;
uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES];
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);
/* 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.
* This data will be recieved by the friend using the Onion_Data_Handlers callbacks.