ffi-tox 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/ProjectTox-Core/CMakeLists.txt +28 -0
  2. data/ProjectTox-Core/COPYING +674 -0
  3. data/ProjectTox-Core/INSTALL.md +91 -0
  4. data/ProjectTox-Core/README.md +54 -0
  5. data/ProjectTox-Core/core/CMakeLists.txt +17 -0
  6. data/ProjectTox-Core/core/DHT.c +1104 -0
  7. data/ProjectTox-Core/core/DHT.h +111 -0
  8. data/ProjectTox-Core/core/LAN_discovery.c +79 -0
  9. data/ProjectTox-Core/core/LAN_discovery.h +50 -0
  10. data/ProjectTox-Core/core/Lossless_UDP.c +749 -0
  11. data/ProjectTox-Core/core/Lossless_UDP.h +106 -0
  12. data/ProjectTox-Core/core/Messenger.c +581 -0
  13. data/ProjectTox-Core/core/Messenger.h +157 -0
  14. data/ProjectTox-Core/core/friend_requests.c +131 -0
  15. data/ProjectTox-Core/core/friend_requests.h +51 -0
  16. data/ProjectTox-Core/core/net_crypto.c +564 -0
  17. data/ProjectTox-Core/core/net_crypto.h +134 -0
  18. data/ProjectTox-Core/core/network.c +188 -0
  19. data/ProjectTox-Core/core/network.h +134 -0
  20. data/ProjectTox-Core/other/CMakeLists.txt +9 -0
  21. data/ProjectTox-Core/other/DHT_bootstrap.c +139 -0
  22. data/ProjectTox-Core/testing/CMakeLists.txt +18 -0
  23. data/ProjectTox-Core/testing/DHT_cryptosendfiletest.c +228 -0
  24. data/ProjectTox-Core/testing/DHT_sendfiletest.c +176 -0
  25. data/ProjectTox-Core/testing/DHT_test.c +182 -0
  26. data/ProjectTox-Core/testing/Lossless_UDP_testclient.c +214 -0
  27. data/ProjectTox-Core/testing/Lossless_UDP_testserver.c +201 -0
  28. data/ProjectTox-Core/testing/Messenger_test.c +145 -0
  29. data/ProjectTox-Core/testing/misc_tools.c +40 -0
  30. data/ProjectTox-Core/testing/misc_tools.h +29 -0
  31. data/ProjectTox-Core/testing/nTox.c +381 -0
  32. data/ProjectTox-Core/testing/nTox.h +50 -0
  33. data/ProjectTox-Core/testing/nTox_win32.c +323 -0
  34. data/ProjectTox-Core/testing/nTox_win32.h +31 -0
  35. data/ProjectTox-Core/testing/rect.py +45 -0
  36. data/ext/ffi-tox/extconf.rb +16 -0
  37. data/interfaces/libtox.i +18 -0
  38. data/lib/ffi-tox/libtox.rb +37 -0
  39. data/lib/ffi-tox.rb +1 -0
  40. metadata +116 -0
