From c59975dd7ecdabe864f341b699f986e5e474acb6 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 3 Sep 2013 08:53:07 -0400 Subject: [PATCH] Work in progress group chats. Not done yet. --- docs/Group_chats.txt | 71 ++++ testing/experiment/group_chats.c | 470 ++++++++++++++++++++++++++ testing/experiment/group_chats.h | 109 ++++++ testing/experiment/group_chats_test.c | 19 ++ toxcore/DHT.c | 6 +- toxcore/net_crypto.c | 43 +-- toxcore/net_crypto.h | 6 + 7 files changed, 700 insertions(+), 24 deletions(-) create mode 100644 docs/Group_chats.txt create mode 100644 testing/experiment/group_chats.c create mode 100644 testing/experiment/group_chats.h create mode 100644 testing/experiment/group_chats_test.c diff --git a/docs/Group_chats.txt b/docs/Group_chats.txt new file mode 100644 index 00000000..0da6da04 --- /dev/null +++ b/docs/Group_chats.txt @@ -0,0 +1,71 @@ +Massive public group chats. + +Everyone generates a short term public private key pair right before joining +the chat. + +Note that for public group chats it is impossible to protect the chat from +being spied on by a very dedicated attacker, encryption is therefor used as a +form of spam/access control. + +## Joining the chats + + +## Protocol + + +Node format: +``` +[char array (node_id), length=32 bytes][ip (in network byte order), length=4 bytes][port (in network byte order), length=2 bytes][Padding , length=2 bytes] +``` + +Get nodes (Request): +Packet contents: +``` +[char with a value of 48][Bob's (The reciever's) Public key (client_id) (32 bytes))][Alice's (The sender's) Public key (client_id) (32 bytes)][Random nonce (24 bytes)][Encrypted with the nonce and private key of the sender:[char with a value of 48][random 8 byte (ping_id)] +``` +Valid replies: a send_nodes packet + +Send_nodes (response): +``` +[char with a value of 48][Bob's (The reciever's) Public key (client_id) (32 bytes))][Alice's (The sender's) Public key (client_id) (32 bytes)][Random nonce (24 bytes)][Encrypted with the nonce and private key of the sender:[char with a value of 49][random 8 byte (ping_id)][Nodes in node format, length=40 * (number of nodes (maximum of 6 nodes)) bytes]] +``` + +Broadcast packet: +``` +[char with a value of 48][Bob's (The reciever's) Public key (client_id) (32 bytes))][Alice's (The sender's) Public key (client_id) (32 bytes)][nonce][Encrypted with the nonce and private key of the sender:[char with a value of 50][Data to send to everyone]] +``` + + +Data to send to everyone: +TODO: signing and spam control + permissions. +[client_id of sender][uint32_t message number][char with a value representing id of message][data] + +Note: the message number is increased by 1 for each sent message. + +message ids: +0 - ping +sent every ~60 seconds by every peer. +No data. + +16 - new_peer +Tell everyone about a new peer in the chat. +[uint8_t public_key[public_key_len]] + +17 - ban_peer +Ban a peer +[uint8_t public_key[public_key_len]] + +18 - topic change +[uint8_t topic[topiclen]] + +48 - name change +[uint8_t name[namelen]] + +49 - status change +[uint8_t (status id)] + +64 - chat message +[uint8_t message[messagelen]] + +65 - action (/me) +[uint8_t message[messagelen]] \ No newline at end of file diff --git a/testing/experiment/group_chats.c b/testing/experiment/group_chats.c new file mode 100644 index 00000000..665707b2 --- /dev/null +++ b/testing/experiment/group_chats.c @@ -0,0 +1,470 @@ +/* group_chats.c + * + * An implementation of massive text only group chats. + * + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ + +#include "group_chats.h" + + +#define GROUPCHAT_MAXDATA_LENGTH (MAX_DATA_SIZE - (1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES)) +#define GROUPCHAT_MAXPLAINDATA_LENGTH (GROUPCHAT_MAXDATA_LENGTH - crypto_box_MACBYTES) + +#define GROUP_MAX_SENDNODES (GROUP_CLOSE_CONNECTIONS * 2) + +typedef struct { + uint64_t pingid; + //uint8_t client_id[crypto_box_PUBLICKEYBYTES]; + +} getnodes_data; + +typedef struct { + uint8_t client_id[crypto_box_PUBLICKEYBYTES]; + IP_Port ip_port; + +} groupchat_nodes; + +typedef struct { + uint64_t pingid; + groupchat_nodes nodes[GROUP_CLOSE_CONNECTIONS]; + //uint8_t client_id[crypto_box_PUBLICKEYBYTES]; + +} sendnodes_data; + +/* Compares client_id1 and client_id2 with client_id + * return 0 if both are same distance + * return 1 if client_id1 is closer + * return 2 if client_id2 is closer + */ +static int id_closest(uint8_t *id, uint8_t *id1, uint8_t *id2) +{ + size_t i; + uint8_t distance1, distance2; + + for (i = 0; i < CLIENT_ID_SIZE; ++i) { + + distance1 = abs(((int8_t *)id)[i] ^ ((int8_t *)id1)[i]); + distance2 = abs(((int8_t *)id)[i] ^ ((int8_t *)id2)[i]); + + if (distance1 < distance2) + return 1; + + if (distance1 > distance2) + return 2; + } + + return 0; +} + + +/* + * check if peer with client_id is in peer array. + * + * return peer number if peer is in chat. + * return -1 if peer is not in chat. + * + * TODO: make this more efficient. + */ + +static int peer_in_chat(Group_Chat *chat, uint8_t *client_id) +{ + uint32_t i; + + for (i = 0; i < chat->numpeers; ++i) { + /* Equal */ + if (memcmp(chat->group[i].client_id, client_id, crypto_box_PUBLICKEYBYTES) == 0) + return i; + } + + return -1; +} + +#define BAD_NODE_TIMEOUT 30 + +/* + * Check if peer is closer to us that the other peers in the list and if the peer is in the list. + * Return the number of peers it is closer to if it is not in the closelist. + * Return -1 if the peer is in the closelist. + */ + +static int peer_okping(Group_Chat *chat, uint8_t *client_id) +{ + uint32_t i, j = 0; + uint64_t temp_time = unix_time(); + + for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { + if (chat->close[i].last_recv < temp_time + BAD_NODE_TIMEOUT) + continue; + + /* Equal */ + if (memcmp(chat->close[i].client_id, client_id, crypto_box_PUBLICKEYBYTES) == 0) + return -1; + + if (id_closest(chat->self_public_key, chat->close[i].client_id, client_id) == 2) + ++j; + } + + return j; +} + + + +/* Attempt to add a peer to the close list. + * Update last_recv if it is in list. + * Attempt to add it to list if it is not. + * + * Return 0 if success. + * Return -1 if peer was not put in list/updated. + */ +static int add_closepeer(Group_Chat *chat, uint8_t *client_id, IP_Port ip_port) +{ + uint32_t i; + uint64_t temp_time = unix_time(); + + for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { /* Check if node is already in list, if it is update its last_recv */ + if (memcmp(chat->close[i].client_id, client_id, crypto_box_PUBLICKEYBYTES) == 0) { + chat->close[i].last_recv = temp_time; + return 0; + } + } + + for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { /* Try replacing bad nodes first */ + if (chat->close[i].last_recv < temp_time + BAD_NODE_TIMEOUT) { + memcpy(chat->close[i].client_id, client_id, crypto_box_PUBLICKEYBYTES); + chat->close[i].ip_port = ip_port; + chat->close[i].last_recv = temp_time; + return 0; + } + } + + for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { /* Replace nodes if given one is closer. */ + if (id_closest(chat->self_public_key, chat->close[i].client_id, client_id) == 2) { + memcpy(chat->close[i].client_id, client_id, crypto_box_PUBLICKEYBYTES); + chat->close[i].ip_port = ip_port; + chat->close[i].last_recv = temp_time; + return 0; + } + } + + return -1; +} + +static int send_groupchatpacket(Group_Chat *chat, IP_Port ip_port, uint8_t *public_key, uint8_t *data, uint32_t length, + uint8_t request_id) +{ + if (memcmp(chat->self_public_key, public_key, crypto_box_PUBLICKEYBYTES) == 0) + return -1; + + uint8_t packet[MAX_DATA_SIZE]; + int len = create_request(chat->self_public_key, chat->self_secret_key, packet, public_key, data, length, request_id); + packet[0] = 48; + + if (len == -1) + return -1; + + if (sendpacket(chat->net->sock, ip_port, packet, len) == len) + return 0; + + return -1; + +} + +/* + * Send data to all peers in close peer list. + * + * return the number of peers the packet was sent to. + */ +static uint8_t sendto_allpeers(Group_Chat *chat, uint8_t *data, uint16_t length, uint8_t request_id) +{ + uint16_t sent = 0; + uint32_t i; + uint64_t temp_time = unix_time(); + + for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { + if (chat->close[i].ip_port.ip.uint32 != 0 && chat->close[i].last_recv > temp_time + BAD_NODE_TIMEOUT) { + if (send_groupchatpacket(chat, chat->close[i].ip_port, chat->close[i].client_id, data, length, request_id) == 0) + ++sent; + } + } + + return sent; +} + + +/* + * Add a peer to the group chat. + * + * return peernum if success or peer already in chat. + * return -1 if error. + */ +static int addpeer(Group_Chat *chat, uint8_t *client_id) +{ + int peernum = peer_in_chat(chat, client_id); + + if (peernum != -1) + return peernum; + + Group_Peer *temp; + temp = realloc(chat->group, sizeof(Group_Peer) * (chat->numpeers + 1)); + + if (temp == NULL) + return -1; + + chat->group = temp; + memcpy(chat->group[chat->numpeers].client_id, client_id, crypto_box_PUBLICKEYBYTES); + ++chat->numpeers; + return (chat->numpeers - 1); +} + +/* + * Delete a peer to the group chat. + * + * return 0 if success + * return -1 if error. + */ +static int delpeer(Group_Chat *chat, uint8_t *client_id) +{ + uint32_t i; + Group_Peer *temp; + + for (i = 0; i < chat->numpeers; ++i) { + /* Equal */ + if (memcmp(chat->group[i].client_id, client_id, crypto_box_PUBLICKEYBYTES) == 0) { + --chat->numpeers; + + if (chat->numpeers != i) { + memcpy( chat->group[i].client_id, + chat->group[chat->numpeers].client_id, + crypto_box_PUBLICKEYBYTES ); + } + + temp = realloc(chat->group, sizeof(Group_Peer) * (chat->numpeers)); + + if (temp == NULL) + return -1; + + chat->group = temp; + return 0; + } + } + + return -1; +} +/* min time between pings sent to one peer in seconds */ +#define PING_TIMEOUT 5 +static int send_getnodes(Group_Chat *chat, IP_Port ip_port, int peernum) +{ + if (peernum < 0 || peernum >= chat->numpeers) + return -1; + + uint64_t temp_time = unix_time(); + + getnodes_data contents; + + if (chat->group[peernum].last_pinged + PING_TIMEOUT > temp_time) + return -1; + + contents.pingid = ((uint64_t)random_int() << 32) + random_int(); + chat->group[peernum].last_pinged = temp_time; + chat->group[peernum].pingid = contents.pingid; + return send_groupchatpacket(chat, ip_port, chat->group[peernum].client_id, (uint8_t *)&contents, sizeof(contents), 48); +} + +static int send_sendnodes(Group_Chat *chat, IP_Port ip_port, int peernum, uint64_t pingid) +{ + if (peernum < 0 || peernum >= chat->numpeers) + return -1; + + sendnodes_data contents; + contents.pingid = pingid; + uint32_t i, j = 0; + uint64_t temp_time = unix_time(); + + for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { + if (chat->close[i].last_recv + BAD_NODE_TIMEOUT > temp_time) { + memcpy(contents.nodes[j].client_id, chat->close[i].client_id, crypto_box_PUBLICKEYBYTES); + contents.nodes[j].ip_port = ip_port; + ++j; + } + } + + if (j == 0) + return -1; + + return send_groupchatpacket(chat, ip_port, chat->group[peernum].client_id, (uint8_t *)&contents, + sizeof(contents.pingid) + sizeof(groupchat_nodes) * j, 49); +} + +static int handle_getnodes(Group_Chat *chat, IP_Port source, int peernum, uint8_t *data, uint32_t len) +{ + if (len != sizeof(getnodes_data)) + return 1; + + if (peernum < 0 || peernum >= chat->numpeers) + return 1; + + getnodes_data contents; + memcpy(&contents, data, sizeof(contents)); + send_sendnodes(chat, source, peernum, contents.pingid); + return 0; +} + +static int handle_sendnodes(Group_Chat *chat, IP_Port source, int peernum, uint8_t *data, uint32_t len) +{ + if (peernum < 0 || peernum >= chat->numpeers) + return 1; + + if (len > sizeof(sendnodes_data) || len < (sizeof(uint64_t) + sizeof(groupchat_nodes))) + return 1; + + if ((len - sizeof(uint64_t)) % sizeof(groupchat_nodes) != 0) + return 1; + + if (chat->group[peernum].last_pinged + PING_TIMEOUT < unix_time()) + return 1; + + sendnodes_data contents; + memcpy(&contents, data, len); + + if (contents.pingid != chat->group[peernum].pingid) + return 1; + + uint16_t numnodes = (len - sizeof(contents.pingid)) / sizeof(groupchat_nodes); + uint32_t i; + + for (i = 0; i < numnodes; ++i) { + if (peer_okping(chat, contents.nodes[i].client_id) > 0) { + int peern = peer_in_chat(chat, contents.nodes[i].client_id); + + if (peern == -1) + continue; + + send_getnodes(chat, contents.nodes[i].ip_port, peern); + } + } + + add_closepeer(chat, chat->group[peernum].client_id, source); + return 0; +} + +static int handle_data(Group_Chat *chat, uint8_t *data, uint32_t len) +{ + if (len < 2) + return 1; + + int handled = 0; + + if (data[0] == 64 && chat->group_message != NULL) { +//TODO + (*chat->group_message)(chat, 0, data + 1, len - 1, chat->group_message_userdata); + handled = 1; + } + + if (handled == 1) { + sendto_allpeers(chat, data, len, 50); + return 0; + } + + return 1; +} + +/* + * Handle get nodes group packet. + * + * return 0 if handled correctly. + * return 1 if error. + */ + +int handle_groupchatpacket(Group_Chat *chat, IP_Port source, uint8_t *packet, uint32_t length) +{ + if (length > MAX_DATA_SIZE) + return 1; + + uint8_t public_key[crypto_box_PUBLICKEYBYTES]; + uint8_t data[MAX_DATA_SIZE]; + uint8_t number; + int len = handle_request(chat->self_public_key, chat->self_secret_key, public_key, data, &number, packet, length); + + if (len <= 0) + return 1; + + if (memcmp(chat->self_public_key, public_key, crypto_box_PUBLICKEYBYTES) == 0) + return 1; + + int peernum = peer_in_chat(chat, public_key); + + if (peernum == -1)/*NOTE: This is just for testing and will be removed later.*/ + peernum = addpeer(chat, public_key); + + if (peernum == -1) + return 1; + + + switch (number) { + case 48: + return handle_getnodes(chat, source, peernum, data, len); + + case 49: + return handle_sendnodes(chat, source, peernum, data, len); + + case 50: + return handle_data(chat, data, len); + + default: + return 1; + } + + return 1; +} + +uint32_t m_sendmessage(Group_Chat *chat, uint8_t *message, uint32_t length) +{ + +} + +void callback_groupmessage(Group_Chat *chat, void (*function)(Group_Chat *chat, int, uint8_t *, uint16_t, void *), + void *userdata) +{ + chat->group_message = function; + chat->group_message_userdata = userdata; +} + +Group_Chat *new_groupchat(Networking_Core *net) +{ + if (net == 0) + return 0; + + Group_Chat *chat = calloc(1, sizeof(Group_Chat)); + chat->net = net; + return chat; +} + + +void kill_groupchat(Group_Chat *chat) +{ + free(chat->group); + free(chat); +} + +void chat_bootstrap(Group_Chat *chat, IP_Port ip_port, int peernum) +{ + send_getnodes(chat, ip_port, peernum); +} diff --git a/testing/experiment/group_chats.h b/testing/experiment/group_chats.h new file mode 100644 index 00000000..527610d8 --- /dev/null +++ b/testing/experiment/group_chats.h @@ -0,0 +1,109 @@ +/* group_chats.h + * + * An implementation of massive text only group chats. + * + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ + +#ifndef GROUP_CHATS_H +#define GROUP_CHATS_H + +#include "../../toxcore/net_crypto.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + uint8_t client_id[crypto_box_PUBLICKEYBYTES]; + uint64_t last_recv; + uint64_t pingid; + uint64_t last_pinged; + uint32_t last_message_number; +} Group_Peer; + +typedef struct { + uint8_t client_id[crypto_box_PUBLICKEYBYTES]; + IP_Port ip_port; + uint64_t last_recv; + +} Group_Close; + +#define GROUP_CLOSE_CONNECTIONS 6 + +typedef struct Group_Chat { + Networking_Core *net; + uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; + uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; + + Group_Peer *group; + Group_Close close[GROUP_CLOSE_CONNECTIONS]; + uint32_t numpeers; + + uint32_t message_number; + void (*group_message)(struct Group_Chat *m, int, uint8_t *, uint16_t, void *); + void *group_message_userdata; + +} Group_Chat; + +/* + * Set callback function for chat messages. + * + * format of function is: function(Group_Chat *chat, peer number, message, message length, userdata) + */ + +void callback_groupmessage(Group_Chat *chat, void (*function)(Group_Chat *chat, int, uint8_t *, uint16_t, void *), + void *userdata); + +/* + * Send a message to the group. + * + */ +uint32_t m_sendmessage(Group_Chat *chat, uint8_t *message, uint32_t length); + +/* Create a new group chat. + * + * Returns a new group chat instance if success. + * + * Returns a NULL pointer if fail. + */ +Group_Chat *new_groupchat(Networking_Core *net); + + +/* Kill a group chat + * + * Frees the memory and everything. + */ +void kill_groupchat(Group_Chat *chat); + + +/* if we receive a group chat packet we call this function so it can be handled. + return 0 if packet is handled correctly. + return 1 if it didn't handle the packet or if the packet was shit. */ +int handle_groupchatpacket(Group_Chat *chat, IP_Port source, uint8_t *packet, uint32_t length); + + +void chat_bootstrap(Group_Chat *chat, IP_Port ip_port, int peernum); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/testing/experiment/group_chats_test.c b/testing/experiment/group_chats_test.c new file mode 100644 index 00000000..f08e4e15 --- /dev/null +++ b/testing/experiment/group_chats_test.c @@ -0,0 +1,19 @@ +#include "group_chats.h" +#define NUM_CHATS 8 + +int main() +{ + IP ip; + ip.uint32 = 0; + uint32_t i; + Group_Chat *chats[NUM_CHATS]; + + for (i = 0; i < NUM_CHATS; ++i) { + chats[i] = new_groupchat(new_networking(ip, 1234)); + + if (chats[i] == 0) + exit(1); + } + + return 0; +} diff --git a/toxcore/DHT.c b/toxcore/DHT.c index 749eb78c..4807c369 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c @@ -483,12 +483,12 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli { /* Check if packet is going to be sent to ourself. */ if (id_equal(public_key, dht->c->self_public_key) || is_gettingnodes(dht, ip_port, 0)) - return 1; + return -1; uint64_t ping_id = add_gettingnodes(dht, ip_port); if (ping_id == 0) - return 1; + return -1; uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING]; uint8_t plain[sizeof(ping_id) + CLIENT_ID_SIZE]; @@ -522,7 +522,7 @@ static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cl { /* Check if packet is going to be sent to ourself. */ if (id_equal(public_key, dht->c->self_public_key)) - return 1; + return -1; uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING]; diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 92727a8c..cfa1bc34 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -254,30 +254,31 @@ int create_request(uint8_t *send_public_key, uint8_t *send_secret_key, uint8_t * * * return -1 if not valid request. */ -static int handle_request(Net_Crypto *c, uint8_t *public_key, uint8_t *data, uint8_t *request_id, uint8_t *packet, - uint16_t length) +int handle_request(uint8_t *self_public_key, uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data, + uint8_t *request_id, uint8_t *packet, uint16_t length) { - if (length > crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING && - length <= MAX_DATA_SIZE + ENCRYPTION_PADDING && - memcmp(packet + 1, c->self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { - memcpy(public_key, packet + 1 + crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); - uint8_t nonce[crypto_box_NONCEBYTES]; - uint8_t temp[MAX_DATA_SIZE]; - memcpy(nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2, crypto_box_NONCEBYTES); - int len1 = decrypt_data(public_key, c->self_secret_key, nonce, - packet + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES, - length - (crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1), temp); + length <= MAX_DATA_SIZE) { + if (memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { + memcpy(public_key, packet + 1 + crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); + uint8_t nonce[crypto_box_NONCEBYTES]; + uint8_t temp[MAX_DATA_SIZE]; + memcpy(nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2, crypto_box_NONCEBYTES); + int len1 = decrypt_data(public_key, self_secret_key, nonce, + packet + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES, + length - (crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1), temp); - if (len1 == -1 || len1 == 0) - return -1; + if (len1 == -1 || len1 == 0) + return -1; - request_id[0] = temp[0]; - --len1; - memcpy(data, temp + 1, len1); - return len1; - } else - return -1; + request_id[0] = temp[0]; + --len1; + memcpy(data, temp + 1, len1); + return len1; + } + } + + return -1; } void cryptopacket_registerhandler(Net_Crypto *c, uint8_t byte, cryptopacket_handler_callback cb, void *object) @@ -299,7 +300,7 @@ static int cryptopacket_handle(void *object, IP_Port source, uint8_t *packet, ui uint8_t public_key[crypto_box_PUBLICKEYBYTES]; uint8_t data[MAX_DATA_SIZE]; uint8_t number; - int len = handle_request(dht->c, public_key, data, &number, packet, length); + int len = handle_request(dht->c->self_public_key, dht->c->self_secret_key, public_key, data, &number, packet, length); if (len == -1 || len == 0) return 1; diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index 030cc678..e5dfcae0 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -139,6 +139,12 @@ int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uin int create_request(uint8_t *send_public_key, uint8_t *send_secret_key, uint8_t *packet, uint8_t *recv_public_key, uint8_t *data, uint32_t length, uint8_t request_id); +/* puts the senders public key in the request in public_key, the data from the request + in data if a friend or ping request was sent to us and returns the length of the data. + packet is the request packet and length is its length + return -1 if not valid request. */ +int handle_request(uint8_t *self_public_key, uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data, + uint8_t *request_id, uint8_t *packet, uint16_t length); /* Function to call when request beginning with byte is received. */ void cryptopacket_registerhandler(Net_Crypto *c, uint8_t byte, cryptopacket_handler_callback cb, void *object);