summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorcharmlesscoin <charmlesscoin@gmail.com>2013-08-05 23:51:32 -0400
committercharmlesscoin <charmlesscoin@gmail.com>2013-08-05 23:51:32 -0400
commit95a3f69580749b8fcabf92cc2ace757d61fa34de (patch)
treec2feed62f06e5fea232b293992cff9cce500cc27 /core
parentd92550506604fcff8164a6dce221f0e4be6adda6 (diff)
parentb4664f3f29f48723cf6ba9ba7119710ce0a88a40 (diff)
Merge branch 'master' of git://github.com/irungentoo/ProjectTox-Core
Diffstat (limited to 'core')
-rw-r--r--core/CMakeLists.txt4
-rw-r--r--core/DHT.c63
-rw-r--r--core/Messenger.c88
-rw-r--r--core/Messenger.h38
-rw-r--r--core/friend_requests.c2
-rw-r--r--core/ping.c103
-rw-r--r--core/ping.h13
-rw-r--r--core/util.c34
-rw-r--r--core/util.h10
9 files changed, 271 insertions, 84 deletions
diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt
index eacb772c..55a41912 100644
--- a/core/CMakeLists.txt
+++ b/core/CMakeLists.txt
@@ -8,7 +8,9 @@ set(core_sources
8 net_crypto.c 8 net_crypto.c
9 friend_requests.c 9 friend_requests.c
10 LAN_discovery.c 10 LAN_discovery.c
11 Messenger.c) 11 Messenger.c
12 util.c
13 ping.c)
12 14
13if(SHARED_TOXCORE) 15if(SHARED_TOXCORE)
14 add_library(toxcore SHARED ${core_sources}) 16 add_library(toxcore SHARED ${core_sources})
diff --git a/core/DHT.c b/core/DHT.c
index 6375b86b..f0b32df5 100644
--- a/core/DHT.c
+++ b/core/DHT.c
@@ -24,6 +24,7 @@
24/*----------------------------------------------------------------------------------*/ 24/*----------------------------------------------------------------------------------*/
25 25
26#include "DHT.h" 26#include "DHT.h"
27#include "ping.h"
27 28
28/* maximum number of clients stored per friend. */ 29/* maximum number of clients stored per friend. */
29#define MAX_FRIEND_CLIENTS 8 30#define MAX_FRIEND_CLIENTS 8
@@ -109,7 +110,6 @@ uint8_t self_secret_key[crypto_box_SECRETKEYBYTES];
109static Client_data close_clientlist[LCLIENT_LIST]; 110static Client_data close_clientlist[LCLIENT_LIST];
110static Friend * friends_list; 111static Friend * friends_list;
111static uint16_t num_friends; 112static uint16_t num_friends;
112static Pinged pings[LPING_ARRAY];
113static Pinged send_nodes[LSEND_NODES_ARRAY]; 113static Pinged send_nodes[LSEND_NODES_ARRAY];
114 114
115/*----------------------------------------------------------------------------------*/ 115/*----------------------------------------------------------------------------------*/
@@ -426,35 +426,6 @@ static void returnedip_ports(IP_Port ip_port, uint8_t * client_id, uint8_t * nod
426 } 426 }
427} 427}
428 428
429/* check if we are currently pinging an ip_port and/or a ping_id variables with
430 * values of zero will not be checked. If we are already, return 1 else return 0
431 *
432 * TODO: optimize this
433 */
434static int is_pinging(IP_Port ip_port, uint64_t ping_id)
435{
436 uint32_t i;
437 uint8_t pinging;
438 uint64_t temp_time = unix_time();
439
440 for (i = 0; i < LPING_ARRAY; ++i ) {
441 if (!is_timeout(temp_time, pings[i].timestamp, PING_TIMEOUT)) {
442 pinging = 0;
443
444 if (ip_port.ip.i != 0 && ipport_equal(pings[i].ip_port, ip_port))
445 ++pinging;
446
447 if (ping_id != 0 && pings[i].ping_id == ping_id)
448 ++pinging;
449
450 if (pinging == ((ping_id != 0) + (ip_port.ip.i != 0)))
451 return 1;
452 }
453 }
454
455 return 0;
456}
457
458/* Same as last function but for get_node requests. */ 429/* Same as last function but for get_node requests. */
459static int is_gettingnodes(IP_Port ip_port, uint64_t ping_id) 430static int is_gettingnodes(IP_Port ip_port, uint64_t ping_id)
460{ 431{
@@ -480,32 +451,6 @@ static int is_gettingnodes(IP_Port ip_port, uint64_t ping_id)
480 return 0; 451 return 0;
481} 452}
482 453
483/* Add a new ping request to the list of ping requests
484 * returns the ping_id to put in the ping request
485 * returns 0 if problem.
486 *
487 * TODO: optimize this
488 */
489static uint64_t add_pinging(IP_Port ip_port)
490{
491 uint32_t i, j;
492 uint64_t ping_id = ((uint64_t)random_int() << 32) + random_int();
493 uint64_t temp_time = unix_time();
494
495 for(i = 0; i < PING_TIMEOUT; ++i ) {
496 for(j = 0; j < LPING_ARRAY; ++j ) {
497 if(is_timeout(temp_time, pings[j].timestamp, PING_TIMEOUT - i)) {
498 pings[j].timestamp = temp_time;
499 pings[j].ip_port = ip_port;
500 pings[j].ping_id = ping_id;
501 return ping_id;
502 }
503 }
504 }
505
506 return 0;
507}
508
509/* Same but for get node requests */ 454/* Same but for get node requests */
510static uint64_t add_gettingnodes(IP_Port ip_port) 455static uint64_t add_gettingnodes(IP_Port ip_port)
511{ 456{
@@ -536,7 +481,7 @@ static int pingreq(IP_Port ip_port, uint8_t * public_key)
536 if(id_equal(public_key, self_public_key) || is_pinging(ip_port, 0)) 481 if(id_equal(public_key, self_public_key) || is_pinging(ip_port, 0))
537 return 1; 482 return 1;
538 483
539 uint64_t ping_id = add_pinging(ip_port); 484 uint64_t ping_id = add_ping(ip_port);
540 if(ping_id == 0) 485 if(ping_id == 0)
541 return 1; 486 return 1;
542 487
@@ -1108,7 +1053,7 @@ static int send_NATping(uint8_t * public_key, uint64_t ping_id, uint8_t type)
1108static int handle_NATping(uint8_t * packet, uint32_t length, IP_Port source) 1053static int handle_NATping(uint8_t * packet, uint32_t length, IP_Port source)
1109{ 1054{
1110 if (length < crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + ENCRYPTION_PADDING 1055 if (length < crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + ENCRYPTION_PADDING
1111 && length > MAX_DATA_SIZE + ENCRYPTION_PADDING) 1056 || length > MAX_DATA_SIZE + ENCRYPTION_PADDING)
1112 return 1; 1057 return 1;
1113 1058
1114 /* check if request is for us. */ 1059 /* check if request is for us. */
@@ -1301,6 +1246,8 @@ void DHT_save(uint8_t * data)
1301 */ 1246 */
1302int DHT_load(uint8_t * data, uint32_t size) 1247int DHT_load(uint8_t * data, uint32_t size)
1303{ 1248{
1249 init_ping();
1250
1304 if(size < sizeof(close_clientlist)) 1251 if(size < sizeof(close_clientlist))
1305 return -1; 1252 return -1;
1306 1253
diff --git a/core/Messenger.c b/core/Messenger.c
index 57d485bb..d8bf3413 100644
--- a/core/Messenger.c
+++ b/core/Messenger.c
@@ -35,6 +35,7 @@ typedef struct {
35 uint8_t *userstatus; 35 uint8_t *userstatus;
36 uint16_t userstatus_length; 36 uint16_t userstatus_length;
37 uint8_t userstatus_sent; 37 uint8_t userstatus_sent;
38 USERSTATUS_KIND userstatus_kind;
38 uint16_t info_size; /* length of the info */ 39 uint16_t info_size; /* length of the info */
39} Friend; 40} Friend;
40 41
@@ -45,6 +46,7 @@ static uint16_t self_name_length;
45 46
46static uint8_t *self_userstatus; 47static uint8_t *self_userstatus;
47static uint16_t self_userstatus_len; 48static uint16_t self_userstatus_len;
49static USERSTATUS_KIND self_userstatus_kind;
48 50
49#define MAX_NUM_FRIENDS 256 51#define MAX_NUM_FRIENDS 256
50 52
@@ -98,12 +100,12 @@ int getclient_id(int friend_id, uint8_t *client_id)
98 * return FAERR_NOMESSAGE if no message (message length must be >= 1 byte) 100 * return FAERR_NOMESSAGE if no message (message length must be >= 1 byte)
99 * return FAERR_OWNKEY if user's own key 101 * return FAERR_OWNKEY if user's own key
100 * return FAERR_ALREADYSENT if friend request already sent or already a friend 102 * return FAERR_ALREADYSENT if friend request already sent or already a friend
101 * return FAERR_UNKNOWN for unknown error 103 * return FAERR_UNKNOWN for unknown error
102 */ 104 */
103int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length) 105int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length)
104{ 106{
105 if (length >= (MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES 107 if (length >= (MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES
106 - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES 108 - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES
107 + crypto_box_ZEROBYTES)) 109 + crypto_box_ZEROBYTES))
108 return FAERR_TOOLONG; 110 return FAERR_TOOLONG;
109 if (length < 1) 111 if (length < 1)
@@ -123,6 +125,7 @@ int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length)
123 memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE); 125 memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE);
124 friendlist[i].userstatus = calloc(1, 1); 126 friendlist[i].userstatus = calloc(1, 1);
125 friendlist[i].userstatus_length = 1; 127 friendlist[i].userstatus_length = 1;
128 friendlist[i].userstatus_kind = USERSTATUS_KIND_OFFLINE;
126 memcpy(friendlist[i].info, data, length); 129 memcpy(friendlist[i].info, data, length);
127 friendlist[i].info_size = length; 130 friendlist[i].info_size = length;
128 131
@@ -205,7 +208,7 @@ int m_sendmessage(int friendnumber, uint8_t *message, uint32_t length)
205 return write_cryptpacket(friendlist[friendnumber].crypt_connection_id, temp, length + 1); 208 return write_cryptpacket(friendlist[friendnumber].crypt_connection_id, temp, length + 1);
206} 209}
207 210
208/* send a name packet to friendnumber 211/* send a name packet to friendnumber
209 length is the length with the NULL terminator*/ 212 length is the length with the NULL terminator*/
210static int m_sendname(int friendnumber, uint8_t * name, uint16_t length) 213static int m_sendname(int friendnumber, uint8_t * name, uint16_t length)
211{ 214{
@@ -247,14 +250,14 @@ int setname(uint8_t * name, uint16_t length)
247} 250}
248 251
249/* get our nickname 252/* get our nickname
250 put it in name 253 put it in name
251 name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes. 254 name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes.
252 return the length of the name */ 255 return the length of the name */
253uint16_t getself_name(uint8_t *name) 256uint16_t getself_name(uint8_t *name)
254{ 257{
255 memcpy(name, self_name, self_name_length); 258 memcpy(name, self_name, self_name_length);
256 return self_name_length; 259 return self_name_length;
257} 260}
258 261
259/* get name of friendnumber 262/* get name of friendnumber
260 put it in name 263 put it in name
@@ -269,10 +272,13 @@ int getname(int friendnumber, uint8_t * name)
269 return 0; 272 return 0;
270} 273}
271 274
272int m_set_userstatus(uint8_t *status, uint16_t length) 275int m_set_userstatus(USERSTATUS_KIND kind, uint8_t *status, uint16_t length)
273{ 276{
274 if (length > MAX_USERSTATUS_LENGTH) 277 if (length > MAX_USERSTATUS_LENGTH)
275 return -1; 278 return -1;
279 if (kind != USERSTATUS_KIND_RETAIN) {
280 self_userstatus_kind = kind;
281 }
276 uint8_t *newstatus = calloc(length, 1); 282 uint8_t *newstatus = calloc(length, 1);
277 memcpy(newstatus, status, length); 283 memcpy(newstatus, status, length);
278 free(self_userstatus); 284 free(self_userstatus);
@@ -285,6 +291,20 @@ int m_set_userstatus(uint8_t *status, uint16_t length)
285 return 0; 291 return 0;
286} 292}
287 293
294int m_set_userstatus_kind(USERSTATUS_KIND kind) {
295 if (kind >= USERSTATUS_KIND_INVALID) {
296 return -1;
297 }
298 if (kind == USERSTATUS_KIND_RETAIN) {
299 return 0;
300 }
301 self_userstatus_kind = kind;
302 uint32_t i;
303 for (i = 0; i < numfriends; ++i)
304 friendlist[i].userstatus_sent = 0;
305 return 0;
306}
307
288/* return the size of friendnumber's user status 308/* return the size of friendnumber's user status
289 guaranteed to be at most MAX_USERSTATUS_LENGTH */ 309 guaranteed to be at most MAX_USERSTATUS_LENGTH */
290int m_get_userstatus_size(int friendnumber) 310int m_get_userstatus_size(int friendnumber)
@@ -305,11 +325,33 @@ int m_copy_userstatus(int friendnumber, uint8_t * buf, uint32_t maxlen)
305 return 0; 325 return 0;
306} 326}
307 327
328int m_copy_self_userstatus(uint8_t * buf, uint32_t maxlen)
329{
330 memset(buf, 0, maxlen);
331 memcpy(buf, self_userstatus, MIN(maxlen, MAX_USERSTATUS_LENGTH) - 1);
332 return 0;
333}
334
335USERSTATUS_KIND m_get_userstatus_kind(int friendnumber) {
336 if (friendnumber >= numfriends || friendnumber < 0)
337 return USERSTATUS_KIND_INVALID;
338 USERSTATUS_KIND uk = friendlist[friendnumber].userstatus_kind;
339 if (uk >= USERSTATUS_KIND_INVALID) {
340 uk = USERSTATUS_KIND_ONLINE;
341 }
342 return uk;
343}
344
345USERSTATUS_KIND m_get_self_userstatus_kind(void) {
346 return self_userstatus_kind;
347}
348
308static int send_userstatus(int friendnumber, uint8_t * status, uint16_t length) 349static int send_userstatus(int friendnumber, uint8_t * status, uint16_t length)
309{ 350{
310 uint8_t *thepacket = malloc(length + 1); 351 uint8_t *thepacket = malloc(length + 2);
311 memcpy(thepacket + 1, status, length); 352 memcpy(thepacket + 2, status, length);
312 thepacket[0] = PACKET_ID_USERSTATUS; 353 thepacket[0] = PACKET_ID_USERSTATUS;
354 thepacket[1] = self_userstatus_kind;
313 int written = write_cryptpacket(friendlist[friendnumber].crypt_connection_id, thepacket, length + 1); 355 int written = write_cryptpacket(friendlist[friendnumber].crypt_connection_id, thepacket, length + 1);
314 free(thepacket); 356 free(thepacket);
315 return written; 357 return written;
@@ -327,6 +369,11 @@ static int set_friend_userstatus(int friendnumber, uint8_t * status, uint16_t le
327 return 0; 369 return 0;
328} 370}
329 371
372static void set_friend_userstatus_kind(int friendnumber, USERSTATUS_KIND k)
373{
374 friendlist[friendnumber].userstatus_kind = k;
375}
376
330/* static void (*friend_request)(uint8_t *, uint8_t *, uint16_t); 377/* static void (*friend_request)(uint8_t *, uint8_t *, uint16_t);
331static uint8_t friend_request_isset = 0; */ 378static uint8_t friend_request_isset = 0; */
332/* set the function that will be executed when a friend request is received. */ 379/* set the function that will be executed when a friend request is received. */
@@ -353,9 +400,9 @@ void m_callback_namechange(void (*function)(int, uint8_t *, uint16_t))
353 friend_namechange_isset = 1; 400 friend_namechange_isset = 1;
354} 401}
355 402
356static void (*friend_statuschange)(int, uint8_t *, uint16_t); 403static void (*friend_statuschange)(int, USERSTATUS_KIND, uint8_t *, uint16_t);
357static uint8_t friend_statuschange_isset = 0; 404static uint8_t friend_statuschange_isset = 0;
358void m_callback_userstatus(void (*function)(int, uint8_t *, uint16_t)) 405void m_callback_userstatus(void (*function)(int, USERSTATUS_KIND, uint8_t *, uint16_t))
359{ 406{
360 friend_statuschange = function; 407 friend_statuschange = function;
361 friend_statuschange_isset = 1; 408 friend_statuschange_isset = 1;
@@ -366,7 +413,7 @@ void m_callback_userstatus(void (*function)(int, uint8_t *, uint16_t))
366int initMessenger(void) 413int initMessenger(void)
367{ 414{
368 new_keys(); 415 new_keys();
369 m_set_userstatus((uint8_t*)"Online", sizeof("Online")); 416 m_set_userstatus(USERSTATUS_KIND_ONLINE, (uint8_t*)"Online", sizeof("Online"));
370 initNetCrypto(); 417 initNetCrypto();
371 IP ip; 418 IP ip;
372 ip.i = 0; 419 ip.i = 0;
@@ -438,12 +485,17 @@ static void doFriends(void)
438 break; 485 break;
439 } 486 }
440 case PACKET_ID_USERSTATUS: { 487 case PACKET_ID_USERSTATUS: {
441 uint8_t *status = calloc(MIN(len - 1, MAX_USERSTATUS_LENGTH), 1); 488 if (len > 2) {
442 memcpy(status, temp + 1, MIN(len - 1, MAX_USERSTATUS_LENGTH)); 489 uint8_t *status = calloc(MIN(len - 2, MAX_USERSTATUS_LENGTH), 1);
443 if (friend_statuschange_isset) 490 memcpy(status, temp + 2, MIN(len - 2, MAX_USERSTATUS_LENGTH));
444 friend_statuschange(i, status, MIN(len - 1, MAX_USERSTATUS_LENGTH)); 491 if (friend_statuschange_isset)
445 set_friend_userstatus(i, status, MIN(len - 1, MAX_USERSTATUS_LENGTH)); 492 friend_statuschange(i, temp[1], status, MIN(len - 2, MAX_USERSTATUS_LENGTH));
446 free(status); 493 set_friend_userstatus(i, status, MIN(len - 2, MAX_USERSTATUS_LENGTH));
494 free(status);
495 } else if (friend_statuschange_isset) {
496 friend_statuschange(i, temp[1], friendlist[i].userstatus, friendlist[i].userstatus_length);
497 }
498 set_friend_userstatus_kind(i, temp[1]);
447 break; 499 break;
448 } 500 }
449 case PACKET_ID_MESSAGE: { 501 case PACKET_ID_MESSAGE: {
diff --git a/core/Messenger.h b/core/Messenger.h
index 20b38caa..8940aadd 100644
--- a/core/Messenger.h
+++ b/core/Messenger.h
@@ -60,6 +60,22 @@ extern "C" {
60/* don't assume MAX_USERSTATUS_LENGTH will stay at 128, it may be increased 60/* don't assume MAX_USERSTATUS_LENGTH will stay at 128, it may be increased
61 to an absurdly large number later */ 61 to an absurdly large number later */
62 62
63/* USERSTATUS_KIND
64 * Represents the different kinds of userstatus
65 * someone can have.
66 * More on this later... */
67
68typedef enum {
69 USERSTATUS_KIND_RETAIN = (uint8_t)0, /* This is a special value that must not be returned by
70 * m_get_userstatus_kind. You can pass it into m_set_userstatus
71 * to keep the current USERSTATUS_KIND. */
72 USERSTATUS_KIND_ONLINE, /* Recommended representation: Green. */
73 USERSTATUS_KIND_AWAY, /* Recommended representation: Orange, or yellow. */
74 USERSTATUS_KIND_BUSY, /* Recommended representation: Red. */
75 USERSTATUS_KIND_OFFLINE, /* Recommended representation: Grey, semi-transparent. */
76 USERSTATUS_KIND_INVALID,
77} USERSTATUS_KIND;
78
63/* 79/*
64 * add a friend 80 * add a friend
65 * set the data that will be sent along with friend request 81 * set the data that will be sent along with friend request
@@ -70,7 +86,7 @@ extern "C" {
70 * return -2 if no message (message length must be >= 1 byte) 86 * return -2 if no message (message length must be >= 1 byte)
71 * return -3 if user's own key 87 * return -3 if user's own key
72 * return -4 if friend request already sent or already a friend 88 * return -4 if friend request already sent or already a friend
73 * return -5 for unknown error 89 * return -5 for unknown error
74 */ 90 */
75int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length); 91int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length);
76 92
@@ -114,7 +130,7 @@ int m_sendmessage(int friendnumber, uint8_t *message, uint32_t length);
114int setname(uint8_t *name, uint16_t length); 130int setname(uint8_t *name, uint16_t length);
115 131
116/* get our nickname 132/* get our nickname
117 put it in name 133 put it in name
118 return the length of the name*/ 134 return the length of the name*/
119uint16_t getself_name(uint8_t *name); 135uint16_t getself_name(uint8_t *name);
120 136
@@ -128,7 +144,8 @@ int getname(int friendnumber, uint8_t *name);
128/* set our user status 144/* set our user status
129 you are responsible for freeing status after 145 you are responsible for freeing status after
130 returns 0 on success, -1 on failure */ 146 returns 0 on success, -1 on failure */
131int m_set_userstatus(uint8_t *status, uint16_t length); 147int m_set_userstatus(USERSTATUS_KIND kind, uint8_t *status, uint16_t length);
148int m_set_userstatus_kind(USERSTATUS_KIND kind);
132 149
133/* return the length of friendnumber's user status, 150/* return the length of friendnumber's user status,
134 including null 151 including null
@@ -136,8 +153,17 @@ int m_set_userstatus(uint8_t *status, uint16_t length);
136int m_get_userstatus_size(int friendnumber); 153int m_get_userstatus_size(int friendnumber);
137 154
138/* copy friendnumber's userstatus into buf, truncating if size is over maxlen 155/* copy friendnumber's userstatus into buf, truncating if size is over maxlen
139 get the size you need to allocate from m_get_userstatus_size */ 156 get the size you need to allocate from m_get_userstatus_size
157 The self variant will copy our own userstatus. */
140int m_copy_userstatus(int friendnumber, uint8_t *buf, uint32_t maxlen); 158int m_copy_userstatus(int friendnumber, uint8_t *buf, uint32_t maxlen);
159int m_copy_self_userstatus(uint8_t *buf, uint32_t maxlen);
160
161/* Return one of USERSTATUS_KIND values, except USERSTATUS_KIND_RETAIN.
162 * Values unknown to your application should be represented as USERSTATUS_KIND_ONLINE.
163 * As above, the self variant will return our own USERSTATUS_KIND.
164 * If friendnumber is invalid, this shall return USERSTATUS_KIND_INVALID. */
165USERSTATUS_KIND m_get_userstatus_kind(int friendnumber);
166USERSTATUS_KIND m_get_self_userstatus_kind(void);
141 167
142/* set the function that will be executed when a friend request is received. 168/* set the function that will be executed when a friend request is received.
143 function format is function(uint8_t * public_key, uint8_t * data, uint16_t length) */ 169 function format is function(uint8_t * public_key, uint8_t * data, uint16_t length) */
@@ -153,9 +179,9 @@ void m_callback_friendmessage(void (*function)(int, uint8_t *, uint16_t));
153void m_callback_namechange(void (*function)(int, uint8_t *, uint16_t)); 179void m_callback_namechange(void (*function)(int, uint8_t *, uint16_t));
154 180
155/* set the callback for user status changes 181/* set the callback for user status changes
156 function(int friendnumber, uint8_t *newstatus, uint16_t length) 182 function(int friendnumber, USERSTATUS_KIND kind, uint8_t *newstatus, uint16_t length)
157 you are not responsible for freeing newstatus */ 183 you are not responsible for freeing newstatus */
158void m_callback_userstatus(void (*function)(int, uint8_t *, uint16_t)); 184void m_callback_userstatus(void (*function)(int, USERSTATUS_KIND, uint8_t *, uint16_t));
159 185
160/* run this at startup 186/* run this at startup
161 returns 0 if no connection problems 187 returns 0 if no connection problems
diff --git a/core/friend_requests.c b/core/friend_requests.c
index f1ffb8d0..5550b662 100644
--- a/core/friend_requests.c
+++ b/core/friend_requests.c
@@ -104,7 +104,7 @@ static int request_recieved(uint8_t * client_id)
104int friendreq_handlepacket(uint8_t * packet, uint32_t length, IP_Port source) 104int friendreq_handlepacket(uint8_t * packet, uint32_t length, IP_Port source)
105{ 105{
106 if (packet[0] == 32) { 106 if (packet[0] == 32) {
107 if (length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING && 107 if (length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING ||
108 length > MAX_DATA_SIZE + ENCRYPTION_PADDING) 108 length > MAX_DATA_SIZE + ENCRYPTION_PADDING)
109 return 1; 109 return 1;
110 if (memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) {// check if request is for us. 110 if (memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) {// check if request is for us.
diff --git a/core/ping.c b/core/ping.c
new file mode 100644
index 00000000..ffabe221
--- /dev/null
+++ b/core/ping.c
@@ -0,0 +1,103 @@
1/*
2 * ping.c -- Buffered pinging using cyclic arrays.
3 *
4 * This file is donated to the Tox Project.
5 * Copyright 2013 plutooo
6 */
7
8#include <stdbool.h>
9#include <stdint.h>
10
11#include "network.h"
12#include "util.h"
13
14#define PING_NUM_MAX 256
15#define PING_TIMEOUT 5 // 5s
16
17typedef struct {
18 IP_Port ipp;
19 uint64_t id;
20 uint64_t timestamp;
21} pinged_t;
22
23static pinged_t pings[PING_NUM_MAX];
24static size_t num_pings;
25static size_t pos_pings;
26
27
28void init_ping()
29{
30 num_pings = 0;
31 pos_pings = 0;
32}
33
34static bool is_timeout(uint64_t time)
35{
36 return (time + PING_TIMEOUT) < now();
37}
38
39static void remove_timeouts() // O(n)
40{
41 size_t i, id;
42 size_t new_pos = pos_pings;
43 size_t new_num = num_pings;
44
45 // Loop through buffer, oldest first
46 for (i=0; i<num_pings; i++) {
47 id = (pos_pings + i) % PING_NUM_MAX;
48
49 if(is_timeout(pings[id].timestamp)) {
50 new_pos++;
51 new_num--;
52 }
53 // Break here because list is sorted.
54 else
55 break;
56 }
57
58 num_pings = new_num;
59 pos_pings = new_pos % PING_NUM_MAX;
60}
61
62uint64_t add_ping(IP_Port ipp) // O(n)
63{
64 size_t p;
65
66 remove_timeouts();
67
68 // Remove oldest ping if full buffer
69 if (num_pings == PING_NUM_MAX) {
70 num_pings--;
71 pos_pings = (pos_pings + 1) % PING_NUM_MAX;
72 }
73
74 // Insert new ping at end of list
75 p = (pos_pings + num_pings) % PING_NUM_MAX;
76
77 pings[p].ipp = ipp;
78 pings[p].timestamp = now();
79 pings[p].id = random_64b();
80
81 num_pings++;
82 return pings[p].id;
83}
84
85bool is_pinging(IP_Port ipp, uint64_t ping_id) // O(n) TODO: replace this with something else.
86{
87 if (ipp.ip.i == 0 && ping_id == 0)
88 return false;
89
90 size_t i, id;
91
92 remove_timeouts();
93
94 for (i=0; i<num_pings; i++) {
95 id = (pos_pings + i) % PING_NUM_MAX;
96
97 if ((ipp_eq(pings[id].ipp, ipp) || ipp.ip.i == 0) && (pings[id].id == ping_id || ping_id == 0)) {
98 return true;
99 }
100 }
101
102 return false;
103}
diff --git a/core/ping.h b/core/ping.h
new file mode 100644
index 00000000..1d23df97
--- /dev/null
+++ b/core/ping.h
@@ -0,0 +1,13 @@
1/*
2 * ping.h -- Buffered pinging using cyclic arrays.
3 *
4 * This file is donated to the Tox Project.
5 * Copyright 2013 plutooo
6 */
7
8#include <stdbool.h>
9
10void init_ping();
11uint64_t add_ping(IP_Port ipp);
12bool is_pinging(IP_Port ipp, uint64_t ping_id);
13
diff --git a/core/util.c b/core/util.c
new file mode 100644
index 00000000..4ce9271e
--- /dev/null
+++ b/core/util.c
@@ -0,0 +1,34 @@
1/*
2 * util.c -- Utilities.
3 *
4 * This file is donated to the Tox Project.
5 * Copyright 2013 plutooo
6 */
7
8#include <time.h>
9#include <stdint.h>
10#include <stdbool.h>
11
12#include "network.h"
13
14uint64_t now()
15{
16 return time(NULL);
17}
18
19uint64_t random_64b()
20{
21 uint64_t r;
22
23 // This is probably not random enough?
24 r = random_int();
25 r <<= 32;
26 r |= random_int();
27
28 return r;
29}
30
31bool ipp_eq(IP_Port a, IP_Port b)
32{
33 return (a.ip.i == b.ip.i) && (a.port == b.port);
34}
diff --git a/core/util.h b/core/util.h
new file mode 100644
index 00000000..aab2ead9
--- /dev/null
+++ b/core/util.h
@@ -0,0 +1,10 @@
1/*
2 * util.h -- Utilities.
3 *
4 * This file is donated to the Tox Project.
5 * Copyright 2013 plutooo
6 */
7
8uint64_t now();
9uint64_t random_64b();
10bool ipp_eq(IP_Port a, IP_Port b);