mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
Onion data packets can now be handled in onion_client.
oniondata_registerhandler(...) can be used to register different packet types to handle them and send_onion_data(...) can be used to send these packets.
This commit is contained in:
parent
878762a8e4
commit
a49a09f94b
|
@ -96,6 +96,7 @@ static int handle_test_3(void *object, IP_Port source, uint8_t *packet, uint32_t
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint8_t nonce[crypto_box_NONCEBYTES];
|
||||
static int handled_test_4;
|
||||
static int handle_test_4(void *object, IP_Port source, uint8_t *packet, uint32_t length)
|
||||
{
|
||||
|
@ -105,6 +106,10 @@ static int handle_test_4(void *object, IP_Port source, uint8_t *packet, uint32_t
|
|||
return 1;
|
||||
|
||||
uint8_t plain[sizeof("Install gentoo")] = {0};
|
||||
|
||||
if (memcmp(nonce, packet + 1, crypto_box_NONCEBYTES) != 0)
|
||||
return 1;
|
||||
|
||||
int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion->dht->c->self_secret_key, packet + 1,
|
||||
packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, sizeof("Install gentoo") + crypto_box_MACBYTES, plain);
|
||||
|
||||
|
@ -195,7 +200,9 @@ START_TEST(test_basic)
|
|||
c_sleep(1000);
|
||||
Onion *onion3 = new_onion(new_DHT(new_net_crypto(new_networking(ip, 34569))));
|
||||
ck_assert_msg((onion3 != NULL), "Onion failed initializing.");
|
||||
ret = send_data_request(onion3->dht, nodes, onion1->dht->c->self_public_key, (uint8_t *)"Install gentoo",
|
||||
|
||||
new_nonce(nonce);
|
||||
ret = send_data_request(onion3->dht, nodes, onion1->dht->c->self_public_key, nonce, (uint8_t *)"Install gentoo",
|
||||
sizeof("Install gentoo"));
|
||||
ck_assert_msg(ret == 0, "Failed to create/send onion data_request packet.");
|
||||
handled_test_4 = 0;
|
||||
|
|
|
@ -108,6 +108,9 @@ data to route request packet:
|
|||
encrypted with that temporary private key and the nonce and the real public key of the destination node:[data]
|
||||
(if Node D contains the ret data for the node, it sends the stuff in this packet as a data to route response packet to the right node)
|
||||
|
||||
The data in the previous packet is in format: [real public key of sender]
|
||||
encrypted with real private key of the sender, the nonce in the data packet and the real public key of the reciever:[[uint8_t id][data (optional)]]
|
||||
|
||||
Data sent to us:
|
||||
announce response packet:
|
||||
[uint8_t packet id (132)][data to send back in response(fixed size)][nonce]
|
||||
|
@ -117,6 +120,8 @@ encrypted with the DHT private key of Node D, the public key in the request and
|
|||
data to route response packet:
|
||||
[uint8_t packet id (134)][nonce][temporary just generated public key]
|
||||
encrypted with that temporary private key and the nonce and the real public key of the destination node:[data]
|
||||
|
||||
|
||||
Onion packet (response):
|
||||
|
||||
initial (sent from node D to node C):
|
||||
|
|
|
@ -78,16 +78,17 @@ int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uin
|
|||
* 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.
|
||||
* nonce is the nonce to encrypt this packet with
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *data, uint16_t length)
|
||||
int send_data_request(DHT *dht, Node_format *nodes, uint8_t *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;
|
||||
memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES);
|
||||
new_nonce(packet + 1 + crypto_box_PUBLICKEYBYTES);
|
||||
memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES);
|
||||
|
||||
uint8_t random_public_key[crypto_box_PUBLICKEYBYTES];
|
||||
uint8_t random_secret_key[crypto_box_SECRETKEYBYTES];
|
||||
|
|
|
@ -75,11 +75,13 @@ int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uin
|
|||
* 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.
|
||||
* nonce is the nonce to encrypt this packet with
|
||||
*
|
||||
* return -1 on failure.
|
||||
* return 0 on success.
|
||||
*/
|
||||
int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *data, uint16_t length);
|
||||
int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *nonce, uint8_t *data,
|
||||
uint16_t length);
|
||||
|
||||
|
||||
Onion_Announce *new_onion_announce(DHT *dht);
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#define ANNOUNCE_TIMEOUT 10
|
||||
|
||||
uint8_t zero_ping[ONION_PING_ID_SIZE];
|
||||
|
||||
/* Creates a sendback for use in an announce request.
|
||||
*
|
||||
|
@ -297,26 +298,93 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define DATA_IN_RESPONSE_MIN_SIZE (crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES)
|
||||
|
||||
static int handle_data_response(void *object, IP_Port source, uint8_t *packet, uint32_t length)
|
||||
{
|
||||
Onion_Client *onion_c = object;
|
||||
|
||||
if (length <= ONION_DATA_RESPONSE_MIN_SIZE)
|
||||
if (length <= (ONION_DATA_RESPONSE_MIN_SIZE + DATA_IN_RESPONSE_MIN_SIZE))
|
||||
return 1;
|
||||
|
||||
if (length > MAX_DATA_SIZE)
|
||||
return 1;
|
||||
|
||||
uint8_t plain[length - ONION_DATA_RESPONSE_MIN_SIZE];
|
||||
uint8_t temp_plain[length - ONION_DATA_RESPONSE_MIN_SIZE];
|
||||
int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion_c->dht->c->self_secret_key, packet + 1,
|
||||
packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES,
|
||||
length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES), plain);
|
||||
length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES), temp_plain);
|
||||
|
||||
if ((uint32_t)len != sizeof(temp_plain))
|
||||
return 1;
|
||||
|
||||
uint8_t plain[sizeof(temp_plain) - DATA_IN_RESPONSE_MIN_SIZE];
|
||||
len = decrypt_data(temp_plain, onion_c->dht->c->self_secret_key, packet + 1, temp_plain + crypto_box_PUBLICKEYBYTES,
|
||||
sizeof(temp_plain) - crypto_box_PUBLICKEYBYTES, plain);
|
||||
|
||||
if ((uint32_t)len != sizeof(plain))
|
||||
return 1;
|
||||
|
||||
//TODO do something with the plain
|
||||
return 0;
|
||||
if (!onion_c->Onion_Data_Handlers[plain[0]].function)
|
||||
return 1;
|
||||
|
||||
return onion_c->Onion_Data_Handlers[plain[0]].function(onion_c->Onion_Data_Handlers[plain[0]].object, temp_plain, plain,
|
||||
sizeof(plain));
|
||||
}
|
||||
|
||||
/* Send data of length length to friendnum.
|
||||
* This data will be recieved by the friend using the Onion_Data_Handlers callbacks.
|
||||
*
|
||||
* Even if this function succeeds, the friend might not recieve any data.
|
||||
*
|
||||
* return the number of packets sent on success
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int send_onion_data(Onion_Client *onion_c, int friend_num, uint8_t *data, uint32_t length)
|
||||
{
|
||||
if ((uint32_t)friend_num >= onion_c->num_friends)
|
||||
return -1;
|
||||
|
||||
if (length + DATA_IN_RESPONSE_MIN_SIZE + ONION_DATA_RESPONSE_MIN_SIZE + ONION_SEND_1 > MAX_DATA_SIZE)
|
||||
return -1;
|
||||
|
||||
if (length == 0)
|
||||
return -1;
|
||||
|
||||
uint8_t nonce[crypto_box_NONCEBYTES];
|
||||
new_nonce(nonce);
|
||||
|
||||
uint8_t packet[DATA_IN_RESPONSE_MIN_SIZE + length];
|
||||
memcpy(packet, onion_c->dht->c->self_public_key, crypto_box_PUBLICKEYBYTES);
|
||||
int len = encrypt_data(onion_c->friends_list[friend_num].real_client_id, onion_c->dht->c->self_secret_key, nonce, data,
|
||||
length, packet + crypto_box_PUBLICKEYBYTES);
|
||||
|
||||
if ((uint32_t)len + crypto_box_PUBLICKEYBYTES != sizeof(packet))
|
||||
return -1;
|
||||
|
||||
uint32_t i, good = 0;
|
||||
Onion_Node *list_nodes = onion_c->friends_list[friend_num].clients_list;
|
||||
|
||||
for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
|
||||
if (is_timeout(list_nodes[i].timestamp, ONION_NODE_TIMEOUT))
|
||||
continue;
|
||||
|
||||
if (memcmp(list_nodes[i].ping_id, zero_ping, ONION_PING_ID_SIZE) == 0) {
|
||||
Node_format nodes[4];
|
||||
|
||||
if (random_path(onion_c, nodes) == -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, nonce, packet,
|
||||
sizeof(packet)) == 0)
|
||||
++good;
|
||||
}
|
||||
}
|
||||
|
||||
return good;
|
||||
}
|
||||
|
||||
/* Get the friend_num of a friend.
|
||||
|
@ -382,7 +450,7 @@ int onion_addfriend(Onion_Client *onion_c, uint8_t *client_id)
|
|||
}
|
||||
}
|
||||
|
||||
if (index == ~0) {
|
||||
if (index == (uint32_t)~0) {
|
||||
if (realloc_onion_friends(onion_c, onion_c->num_friends + 1) == -1)
|
||||
return -1;
|
||||
|
||||
|
@ -453,7 +521,7 @@ int random_path(Onion_Client *onion_c, Node_format *nodes)
|
|||
}
|
||||
|
||||
#define ANNOUNCE_FRIEND 30
|
||||
uint8_t zero_ping[ONION_PING_ID_SIZE];
|
||||
|
||||
static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
|
||||
{
|
||||
if (friendnum >= onion_c->num_friends)
|
||||
|
@ -489,6 +557,12 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
|
|||
|
||||
//TODO send packets to friend telling them our fake DHT id.
|
||||
}
|
||||
/* Function to call when onion data packet with contents beginning with byte is received. */
|
||||
void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_handler_callback cb, void *object)
|
||||
{
|
||||
onion_c->Onion_Data_Handlers[byte].function = cb;
|
||||
onion_c->Onion_Data_Handlers[byte].object = object;
|
||||
}
|
||||
|
||||
#define ANNOUNCE_INTERVAL_NOT_ANNOUNCED 10
|
||||
#define ANNOUNCE_INTERVAL_ANNOUNCED 60
|
||||
|
|
|
@ -48,6 +48,8 @@ typedef struct {
|
|||
uint8_t temp_secret_key[crypto_box_SECRETKEYBYTES];
|
||||
} Onion_Friend;
|
||||
|
||||
typedef int (*oniondata_handler_callback)(void *object, uint8_t *source_pubkey, uint8_t *data, uint32_t len);
|
||||
|
||||
typedef struct {
|
||||
DHT *dht;
|
||||
Networking_Core *net;
|
||||
|
@ -58,6 +60,11 @@ typedef struct {
|
|||
|
||||
uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES];
|
||||
uint64_t last_run;
|
||||
|
||||
struct {
|
||||
oniondata_handler_callback function;
|
||||
void *object;
|
||||
} Onion_Data_Handlers[256];
|
||||
} Onion_Client;
|
||||
|
||||
/* Add a friend who we want to connect to.
|
||||
|
@ -99,6 +106,19 @@ int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port);
|
|||
*/
|
||||
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.
|
||||
*
|
||||
* Even if this function succeeds, the friend might not recieve any data.
|
||||
*
|
||||
* return the number of packets sent on success
|
||||
* return -1 on failure.
|
||||
*/
|
||||
int send_onion_data(Onion_Client *onion_c, int friend_num, uint8_t *data, uint32_t length);
|
||||
|
||||
/* Function to call when onion data packet with contents beginning with byte is received. */
|
||||
void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_handler_callback cb, void *object);
|
||||
|
||||
void do_onion_client(Onion_Client *onion_c);
|
||||
|
||||
Onion_Client *new_onion_client(DHT *dht);
|
||||
|
|
Loading…
Reference in New Issue
Block a user