summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2013-09-03 08:53:07 -0400
committerirungentoo <irungentoo@gmail.com>2013-09-03 08:53:07 -0400
commitc59975dd7ecdabe864f341b699f986e5e474acb6 (patch)
treece8d223ce2c552b257efdca2496e621a4c0768c2
parentb73ba8244a1c04503f151c20f2eee8ccf58a0646 (diff)
Work in progress group chats.
Not done yet.
-rw-r--r--docs/Group_chats.txt71
-rw-r--r--testing/experiment/group_chats.c470
-rw-r--r--testing/experiment/group_chats.h109
-rw-r--r--testing/experiment/group_chats_test.c19
-rw-r--r--toxcore/DHT.c6
-rw-r--r--toxcore/net_crypto.c45
-rw-r--r--toxcore/net_crypto.h6
7 files changed, 701 insertions, 25 deletions
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 @@
1Massive public group chats.
2
3Everyone generates a short term public private key pair right before joining
4the chat.
5
6Note that for public group chats it is impossible to protect the chat from
7being spied on by a very dedicated attacker, encryption is therefor used as a
8form of spam/access control.
9
10## Joining the chats
11
12
13## Protocol
14
15
16Node format:
17```
18[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]
19```
20
21Get nodes (Request):
22Packet contents:
23```
24[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)]
25```
26Valid replies: a send_nodes packet
27
28Send_nodes (response):
29```
30[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]]
31```
32
33Broadcast packet:
34```
35[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]]
36```
37
38
39Data to send to everyone:
40TODO: signing and spam control + permissions.
41[client_id of sender][uint32_t message number][char with a value representing id of message][data]
42
43Note: the message number is increased by 1 for each sent message.
44
45message ids:
460 - ping
47sent every ~60 seconds by every peer.
48No data.
49
5016 - new_peer
51Tell everyone about a new peer in the chat.
52[uint8_t public_key[public_key_len]]
53
5417 - ban_peer
55Ban a peer
56[uint8_t public_key[public_key_len]]
57
5818 - topic change
59[uint8_t topic[topiclen]]
60
6148 - name change
62[uint8_t name[namelen]]
63
6449 - status change
65[uint8_t (status id)]
66
6764 - chat message
68[uint8_t message[messagelen]]
69
7065 - action (/me)
71[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 @@
1/* group_chats.c
2 *
3 * An implementation of massive text only group chats.
4 *
5 *
6 * Copyright (C) 2013 Tox project All Rights Reserved.
7 *
8 * This file is part of Tox.
9 *
10 * Tox is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * Tox is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 *
23 */
24
25#include "group_chats.h"
26
27
28#define GROUPCHAT_MAXDATA_LENGTH (MAX_DATA_SIZE - (1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES))
29#define GROUPCHAT_MAXPLAINDATA_LENGTH (GROUPCHAT_MAXDATA_LENGTH - crypto_box_MACBYTES)
30
31#define GROUP_MAX_SENDNODES (GROUP_CLOSE_CONNECTIONS * 2)
32
33typedef struct {
34 uint64_t pingid;
35 //uint8_t client_id[crypto_box_PUBLICKEYBYTES];
36
37} getnodes_data;
38
39typedef struct {
40 uint8_t client_id[crypto_box_PUBLICKEYBYTES];
41 IP_Port ip_port;
42
43} groupchat_nodes;
44
45typedef struct {
46 uint64_t pingid;
47 groupchat_nodes nodes[GROUP_CLOSE_CONNECTIONS];
48 //uint8_t client_id[crypto_box_PUBLICKEYBYTES];
49
50} sendnodes_data;
51
52/* Compares client_id1 and client_id2 with client_id
53 * return 0 if both are same distance
54 * return 1 if client_id1 is closer
55 * return 2 if client_id2 is closer
56 */
57static int id_closest(uint8_t *id, uint8_t *id1, uint8_t *id2)
58{
59 size_t i;
60 uint8_t distance1, distance2;
61
62 for (i = 0; i < CLIENT_ID_SIZE; ++i) {
63
64 distance1 = abs(((int8_t *)id)[i] ^ ((int8_t *)id1)[i]);
65 distance2 = abs(((int8_t *)id)[i] ^ ((int8_t *)id2)[i]);
66
67 if (distance1 < distance2)
68 return 1;
69
70 if (distance1 > distance2)
71 return 2;
72 }
73
74 return 0;
75}
76
77
78/*
79 * check if peer with client_id is in peer array.
80 *
81 * return peer number if peer is in chat.
82 * return -1 if peer is not in chat.
83 *
84 * TODO: make this more efficient.
85 */
86
87static int peer_in_chat(Group_Chat *chat, uint8_t *client_id)
88{
89 uint32_t i;
90
91 for (i = 0; i < chat->numpeers; ++i) {
92 /* Equal */
93 if (memcmp(chat->group[i].client_id, client_id, crypto_box_PUBLICKEYBYTES) == 0)
94 return i;
95 }
96
97 return -1;
98}
99
100#define BAD_NODE_TIMEOUT 30
101
102/*
103 * Check if peer is closer to us that the other peers in the list and if the peer is in the list.
104 * Return the number of peers it is closer to if it is not in the closelist.
105 * Return -1 if the peer is in the closelist.
106 */
107
108static int peer_okping(Group_Chat *chat, uint8_t *client_id)
109{
110 uint32_t i, j = 0;
111 uint64_t temp_time = unix_time();
112
113 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) {
114 if (chat->close[i].last_recv < temp_time + BAD_NODE_TIMEOUT)
115 continue;
116
117 /* Equal */
118 if (memcmp(chat->close[i].client_id, client_id, crypto_box_PUBLICKEYBYTES) == 0)
119 return -1;
120
121 if (id_closest(chat->self_public_key, chat->close[i].client_id, client_id) == 2)
122 ++j;
123 }
124
125 return j;
126}
127
128
129
130/* Attempt to add a peer to the close list.
131 * Update last_recv if it is in list.
132 * Attempt to add it to list if it is not.
133 *
134 * Return 0 if success.
135 * Return -1 if peer was not put in list/updated.
136 */
137static int add_closepeer(Group_Chat *chat, uint8_t *client_id, IP_Port ip_port)
138{
139 uint32_t i;
140 uint64_t temp_time = unix_time();
141
142 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { /* Check if node is already in list, if it is update its last_recv */
143 if (memcmp(chat->close[i].client_id, client_id, crypto_box_PUBLICKEYBYTES) == 0) {
144 chat->close[i].last_recv = temp_time;
145 return 0;
146 }
147 }
148
149 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { /* Try replacing bad nodes first */
150 if (chat->close[i].last_recv < temp_time + BAD_NODE_TIMEOUT) {
151 memcpy(chat->close[i].client_id, client_id, crypto_box_PUBLICKEYBYTES);
152 chat->close[i].ip_port = ip_port;
153 chat->close[i].last_recv = temp_time;
154 return 0;
155 }
156 }
157
158 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { /* Replace nodes if given one is closer. */
159 if (id_closest(chat->self_public_key, chat->close[i].client_id, client_id) == 2) {
160 memcpy(chat->close[i].client_id, client_id, crypto_box_PUBLICKEYBYTES);
161 chat->close[i].ip_port = ip_port;
162 chat->close[i].last_recv = temp_time;
163 return 0;
164 }
165 }
166
167 return -1;
168}
169
170static int send_groupchatpacket(Group_Chat *chat, IP_Port ip_port, uint8_t *public_key, uint8_t *data, uint32_t length,
171 uint8_t request_id)
172{
173 if (memcmp(chat->self_public_key, public_key, crypto_box_PUBLICKEYBYTES) == 0)
174 return -1;
175
176 uint8_t packet[MAX_DATA_SIZE];
177 int len = create_request(chat->self_public_key, chat->self_secret_key, packet, public_key, data, length, request_id);
178 packet[0] = 48;
179
180 if (len == -1)
181 return -1;
182
183 if (sendpacket(chat->net->sock, ip_port, packet, len) == len)
184 return 0;
185
186 return -1;
187
188}
189
190/*
191 * Send data to all peers in close peer list.
192 *
193 * return the number of peers the packet was sent to.
194 */
195static uint8_t sendto_allpeers(Group_Chat *chat, uint8_t *data, uint16_t length, uint8_t request_id)
196{
197 uint16_t sent = 0;
198 uint32_t i;
199 uint64_t temp_time = unix_time();
200
201 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) {
202 if (chat->close[i].ip_port.ip.uint32 != 0 && chat->close[i].last_recv > temp_time + BAD_NODE_TIMEOUT) {
203 if (send_groupchatpacket(chat, chat->close[i].ip_port, chat->close[i].client_id, data, length, request_id) == 0)
204 ++sent;
205 }
206 }
207
208 return sent;
209}
210
211
212/*
213 * Add a peer to the group chat.
214 *
215 * return peernum if success or peer already in chat.
216 * return -1 if error.
217 */
218static int addpeer(Group_Chat *chat, uint8_t *client_id)
219{
220 int peernum = peer_in_chat(chat, client_id);
221
222 if (peernum != -1)
223 return peernum;
224
225 Group_Peer *temp;
226 temp = realloc(chat->group, sizeof(Group_Peer) * (chat->numpeers + 1));
227
228 if (temp == NULL)
229 return -1;
230
231 chat->group = temp;
232 memcpy(chat->group[chat->numpeers].client_id, client_id, crypto_box_PUBLICKEYBYTES);
233 ++chat->numpeers;
234 return (chat->numpeers - 1);
235}
236
237/*
238 * Delete a peer to the group chat.
239 *
240 * return 0 if success
241 * return -1 if error.
242 */
243static int delpeer(Group_Chat *chat, uint8_t *client_id)
244{
245 uint32_t i;
246 Group_Peer *temp;
247
248 for (i = 0; i < chat->numpeers; ++i) {
249 /* Equal */
250 if (memcmp(chat->group[i].client_id, client_id, crypto_box_PUBLICKEYBYTES) == 0) {
251 --chat->numpeers;
252
253 if (chat->numpeers != i) {
254 memcpy( chat->group[i].client_id,
255 chat->group[chat->numpeers].client_id,
256 crypto_box_PUBLICKEYBYTES );
257 }
258
259 temp = realloc(chat->group, sizeof(Group_Peer) * (chat->numpeers));
260
261 if (temp == NULL)
262 return -1;
263
264 chat->group = temp;
265 return 0;
266 }
267 }
268
269 return -1;
270}
271/* min time between pings sent to one peer in seconds */
272#define PING_TIMEOUT 5
273static int send_getnodes(Group_Chat *chat, IP_Port ip_port, int peernum)
274{
275 if (peernum < 0 || peernum >= chat->numpeers)
276 return -1;
277
278 uint64_t temp_time = unix_time();
279
280 getnodes_data contents;
281
282 if (chat->group[peernum].last_pinged + PING_TIMEOUT > temp_time)
283 return -1;
284
285 contents.pingid = ((uint64_t)random_int() << 32) + random_int();
286 chat->group[peernum].last_pinged = temp_time;
287 chat->group[peernum].pingid = contents.pingid;
288 return send_groupchatpacket(chat, ip_port, chat->group[peernum].client_id, (uint8_t *)&contents, sizeof(contents), 48);
289}
290
291static int send_sendnodes(Group_Chat *chat, IP_Port ip_port, int peernum, uint64_t pingid)
292{
293 if (peernum < 0 || peernum >= chat->numpeers)
294 return -1;
295
296 sendnodes_data contents;
297 contents.pingid = pingid;
298 uint32_t i, j = 0;
299 uint64_t temp_time = unix_time();
300
301 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) {
302 if (chat->close[i].last_recv + BAD_NODE_TIMEOUT > temp_time) {
303 memcpy(contents.nodes[j].client_id, chat->close[i].client_id, crypto_box_PUBLICKEYBYTES);
304 contents.nodes[j].ip_port = ip_port;
305 ++j;
306 }
307 }
308
309 if (j == 0)
310 return -1;
311
312 return send_groupchatpacket(chat, ip_port, chat->group[peernum].client_id, (uint8_t *)&contents,
313 sizeof(contents.pingid) + sizeof(groupchat_nodes) * j, 49);
314}
315
316static int handle_getnodes(Group_Chat *chat, IP_Port source, int peernum, uint8_t *data, uint32_t len)
317{
318 if (len != sizeof(getnodes_data))
319 return 1;
320
321 if (peernum < 0 || peernum >= chat->numpeers)
322 return 1;
323
324 getnodes_data contents;
325 memcpy(&contents, data, sizeof(contents));
326 send_sendnodes(chat, source, peernum, contents.pingid);
327 return 0;
328}
329
330static int handle_sendnodes(Group_Chat *chat, IP_Port source, int peernum, uint8_t *data, uint32_t len)
331{
332 if (peernum < 0 || peernum >= chat->numpeers)
333 return 1;
334
335 if (len > sizeof(sendnodes_data) || len < (sizeof(uint64_t) + sizeof(groupchat_nodes)))
336 return 1;
337
338 if ((len - sizeof(uint64_t)) % sizeof(groupchat_nodes) != 0)
339 return 1;
340
341 if (chat->group[peernum].last_pinged + PING_TIMEOUT < unix_time())
342 return 1;
343
344 sendnodes_data contents;
345 memcpy(&contents, data, len);
346
347 if (contents.pingid != chat->group[peernum].pingid)
348 return 1;
349
350 uint16_t numnodes = (len - sizeof(contents.pingid)) / sizeof(groupchat_nodes);
351 uint32_t i;
352
353 for (i = 0; i < numnodes; ++i) {
354 if (peer_okping(chat, contents.nodes[i].client_id) > 0) {
355 int peern = peer_in_chat(chat, contents.nodes[i].client_id);
356
357 if (peern == -1)
358 continue;
359
360 send_getnodes(chat, contents.nodes[i].ip_port, peern);
361 }
362 }
363
364 add_closepeer(chat, chat->group[peernum].client_id, source);
365 return 0;
366}
367
368static int handle_data(Group_Chat *chat, uint8_t *data, uint32_t len)
369{
370 if (len < 2)
371 return 1;
372
373 int handled = 0;
374
375 if (data[0] == 64 && chat->group_message != NULL) {
376//TODO
377 (*chat->group_message)(chat, 0, data + 1, len - 1, chat->group_message_userdata);
378 handled = 1;
379 }
380
381 if (handled == 1) {
382 sendto_allpeers(chat, data, len, 50);
383 return 0;
384 }
385
386 return 1;
387}
388
389/*
390 * Handle get nodes group packet.
391 *
392 * return 0 if handled correctly.
393 * return 1 if error.
394 */
395
396int handle_groupchatpacket(Group_Chat *chat, IP_Port source, uint8_t *packet, uint32_t length)
397{
398 if (length > MAX_DATA_SIZE)
399 return 1;
400
401 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
402 uint8_t data[MAX_DATA_SIZE];
403 uint8_t number;
404 int len = handle_request(chat->self_public_key, chat->self_secret_key, public_key, data, &number, packet, length);
405
406 if (len <= 0)
407 return 1;
408
409 if (memcmp(chat->self_public_key, public_key, crypto_box_PUBLICKEYBYTES) == 0)
410 return 1;
411
412 int peernum = peer_in_chat(chat, public_key);
413
414 if (peernum == -1)/*NOTE: This is just for testing and will be removed later.*/
415 peernum = addpeer(chat, public_key);
416
417 if (peernum == -1)
418 return 1;
419
420
421 switch (number) {
422 case 48:
423 return handle_getnodes(chat, source, peernum, data, len);
424
425 case 49:
426 return handle_sendnodes(chat, source, peernum, data, len);
427
428 case 50:
429 return handle_data(chat, data, len);
430
431 default:
432 return 1;
433 }
434
435 return 1;
436}
437
438uint32_t m_sendmessage(Group_Chat *chat, uint8_t *message, uint32_t length)
439{
440
441}
442
443void callback_groupmessage(Group_Chat *chat, void (*function)(Group_Chat *chat, int, uint8_t *, uint16_t, void *),
444 void *userdata)
445{
446 chat->group_message = function;
447 chat->group_message_userdata = userdata;
448}
449
450Group_Chat *new_groupchat(Networking_Core *net)
451{
452 if (net == 0)
453 return 0;
454
455 Group_Chat *chat = calloc(1, sizeof(Group_Chat));
456 chat->net = net;
457 return chat;
458}
459
460
461void kill_groupchat(Group_Chat *chat)
462{
463 free(chat->group);
464 free(chat);
465}
466
467void chat_bootstrap(Group_Chat *chat, IP_Port ip_port, int peernum)
468{
469 send_getnodes(chat, ip_port, peernum);
470}
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 @@
1/* group_chats.h
2 *
3 * An implementation of massive text only group chats.
4 *
5 *
6 * Copyright (C) 2013 Tox project All Rights Reserved.
7 *
8 * This file is part of Tox.
9 *
10 * Tox is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * Tox is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 *
23 */
24
25#ifndef GROUP_CHATS_H
26#define GROUP_CHATS_H
27
28#include "../../toxcore/net_crypto.h"
29
30#ifdef __cplusplus
31extern "C" {
32#endif
33
34typedef struct {
35 uint8_t client_id[crypto_box_PUBLICKEYBYTES];
36 uint64_t last_recv;
37 uint64_t pingid;
38 uint64_t last_pinged;
39 uint32_t last_message_number;
40} Group_Peer;
41
42typedef struct {
43 uint8_t client_id[crypto_box_PUBLICKEYBYTES];
44 IP_Port ip_port;
45 uint64_t last_recv;
46
47} Group_Close;
48
49#define GROUP_CLOSE_CONNECTIONS 6
50
51typedef struct Group_Chat {
52 Networking_Core *net;
53 uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
54 uint8_t self_secret_key[crypto_box_SECRETKEYBYTES];
55
56 Group_Peer *group;
57 Group_Close close[GROUP_CLOSE_CONNECTIONS];
58 uint32_t numpeers;
59
60 uint32_t message_number;
61 void (*group_message)(struct Group_Chat *m, int, uint8_t *, uint16_t, void *);
62 void *group_message_userdata;
63
64} Group_Chat;
65
66/*
67 * Set callback function for chat messages.
68 *
69 * format of function is: function(Group_Chat *chat, peer number, message, message length, userdata)
70 */
71
72void callback_groupmessage(Group_Chat *chat, void (*function)(Group_Chat *chat, int, uint8_t *, uint16_t, void *),
73 void *userdata);
74
75/*
76 * Send a message to the group.
77 *
78 */
79uint32_t m_sendmessage(Group_Chat *chat, uint8_t *message, uint32_t length);
80
81/* Create a new group chat.
82 *
83 * Returns a new group chat instance if success.
84 *
85 * Returns a NULL pointer if fail.
86 */
87Group_Chat *new_groupchat(Networking_Core *net);
88
89
90/* Kill a group chat
91 *
92 * Frees the memory and everything.
93 */
94void kill_groupchat(Group_Chat *chat);
95
96
97/* if we receive a group chat packet we call this function so it can be handled.
98 return 0 if packet is handled correctly.
99 return 1 if it didn't handle the packet or if the packet was shit. */
100int handle_groupchatpacket(Group_Chat *chat, IP_Port source, uint8_t *packet, uint32_t length);
101
102
103void chat_bootstrap(Group_Chat *chat, IP_Port ip_port, int peernum);
104
105#ifdef __cplusplus
106}
107#endif
108
109#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 @@
1#include "group_chats.h"
2#define NUM_CHATS 8
3
4int main()
5{
6 IP ip;
7 ip.uint32 = 0;
8 uint32_t i;
9 Group_Chat *chats[NUM_CHATS];
10
11 for (i = 0; i < NUM_CHATS; ++i) {
12 chats[i] = new_groupchat(new_networking(ip, 1234));
13
14 if (chats[i] == 0)
15 exit(1);
16 }
17
18 return 0;
19}
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
483{ 483{
484 /* Check if packet is going to be sent to ourself. */ 484 /* Check if packet is going to be sent to ourself. */
485 if (id_equal(public_key, dht->c->self_public_key) || is_gettingnodes(dht, ip_port, 0)) 485 if (id_equal(public_key, dht->c->self_public_key) || is_gettingnodes(dht, ip_port, 0))
486 return 1; 486 return -1;
487 487
488 uint64_t ping_id = add_gettingnodes(dht, ip_port); 488 uint64_t ping_id = add_gettingnodes(dht, ip_port);
489 489
490 if (ping_id == 0) 490 if (ping_id == 0)
491 return 1; 491 return -1;
492 492
493 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING]; 493 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING];
494 uint8_t plain[sizeof(ping_id) + CLIENT_ID_SIZE]; 494 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
522{ 522{
523 /* Check if packet is going to be sent to ourself. */ 523 /* Check if packet is going to be sent to ourself. */
524 if (id_equal(public_key, dht->c->self_public_key)) 524 if (id_equal(public_key, dht->c->self_public_key))
525 return 1; 525 return -1;
526 526
527 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) 527 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id)
528 + sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING]; 528 + 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 *
254 * 254 *
255 * return -1 if not valid request. 255 * return -1 if not valid request.
256 */ 256 */
257static int handle_request(Net_Crypto *c, uint8_t *public_key, uint8_t *data, uint8_t *request_id, uint8_t *packet, 257int handle_request(uint8_t *self_public_key, uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data,
258 uint16_t length) 258 uint8_t *request_id, uint8_t *packet, uint16_t length)
259{ 259{
260
261 if (length > crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING && 260 if (length > crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING &&
262 length <= MAX_DATA_SIZE + ENCRYPTION_PADDING && 261 length <= MAX_DATA_SIZE) {
263 memcmp(packet + 1, c->self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { 262 if (memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) {
264 memcpy(public_key, packet + 1 + crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); 263 memcpy(public_key, packet + 1 + crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES);
265 uint8_t nonce[crypto_box_NONCEBYTES]; 264 uint8_t nonce[crypto_box_NONCEBYTES];
266 uint8_t temp[MAX_DATA_SIZE]; 265 uint8_t temp[MAX_DATA_SIZE];
267 memcpy(nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2, crypto_box_NONCEBYTES); 266 memcpy(nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2, crypto_box_NONCEBYTES);
268 int len1 = decrypt_data(public_key, c->self_secret_key, nonce, 267 int len1 = decrypt_data(public_key, self_secret_key, nonce,
269 packet + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES, 268 packet + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES,
270 length - (crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1), temp); 269 length - (crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1), temp);
271 270
272 if (len1 == -1 || len1 == 0) 271 if (len1 == -1 || len1 == 0)
273 return -1; 272 return -1;
274 273
275 request_id[0] = temp[0]; 274 request_id[0] = temp[0];
276 --len1; 275 --len1;
277 memcpy(data, temp + 1, len1); 276 memcpy(data, temp + 1, len1);
278 return len1; 277 return len1;
279 } else 278 }
280 return -1; 279 }
280
281 return -1;
281} 282}
282 283
283void cryptopacket_registerhandler(Net_Crypto *c, uint8_t byte, cryptopacket_handler_callback cb, void *object) 284void 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
299 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; 300 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
300 uint8_t data[MAX_DATA_SIZE]; 301 uint8_t data[MAX_DATA_SIZE];
301 uint8_t number; 302 uint8_t number;
302 int len = handle_request(dht->c, public_key, data, &number, packet, length); 303 int len = handle_request(dht->c->self_public_key, dht->c->self_secret_key, public_key, data, &number, packet, length);
303 304
304 if (len == -1 || len == 0) 305 if (len == -1 || len == 0)
305 return 1; 306 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
139int create_request(uint8_t *send_public_key, uint8_t *send_secret_key, uint8_t *packet, uint8_t *recv_public_key, 139int create_request(uint8_t *send_public_key, uint8_t *send_secret_key, uint8_t *packet, uint8_t *recv_public_key,
140 uint8_t *data, uint32_t length, uint8_t request_id); 140 uint8_t *data, uint32_t length, uint8_t request_id);
141 141
142/* puts the senders public key in the request in public_key, the data from the request
143 in data if a friend or ping request was sent to us and returns the length of the data.
144 packet is the request packet and length is its length
145 return -1 if not valid request. */
146int handle_request(uint8_t *self_public_key, uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data,
147 uint8_t *request_id, uint8_t *packet, uint16_t length);
142 148
143/* Function to call when request beginning with byte is received. */ 149/* Function to call when request beginning with byte is received. */
144void cryptopacket_registerhandler(Net_Crypto *c, uint8_t byte, cryptopacket_handler_callback cb, void *object); 150void cryptopacket_registerhandler(Net_Crypto *c, uint8_t byte, cryptopacket_handler_callback cb, void *object);