summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/Messenger.c147
-rw-r--r--core/Messenger.h35
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
29typedef struct 28typedef 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
43uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; 45uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
44 46
45static uint8_t self_name[MAX_NAME_LENGTH]; 47static uint8_t self_name[MAX_NAME_LENGTH];
48static uint8_t *self_userstatus;
49static 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.
103int m_addfriend(uint8_t * client_id, uint8_t * data, uint16_t length) 107int 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
289int 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
311int 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
322int 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
333static 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
341static 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
281static void (*friend_request)(uint8_t *, uint8_t *, uint16_t); 355static 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
373static void (*friend_namechange)(int, uint8_t *, uint16_t);
374void m_callback_namechange(void (*function)(int, uint8_t *, uint16_t))
375{
376 friend_namechange = function;
377}
378
379static void (*friend_statuschange)(int, uint8_t *, uint16_t);
380void 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
301void initMessenger() 387void 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
86int getname(int friendnumber, uint8_t * name); 90int 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
95int 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
100int 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
104int 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)
90void m_callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t)); 108void 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)
95void m_callback_friendmessage(void (*function)(int, uint8_t *, uint16_t)); 113void 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
118void 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
123void m_callback_userstatus(void (*function)(int, uint8_t *, uint16_t));
97 124
98//run this at startup 125//run this at startup
99void initMessenger(); 126void initMessenger();