summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/Messenger.c.orig795
1 files changed, 0 insertions, 795 deletions
diff --git a/core/Messenger.c.orig b/core/Messenger.c.orig
deleted file mode 100644
index 58993a08..00000000
--- a/core/Messenger.c.orig
+++ /dev/null
@@ -1,795 +0,0 @@
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#include "timer.h"
26
27#define MIN(a,b) (((a)<(b))?(a):(b))
28
29static void set_friend_status(Messenger *m, int friendnumber, uint8_t status);
30static int write_cryptpacket_id(Messenger *m, int friendnumber, uint8_t packet_id, uint8_t *data, uint32_t length);
31
32/* 1 if we are online
33 0 if we are offline
34 static uint8_t online; */
35
36/* set the size of the friend list to numfriends
37 return -1 if realloc fails */
38int realloc_friendlist(Messenger *m, uint32_t num) {
39 Friend *newfriendlist = realloc(m->friendlist, num*sizeof(Friend));
40 if (newfriendlist == NULL)
41 return -1;
42 memset(&newfriendlist[num-1], 0, sizeof(Friend));
43 m->friendlist = newfriendlist;
44 return 0;
45}
46
47/* return the friend id associated to that public key.
48 return -1 if no such friend */
49int getfriend_id(Messenger *m, uint8_t *client_id)
50{
51 uint32_t i;
52
53 for (i = 0; i < m->numfriends; ++i) {
54 if (m->friendlist[i].status > 0)
55 if (memcmp(client_id, m->friendlist[i].client_id, crypto_box_PUBLICKEYBYTES) == 0)
56 return i;
57 }
58
59 return -1;
60}
61
62/* copies the public key associated to that friend id into client_id buffer.
63 make sure that client_id is of size CLIENT_ID_SIZE.
64 return 0 if success
65 return -1 if failure. */
66int getclient_id(Messenger *m, int friend_id, uint8_t *client_id)
67{
68 if (friend_id >= m->numfriends || friend_id < 0)
69 return -1;
70
71 if (m->friendlist[friend_id].status > 0) {
72 memcpy(client_id, m->friendlist[friend_id].client_id, CLIENT_ID_SIZE);
73 return 0;
74 }
75
76 return -1;
77}
78
79/*
80 * add a friend
81 * set the data that will be sent along with friend request
82 * client_id is the client id of the friend
83 * data is the data and length is the length
84 * returns the friend number if success
85 * return FA_TOOLONG if message length is too long
86 * return FAERR_NOMESSAGE if no message (message length must be >= 1 byte)
87 * return FAERR_OWNKEY if user's own key
88 * return FAERR_ALREADYSENT if friend request already sent or already a friend
89 * return FAERR_UNKNOWN for unknown error
90 */
91int m_addfriend(Messenger *m, uint8_t *client_id, uint8_t *data, uint16_t length)
92{
93 if (length >= (MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES
94 - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES
95 + crypto_box_ZEROBYTES))
96 return FAERR_TOOLONG;
97 if (length < 1)
98 return FAERR_NOMESSAGE;
99 if (memcmp(client_id, self_public_key, crypto_box_PUBLICKEYBYTES) == 0)
100 return FAERR_OWNKEY;
101 if (getfriend_id(m, client_id) != -1)
102 return FAERR_ALREADYSENT;
103
104 /* resize the friend list if necessary */
105 realloc_friendlist(m, m->numfriends + 1);
106
107 uint32_t i;
108 for (i = 0; i <= m->numfriends; ++i) {
109 if (m->friendlist[i].status == NOFRIEND) {
110 DHT_addfriend(client_id);
111 m->friendlist[i].status = FRIEND_ADDED;
112 m->friendlist[i].crypt_connection_id = -1;
113 m->friendlist[i].friend_request_id = -1;
114 memcpy(m->friendlist[i].client_id, client_id, CLIENT_ID_SIZE);
115 m->friendlist[i].statusmessage = calloc(1, 1);
116 m->friendlist[i].statusmessage_length = 1;
117 m->friendlist[i].userstatus = USERSTATUS_NONE;
118 memcpy(m->friendlist[i].info, data, length);
119 m->friendlist[i].info_size = length;
120 m->friendlist[i].message_id = 0;
121 m->friendlist[i].receives_read_receipts = 1; /* default: YES */
122
123 ++ m->numfriends;
124 return i;
125 }
126 }
127 return FAERR_UNKNOWN;
128}
129
130int m_addfriend_norequest(Messenger *m, uint8_t * client_id)
131{
132 if (getfriend_id(m, client_id) != -1)
133 return -1;
134
135 /* resize the friend list if necessary */
136 realloc_friendlist(m, m->numfriends + 1);
137
138 uint32_t i;
139 for (i = 0; i <= m->numfriends; ++i) {
140 if(m->friendlist[i].status == NOFRIEND) {
141 DHT_addfriend(client_id);
142 m->friendlist[i].status = FRIEND_REQUESTED;
143 m->friendlist[i].crypt_connection_id = -1;
144 m->friendlist[i].friend_request_id = -1;
145 memcpy(m->friendlist[i].client_id, client_id, CLIENT_ID_SIZE);
146 m->friendlist[i].statusmessage = calloc(1, 1);
147 m->friendlist[i].statusmessage_length = 1;
148 m->friendlist[i].userstatus = USERSTATUS_NONE;
149 m->friendlist[i].message_id = 0;
150 m->friendlist[i].receives_read_receipts = 1; /* default: YES */
151 ++ m->numfriends;
152 return i;
153 }
154 }
155 return -1;
156}
157
158/* remove a friend
159 return 0 if success
160 return -1 if failure */
161int m_delfriend(Messenger *m, int friendnumber)
162{
163 if (friendnumber >= m->numfriends || friendnumber < 0)
164 return -1;
165
166 DHT_delfriend(m->friendlist[friendnumber].client_id);
167 crypto_kill(m->friendlist[friendnumber].crypt_connection_id);
168 free(m->friendlist[friendnumber].statusmessage);
169 memset(&(m->friendlist[friendnumber]), 0, sizeof(Friend));
170 uint32_t i;
171
172 for (i = m->numfriends; i != 0; --i) {
173 if (m->friendlist[i-1].status != NOFRIEND)
174 break;
175 }
176 m->numfriends = i;
177 realloc_friendlist(m, m->numfriends + 1);
178
179 return 0;
180}
181
182/* return FRIEND_ONLINE if friend is online
183 return FRIEND_CONFIRMED if friend is confirmed
184 return FRIEND_REQUESTED if the friend request was sent
185 return FRIEND_ADDED if the friend was added
186 return NOFRIEND if there is no friend with that number */
187int m_friendstatus(Messenger *m, int friendnumber)
188{
189 if (friendnumber < 0 || friendnumber >= m->numfriends)
190 return NOFRIEND;
191 return m->friendlist[friendnumber].status;
192}
193
194/* send a text chat message to an online friend
195 return the message id if packet was successfully put into the send queue
196 return 0 if it was not */
197uint32_t m_sendmessage(Messenger *m, int friendnumber, uint8_t *message, uint32_t length)
198{
199 if (friendnumber < 0 || friendnumber >= m->numfriends)
200 return 0;
201 uint32_t msgid = ++m->friendlist[friendnumber].message_id;
202 if (msgid == 0)
203 msgid = 1; /* otherwise, false error */
204 if(m_sendmessage_withid(m, friendnumber, msgid, message, length)) {
205 return msgid;
206 }
207
208 return 0;
209}
210
211uint32_t m_sendmessage_withid(Messenger *m, int friendnumber, uint32_t theid, uint8_t *message, uint32_t length)
212{
213 if (length >= (MAX_DATA_SIZE - sizeof(theid)))
214 return 0;
215 uint8_t temp[MAX_DATA_SIZE];
216 theid = htonl(theid);
217 memcpy(temp, &theid, sizeof(theid));
218 memcpy(temp + sizeof(theid), message, length);
219 return write_cryptpacket_id(m, friendnumber, PACKET_ID_MESSAGE, temp, length + sizeof(theid));
220}
221
222/* send an action to an online friend
223 return 1 if packet was successfully put into the send queue
224 return 0 if it was not */
225int m_sendaction(Messenger *m, int friendnumber, uint8_t *action, uint32_t length)
226{
227 return write_cryptpacket_id(m, friendnumber, PACKET_ID_ACTION, action, length);
228}
229
230/* send a name packet to friendnumber
231 length is the length with the NULL terminator*/
232static int m_sendname(Messenger *m, int friendnumber, uint8_t * name, uint16_t length)
233{
234 if(length > MAX_NAME_LENGTH || length == 0)
235 return 0;
236 return write_cryptpacket_id(m, friendnumber, PACKET_ID_NICKNAME, name, length);
237}
238
239/* set the name of a friend
240 return 0 if success
241 return -1 if failure */
242static int setfriendname(Messenger *m, int friendnumber, uint8_t * name)
243{
244 if (friendnumber >= m->numfriends || friendnumber < 0)
245 return -1;
246 memcpy(m->friendlist[friendnumber].name, name, MAX_NAME_LENGTH);
247 return 0;
248}
249
250/* Set our nickname
251 name must be a string of maximum MAX_NAME_LENGTH length.
252 length must be at least 1 byte
253 length is the length of name with the NULL terminator
254 return 0 if success
255 return -1 if failure */
256int setname(Messenger *m, uint8_t * name, uint16_t length)
257{
258 if (length > MAX_NAME_LENGTH || length == 0)
259 return -1;
260 memcpy(m->name, name, length);
261 m->name_length = length;
262 uint32_t i;
263 for (i = 0; i < m->numfriends; ++i)
264 m->friendlist[i].name_sent = 0;
265 return 0;
266}
267
268/* get our nickname
269 put it in name
270 name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes.
271 return the length of the name */
272uint16_t getself_name(Messenger *m, uint8_t *name)
273{
274 memcpy(name, m->name, m->name_length);
275 return m->name_length;
276}
277
278/* get name of friendnumber
279 put it in name
280 name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes.
281 return 0 if success
282 return -1 if failure */
283int getname(Messenger *m, int friendnumber, uint8_t * name)
284{
285 if (friendnumber >= m->numfriends || friendnumber < 0)
286 return -1;
287 memcpy(name, m->friendlist[friendnumber].name, MAX_NAME_LENGTH);
288 return 0;
289}
290
291int m_set_statusmessage(Messenger *m, uint8_t *status, uint16_t length)
292{
293 if (length > MAX_STATUSMESSAGE_LENGTH)
294 return -1;
295 memcpy(m->statusmessage, status, length);
296 m->statusmessage_length = length;
297
298 uint32_t i;
299 for (i = 0; i < m->numfriends; ++i)
300 m->friendlist[i].statusmessage_sent = 0;
301 return 0;
302}
303
304int m_set_userstatus(Messenger *m, USERSTATUS status)
305{
306 if (status >= USERSTATUS_INVALID) {
307 return -1;
308 }
309 m->userstatus = status;
310 uint32_t i;
311 for (i = 0; i < m->numfriends; ++i)
312 m->friendlist[i].userstatus_sent = 0;
313 return 0;
314}
315
316/* return the size of friendnumber's user status
317 guaranteed to be at most MAX_STATUSMESSAGE_LENGTH */
318int m_get_statusmessage_size(Messenger *m, int friendnumber)
319{
320 if (friendnumber >= m->numfriends || friendnumber < 0)
321 return -1;
322 return m->friendlist[friendnumber].statusmessage_length;
323}
324
325/* copy the user status of friendnumber into buf, truncating if needed to maxlen
326 bytes, use m_get_statusmessage_size to find out how much you need to allocate */
327int m_copy_statusmessage(Messenger *m, int friendnumber, uint8_t * buf, uint32_t maxlen)
328{
329 if (friendnumber >= m->numfriends || friendnumber < 0)
330 return -1;
331 memset(buf, 0, maxlen);
332 memcpy(buf, m->friendlist[friendnumber].statusmessage, MIN(maxlen, MAX_STATUSMESSAGE_LENGTH) - 1);
333 return 0;
334}
335
336int m_copy_self_statusmessage(Messenger *m, uint8_t * buf, uint32_t maxlen)
337{
338 memset(buf, 0, maxlen);
339 memcpy(buf, m->statusmessage, MIN(maxlen, MAX_STATUSMESSAGE_LENGTH) - 1);
340 return 0;
341}
342
343USERSTATUS m_get_userstatus(Messenger *m, int friendnumber)
344{
345 if (friendnumber >= m->numfriends || friendnumber < 0)
346 return USERSTATUS_INVALID;
347 USERSTATUS status = m->friendlist[friendnumber].userstatus;
348 if (status >= USERSTATUS_INVALID) {
349 status = USERSTATUS_NONE;
350 }
351 return status;
352}
353
354USERSTATUS m_get_self_userstatus(Messenger *m)
355{
356 return m->userstatus;
357}
358
359static int send_statusmessage(Messenger *m, int friendnumber, uint8_t * status, uint16_t length)
360{
361 return write_cryptpacket_id(m, friendnumber, PACKET_ID_STATUSMESSAGE, status, length);
362}
363
364static int send_userstatus(Messenger *m, int friendnumber, USERSTATUS status)
365{
366 uint8_t stat = status;
367 return write_cryptpacket_id(m, friendnumber, PACKET_ID_USERSTATUS, &stat, sizeof(stat));
368}
369
370static int set_friend_statusmessage(Messenger *m, int friendnumber, uint8_t * status, uint16_t length)
371{
372 if (friendnumber >= m->numfriends || friendnumber < 0)
373 return -1;
374 uint8_t *newstatus = calloc(length, 1);
375 memcpy(newstatus, status, length);
376 free(m->friendlist[friendnumber].statusmessage);
377 m->friendlist[friendnumber].statusmessage = newstatus;
378 m->friendlist[friendnumber].statusmessage_length = length;
379 return 0;
380}
381
382static void set_friend_userstatus(Messenger *m, int friendnumber, USERSTATUS status)
383{
384 m->friendlist[friendnumber].userstatus = status;
385}
386
387/* Sets whether we send read receipts for friendnumber. */
388void m_set_sends_receipts(Messenger *m, int friendnumber, int yesno)
389{
390 if (yesno != 0 || yesno != 1)
391 return;
392 if (friendnumber >= m->numfriends || friendnumber < 0)
393 return;
394 m->friendlist[friendnumber].receives_read_receipts = yesno;
395}
396
397/* static void (*friend_request)(uint8_t *, uint8_t *, uint16_t);
398static uint8_t friend_request_isset = 0; */
399/* set the function that will be executed when a friend request is received. */
400void m_callback_friendrequest(Messenger *m, void (*function)(uint8_t *, uint8_t *, uint16_t, void*), void* userdata)
401{
402 callback_friendrequest(function, userdata);
403}
404
405/* set the function that will be executed when a message from a friend is received. */
406void m_callback_friendmessage(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void*), void* userdata)
407{
408 m->friend_message = function;
409 m->friend_message_isset = 1;
410 m->friend_message_userdata = userdata;
411}
412
413void m_callback_action(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void*), void* userdata)
414{
415 m->friend_action = function;
416 m->friend_action_isset = 1;
417 m->friend_action_userdata = userdata;
418}
419
420void m_callback_namechange(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void*), void* userdata)
421{
422 m->friend_namechange = function;
423 m->friend_namechange_isset = 1;
424 m->friend_namechange_userdata = userdata;
425}
426
427void m_callback_statusmessage(Messenger *m, void (*function)(Messenger *m, int, uint8_t *, uint16_t, void*), void* userdata)
428{
429 m->friend_statusmessagechange = function;
430 m->friend_statusmessagechange_isset = 1;
431 m->friend_statuschange_userdata = userdata;
432}
433
434void m_callback_userstatus(Messenger *m, void (*function)(Messenger *m, int, USERSTATUS, void*), void* userdata)
435{
436 m->friend_userstatuschange = function;
437 m->friend_userstatuschange_isset = 1;
438 m->friend_userstatuschange_userdata = userdata;
439}
440
441void m_callback_read_receipt(Messenger *m, void (*function)(Messenger *m, int, uint32_t, void*), void* userdata)
442{
443 m->read_receipt = function;
444 m->read_receipt_isset = 1;
445 m->read_receipt_userdata = userdata;
446}
447
448void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, int, uint8_t, void*), void* userdata)
449{
450 m->friend_connectionstatuschange = function;
451 m->friend_connectionstatuschange_isset = 1;
452 m->friend_connectionstatuschange_userdata = userdata;
453}
454
455static void check_friend_connectionstatus(Messenger *m, int friendnumber, uint8_t status)
456{
457 if (!m->friend_connectionstatuschange_isset)
458 return;
459 if (status == NOFRIEND)
460 return;
461 const uint8_t was_connected = m->friendlist[friendnumber].status == FRIEND_ONLINE;
462 const uint8_t is_connected = status == FRIEND_ONLINE;
463 if (is_connected != was_connected)
464 m->friend_connectionstatuschange(m, friendnumber, is_connected, m->friend_connectionstatuschange_userdata);
465}
466
467void set_friend_status(Messenger *m, int friendnumber, uint8_t status)
468{
469 check_friend_connectionstatus(m, friendnumber, status);
470 m->friendlist[friendnumber].status = status;
471}
472
473int write_cryptpacket_id(Messenger *m, int friendnumber, uint8_t packet_id, uint8_t *data, uint32_t length)
474{
475 if (friendnumber < 0 || friendnumber >= m->numfriends)
476 return 0;
477 if (length >= MAX_DATA_SIZE || m->friendlist[friendnumber].status != FRIEND_ONLINE)
478 return 0;
479 uint8_t packet[length + 1];
480 packet[0] = packet_id;
481 memcpy(packet + 1, data, length);
482 return write_cryptpacket(m->friendlist[friendnumber].crypt_connection_id, packet, length + 1);
483}
484
485<<<<<<< HEAD
486=======
487#define PORT 33445
488/* run this at startup */
489Messenger * initMessenger(void)
490{
491 Messenger *m = calloc(1, sizeof(Messenger));
492 if( ! m )
493 return 0;
494
495 new_keys();
496 m_set_statusmessage(m, (uint8_t*)"Online", sizeof("Online"));
497 initNetCrypto();
498 IP ip;
499 ip.i = 0;
500
501 if(init_networking(ip,PORT) == -1)
502 return 0;
503
504 DHT_init();
505 LosslessUDP_init();
506 friendreq_init();
507 LANdiscovery_init();
508
509 return m;
510}
511
512/* run this before closing shop */
513void cleanupMessenger(Messenger *m){
514 /* FIXME TODO it seems no one frees friendlist or all the elements status */
515 free(m);
516}
517
518>>>>>>> upstream/master
519//TODO: make this function not suck.
520void doFriends(Messenger *m)
521{
522 /* TODO: add incoming connections and some other stuff. */
523 uint32_t i;
524 int len;
525 uint8_t temp[MAX_DATA_SIZE];
526 for (i = 0; i < m->numfriends; ++i) {
527 if (m->friendlist[i].status == FRIEND_ADDED) {
528 int fr = send_friendrequest(m->friendlist[i].client_id, m->friendlist[i].info, m->friendlist[i].info_size);
529 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 */
530 set_friend_status(m, i, FRIEND_REQUESTED);
531 else if (fr > 0)
532 set_friend_status(m, i, FRIEND_REQUESTED);
533 }
534 if (m->friendlist[i].status == FRIEND_REQUESTED || m->friendlist[i].status == FRIEND_CONFIRMED) { /* friend is not online */
535 if (m->friendlist[i].status == FRIEND_REQUESTED) {
536 if (m->friendlist[i].friend_request_id + 10 < unix_time()) { /*I know this is hackish but it should work.*/
537 send_friendrequest(m->friendlist[i].client_id, m->friendlist[i].info, m->friendlist[i].info_size);
538 m->friendlist[i].friend_request_id = unix_time();
539 }
540 }
541 IP_Port friendip = DHT_getfriendip(m->friendlist[i].client_id);
542 switch (is_cryptoconnected(m->friendlist[i].crypt_connection_id)) {
543 case 0:
544 if (friendip.ip.i > 1)
545 m->friendlist[i].crypt_connection_id = crypto_connect(m->friendlist[i].client_id, friendip);
546 break;
547 case 3: /* Connection is established */
548 set_friend_status(m, i, FRIEND_ONLINE);
549 m->friendlist[i].name_sent = 0;
550 m->friendlist[i].userstatus_sent = 0;
551 m->friendlist[i].statusmessage_sent = 0;
552 break;
553 case 4:
554 crypto_kill(m->friendlist[i].crypt_connection_id);
555 m->friendlist[i].crypt_connection_id = -1;
556 break;
557 default:
558 break;
559 }
560 }
561 while (m->friendlist[i].status == FRIEND_ONLINE) { /* friend is online */
562 if (m->friendlist[i].name_sent == 0) {
563 if (m_sendname(m, i, m->name, m->name_length))
564 m->friendlist[i].name_sent = 1;
565 }
566 if (m->friendlist[i].statusmessage_sent == 0) {
567 if (send_statusmessage(m, i, m->statusmessage, m->statusmessage_length))
568 m->friendlist[i].statusmessage_sent = 1;
569 }
570 if (m->friendlist[i].userstatus_sent == 0) {
571 if (send_userstatus(m, i, m->userstatus))
572 m->friendlist[i].userstatus_sent = 1;
573 }
574 len = read_cryptpacket(m->friendlist[i].crypt_connection_id, temp);
575 uint8_t packet_id = temp[0];
576 uint8_t* data = temp + 1;
577 int data_length = len - 1;
578 if (len > 0) {
579 switch (packet_id) {
580 case PACKET_ID_NICKNAME: {
581 if (data_length >= MAX_NAME_LENGTH || data_length == 0)
582 break;
583 if(m->friend_namechange_isset)
584 m->friend_namechange(m, i, data, data_length, m->friend_namechange_userdata);
585 memcpy(m->friendlist[i].name, data, data_length);
586 m->friendlist[i].name[data_length - 1] = 0; /* make sure the NULL terminator is present. */
587 break;
588 }
589 case PACKET_ID_STATUSMESSAGE: {
590 if (data_length == 0)
591 break;
592 uint8_t *status = calloc(MIN(data_length, MAX_STATUSMESSAGE_LENGTH), 1);
593 memcpy(status, data, MIN(data_length, MAX_STATUSMESSAGE_LENGTH));
594 if (m->friend_statusmessagechange_isset)
595 m->friend_statusmessagechange(m, i, status, MIN(data_length, MAX_STATUSMESSAGE_LENGTH),
596 m->friend_statuschange_userdata);
597 set_friend_statusmessage(m, i, status, MIN(data_length, MAX_STATUSMESSAGE_LENGTH));
598 free(status);
599 break;
600 }
601 case PACKET_ID_USERSTATUS: {
602 if (data_length != 1)
603 break;
604 USERSTATUS status = data[0];
605 if (m->friend_userstatuschange_isset)
606 m->friend_userstatuschange(m, i, status, m->friend_userstatuschange_userdata);
607 set_friend_userstatus(m, i, status);
608 break;
609 }
610 case PACKET_ID_MESSAGE: {
611 uint8_t *message_id = data;
612 uint8_t message_id_length = 4;
613 uint8_t *message = data + message_id_length;
614 uint16_t message_length = data_length - message_id_length;
615 if (m->friendlist[i].receives_read_receipts) {
616 write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length);
617 }
618 if (m->friend_message_isset)
619 (*m->friend_message)(m, i, message, message_length, m->friend_message_userdata);
620 break;
621 }
622 case PACKET_ID_ACTION: {
623 if (m->friend_action_isset)
624 (*m->friend_action)(m, i, data, data_length, m->friend_action_userdata);
625 break;
626 }
627 case PACKET_ID_RECEIPT: {
628 uint32_t msgid;
629 if (data_length < sizeof(msgid))
630 break;
631 memcpy(&msgid, data, sizeof(msgid));
632 msgid = ntohl(msgid);
633 if (m->read_receipt_isset)
634 (*m->read_receipt)(m, i, msgid, m->read_receipt_userdata);
635 break;
636 }
637 }
638 } else {
639 if (is_cryptoconnected(m->friendlist[i].crypt_connection_id) == 4) { /* if the connection timed out, kill it */
640 crypto_kill(m->friendlist[i].crypt_connection_id);
641 m->friendlist[i].crypt_connection_id = -1;
642 set_friend_status(m, i, FRIEND_CONFIRMED);
643 }
644 break;
645 }
646 }
647 }
648}
649
650void doInbound(Messenger *m)
651{
652 uint8_t secret_nonce[crypto_box_NONCEBYTES];
653 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
654 uint8_t session_key[crypto_box_PUBLICKEYBYTES];
655 int inconnection = crypto_inbound(public_key, secret_nonce, session_key);
656 if (inconnection != -1) {
657 int friend_id = getfriend_id(m, public_key);
658 if (friend_id != -1) {
659 crypto_kill(m->friendlist[friend_id].crypt_connection_id);
660 m->friendlist[friend_id].crypt_connection_id =
661 accept_crypto_inbound(inconnection, public_key, secret_nonce, session_key);
662
663 set_friend_status(m, friend_id, FRIEND_CONFIRMED);
664 }
665 }
666}
667
668#define PORT 33445
669
670/*Interval in seconds between LAN discovery packet sending*/
671#define LAN_DISCOVERY_INTERVAL 60
672
673/*Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds*/
674<<<<<<< HEAD
675static int LANdiscovery_timercallback(timer* t, void* ignore)
676=======
677void LANdiscovery(Messenger *m)
678>>>>>>> upstream/master
679{
680 send_LANdiscovery(htons(PORT));
681 timer_start(t, LAN_DISCOVERY_INTERVAL);
682 return 0;
683}
684
685/* run this at startup */
686int initMessenger(void)
687{
688 timer_init();
689 new_keys();
690 m_set_statusmessage((uint8_t*)"Online", sizeof("Online"));
691 initNetCrypto();
692 IP ip;
693 ip.i = 0;
694
695 if(init_networking(ip,PORT) == -1)
696 return -1;
697
698 DHT_init();
699 LosslessUDP_init();
700 friendreq_init();
701 LANdiscovery_init();
702
703 timer_single(&LANdiscovery_timercallback, 0, LAN_DISCOVERY_INTERVAL);
704
705 return 0;
706}
707
708/* the main loop that needs to be run at least 200 times per second. */
709void doMessenger(Messenger *m)
710{
711 networking_poll();
712<<<<<<< HEAD
713 timer_poll();
714
715 doDHT();
716 doLossless_UDP();
717 doNetCrypto();
718 doInbound();
719 doFriends();
720=======
721
722 doDHT();
723 doLossless_UDP();
724 doNetCrypto();
725 doInbound(m);
726 doFriends(m);
727 LANdiscovery(m);
728>>>>>>> upstream/master
729}
730
731/* returns the size of the messenger data (for saving) */
732uint32_t Messenger_size(Messenger *m)
733{
734 return crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES
735 + sizeof(uint32_t) + DHT_size() + sizeof(uint32_t) + sizeof(Friend) * m->numfriends;
736}
737
738/* save the messenger in data of size Messenger_size() */
739void Messenger_save(Messenger *m, uint8_t *data)
740{
741 save_keys(data);
742 data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES;
743 uint32_t size = DHT_size();
744 memcpy(data, &size, sizeof(size));
745 data += sizeof(size);
746 DHT_save(data);
747 data += size;
748 size = sizeof(Friend) * m->numfriends;
749 memcpy(data, &size, sizeof(size));
750 data += sizeof(size);
751 memcpy(data, m->friendlist, sizeof(Friend) * m->numfriends);
752}
753
754/* load the messenger from data of size length. */
755int Messenger_load(Messenger *m, uint8_t * data, uint32_t length)
756{
757 if (length == ~0)
758 return -1;
759 if (length < crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t) * 2)
760 return -1;
761 length -= crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t) * 2;
762 load_keys(data);
763 data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES;
764 uint32_t size;
765 memcpy(&size, data, sizeof(size));
766 data += sizeof(size);
767
768 if (length < size)
769 return -1;
770 length -= size;
771 if (DHT_load(data, size) == -1)
772 return -1;
773 data += size;
774 memcpy(&size, data, sizeof(size));
775 data += sizeof(size);
776 if (length != size || length % sizeof(Friend) != 0)
777 return -1;
778
779 Friend * temp = malloc(size);
780 memcpy(temp, data, size);
781
782 uint16_t num = size / sizeof(Friend);
783
784 uint32_t i;
785 for (i = 0; i < num; ++i) {
786 if(temp[i].status != 0) {
787 int fnum = m_addfriend_norequest(m, temp[i].client_id);
788 setfriendname(m, fnum, temp[i].name);
789 /* set_friend_statusmessage(fnum, temp[i].statusmessage, temp[i].statusmessage_length); */
790 }
791 }
792 free(temp);
793 return 0;
794}
795