summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/Messenger.c147
-rw-r--r--core/Messenger.h35
-rw-r--r--docs/Messenger_Protocol.txt6
-rw-r--r--testing/nTox.c51
4 files changed, 209 insertions, 30 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();
diff --git a/docs/Messenger_Protocol.txt b/docs/Messenger_Protocol.txt
index 377a6016..78f756ae 100644
--- a/docs/Messenger_Protocol.txt
+++ b/docs/Messenger_Protocol.txt
@@ -2,8 +2,8 @@ Protocol for messages, data, etc..
2 2
3Streaming audio/video will not use this protocol as they can absorb some data loss. 3Streaming audio/video will not use this protocol as they can absorb some data loss.
4 4
5The protocol itself will run on top of the encryption which means it should be 5The protocol itself will run on top of the encryption which means it should be
6impossible for someone to know what type of data is being transmitted.(Well they 6impossible for someone to know what type of data is being transmitted.(Well they
7could just analyze how much data is being transmitted for a pretty good guess) 7could just analyze how much data is being transmitted for a pretty good guess)
8 8
9Because it runs on the encryption which itself runs on our Lossless UDP protocol 9Because it runs on the encryption which itself runs on our Lossless UDP protocol
@@ -29,4 +29,4 @@ ids 0 to 16 are reserved.
29 29
3064 Chat message 3064 Chat message
316? File transmission. 316? File transmission.
32 3270 Status change
diff --git a/testing/nTox.c b/testing/nTox.c
index d3f6e6a8..ac82d021 100644
--- a/testing/nTox.c
+++ b/testing/nTox.c
@@ -72,6 +72,30 @@ void line_eval(char lines[HISTORY][STRING_LENGTH], char *line)
72 } 72 }
73 int num = atoi(numstring); 73 int num = atoi(numstring);
74 m_sendmessage(num, (uint8_t*) message, sizeof(message)); 74 m_sendmessage(num, (uint8_t*) message, sizeof(message));
75 } else if (line[1] == 'n') {
76 uint8_t name[MAX_NAME_LENGTH];
77 int i = 0;
78 for (i=3; i<strlen(line); i++) {
79 if (line[i] == 0 || line[i] == '\n') break;
80 name[i - 3] = line[i];
81 }
82 name[i - 3] = 0;
83 setname(name, i);
84 char numstring[100];
85 sprintf(numstring, "Changed nick to: %s", (char*)name);
86 new_lines(numstring);
87 } else if (line[1] == 's') {
88 uint8_t status[MAX_USERSTATUS_LENGTH];
89 int i = 0;
90 for (i=3; i<strlen(line); i++) {
91 if (line[i] == 0 || line[i] == '\n') break;
92 status[i - 3] = line[i];
93 }
94 status[i - 3] = 0;
95 m_set_userstatus(status, strlen((char*)status));
96 char numstring[100];
97 sprintf(numstring, "Changed status to: %s", (char*)status);
98 new_lines(numstring);
75 } else if (line[1] == 'q') { //exit 99 } else if (line[1] == 'q') { //exit
76 endwin(); 100 endwin();
77 exit(EXIT_SUCCESS); 101 exit(EXIT_SUCCESS);
@@ -81,7 +105,7 @@ void line_eval(char lines[HISTORY][STRING_LENGTH], char *line)
81 } 105 }
82} 106}
83 107
84void wrap(char output[STRING_LENGTH], char input[STRING_LENGTH], int line_width) 108void wrap(char output[STRING_LENGTH], char input[STRING_LENGTH], int line_width)
85{ 109{
86 int i = 0; 110 int i = 0;
87 strcpy(output,input); 111 strcpy(output,input);
@@ -95,7 +119,7 @@ void wrap(char output[STRING_LENGTH], char input[STRING_LENGTH], int line_width)
95 } 119 }
96} 120}
97 121
98int count_lines(char *string) 122int count_lines(char *string)
99{ 123{
100 int len = strlen(string); 124 int len = strlen(string);
101 int i; 125 int i;
@@ -158,8 +182,27 @@ void print_request(uint8_t * public_key, uint8_t * data, uint16_t length)
158} 182}
159void print_message(int friendnumber, uint8_t * string, uint16_t length) 183void print_message(int friendnumber, uint8_t * string, uint16_t length)
160{ 184{
185 char *name = malloc(MAX_NAME_LENGTH);
186 getname(friendnumber, (uint8_t*)name);
187 char msg[100+length+strlen(name)+1];
188 sprintf(msg, "[%d] <%s> %s", friendnumber, name, string);
189 free(name);
190 new_lines(msg);
191}
192void print_nickchange(int friendnumber, uint8_t *string, uint16_t length) {
193 char *name = malloc(MAX_NAME_LENGTH);
194 getname(friendnumber, (uint8_t*)name);
161 char msg[100+length]; 195 char msg[100+length];
162 sprintf(msg, "Message [%d]: %s", friendnumber, string); 196 sprintf(msg, "[%d] %s is now known as %s.", friendnumber, name, string);
197 free(name);
198 new_lines(msg);
199}
200void print_statuschange(int friendnumber, uint8_t *string, uint16_t length) {
201 char *name = malloc(MAX_NAME_LENGTH);
202 getname(friendnumber, (uint8_t*)name);
203 char msg[100+length+strlen(name)+1];
204 sprintf(msg, "[%d] %s's status changed to %s.", friendnumber, name, string);
205 free(name);
163 new_lines(msg); 206 new_lines(msg);
164} 207}
165int main(int argc, char *argv[]) 208int main(int argc, char *argv[])
@@ -173,6 +216,8 @@ int main(int argc, char *argv[])
173 initMessenger(); 216 initMessenger();
174 m_callback_friendrequest(print_request); 217 m_callback_friendrequest(print_request);
175 m_callback_friendmessage(print_message); 218 m_callback_friendmessage(print_message);
219 m_callback_namechange(print_nickchange);
220 m_callback_userstatus(print_statuschange);
176 char idstring0[200]; 221 char idstring0[200];
177 char idstring1[32][5]; 222 char idstring1[32][5];
178 char idstring2[32][5]; 223 char idstring2[32][5];