diff options
-rw-r--r-- | core/Messenger.c.orig | 795 |
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 | |||
29 | static void set_friend_status(Messenger *m, int friendnumber, uint8_t status); | ||
30 | static 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 */ | ||
38 | int 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 */ | ||
49 | int 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. */ | ||
66 | int 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 | */ | ||
91 | int 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 | |||
130 | int 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 */ | ||
161 | int 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 */ | ||
187 | int 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 */ | ||
197 | uint32_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 | |||
211 | uint32_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 */ | ||
225 | int 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*/ | ||
232 | static 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 */ | ||
242 | static 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 */ | ||
256 | int 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 */ | ||
272 | uint16_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 */ | ||
283 | int 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 | |||
291 | int 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 | |||
304 | int 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 */ | ||
318 | int 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 */ | ||
327 | int 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 | |||
336 | int 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 | |||
343 | USERSTATUS 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 | |||
354 | USERSTATUS m_get_self_userstatus(Messenger *m) | ||
355 | { | ||
356 | return m->userstatus; | ||
357 | } | ||
358 | |||
359 | static 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 | |||
364 | static 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 | |||
370 | static 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 | |||
382 | static 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. */ | ||
388 | void 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); | ||
398 | static uint8_t friend_request_isset = 0; */ | ||
399 | /* set the function that will be executed when a friend request is received. */ | ||
400 | void 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. */ | ||
406 | void 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 | |||
413 | void 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 | |||
420 | void 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 | |||
427 | void 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 | |||
434 | void 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 | |||
441 | void 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 | |||
448 | void 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 | |||
455 | static 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 | |||
467 | void 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 | |||
473 | int 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 */ | ||
489 | Messenger * 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 */ | ||
513 | void 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. | ||
520 | void 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 | |||
650 | void 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 | ||
675 | static int LANdiscovery_timercallback(timer* t, void* ignore) | ||
676 | ======= | ||
677 | void 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 */ | ||
686 | int 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. */ | ||
709 | void 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) */ | ||
732 | uint32_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() */ | ||
739 | void 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. */ | ||
755 | int 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 | |||