diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/Messenger.c | 147 | ||||
-rw-r--r-- | core/Messenger.h | 35 |
2 files changed, 158 insertions, 24 deletions
diff --git a/core/Messenger.c b/core/Messenger.c index 85b2ac5a..a14be9d0 100644 --- a/core/Messenger.c +++ b/core/Messenger.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* Messenger.c | 1 | /* Messenger.c |
2 | * | 2 | * |
3 | * An implementation of a simple text chat only messenger on the tox network core. | 3 | * An implementation of a simple text chat only messenger on the tox network core. |
4 | * | 4 | * |
5 | 5 | ||
6 | Copyright (C) 2013 Tox project All Rights Reserved. | 6 | Copyright (C) 2013 Tox project All Rights Reserved. |
7 | 7 | ||
@@ -23,8 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "Messenger.h" | 25 | #include "Messenger.h" |
26 | 26 | #define MIN(a,b) (((a)<(b))?(a):(b)) | |
27 | #define MAX_NAME_LENGTH 128 | ||
28 | 27 | ||
29 | typedef struct | 28 | typedef struct |
30 | { | 29 | { |
@@ -35,6 +34,9 @@ typedef struct | |||
35 | uint8_t info[MAX_DATA_SIZE]; //the data that is sent during the friend requests we do | 34 | uint8_t info[MAX_DATA_SIZE]; //the data that is sent during the friend requests we do |
36 | uint8_t name[MAX_NAME_LENGTH]; | 35 | uint8_t name[MAX_NAME_LENGTH]; |
37 | uint8_t name_sent;//0 if we didn't send our name to this friend 1 if we have. | 36 | uint8_t name_sent;//0 if we didn't send our name to this friend 1 if we have. |
37 | uint8_t *userstatus; | ||
38 | uint16_t userstatus_length; | ||
39 | uint8_t userstatus_sent; | ||
38 | uint16_t info_size; //length of the info | 40 | uint16_t info_size; //length of the info |
39 | }Friend; | 41 | }Friend; |
40 | 42 | ||
@@ -43,6 +45,8 @@ typedef struct | |||
43 | uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; | 45 | uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; |
44 | 46 | ||
45 | static uint8_t self_name[MAX_NAME_LENGTH]; | 47 | static uint8_t self_name[MAX_NAME_LENGTH]; |
48 | static uint8_t *self_userstatus; | ||
49 | static uint16_t self_userstatus_len; | ||
46 | 50 | ||
47 | #define MAX_NUM_FRIENDS 256 | 51 | #define MAX_NUM_FRIENDS 256 |
48 | 52 | ||
@@ -102,7 +106,7 @@ int getclient_id(int friend_id, uint8_t * client_id) | |||
102 | //return -1 if failure. | 106 | //return -1 if failure. |
103 | int m_addfriend(uint8_t * client_id, uint8_t * data, uint16_t length) | 107 | int m_addfriend(uint8_t * client_id, uint8_t * data, uint16_t length) |
104 | { | 108 | { |
105 | if(length == 0 || length >= | 109 | if(length == 0 || length >= |
106 | (MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES)) | 110 | (MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES)) |
107 | { | 111 | { |
108 | return -1; | 112 | return -1; |
@@ -125,7 +129,8 @@ int m_addfriend(uint8_t * client_id, uint8_t * data, uint16_t length) | |||
125 | friendlist[i].crypt_connection_id = -1; | 129 | friendlist[i].crypt_connection_id = -1; |
126 | friendlist[i].friend_request_id = -1; | 130 | friendlist[i].friend_request_id = -1; |
127 | memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE); | 131 | memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE); |
128 | 132 | friendlist[i].userstatus = calloc(1, 1); | |
133 | friendlist[i].userstatus_length = 1; | ||
129 | memcpy(friendlist[i].info, data, length); | 134 | memcpy(friendlist[i].info, data, length); |
130 | friendlist[i].info_size = length; | 135 | friendlist[i].info_size = length; |
131 | 136 | ||
@@ -152,6 +157,8 @@ int m_addfriend_norequest(uint8_t * client_id) | |||
152 | friendlist[i].crypt_connection_id = -1; | 157 | friendlist[i].crypt_connection_id = -1; |
153 | friendlist[i].friend_request_id = -1; | 158 | friendlist[i].friend_request_id = -1; |
154 | memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE); | 159 | memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE); |
160 | friendlist[i].userstatus = calloc(1, 1); | ||
161 | friendlist[i].userstatus_length = 1; | ||
155 | numfriends++; | 162 | numfriends++; |
156 | return i; | 163 | return i; |
157 | } | 164 | } |
@@ -171,6 +178,7 @@ int m_delfriend(int friendnumber) | |||
171 | 178 | ||
172 | DHT_delfriend(friendlist[friendnumber].client_id); | 179 | DHT_delfriend(friendlist[friendnumber].client_id); |
173 | crypto_kill(friendlist[friendnumber].crypt_connection_id); | 180 | crypto_kill(friendlist[friendnumber].crypt_connection_id); |
181 | free(friendlist[friendnumber].userstatus); | ||
174 | memset(&friendlist[friendnumber], 0, sizeof(Friend)); | 182 | memset(&friendlist[friendnumber], 0, sizeof(Friend)); |
175 | uint32_t i; | 183 | uint32_t i; |
176 | for(i = numfriends; i != 0; i--) | 184 | for(i = numfriends; i != 0; i--) |
@@ -212,7 +220,7 @@ int m_sendmessage(int friendnumber, uint8_t * message, uint32_t length) | |||
212 | if(length >= MAX_DATA_SIZE || friendlist[friendnumber].status != 4) | 220 | if(length >= MAX_DATA_SIZE || friendlist[friendnumber].status != 4) |
213 | //this does not mean the maximum message length is MAX_DATA_SIZE - 1, it is actually 17 bytes less. | 221 | //this does not mean the maximum message length is MAX_DATA_SIZE - 1, it is actually 17 bytes less. |
214 | { | 222 | { |
215 | return 0; | 223 | return 0; |
216 | } | 224 | } |
217 | uint8_t temp[MAX_DATA_SIZE]; | 225 | uint8_t temp[MAX_DATA_SIZE]; |
218 | temp[0] = 64; | 226 | temp[0] = 64; |
@@ -278,6 +286,72 @@ int getname(int friendnumber, uint8_t * name) | |||
278 | return 0; | 286 | return 0; |
279 | } | 287 | } |
280 | 288 | ||
289 | int m_set_userstatus(uint8_t *status, uint16_t length) | ||
290 | { | ||
291 | if(length > MAX_USERSTATUS_LENGTH) | ||
292 | { | ||
293 | return -1; | ||
294 | } | ||
295 | uint8_t *newstatus = calloc(length, 1); | ||
296 | memcpy(newstatus, status, length); | ||
297 | free(self_userstatus); | ||
298 | self_userstatus = newstatus; | ||
299 | self_userstatus_len = length; | ||
300 | |||
301 | uint32_t i; | ||
302 | for(i = 0; i < numfriends; i++) | ||
303 | { | ||
304 | friendlist[i].userstatus_sent = 0; | ||
305 | } | ||
306 | return 0; | ||
307 | } | ||
308 | |||
309 | // return the size of friendnumber's user status | ||
310 | // guaranteed to be at most MAX_USERSTATUS_LENGTH | ||
311 | int m_get_userstatus_size(int friendnumber) | ||
312 | { | ||
313 | if(friendnumber >= numfriends || friendnumber < 0) | ||
314 | { | ||
315 | return -1; | ||
316 | } | ||
317 | return friendlist[friendnumber].userstatus_length; | ||
318 | } | ||
319 | |||
320 | // copy the user status of friendnumber into buf, truncating if needed to maxlen | ||
321 | // bytes, use m_get_userstatus_size to find out how much you need to allocate | ||
322 | int m_copy_userstatus(int friendnumber, uint8_t * buf, uint32_t maxlen) | ||
323 | { | ||
324 | if(friendnumber >= numfriends || friendnumber < 0) | ||
325 | { | ||
326 | return -1; | ||
327 | } | ||
328 | memset(buf, 0, 1); | ||
329 | memcpy(buf, friendlist[friendnumber].userstatus, MIN(maxlen, MAX_USERSTATUS_LENGTH) - 1); | ||
330 | return 0; | ||
331 | } | ||
332 | |||
333 | static int send_userstatus(int friendnumber, uint8_t * status, uint16_t length) | ||
334 | { | ||
335 | uint8_t *thepacket = malloc(length + 1); | ||
336 | memcpy(thepacket + 1, status, length); | ||
337 | thepacket[0] = 70; | ||
338 | return write_cryptpacket(friendlist[friendnumber].crypt_connection_id, thepacket, length + 1); | ||
339 | } | ||
340 | |||
341 | static int set_friend_userstatus(int friendnumber, uint8_t * status, uint16_t length) | ||
342 | { | ||
343 | if(friendnumber >= numfriends || friendnumber < 0) | ||
344 | { | ||
345 | return -1; | ||
346 | } | ||
347 | uint8_t *newstatus = calloc(length, 1); | ||
348 | memcpy(newstatus, status, length); | ||
349 | free(friendlist[friendnumber].userstatus); | ||
350 | friendlist[friendnumber].userstatus = newstatus; | ||
351 | friendlist[friendnumber].userstatus_length = length; | ||
352 | return 0; | ||
353 | } | ||
354 | |||
281 | static void (*friend_request)(uint8_t *, uint8_t *, uint16_t); | 355 | static void (*friend_request)(uint8_t *, uint8_t *, uint16_t); |
282 | 356 | ||
283 | //set the function that will be executed when a friend request is received. | 357 | //set the function that will be executed when a friend request is received. |
@@ -296,11 +370,24 @@ void m_callback_friendmessage(void (*function)(int, uint8_t *, uint16_t)) | |||
296 | } | 370 | } |
297 | 371 | ||
298 | 372 | ||
373 | static void (*friend_namechange)(int, uint8_t *, uint16_t); | ||
374 | void m_callback_namechange(void (*function)(int, uint8_t *, uint16_t)) | ||
375 | { | ||
376 | friend_namechange = function; | ||
377 | } | ||
378 | |||
379 | static void (*friend_statuschange)(int, uint8_t *, uint16_t); | ||
380 | void m_callback_userstatus(void (*function)(int, uint8_t *, uint16_t)) | ||
381 | { | ||
382 | friend_statuschange = function; | ||
383 | } | ||
384 | |||
299 | #define PORT 33445 | 385 | #define PORT 33445 |
300 | //run this at startup | 386 | //run this at startup |
301 | void initMessenger() | 387 | void initMessenger() |
302 | { | 388 | { |
303 | new_keys(); | 389 | new_keys(); |
390 | m_set_userstatus((uint8_t*)"Online", sizeof("Online")); | ||
304 | initNetCrypto(); | 391 | initNetCrypto(); |
305 | IP ip; | 392 | IP ip; |
306 | ip.i = 0; | 393 | ip.i = 0; |
@@ -321,7 +408,7 @@ static void doFriends() | |||
321 | //printf("\n%u %u %u\n", friendip.ip.i, request, friendlist[i].friend_request_id); | 408 | //printf("\n%u %u %u\n", friendip.ip.i, request, friendlist[i].friend_request_id); |
322 | if(friendip.ip.i > 1 && request == -1) | 409 | if(friendip.ip.i > 1 && request == -1) |
323 | { | 410 | { |
324 | friendlist[i].friend_request_id = send_friendrequest(friendlist[i].client_id, | 411 | friendlist[i].friend_request_id = send_friendrequest(friendlist[i].client_id, |
325 | friendip, friendlist[i].info, friendlist[i].info_size); | 412 | friendip, friendlist[i].info, friendlist[i].info_size); |
326 | friendlist[i].status = 2; | 413 | friendlist[i].status = 2; |
327 | } | 414 | } |
@@ -356,19 +443,37 @@ static void doFriends() | |||
356 | friendlist[i].name_sent = 1; | 443 | friendlist[i].name_sent = 1; |
357 | } | 444 | } |
358 | } | 445 | } |
446 | if(friendlist[i].userstatus_sent == 0) | ||
447 | { | ||
448 | if(send_userstatus(i, self_userstatus, self_userstatus_len)) | ||
449 | { | ||
450 | friendlist[i].userstatus_sent = 1; | ||
451 | } | ||
452 | } | ||
359 | len = read_cryptpacket(friendlist[i].crypt_connection_id, temp); | 453 | len = read_cryptpacket(friendlist[i].crypt_connection_id, temp); |
360 | if(len > 0) | 454 | if(len > 0) |
361 | { | 455 | { |
362 | if(temp[0] == 48 && len == MAX_NAME_LENGTH + 1)//Username | 456 | switch(temp[0]) { |
363 | { | 457 | case 48: { |
364 | memcpy(friendlist[i].name, temp + 1, MAX_NAME_LENGTH); | 458 | if (len != MAX_NAME_LENGTH + 1) break; |
365 | friendlist[i].name[MAX_NAME_LENGTH - 1] = 0;//make sure the NULL terminator is present. | 459 | friend_namechange(i, temp + 1, MAX_NAME_LENGTH); // todo: use the actual length |
366 | } | 460 | memcpy(friendlist[i].name, temp + 1, MAX_NAME_LENGTH); |
367 | else | 461 | friendlist[i].name[MAX_NAME_LENGTH - 1] = 0;//make sure the NULL terminator is present. |
368 | if(temp[0] == 64)//Chat message | 462 | break; |
369 | { | 463 | } |
370 | (*friend_message)(i, temp + 1, len - 1); | 464 | case 64: { |
371 | } | 465 | (*friend_message)(i, temp + 1, len - 1); |
466 | break; | ||
467 | } | ||
468 | case 70: { | ||
469 | uint8_t *status = calloc(MIN(len - 1, MAX_USERSTATUS_LENGTH), 1); | ||
470 | memcpy(status, temp + 1, MIN(len - 1, MAX_USERSTATUS_LENGTH)); | ||
471 | friend_statuschange(i, status, MIN(len - 1, MAX_USERSTATUS_LENGTH)); | ||
472 | set_friend_userstatus(i, status, MIN(len - 1, MAX_USERSTATUS_LENGTH)); | ||
473 | free(status); | ||
474 | break; | ||
475 | } | ||
476 | } | ||
372 | } | 477 | } |
373 | else | 478 | else |
374 | { | 479 | { |
@@ -410,7 +515,7 @@ static void doInbound() | |||
410 | if(friend_id != -1) | 515 | if(friend_id != -1) |
411 | { | 516 | { |
412 | crypto_kill(friendlist[friend_id].crypt_connection_id); | 517 | crypto_kill(friendlist[friend_id].crypt_connection_id); |
413 | friendlist[friend_id].crypt_connection_id = | 518 | friendlist[friend_id].crypt_connection_id = |
414 | accept_crypto_inbound(inconnection, public_key, secret_nonce, session_key); | 519 | accept_crypto_inbound(inconnection, public_key, secret_nonce, session_key); |
415 | 520 | ||
416 | friendlist[friend_id].status = 3; | 521 | friendlist[friend_id].status = 3; |
@@ -520,7 +625,9 @@ int Messenger_load(uint8_t * data, uint32_t length) | |||
520 | uint32_t i; | 625 | uint32_t i; |
521 | for(i = 0; i < num; i++) | 626 | for(i = 0; i < num; i++) |
522 | { | 627 | { |
523 | setfriendname(m_addfriend_norequest(temp[i].client_id), temp[i].name); | 628 | int fnum = m_addfriend_norequest(temp[i].client_id); |
629 | setfriendname(fnum, temp[i].name); | ||
630 | set_friend_userstatus(fnum, temp[i].userstatus, temp[i].userstatus_length); | ||
524 | } | 631 | } |
525 | free(temp); | 632 | free(temp); |
526 | return 0; | 633 | return 0; |
diff --git a/core/Messenger.h b/core/Messenger.h index 0b8aa7aa..c89d0f52 100644 --- a/core/Messenger.h +++ b/core/Messenger.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* Messenger.h | 1 | /* Messenger.h |
2 | * | 2 | * |
3 | * An implementation of a simple text chat only messenger on the tox network core. | 3 | * An implementation of a simple text chat only messenger on the tox network core. |
4 | * | 4 | * |
5 | * NOTE: All the text in the messages must be encoded using UTF-8 | 5 | * NOTE: All the text in the messages must be encoded using UTF-8 |
6 | 6 | ||
7 | Copyright (C) 2013 Tox project All Rights Reserved. | 7 | Copyright (C) 2013 Tox project All Rights Reserved. |
@@ -24,12 +24,16 @@ | |||
24 | */ | 24 | */ |
25 | 25 | ||
26 | 26 | ||
27 | #ifndef MESSENGER_H | 27 | #ifndef MESSENGER_H |
28 | #define MESSENGER_H | 28 | #define MESSENGER_H |
29 | 29 | ||
30 | #include "net_crypto.h" | 30 | #include "net_crypto.h" |
31 | #include "DHT.h" | 31 | #include "DHT.h" |
32 | 32 | ||
33 | #define MAX_NAME_LENGTH 128 | ||
34 | #define MAX_USERSTATUS_LENGTH 128 | ||
35 | // don't assume MAX_USERSTATUS_LENGTH will stay at 128, it may be increased | ||
36 | // to an absurdly large number later | ||
33 | 37 | ||
34 | //add a friend | 38 | //add a friend |
35 | //set the data that will be sent along with friend request | 39 | //set the data that will be sent along with friend request |
@@ -85,6 +89,20 @@ int setname(uint8_t * name, uint16_t length); | |||
85 | //return -1 if failure | 89 | //return -1 if failure |
86 | int getname(int friendnumber, uint8_t * name); | 90 | int getname(int friendnumber, uint8_t * name); |
87 | 91 | ||
92 | // set our user status | ||
93 | // you are responsible for freeing status after | ||
94 | // returns 0 on success, -1 on failure | ||
95 | int m_set_userstatus(uint8_t *status, uint16_t length); | ||
96 | |||
97 | // return the length of friendnumber's user status, | ||
98 | // including null | ||
99 | // pass it into malloc | ||
100 | int m_get_userstatus_size(int friendnumber); | ||
101 | |||
102 | // copy friendnumber's userstatus into buf, truncating if size is over maxlen | ||
103 | // get the size you need to allocate from m_get_userstatus_size | ||
104 | int m_copy_userstatus(int friendnumber, uint8_t * buf, uint32_t maxlen); | ||
105 | |||
88 | //set the function that will be executed when a friend request is received. | 106 | //set the function that will be executed when a friend request is received. |
89 | //function format is function(uint8_t * public_key, uint8_t * data, uint16_t length) | 107 | //function format is function(uint8_t * public_key, uint8_t * data, uint16_t length) |
90 | void m_callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t)); | 108 | void m_callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t)); |
@@ -94,6 +112,15 @@ void m_callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t)); | |||
94 | //function format is: function(int friendnumber, uint8_t * message, uint32_t length) | 112 | //function format is: function(int friendnumber, uint8_t * message, uint32_t length) |
95 | void m_callback_friendmessage(void (*function)(int, uint8_t *, uint16_t)); | 113 | void m_callback_friendmessage(void (*function)(int, uint8_t *, uint16_t)); |
96 | 114 | ||
115 | // set the callback for name changes | ||
116 | // function(int friendnumber, uint8_t *newname, uint16_t length) | ||
117 | // you are not responsible for freeing newname | ||
118 | void m_callback_namechange(void (*function)(int, uint8_t *, uint16_t)); | ||
119 | |||
120 | // set the callback for user status changes | ||
121 | // function(int friendnumber, uint8_t *newstatus, uint16_t length) | ||
122 | // you are not responsible for freeing newstatus | ||
123 | void m_callback_userstatus(void (*function)(int, uint8_t *, uint16_t)); | ||
97 | 124 | ||
98 | //run this at startup | 125 | //run this at startup |
99 | void initMessenger(); | 126 | void initMessenger(); |