diff options
-rw-r--r-- | core/CMakeLists.txt | 4 | ||||
-rw-r--r-- | core/DHT.c | 61 | ||||
-rw-r--r-- | core/Messenger.c | 88 | ||||
-rw-r--r-- | core/Messenger.h | 38 | ||||
-rw-r--r-- | core/ping.c | 103 | ||||
-rw-r--r-- | core/ping.h | 13 | ||||
-rw-r--r-- | core/util.c | 34 | ||||
-rw-r--r-- | core/util.h | 10 | ||||
-rw-r--r-- | testing/nTox.c | 6 | ||||
-rw-r--r-- | testing/nTox_win32.c | 26 | ||||
-rw-r--r-- | testing/toxic/chat.c | 2 | ||||
-rw-r--r-- | testing/toxic/main.c | 8 | ||||
-rw-r--r-- | testing/toxic/prompt.c | 8 |
13 files changed, 294 insertions, 107 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 | ||
13 | if(SHARED_TOXCORE) | 15 | if(SHARED_TOXCORE) |
14 | add_library(toxcore SHARED ${core_sources}) | 16 | add_library(toxcore SHARED ${core_sources}) |
@@ -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]; | |||
109 | static Client_data close_clientlist[LCLIENT_LIST]; | 110 | static Client_data close_clientlist[LCLIENT_LIST]; |
110 | static Friend * friends_list; | 111 | static Friend * friends_list; |
111 | static uint16_t num_friends; | 112 | static uint16_t num_friends; |
112 | static Pinged pings[LPING_ARRAY]; | ||
113 | static Pinged send_nodes[LSEND_NODES_ARRAY]; | 113 | static 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 | */ | ||
434 | static 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. */ |
459 | static int is_gettingnodes(IP_Port ip_port, uint64_t ping_id) | 430 | static 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 | */ | ||
489 | static 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 */ |
510 | static uint64_t add_gettingnodes(IP_Port ip_port) | 455 | static 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 | ||
@@ -1301,6 +1246,8 @@ void DHT_save(uint8_t * data) | |||
1301 | */ | 1246 | */ |
1302 | int DHT_load(uint8_t * data, uint32_t size) | 1247 | int 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 | ||
46 | static uint8_t *self_userstatus; | 47 | static uint8_t *self_userstatus; |
47 | static uint16_t self_userstatus_len; | 48 | static uint16_t self_userstatus_len; |
49 | static 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 | */ |
103 | int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length) | 105 | int 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*/ |
210 | static int m_sendname(int friendnumber, uint8_t * name, uint16_t length) | 213 | static 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 */ |
253 | uint16_t getself_name(uint8_t *name) | 256 | uint16_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 | ||
272 | int m_set_userstatus(uint8_t *status, uint16_t length) | 275 | int 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 | ||
294 | int 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 */ |
290 | int m_get_userstatus_size(int friendnumber) | 310 | int 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 | ||
328 | int 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 | |||
335 | USERSTATUS_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 | |||
345 | USERSTATUS_KIND m_get_self_userstatus_kind(void) { | ||
346 | return self_userstatus_kind; | ||
347 | } | ||
348 | |||
308 | static int send_userstatus(int friendnumber, uint8_t * status, uint16_t length) | 349 | static 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 | ||
372 | static 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); |
331 | static uint8_t friend_request_isset = 0; */ | 378 | static 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 | ||
356 | static void (*friend_statuschange)(int, uint8_t *, uint16_t); | 403 | static void (*friend_statuschange)(int, USERSTATUS_KIND, uint8_t *, uint16_t); |
357 | static uint8_t friend_statuschange_isset = 0; | 404 | static uint8_t friend_statuschange_isset = 0; |
358 | void m_callback_userstatus(void (*function)(int, uint8_t *, uint16_t)) | 405 | void 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)) | |||
366 | int initMessenger(void) | 413 | int 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 | |||
68 | typedef 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 | */ |
75 | int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length); | 91 | int 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); | |||
114 | int setname(uint8_t *name, uint16_t length); | 130 | int 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*/ |
119 | uint16_t getself_name(uint8_t *name); | 135 | uint16_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 */ |
131 | int m_set_userstatus(uint8_t *status, uint16_t length); | 147 | int m_set_userstatus(USERSTATUS_KIND kind, uint8_t *status, uint16_t length); |
148 | int 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); | |||
136 | int m_get_userstatus_size(int friendnumber); | 153 | int 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. */ | ||
140 | int m_copy_userstatus(int friendnumber, uint8_t *buf, uint32_t maxlen); | 158 | int m_copy_userstatus(int friendnumber, uint8_t *buf, uint32_t maxlen); |
159 | int 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. */ | ||
165 | USERSTATUS_KIND m_get_userstatus_kind(int friendnumber); | ||
166 | USERSTATUS_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)); | |||
153 | void m_callback_namechange(void (*function)(int, uint8_t *, uint16_t)); | 179 | void 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 */ |
158 | void m_callback_userstatus(void (*function)(int, uint8_t *, uint16_t)); | 184 | void 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/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 | |||
17 | typedef struct { | ||
18 | IP_Port ipp; | ||
19 | uint64_t id; | ||
20 | uint64_t timestamp; | ||
21 | } pinged_t; | ||
22 | |||
23 | static pinged_t pings[PING_NUM_MAX]; | ||
24 | static size_t num_pings; | ||
25 | static size_t pos_pings; | ||
26 | |||
27 | |||
28 | void init_ping() | ||
29 | { | ||
30 | num_pings = 0; | ||
31 | pos_pings = 0; | ||
32 | } | ||
33 | |||
34 | static bool is_timeout(uint64_t time) | ||
35 | { | ||
36 | return (time + PING_TIMEOUT) < now(); | ||
37 | } | ||
38 | |||
39 | static 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 | |||
62 | uint64_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 | |||
85 | bool 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 | |||
10 | void init_ping(); | ||
11 | uint64_t add_ping(IP_Port ipp); | ||
12 | bool 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 | |||
14 | uint64_t now() | ||
15 | { | ||
16 | return time(NULL); | ||
17 | } | ||
18 | |||
19 | uint64_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 | |||
31 | bool 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 | |||
8 | uint64_t now(); | ||
9 | uint64_t random_64b(); | ||
10 | bool ipp_eq(IP_Port a, IP_Port b); | ||
diff --git a/testing/nTox.c b/testing/nTox.c index fe91b1fa..63d0c32e 100644 --- a/testing/nTox.c +++ b/testing/nTox.c | |||
@@ -228,7 +228,7 @@ void line_eval(char *line) | |||
228 | status[i-3] = line[i]; | 228 | status[i-3] = line[i]; |
229 | } | 229 | } |
230 | status[i-3] = 0; | 230 | status[i-3] = 0; |
231 | m_set_userstatus(status, strlen((char*)status) + 1); | 231 | m_set_userstatus(USERSTATUS_KIND_ONLINE, status, strlen((char*)status) + 1); |
232 | char numstring[100]; | 232 | char numstring[100]; |
233 | sprintf(numstring, "[i] changed status to %s", (char*)status); | 233 | sprintf(numstring, "[i] changed status to %s", (char*)status); |
234 | new_lines(numstring); | 234 | new_lines(numstring); |
@@ -364,7 +364,7 @@ void print_nickchange(int friendnumber, uint8_t *string, uint16_t length) | |||
364 | } | 364 | } |
365 | } | 365 | } |
366 | 366 | ||
367 | void print_statuschange(int friendnumber, uint8_t *string, uint16_t length) | 367 | void print_statuschange(int friendnumber, USERSTATUS_KIND kind, uint8_t *string, uint16_t length) |
368 | { | 368 | { |
369 | char name[MAX_NAME_LENGTH]; | 369 | char name[MAX_NAME_LENGTH]; |
370 | if(getname(friendnumber, (uint8_t*)name) != -1) { | 370 | if(getname(friendnumber, (uint8_t*)name) != -1) { |
@@ -392,7 +392,7 @@ void load_key(char *path) | |||
392 | } | 392 | } |
393 | Messenger_load(data, size); | 393 | Messenger_load(data, size); |
394 | 394 | ||
395 | } else { | 395 | } else { |
396 | //else save new keys | 396 | //else save new keys |
397 | int size = Messenger_size(); | 397 | int size = Messenger_size(); |
398 | uint8_t data[size]; | 398 | uint8_t data[size]; |
diff --git a/testing/nTox_win32.c b/testing/nTox_win32.c index f3c7a188..dbbd0f6e 100644 --- a/testing/nTox_win32.c +++ b/testing/nTox_win32.c | |||
@@ -18,7 +18,7 @@ | |||
18 | * | 18 | * |
19 | * You should have received a copy of the GNU General Public License | 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/>. | 20 | * along with Tox. If not, see <http://www.gnu.org/licenses/>. |
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include "nTox_win32.h" | 24 | #include "nTox_win32.h" |
@@ -86,7 +86,7 @@ void print_nickchange(int friendnumber, uint8_t *string, uint16_t length) | |||
86 | printf(msg); | 86 | printf(msg); |
87 | } | 87 | } |
88 | 88 | ||
89 | void print_statuschange(int friendnumber, uint8_t *string, uint16_t length) | 89 | void print_statuschange(int friendnumber, USERSTATUS_KIND kind, uint8_t *string, uint16_t length) |
90 | { | 90 | { |
91 | char name[MAX_NAME_LENGTH]; | 91 | char name[MAX_NAME_LENGTH]; |
92 | getname(friendnumber, (uint8_t*)name); | 92 | getname(friendnumber, (uint8_t*)name); |
@@ -95,7 +95,7 @@ void print_statuschange(int friendnumber, uint8_t *string, uint16_t length) | |||
95 | printf(msg); | 95 | printf(msg); |
96 | } | 96 | } |
97 | 97 | ||
98 | void load_key() | 98 | void load_key() |
99 | { | 99 | { |
100 | FILE *data_file = NULL; | 100 | FILE *data_file = NULL; |
101 | data_file = fopen("data","r"); | 101 | data_file = fopen("data","r"); |
@@ -130,7 +130,7 @@ void add_friend() | |||
130 | int i; | 130 | int i; |
131 | char temp_id[128]; | 131 | char temp_id[128]; |
132 | 132 | ||
133 | for (i = 0; i < 128; i++) | 133 | for (i = 0; i < 128; i++) |
134 | temp_id[i] = line[i+3]; | 134 | temp_id[i] = line[i+3]; |
135 | 135 | ||
136 | int num = m_addfriend(hex_string_to_bin(temp_id), (uint8_t*)"Install Gentoo", sizeof("Install Gentoo")); | 136 | int num = m_addfriend(hex_string_to_bin(temp_id), (uint8_t*)"Install Gentoo", sizeof("Install Gentoo")); |
@@ -141,7 +141,7 @@ void add_friend() | |||
141 | printf(numstring); | 141 | printf(numstring); |
142 | ++maxnumfriends; | 142 | ++maxnumfriends; |
143 | } | 143 | } |
144 | else if (num == -1) | 144 | else if (num == -1) |
145 | printf("\n[i] Message is too long.\n\n"); | 145 | printf("\n[i] Message is too long.\n\n"); |
146 | 146 | ||
147 | else if (num == -2) | 147 | else if (num == -2) |
@@ -180,7 +180,7 @@ void list_friends() | |||
180 | char name[MAX_NAME_LENGTH]; | 180 | char name[MAX_NAME_LENGTH]; |
181 | getname(i, (uint8_t*)name); | 181 | getname(i, (uint8_t*)name); |
182 | 182 | ||
183 | if (m_friendstatus(i) == 4) | 183 | if (m_friendstatus(i) == 4) |
184 | printf("[%d] %s\n", i, (uint8_t*)name); | 184 | printf("[%d] %s\n", i, (uint8_t*)name); |
185 | } | 185 | } |
186 | 186 | ||
@@ -213,7 +213,7 @@ void message_friend() | |||
213 | 213 | ||
214 | for (i = 0; i < len; i++) { | 214 | for (i = 0; i < len; i++) { |
215 | 215 | ||
216 | if (line[i+3] != ' ') | 216 | if (line[i+3] != ' ') |
217 | numstring[i] = line[i+3]; | 217 | numstring[i] = line[i+3]; |
218 | 218 | ||
219 | else { | 219 | else { |
@@ -243,7 +243,7 @@ void change_nickname() | |||
243 | 243 | ||
244 | for (i = 3; i < len; i++) { | 244 | for (i = 3; i < len; i++) { |
245 | 245 | ||
246 | if (line[i] == 0 || line[i] == '\n') | 246 | if (line[i] == 0 || line[i] == '\n') |
247 | break; | 247 | break; |
248 | 248 | ||
249 | name[i-3] = line[i]; | 249 | name[i-3] = line[i]; |
@@ -268,7 +268,7 @@ void change_status(int savetofile) | |||
268 | size_t len = strlen(line); | 268 | size_t len = strlen(line); |
269 | 269 | ||
270 | for (i = 3; i < len; i++) { | 270 | for (i = 3; i < len; i++) { |
271 | if (line[i] == 0 || line[i] == '\n') | 271 | if (line[i] == 0 || line[i] == '\n') |
272 | break; | 272 | break; |
273 | 273 | ||
274 | status[i-3] = line[i]; | 274 | status[i-3] = line[i]; |
@@ -350,7 +350,7 @@ void line_eval(char* line) | |||
350 | accept_friend_request(line); | 350 | accept_friend_request(line); |
351 | } | 351 | } |
352 | /* EXIT */ | 352 | /* EXIT */ |
353 | else if (inpt_command == 'q') { | 353 | else if (inpt_command == 'q') { |
354 | strcpy(line, "---Offline"); | 354 | strcpy(line, "---Offline"); |
355 | change_status(0); | 355 | change_status(0); |
356 | exit(EXIT_SUCCESS); | 356 | exit(EXIT_SUCCESS); |
@@ -398,7 +398,7 @@ int main(int argc, char *argv[]) | |||
398 | nameloaded = 1; | 398 | nameloaded = 1; |
399 | printf("%s\n", name); | 399 | printf("%s\n", name); |
400 | fclose(name_file); | 400 | fclose(name_file); |
401 | } | 401 | } |
402 | 402 | ||
403 | FILE* status_file = NULL; | 403 | FILE* status_file = NULL; |
404 | status_file = fopen("statusfile.txt", "r"); | 404 | status_file = fopen("statusfile.txt", "r"); |
@@ -424,7 +424,7 @@ int main(int argc, char *argv[]) | |||
424 | { | 424 | { |
425 | if(self_public_key[i] < (PUB_KEY_BYTES/2)) | 425 | if(self_public_key[i] < (PUB_KEY_BYTES/2)) |
426 | strcpy(idstring1[i],"0"); | 426 | strcpy(idstring1[i],"0"); |
427 | else | 427 | else |
428 | strcpy(idstring1[i], ""); | 428 | strcpy(idstring1[i], ""); |
429 | sprintf(idstring2[i], "%hhX",self_public_key[i]); | 429 | sprintf(idstring2[i], "%hhX",self_public_key[i]); |
430 | } | 430 | } |
@@ -442,7 +442,7 @@ int main(int argc, char *argv[]) | |||
442 | int resolved_address = resolve_addr(argv[1]); | 442 | int resolved_address = resolve_addr(argv[1]); |
443 | if (resolved_address != 0) | 443 | if (resolved_address != 0) |
444 | bootstrap_ip_port.ip.i = resolved_address; | 444 | bootstrap_ip_port.ip.i = resolved_address; |
445 | else | 445 | else |
446 | exit(1); | 446 | exit(1); |
447 | 447 | ||
448 | DHT_bootstrap(bootstrap_ip_port, hex_string_to_bin(argv[3])); | 448 | DHT_bootstrap(bootstrap_ip_port, hex_string_to_bin(argv[3])); |
diff --git a/testing/toxic/chat.c b/testing/toxic/chat.c index ee68dc9f..4ea459d9 100644 --- a/testing/toxic/chat.c +++ b/testing/toxic/chat.c | |||
@@ -162,7 +162,7 @@ void execute(ToxWindow* self, ChatContext* ctx, char* cmd) | |||
162 | return; | 162 | return; |
163 | } | 163 | } |
164 | msg++; | 164 | msg++; |
165 | m_set_userstatus((uint8_t*) msg, strlen(msg)+1); | 165 | m_set_userstatus(USERSTATUS_KIND_RETAIN, (uint8_t*) msg, strlen(msg)+1); |
166 | wprintw(ctx->history, "Status set to: %s\n", msg); | 166 | wprintw(ctx->history, "Status set to: %s\n", msg); |
167 | } | 167 | } |
168 | else if (!strncmp(cmd, "/nick ", strlen("/nick "))) { | 168 | else if (!strncmp(cmd, "/nick ", strlen("/nick "))) { |
diff --git a/testing/toxic/main.c b/testing/toxic/main.c index 45760b1c..ee5e9f2a 100644 --- a/testing/toxic/main.c +++ b/testing/toxic/main.c | |||
@@ -69,10 +69,10 @@ void on_nickchange(int friendnumber, uint8_t* string, uint16_t length) { | |||
69 | } | 69 | } |
70 | } | 70 | } |
71 | 71 | ||
72 | void on_statuschange(int friendnumber, uint8_t* string, uint16_t length) { | 72 | void on_statuschange(int friendnumber, USERSTATUS_KIND kind, uint8_t* string, uint16_t length) { |
73 | size_t i; | 73 | size_t i; |
74 | 74 | ||
75 | wprintw(prompt->window, "\n(statuschange) %d: %s!\n", friendnumber, string); | 75 | wprintw(prompt->window, "\n(statuschange) %d: %s\n", friendnumber, string); |
76 | 76 | ||
77 | for(i=0; i<w_num; i++) { | 77 | for(i=0; i<w_num; i++) { |
78 | if(windows[i].onStatusChange != NULL) | 78 | if(windows[i].onStatusChange != NULL) |
@@ -201,7 +201,7 @@ static void load_data(char *path) { | |||
201 | 201 | ||
202 | Messenger_load(buf, len); | 202 | Messenger_load(buf, len); |
203 | } | 203 | } |
204 | else { | 204 | else { |
205 | len = Messenger_size(); | 205 | len = Messenger_size(); |
206 | buf = malloc(len); | 206 | buf = malloc(len); |
207 | 207 | ||
@@ -289,7 +289,7 @@ int main(int argc, char* argv[]) { | |||
289 | 289 | ||
290 | for(i = 0; i < argc; i++) { | 290 | for(i = 0; i < argc; i++) { |
291 | if (argv[i] == NULL){ | 291 | if (argv[i] == NULL){ |
292 | break; | 292 | break; |
293 | } else if(argv[i][0] == '-') { | 293 | } else if(argv[i][0] == '-') { |
294 | if(argv[i][1] == 'f') { | 294 | if(argv[i][1] == 'f') { |
295 | if(argv[i + 1] != NULL) | 295 | if(argv[i + 1] != NULL) |
diff --git a/testing/toxic/prompt.c b/testing/toxic/prompt.c index e5dc5086..16750c5d 100644 --- a/testing/toxic/prompt.c +++ b/testing/toxic/prompt.c | |||
@@ -91,7 +91,7 @@ static void execute(ToxWindow* self, char* cmd) { | |||
91 | dht.ip.i = resolved_address; | 91 | dht.ip.i = resolved_address; |
92 | unsigned char *binary_string = hex_string_to_bin(key); | 92 | unsigned char *binary_string = hex_string_to_bin(key); |
93 | DHT_bootstrap(dht, binary_string); | 93 | DHT_bootstrap(dht, binary_string); |
94 | free(binary_string); | 94 | free(binary_string); |
95 | } | 95 | } |
96 | else if(!strncmp(cmd, "add ", strlen("add "))) { | 96 | else if(!strncmp(cmd, "add ", strlen("add "))) { |
97 | uint8_t id_bin[32]; | 97 | uint8_t id_bin[32]; |
@@ -137,7 +137,7 @@ static void execute(ToxWindow* self, char* cmd) { | |||
137 | 137 | ||
138 | num = m_addfriend(id_bin, (uint8_t*) msg, strlen(msg)+1); | 138 | num = m_addfriend(id_bin, (uint8_t*) msg, strlen(msg)+1); |
139 | switch (num) { | 139 | switch (num) { |
140 | case -1: | 140 | case -1: |
141 | wprintw(self->window, "Message is too long.\n"); | 141 | wprintw(self->window, "Message is too long.\n"); |
142 | break; | 142 | break; |
143 | case -2: | 143 | case -2: |
@@ -151,7 +151,7 @@ static void execute(ToxWindow* self, char* cmd) { | |||
151 | break; | 151 | break; |
152 | case -5: | 152 | case -5: |
153 | wprintw(self->window, "Undefined error when adding friend.\n"); | 153 | wprintw(self->window, "Undefined error when adding friend.\n"); |
154 | break; | 154 | break; |
155 | default: | 155 | default: |
156 | wprintw(self->window, "Friend added as %d.\n", num); | 156 | wprintw(self->window, "Friend added as %d.\n", num); |
157 | on_friendadded(num); | 157 | on_friendadded(num); |
@@ -174,7 +174,7 @@ static void execute(ToxWindow* self, char* cmd) { | |||
174 | } | 174 | } |
175 | msg++; | 175 | msg++; |
176 | 176 | ||
177 | m_set_userstatus((uint8_t*) msg, strlen(msg)+1); | 177 | m_set_userstatus(USERSTATUS_KIND_RETAIN, (uint8_t*) msg, strlen(msg)+1); |
178 | wprintw(self->window, "Status set to: %s\n", msg); | 178 | wprintw(self->window, "Status set to: %s\n", msg); |
179 | } | 179 | } |
180 | else if(!strncmp(cmd, "nick ", strlen("nick "))) { | 180 | else if(!strncmp(cmd, "nick ", strlen("nick "))) { |