@@ -0,0 +1,106 @@
1
+ /* Lossless_UDP.h
2
+ *
3
+ * An implementation of the Lossless_UDP protocol as seen in docs/Lossless_UDP.txt
4
+ *
5
+ * Copyright (C) 2013 Tox project All Rights Reserved.
6
+ *
7
+ * This file is part of Tox.
8
+ *
9
+ * Tox is free software: you can redistribute it and/or modify
10
+ * it under the terms of the GNU General Public License as published by
11
+ * the Free Software Foundation, either version 3 of the License, or
12
+ * (at your option) any later version.
13
+ *
14
+ * Tox is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ * GNU General Public License for more details.
18
+ *
19
+ * You should have received a copy of the GNU General Public License
20
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
21
+ *
22
+ */
23
+
24
+ #ifndef LOSSLESS_UDP_H
25
+ #define LOSSLESS_UDP_H
26
+
27
+ #include "network.h"
28
+
29
+ #ifdef __cplusplus
30
+ extern "C" {
31
+ #endif
32
+
33
+ /* maximum length of the data in the data packets */
34
+ #define MAX_DATA_SIZE 1024
35
+
36
+ /* Functions */
37
+
38
+ /* initialize a new connection to ip_port
39
+ returns an integer corresponding to the connection id.
40
+ return -1 if it could not initialize the connection.
41
+ if there already was an existing connection to that ip_port return its number. */
42
+ int new_connection(IP_Port ip_port);
43
+
44
+ /* get connection id from IP_Port
45
+ return -1 if there are no connections like we are looking for
46
+ return id if it found it */
47
+ int getconnection_id(IP_Port ip_port);
48
+
49
+ /* returns an integer corresponding to the next connection in our imcoming connection list
50
+ return -1 if there are no new incoming connections in the list. */
51
+ int incoming_connection();
52
+
53
+ /* return -1 if it could not kill the connection.
54
+ return 0 if killed successfully */
55
+ int kill_connection(int connection_id);
56
+
57
+ /* kill connection in seconds seconds.
58
+ return -1 if it can not kill the connection.
59
+ return 0 if it will kill it */
60
+ int kill_connection_in(int connection_id, uint32_t seconds);
61
+
62
+ /* returns the ip_port of the corresponding connection.
63
+ return 0 if there is no such connection. */
64
+ IP_Port connection_ip(int connection_id);
65
+
66
+ /* returns the id of the next packet in the queue
67
+ return -1 if no packet in queue */
68
+ char id_packet(int connection_id);
69
+
70
+ /* return 0 if there is no received data in the buffer.
71
+ return length of received packet if successful */
72
+ int read_packet(int connection_id, uint8_t *data);
73
+
74
+ /* return 0 if data could not be put in packet queue
75
+ return 1 if data was put into the queue */
76
+ int write_packet(int connection_id, uint8_t *data, uint32_t length);
77
+
78
+ /* returns the number of packets in the queue waiting to be successfully sent. */
79
+ uint32_t sendqueue(int connection_id);
80
+
81
+ /* returns the number of packets in the queue waiting to be successfully read with read_packet(...) */
82
+ uint32_t recvqueue(int connection_id);
83
+
84
+ /* check if connection is connected
85
+ return 0 no.
86
+ return 1 if attempting handshake
87
+ return 2 if handshake is done
88
+ return 3 if fully connected
89
+ return 4 if timed out and wating to be killed */
90
+ int is_connected(int connection_id);
91
+
92
+ /* Call this function a couple times per second
93
+ It's the main loop. */
94
+ void doLossless_UDP();
95
+
96
+
97
+ /* if we receive a Lossless_UDP 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. */
100
+ int LosslessUDP_handlepacket(uint8_t *packet, uint32_t length, IP_Port source);
101
+
102
+ #ifdef __cplusplus
103
+ }
104
+ #endif
105
+
106
+ #endif
@@ -0,0 +1,581 @@
1
+ /* Messenger.c
2
+ *
3
+ * An implementation of a simple text chat only messenger on the tox network core.
4
+ *
5
+ * Copyright (C) 2013 Tox project All Rights Reserved.
6
+ *
7
+ * This file is part of Tox.
8
+ *
9
+ * Tox is free software: you can redistribute it and/or modify
10
+ * it under the terms of the GNU General Public License as published by
11
+ * the Free Software Foundation, either version 3 of the License, or
12
+ * (at your option) any later version.
13
+ *
14
+ * Tox is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ * GNU General Public License for more details.
18
+ *
19
+ * You should have received a copy of the GNU General Public License
20
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
21
+ *
22
+ */
23
+
24
+ #include "Messenger.h"
25
+ #define MIN(a,b) (((a)<(b))?(a):(b))
26
+
27
+ typedef struct {
28
+ uint8_t client_id[CLIENT_ID_SIZE];
29
+ int crypt_connection_id;
30
+ int friend_request_id; /* id of the friend request corresponding to the current friend request to the current friend. */
31
+ uint8_t status; /* 0 if no friend, 1 if added, 2 if friend request sent, 3 if confirmed friend, 4 if online. */
32
+ uint8_t info[MAX_DATA_SIZE]; /* the data that is sent during the friend requests we do */
33
+ uint8_t name[MAX_NAME_LENGTH];
34
+ uint8_t name_sent; /* 0 if we didn't send our name to this friend 1 if we have. */
35
+ uint8_t *userstatus;
36
+ uint16_t userstatus_length;
37
+ uint8_t userstatus_sent;
38
+ uint16_t info_size; /* length of the info */
39
+ } Friend;
40
+
41
+ uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
42
+
43
+ static uint8_t self_name[MAX_NAME_LENGTH];
44
+ static uint16_t self_name_length;
45
+
46
+ static uint8_t *self_userstatus;
47
+ static uint16_t self_userstatus_len;
48
+
49
+ #define MAX_NUM_FRIENDS 256
50
+
51
+ static Friend friendlist[MAX_NUM_FRIENDS];
52
+
53
+ static uint32_t numfriends;
54
+
55
+ /* 1 if we are online
56
+ 0 if we are offline
57
+ static uint8_t online; */
58
+
59
+ /* return the friend id associated to that public key.
60
+ return -1 if no such friend */
61
+ int getfriend_id(uint8_t *client_id)
62
+ {
63
+ uint32_t i;
64
+
65
+ for (i = 0; i < numfriends; ++i) {
66
+ if (friendlist[i].status > 0)
67
+ if (memcmp(client_id, friendlist[i].client_id, crypto_box_PUBLICKEYBYTES) == 0)
68
+ return i;
69
+ }
70
+
71
+ return -1;
72
+ }
73
+
74
+ /* Returns number of friends */
75
+ int getnumfriends()
76
+ {
77
+ return numfriends;
78
+ }
79
+
80
+ /* copies the public key associated to that friend id into client_id buffer.
81
+ make sure that client_id is of size CLIENT_ID_SIZE.
82
+ return 0 if success
83
+ return -1 if failure. */
84
+ int getclient_id(int friend_id, uint8_t *client_id)
85
+ {
86
+ if (friend_id >= numfriends || friend_id < 0)
87
+ return -1;
88
+
89
+ if (friendlist[friend_id].status > 0) {
90
+ memcpy(client_id, friendlist[friend_id].client_id, CLIENT_ID_SIZE);
91
+ return 0;
92
+ }
93
+
94
+ return -1;
95
+ }
96
+
97
+ /* add a friend
98
+ set the data that will be sent along with friend request
99
+ client_id is the client id of the friend
100
+ data is the data and length is the length
101
+ returns the friend number if success
102
+ return -1 if failure. */
103
+ int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length)
104
+ {
105
+ if (length == 0 || length >=
106
+ (MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES))
107
+ return -1;
108
+ if (memcmp(client_id, self_public_key, crypto_box_PUBLICKEYBYTES) == 0)
109
+ return -1;
110
+ if (getfriend_id(client_id) != -1)
111
+ return -1;
112
+ uint32_t i;
113
+ for (i = 0; i <= numfriends; ++i) {
114
+ if(friendlist[i].status == 0) {
115
+ DHT_addfriend(client_id);
116
+ friendlist[i].status = 1;
117
+ friendlist[i].crypt_connection_id = -1;
118
+ friendlist[i].friend_request_id = -1;
119
+ memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE);
120
+ friendlist[i].userstatus = calloc(1, 1);
121
+ friendlist[i].userstatus_length = 1;
122
+ memcpy(friendlist[i].info, data, length);
123
+ friendlist[i].info_size = length;
124
+
125
+ ++numfriends;
126
+ return i;
127
+ }
128
+ }
129
+ return -1;
130
+ }
131
+
132
+ int m_addfriend_norequest(uint8_t * client_id)
133
+ {
134
+ if (getfriend_id(client_id) != -1)
135
+ return -1;
136
+ uint32_t i;
137
+ for (i = 0; i <= numfriends; ++i) {
138
+ if(friendlist[i].status == 0) {
139
+ DHT_addfriend(client_id);
140
+ friendlist[i].status = 2;
141
+ friendlist[i].crypt_connection_id = -1;
142
+ friendlist[i].friend_request_id = -1;
143
+ memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE);
144
+ friendlist[i].userstatus = calloc(1, 1);
145
+ friendlist[i].userstatus_length = 1;
146
+ numfriends++;
147
+ return i;
148
+ }
149
+ }
150
+ return -1;
151
+ }
152
+
153
+ /* remove a friend
154
+ return 0 if success
155
+ return -1 if failure */
156
+ int m_delfriend(int friendnumber)
157
+ {
158
+ if (friendnumber >= numfriends || friendnumber < 0)
159
+ return -1;
160
+
161
+ DHT_delfriend(friendlist[friendnumber].client_id);
162
+ crypto_kill(friendlist[friendnumber].crypt_connection_id);
163
+ free(friendlist[friendnumber].userstatus);
164
+ memset(&friendlist[friendnumber], 0, sizeof(Friend));
165
+ uint32_t i;
166
+ for (i = numfriends; i != 0; --i) {
167
+ if (friendlist[i].status != 0)
168
+ break;
169
+ }
170
+ numfriends = i;
171
+ return 0;
172
+ }
173
+
174
+ /* return 4 if friend is online
175
+ return 3 if friend is confirmed
176
+ return 2 if the friend request was sent
177
+ return 1 if the friend was added
178
+ return 0 if there is no friend with that number */
179
+ int m_friendstatus(int friendnumber)
180
+ {
181
+ if (friendnumber < 0 || friendnumber >= MAX_NUM_FRIENDS)
182
+ return 0;
183
+ return friendlist[friendnumber].status;
184
+ }
185
+
186
+ /* send a text chat message to an online friend
187
+ return 1 if packet was successfully put into the send queue
188
+ return 0 if it was not */
189
+ int m_sendmessage(int friendnumber, uint8_t *message, uint32_t length)
190
+ {
191
+ if (friendnumber < 0 || friendnumber >= MAX_NUM_FRIENDS)
192
+ return 0;
193
+ if (length >= MAX_DATA_SIZE || friendlist[friendnumber].status != 4)
194
+ /* this does not mean the maximum message length is MAX_DATA_SIZE - 1, it is actually 17 bytes less. */
195
+ return 0;
196
+ uint8_t temp[MAX_DATA_SIZE];
197
+ temp[0] = PACKET_ID_MESSAGE;
198
+ memcpy(temp + 1, message, length);
199
+ return write_cryptpacket(friendlist[friendnumber].crypt_connection_id, temp, length + 1);
200
+ }
201
+
202
+ /* send a name packet to friendnumber
203
+ length is the length with the NULL terminator*/
204
+ static int m_sendname(int friendnumber, uint8_t * name, uint16_t length)
205
+ {
206
+ if(length > MAX_NAME_LENGTH || length == 0)
207
+ return 0;
208
+ uint8_t temp[MAX_NAME_LENGTH + 1];
209
+ memcpy(temp + 1, name, length);
210
+ temp[0] = PACKET_ID_NICKNAME;
211
+ return write_cryptpacket(friendlist[friendnumber].crypt_connection_id, temp, length + 1);
212
+ }
213
+
214
+ /* set the name of a friend
215
+ return 0 if success
216
+ return -1 if failure */
217
+ static int setfriendname(int friendnumber, uint8_t * name)
218
+ {
219
+ if (friendnumber >= numfriends || friendnumber < 0)
220
+ return -1;
221
+ memcpy(friendlist[friendnumber].name, name, MAX_NAME_LENGTH);
222
+ return 0;
223
+ }
224
+
225
+ /* Set our nickname
226
+ name must be a string of maximum MAX_NAME_LENGTH length.
227
+ length must be at least 1 byte
228
+ length is the length of name with the NULL terminator
229
+ return 0 if success
230
+ return -1 if failure */
231
+ int setname(uint8_t * name, uint16_t length)
232
+ {
233
+ if (length > MAX_NAME_LENGTH || length == 0)
234
+ return -1;
235
+ memcpy(self_name, name, length);
236
+ self_name_length = length;
237
+ uint32_t i;
238
+ for (i = 0; i < numfriends; ++i)
239
+ friendlist[i].name_sent = 0;
240
+ return 0;
241
+ }
242
+
243
+ /* get name of friendnumber
244
+ put it in name
245
+ name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes.
246
+ return 0 if success
247
+ return -1 if failure */
248
+ int getname(int friendnumber, uint8_t * name)
249
+ {
250
+ if (friendnumber >= numfriends || friendnumber < 0)
251
+ return -1;
252
+ memcpy(name, friendlist[friendnumber].name, MAX_NAME_LENGTH);
253
+ return 0;
254
+ }
255
+
256
+ int m_set_userstatus(uint8_t *status, uint16_t length)
257
+ {
258
+ if (length > MAX_USERSTATUS_LENGTH)
259
+ return -1;
260
+ uint8_t *newstatus = calloc(length, 1);
261
+ memcpy(newstatus, status, length);
262
+ free(self_userstatus);
263
+ self_userstatus = newstatus;
264
+ self_userstatus_len = length;
265
+
266
+ uint32_t i;
267
+ for (i = 0; i < numfriends; ++i)
268
+ friendlist[i].userstatus_sent = 0;
269
+ return 0;
270
+ }
271
+
272
+ /* return the size of friendnumber's user status
273
+ guaranteed to be at most MAX_USERSTATUS_LENGTH */
274
+ int m_get_userstatus_size(int friendnumber)
275
+ {
276
+ if (friendnumber >= numfriends || friendnumber < 0)
277
+ return -1;
278
+ return friendlist[friendnumber].userstatus_length;
279
+ }
280
+
281
+ /* copy the user status of friendnumber into buf, truncating if needed to maxlen
282
+ bytes, use m_get_userstatus_size to find out how much you need to allocate */
283
+ int m_copy_userstatus(int friendnumber, uint8_t * buf, uint32_t maxlen)
284
+ {
285
+ if (friendnumber >= numfriends || friendnumber < 0)
286
+ return -1;
287
+ memset(buf, 0, maxlen);
288
+ memcpy(buf, friendlist[friendnumber].userstatus, MIN(maxlen, MAX_USERSTATUS_LENGTH) - 1);
289
+ return 0;
290
+ }
291
+
292
+ static int send_userstatus(int friendnumber, uint8_t * status, uint16_t length)
293
+ {
294
+ uint8_t *thepacket = malloc(length + 1);
295
+ memcpy(thepacket + 1, status, length);
296
+ thepacket[0] = PACKET_ID_USERSTATUS;
297
+ int written = write_cryptpacket(friendlist[friendnumber].crypt_connection_id, thepacket, length + 1);
298
+ free(thepacket);
299
+ return written;
300
+ }
301
+
302
+ static int set_friend_userstatus(int friendnumber, uint8_t * status, uint16_t length)
303
+ {
304
+ if (friendnumber >= numfriends || friendnumber < 0)
305
+ return -1;
306
+ uint8_t *newstatus = calloc(length, 1);
307
+ memcpy(newstatus, status, length);
308
+ free(friendlist[friendnumber].userstatus);
309
+ friendlist[friendnumber].userstatus = newstatus;
310
+ friendlist[friendnumber].userstatus_length = length;
311
+ return 0;
312
+ }
313
+
314
+ /* static void (*friend_request)(uint8_t *, uint8_t *, uint16_t);
315
+ static uint8_t friend_request_isset = 0; */
316
+ /* set the function that will be executed when a friend request is received. */
317
+ void m_callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t))
318
+ {
319
+ callback_friendrequest(function);
320
+ }
321
+
322
+ static void (*friend_message)(int, uint8_t *, uint16_t);
323
+ static uint8_t friend_message_isset = 0;
324
+
325
+ /* set the function that will be executed when a message from a friend is received. */
326
+ void m_callback_friendmessage(void (*function)(int, uint8_t *, uint16_t))
327
+ {
328
+ friend_message = function;
329
+ friend_message_isset = 1;
330
+ }
331
+
332
+ static void (*friend_namechange)(int, uint8_t *, uint16_t);
333
+ static uint8_t friend_namechange_isset = 0;
334
+ void m_callback_namechange(void (*function)(int, uint8_t *, uint16_t))
335
+ {
336
+ friend_namechange = function;
337
+ friend_namechange_isset = 1;
338
+ }
339
+
340
+ static void (*friend_statuschange)(int, uint8_t *, uint16_t);
341
+ static uint8_t friend_statuschange_isset = 0;
342
+ void m_callback_userstatus(void (*function)(int, uint8_t *, uint16_t))
343
+ {
344
+ friend_statuschange = function;
345
+ friend_statuschange_isset = 1;
346
+ }
347
+
348
+ #define PORT 33445
349
+ /* run this at startup */
350
+ int initMessenger()
351
+ {
352
+ new_keys();
353
+ m_set_userstatus((uint8_t*)"Online", sizeof("Online"));
354
+ initNetCrypto();
355
+ IP ip;
356
+ ip.i = 0;
357
+
358
+ if(init_networking(ip,PORT) == -1)
359
+ return -1;
360
+
361
+ return 0;
362
+ }
363
+
364
+ //TODO: make this function not suck.
365
+ static void doFriends()
366
+ {
367
+ /* TODO: add incoming connections and some other stuff. */
368
+ uint32_t i;
369
+ int len;
370
+ uint8_t temp[MAX_DATA_SIZE];
371
+ for (i = 0; i < numfriends; ++i) {
372
+ if (friendlist[i].status == 1) {
373
+ int fr = send_friendrequest(friendlist[i].client_id, friendlist[i].info, friendlist[i].info_size);
374
+ if (fr == 0) /* TODO: This needs to be fixed so that it sends the friend requests a couple of times in case of packet loss */
375
+ friendlist[i].status = 2;
376
+ else if (fr > 0)
377
+ friendlist[i].status = 2;
378
+ }
379
+ if (friendlist[i].status == 2 || friendlist[i].status == 3) { /* friend is not online */
380
+ if (friendlist[i].status == 2) {
381
+ if (friendlist[i].friend_request_id + 10 < unix_time()) { /*I know this is hackish but it should work.*/
382
+ send_friendrequest(friendlist[i].client_id, friendlist[i].info, friendlist[i].info_size);
383
+ friendlist[i].friend_request_id = unix_time();
384
+ }
385
+ }
386
+ IP_Port friendip = DHT_getfriendip(friendlist[i].client_id);
387
+ switch (is_cryptoconnected(friendlist[i].crypt_connection_id)) {
388
+ case 0:
389
+ if (friendip.ip.i > 1)
390
+ friendlist[i].crypt_connection_id = crypto_connect(friendlist[i].client_id, friendip);
391
+ break;
392
+ case 3: /* Connection is established */
393
+ friendlist[i].status = 4;
394
+ break;
395
+ case 4:
396
+ crypto_kill(friendlist[i].crypt_connection_id);
397
+ friendlist[i].crypt_connection_id = -1;
398
+ break;
399
+ default:
400
+ break;
401
+ }
402
+ }
403
+ while (friendlist[i].status == 4) { /* friend is online */
404
+ if (friendlist[i].name_sent == 0) {
405
+ if (m_sendname(i, self_name, self_name_length))
406
+ friendlist[i].name_sent = 1;
407
+ }
408
+ if (friendlist[i].userstatus_sent == 0) {
409
+ if (send_userstatus(i, self_userstatus, self_userstatus_len))
410
+ friendlist[i].userstatus_sent = 1;
411
+ }
412
+ len = read_cryptpacket(friendlist[i].crypt_connection_id, temp);
413
+ if (len > 0) {
414
+ switch (temp[0]) {
415
+ case PACKET_ID_NICKNAME: {
416
+ if (len >= MAX_NAME_LENGTH + 1 || len == 1)
417
+ break;
418
+ if(friend_namechange_isset)
419
+ friend_namechange(i, temp + 1, len - 1);
420
+ memcpy(friendlist[i].name, temp + 1, len - 1);
421
+ friendlist[i].name[len - 2] = 0; /* make sure the NULL terminator is present. */
422
+ break;
423
+ }
424
+ case PACKET_ID_USERSTATUS: {
425
+ uint8_t *status = calloc(MIN(len - 1, MAX_USERSTATUS_LENGTH), 1);
426
+ memcpy(status, temp + 1, MIN(len - 1, MAX_USERSTATUS_LENGTH));
427
+ if (friend_statuschange_isset)
428
+ friend_statuschange(i, status, MIN(len - 1, MAX_USERSTATUS_LENGTH));
429
+ set_friend_userstatus(i, status, MIN(len - 1, MAX_USERSTATUS_LENGTH));
430
+ free(status);
431
+ break;
432
+ }
433
+ case PACKET_ID_MESSAGE: {
434
+ if (friend_message_isset)
435
+ (*friend_message)(i, temp + 1, len - 1);
436
+ break;
437
+ }
438
+ }
439
+ } else {
440
+ if (is_cryptoconnected(friendlist[i].crypt_connection_id) == 4) { /* if the connection timed out, kill it */
441
+ crypto_kill(friendlist[i].crypt_connection_id);
442
+ friendlist[i].crypt_connection_id = -1;
443
+ friendlist[i].status = 3;
444
+ }
445
+ break;
446
+ }
447
+ }
448
+ }
449
+ }
450
+
451
+ static void doInbound()
452
+ {
453
+ uint8_t secret_nonce[crypto_box_NONCEBYTES];
454
+ uint8_t public_key[crypto_box_PUBLICKEYBYTES];
455
+ uint8_t session_key[crypto_box_PUBLICKEYBYTES];
456
+ int inconnection = crypto_inbound(public_key, secret_nonce, session_key);
457
+ if (inconnection != -1) {
458
+ int friend_id = getfriend_id(public_key);
459
+ if (friend_id != -1) {
460
+ crypto_kill(friendlist[friend_id].crypt_connection_id);
461
+ friendlist[friend_id].crypt_connection_id =
462
+ accept_crypto_inbound(inconnection, public_key, secret_nonce, session_key);
463
+
464
+ friendlist[friend_id].status = 3;
465
+ }
466
+ }
467
+ }
468
+
469
+ /*Interval in seconds between LAN discovery packet sending*/
470
+ #define LAN_DISCOVERY_INTERVAL 60
471
+
472
+ static uint32_t last_LANdiscovery;
473
+
474
+ /*Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds*/
475
+ static void LANdiscovery()
476
+ {
477
+ if (last_LANdiscovery + LAN_DISCOVERY_INTERVAL < unix_time()) {
478
+ send_LANdiscovery(htons(PORT));
479
+ last_LANdiscovery = unix_time();
480
+ }
481
+ }
482
+
483
+
484
+ /* the main loop that needs to be run at least 200 times per second. */
485
+ void doMessenger()
486
+ {
487
+ IP_Port ip_port;
488
+ uint8_t data[MAX_UDP_PACKET_SIZE];
489
+ uint32_t length;
490
+ while (receivepacket(&ip_port, data, &length) != -1) {
491
+ #ifdef DEBUG
492
+ /* if(rand() % 3 != 1) //simulate packet loss */
493
+ /* { */
494
+ if (DHT_handlepacket(data, length, ip_port) && LosslessUDP_handlepacket(data, length, ip_port) &&
495
+ friendreq_handlepacket(data, length, ip_port) && LANdiscovery_handlepacket(data, length, ip_port))
496
+ /* if packet is discarded */
497
+ printf("Received unhandled packet with length: %u\n", length);
498
+ else
499
+ printf("Received handled packet with length: %u\n", length);
500
+ /* } */
501
+ printf("Status: %u %u %u\n",friendlist[0].status ,is_cryptoconnected(friendlist[0].crypt_connection_id), friendlist[0].crypt_connection_id);
502
+ #else
503
+ DHT_handlepacket(data, length, ip_port);
504
+ LosslessUDP_handlepacket(data, length, ip_port);
505
+ friendreq_handlepacket(data, length, ip_port);
506
+ LANdiscovery_handlepacket(data, length, ip_port);
507
+ #endif
508
+
509
+ }
510
+ doDHT();
511
+ doLossless_UDP();
512
+ doNetCrypto();
513
+ doInbound();
514
+ doFriends();
515
+ LANdiscovery();
516
+ }
517
+
518
+ /* returns the size of the messenger data (for saving) */
519
+ uint32_t Messenger_size()
520
+ {
521
+ return crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES
522
+ + sizeof(uint32_t) + DHT_size() + sizeof(uint32_t) + sizeof(Friend) * numfriends;
523
+ }
524
+
525
+ /* save the messenger in data of size Messenger_size() */
526
+ void Messenger_save(uint8_t *data)
527
+ {
528
+ save_keys(data);
529
+ data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES;
530
+ uint32_t size = DHT_size();
531
+ memcpy(data, &size, sizeof(size));
532
+ data += sizeof(size);
533
+ DHT_save(data);
534
+ data += size;
535
+ size = sizeof(Friend) * numfriends;
536
+ memcpy(data, &size, sizeof(size));
537
+ data += sizeof(size);
538
+ memcpy(data, friendlist, sizeof(Friend) * numfriends);
539
+ }
540
+
541
+ /* load the messenger from data of size length. */
542
+ int Messenger_load(uint8_t * data, uint32_t length)
543
+ {
544
+ if (length == ~0)
545
+ return -1;
546
+ if (length < crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t) * 2)
547
+ return -1;
548
+ length -= crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t) * 2;
549
+ load_keys(data);
550
+ data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES;
551
+ uint32_t size;
552
+ memcpy(&size, data, sizeof(size));
553
+ data += sizeof(size);
554
+
555
+ if (length < size)
556
+ return -1;
557
+ length -= size;
558
+ if (DHT_load(data, size) == -1)
559
+ return -1;
560
+ data += size;
561
+ memcpy(&size, data, sizeof(size));
562
+ data += sizeof(size);
563
+ if (length != size || length % sizeof(Friend) != 0)
564
+ return -1;
565
+
566
+ Friend * temp = malloc(size);
567
+ memcpy(temp, data, size);
568
+
569
+ uint16_t num = size / sizeof(Friend);
570
+
571
+ uint32_t i;
572
+ for (i = 0; i < num; ++i) {
573
+ if(temp[i].status != 0) {
574
+ int fnum = m_addfriend_norequest(temp[i].client_id);
575
+ setfriendname(fnum, temp[i].name);
576
+ /* set_friend_userstatus(fnum, temp[i].userstatus, temp[i].userstatus_length); */
577
+ }
578
+ }
579
+ free(temp);
580
+ return 0;
581
+ }