ffi-tox 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }