summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--toxcore/Messenger.c200
-rw-r--r--toxcore/Messenger.h25
-rw-r--r--toxcore/tox.h2
3 files changed, 119 insertions, 108 deletions
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index 11da5951..a9d5e6a1 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -214,7 +214,6 @@ static int32_t init_new_friend(Messenger *m, const uint8_t *real_pk, uint8_t sta
214 m->friendlist[i].avatar_send_data.last_reset = 0; 214 m->friendlist[i].avatar_send_data.last_reset = 0;
215 m->friendlist[i].is_typing = 0; 215 m->friendlist[i].is_typing = 0;
216 m->friendlist[i].message_id = 0; 216 m->friendlist[i].message_id = 0;
217 m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */
218 friend_connection_callbacks(m->fr_c, friendcon_id, MESSENGER_CALLBACK_INDEX, &handle_status, &handle_packet, 217 friend_connection_callbacks(m->fr_c, friendcon_id, MESSENGER_CALLBACK_INDEX, &handle_status, &handle_packet,
219 &handle_custom_lossy_packet, m, i); 218 &handle_custom_lossy_packet, m, i);
220 219
@@ -315,6 +314,75 @@ int32_t m_addfriend_norequest(Messenger *m, const uint8_t *real_pk)
315 return init_new_friend(m, real_pk, FRIEND_CONFIRMED); 314 return init_new_friend(m, real_pk, FRIEND_CONFIRMED);
316} 315}
317 316
317static int clear_receipts(Messenger *m, int32_t friendnumber)
318{
319 if (friend_not_valid(m, friendnumber))
320 return -1;
321
322 struct Receipts *receipts = m->friendlist[friendnumber].receipts_start;
323
324 while (receipts) {
325 struct Receipts *temp_r = receipts->next;
326 free(receipts);
327 receipts = temp_r;
328 }
329
330 m->friendlist[friendnumber].receipts_start = NULL;
331 m->friendlist[friendnumber].receipts_end = NULL;
332 return 0;
333}
334
335static int add_receipt(Messenger *m, int32_t friendnumber, uint32_t packet_num, uint32_t msg_id)
336{
337 if (friend_not_valid(m, friendnumber))
338 return -1;
339
340 struct Receipts *new = calloc(1, sizeof(struct Receipts));
341
342 if (!new)
343 return -1;
344
345 new->packet_num = packet_num;
346 new->msg_id = msg_id;
347
348 if (!m->friendlist[friendnumber].receipts_start) {
349 m->friendlist[friendnumber].receipts_start = new;
350 } else {
351 m->friendlist[friendnumber].receipts_end->next = new;
352 }
353
354 m->friendlist[friendnumber].receipts_end = new;
355 new->next = NULL;
356 return 0;
357}
358
359static int do_receipts(Messenger *m, int32_t friendnumber)
360{
361 if (friend_not_valid(m, friendnumber))
362 return -1;
363
364 struct Receipts *receipts = m->friendlist[friendnumber].receipts_start;
365
366 while (receipts) {
367 struct Receipts *temp_r = receipts->next;
368
369 if (cryptpacket_received(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, m->friendlist[friendnumber].friendcon_id), receipts->packet_num) == -1)
370 break;
371
372 if (m->read_receipt)
373 (*m->read_receipt)(m, friendnumber, receipts->msg_id, m->read_receipt_userdata);
374
375 free(receipts);
376 m->friendlist[friendnumber].receipts_start = temp_r;
377 receipts = temp_r;
378 }
379
380 if (!m->friendlist[friendnumber].receipts_start)
381 m->friendlist[friendnumber].receipts_end = NULL;
382
383 return 0;
384}
385
318/* Remove a friend. 386/* Remove a friend.
319 * 387 *
320 * return 0 if success. 388 * return 0 if success.
@@ -329,6 +397,7 @@ int m_delfriend(Messenger *m, int32_t friendnumber)
329 remove_online_friend(m, friendnumber); 397 remove_online_friend(m, friendnumber);
330 398
331 free(m->friendlist[friendnumber].avatar_recv_data); 399 free(m->friendlist[friendnumber].avatar_recv_data);
400 clear_receipts(m, friendnumber);
332 remove_request_received(&(m->fr), m->friendlist[friendnumber].real_pk); 401 remove_request_received(&(m->fr), m->friendlist[friendnumber].real_pk);
333 friend_connection_callbacks(m->fr_c, m->friendlist[friendnumber].friendcon_id, MESSENGER_CALLBACK_INDEX, 0, 0, 0, 0, 0); 402 friend_connection_callbacks(m->fr_c, m->friendlist[friendnumber].friendcon_id, MESSENGER_CALLBACK_INDEX, 0, 0, 0, 0, 0);
334 kill_friend_connection(m->fr_c, m->friendlist[friendnumber].friendcon_id); 403 kill_friend_connection(m->fr_c, m->friendlist[friendnumber].friendcon_id);
@@ -381,39 +450,45 @@ int m_friend_exists(const Messenger *m, int32_t friendnumber)
381 return 1; 450 return 1;
382} 451}
383 452
384/* Send a text chat message to an online friend. 453
385 * 454static uint32_t send_message_generic(Messenger *m, int32_t friendnumber, const uint8_t *message, uint32_t length,
386 * return the message id if packet was successfully put into the send queue. 455 uint8_t packet_id)
387 * return 0 if it was not.
388 */
389uint32_t m_sendmessage(Messenger *m, int32_t friendnumber, const uint8_t *message, uint32_t length)
390{ 456{
391 if (friend_not_valid(m, friendnumber)) 457 if (friend_not_valid(m, friendnumber))
392 return 0; 458 return 0;
393 459
394 uint32_t msgid = ++m->friendlist[friendnumber].message_id; 460 if (length >= MAX_CRYPTO_DATA_SIZE || m->friendlist[friendnumber].status != FRIEND_ONLINE)
461 return 0;
462
463 uint8_t packet[length + 1];
464 packet[0] = packet_id;
465
466 if (length != 0)
467 memcpy(packet + 1, message, length);
395 468
396 if (msgid == 0) 469 int64_t packet_num = write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c, m->friendlist[friendnumber].friendcon_id), packet, length + 1, 0);
397 msgid = 1; // Otherwise, false error
398 470
399 if (m_sendmessage_withid(m, friendnumber, msgid, message, length)) { 471 if (packet_num == -1)
400 return msgid; 472 return 0;
473
474 uint32_t msg_id = ++m->friendlist[friendnumber].message_id;
475
476 if (msg_id == 0) {
477 msg_id = ++m->friendlist[friendnumber].message_id; // Otherwise, false error
401 } 478 }
402 479
403 return 0; 480 add_receipt(m, friendnumber, packet_num, msg_id);
481 return msg_id;
404} 482}
405 483
406uint32_t m_sendmessage_withid(Messenger *m, int32_t friendnumber, uint32_t theid, const uint8_t *message, 484/* Send a text chat message to an online friend.
407 uint32_t length) 485 *
486 * return the message id if packet was successfully put into the send queue.
487 * return 0 if it was not.
488 */
489uint32_t m_sendmessage(Messenger *m, int32_t friendnumber, const uint8_t *message, uint32_t length)
408{ 490{
409 if (length >= (MAX_CRYPTO_DATA_SIZE - sizeof(theid)) || length == 0) 491 return send_message_generic(m, friendnumber, message, length, PACKET_ID_MESSAGE);
410 return 0;
411
412 uint8_t temp[sizeof(theid) + length];
413 theid = htonl(theid);
414 memcpy(temp, &theid, sizeof(theid));
415 memcpy(temp + sizeof(theid), message, length);
416 return write_cryptpacket_id(m, friendnumber, PACKET_ID_MESSAGE, temp, sizeof(temp), 0);
417} 492}
418 493
419/* Send an action to an online friend. 494/* Send an action to an online friend.
@@ -423,32 +498,7 @@ uint32_t m_sendmessage_withid(Messenger *m, int32_t friendnumber, uint32_t theid
423 */ 498 */
424uint32_t m_sendaction(Messenger *m, int32_t friendnumber, const uint8_t *action, uint32_t length) 499uint32_t m_sendaction(Messenger *m, int32_t friendnumber, const uint8_t *action, uint32_t length)
425{ 500{
426 if (friend_not_valid(m, friendnumber)) 501 return send_message_generic(m, friendnumber, action, length, PACKET_ID_ACTION);
427 return 0;
428
429 uint32_t msgid = ++m->friendlist[friendnumber].message_id;
430
431 if (msgid == 0)
432 msgid = 1; // Otherwise, false error
433
434 if (m_sendaction_withid(m, friendnumber, msgid, action, length)) {
435 return msgid;
436 }
437
438 return 0;
439}
440
441uint32_t m_sendaction_withid(const Messenger *m, int32_t friendnumber, uint32_t theid, const uint8_t *action,
442 uint32_t length)
443{
444 if (length >= (MAX_CRYPTO_DATA_SIZE - sizeof(theid)) || length == 0)
445 return 0;
446
447 uint8_t temp[sizeof(theid) + length];
448 theid = htonl(theid);
449 memcpy(temp, &theid, sizeof(theid));
450 memcpy(temp + sizeof(theid), action, length);
451 return write_cryptpacket_id(m, friendnumber, PACKET_ID_ACTION, temp, sizeof(temp), 0);
452} 502}
453 503
454/* Send a name packet to friendnumber. 504/* Send a name packet to friendnumber.
@@ -886,18 +936,6 @@ static void set_friend_typing(const Messenger *m, int32_t friendnumber, uint8_t
886 m->friendlist[friendnumber].is_typing = is_typing; 936 m->friendlist[friendnumber].is_typing = is_typing;
887} 937}
888 938
889/* Sets whether we send read receipts for friendnumber. */
890void m_set_sends_receipts(Messenger *m, int32_t friendnumber, int yesno)
891{
892 if (yesno != 0 && yesno != 1)
893 return;
894
895 if (friend_not_valid(m, friendnumber))
896 return;
897
898 m->friendlist[friendnumber].receives_read_receipts = yesno;
899}
900
901/* Set the function that will be executed when a friend request is received. */ 939/* Set the function that will be executed when a friend request is received. */
902void m_callback_friendrequest(Messenger *m, void (*function)(Messenger *m, const uint8_t *, const uint8_t *, size_t, 940void m_callback_friendrequest(Messenger *m, void (*function)(Messenger *m, const uint8_t *, const uint8_t *, size_t,
903 void *), void *userdata) 941 void *), void *userdata)
@@ -1011,6 +1049,7 @@ static void check_friend_connectionstatus(Messenger *m, int32_t friendnumber, ui
1011 if (was_online) { 1049 if (was_online) {
1012 break_files(m, friendnumber); 1050 break_files(m, friendnumber);
1013 remove_online_friend(m, friendnumber); 1051 remove_online_friend(m, friendnumber);
1052 clear_receipts(m, friendnumber);
1014 } else { 1053 } else {
1015 add_online_friend(m, friendnumber); 1054 add_online_friend(m, friendnumber);
1016 } 1055 }
@@ -1660,6 +1699,7 @@ void kill_messenger(Messenger *m)
1660 1699
1661 for (i = 0; i < m->numfriends; ++i) { 1700 for (i = 0; i < m->numfriends; ++i) {
1662 free(m->friendlist[i].avatar_recv_data); 1701 free(m->friendlist[i].avatar_recv_data);
1702 clear_receipts(m, i);
1663 } 1703 }
1664 1704
1665 free(m->avatar_data); 1705 free(m->avatar_data);
@@ -2083,23 +2123,18 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len)
2083 2123
2084 case PACKET_ID_MESSAGE: { 2124 case PACKET_ID_MESSAGE: {
2085 const uint8_t *message_id = data; 2125 const uint8_t *message_id = data;
2086 uint8_t message_id_length = 4;
2087 2126
2088 if (data_length <= message_id_length) 2127 if (data_length == 0)
2089 break; 2128 break;
2090 2129
2091 const uint8_t *message = data + message_id_length; 2130 const uint8_t *message = data;
2092 uint16_t message_length = data_length - message_id_length; 2131 uint16_t message_length = data_length;
2093 2132
2094 /* Make sure the NULL terminator is present. */ 2133 /* Make sure the NULL terminator is present. */
2095 uint8_t message_terminated[message_length + 1]; 2134 uint8_t message_terminated[message_length + 1];
2096 memcpy(message_terminated, message, message_length); 2135 memcpy(message_terminated, message, message_length);
2097 message_terminated[message_length] = 0; 2136 message_terminated[message_length] = 0;
2098 2137
2099 if (m->friendlist[i].receives_read_receipts) {
2100 write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length, 0);
2101 }
2102
2103 if (m->friend_message) 2138 if (m->friend_message)
2104 (*m->friend_message)(m, i, message_terminated, message_length, m->friend_message_userdata); 2139 (*m->friend_message)(m, i, message_terminated, message_length, m->friend_message_userdata);
2105 2140
@@ -2108,23 +2143,18 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len)
2108 2143
2109 case PACKET_ID_ACTION: { 2144 case PACKET_ID_ACTION: {
2110 const uint8_t *message_id = data; 2145 const uint8_t *message_id = data;
2111 uint8_t message_id_length = 4;
2112 2146
2113 if (data_length <= message_id_length) 2147 if (data_length == 0)
2114 break; 2148 break;
2115 2149
2116 const uint8_t *action = data + message_id_length; 2150 const uint8_t *action = data;
2117 uint16_t action_length = data_length - message_id_length; 2151 uint16_t action_length = data_length;
2118 2152
2119 /* Make sure the NULL terminator is present. */ 2153 /* Make sure the NULL terminator is present. */
2120 uint8_t action_terminated[action_length + 1]; 2154 uint8_t action_terminated[action_length + 1];
2121 memcpy(action_terminated, action, action_length); 2155 memcpy(action_terminated, action, action_length);
2122 action_terminated[action_length] = 0; 2156 action_terminated[action_length] = 0;
2123 2157
2124 if (m->friendlist[i].receives_read_receipts) {
2125 write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length, 0);
2126 }
2127
2128 if (m->friend_action) 2158 if (m->friend_action)
2129 (*m->friend_action)(m, i, action_terminated, action_length, m->friend_action_userdata); 2159 (*m->friend_action)(m, i, action_terminated, action_length, m->friend_action_userdata);
2130 2160
@@ -2168,21 +2198,6 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len)
2168 break; 2198 break;
2169 } 2199 }
2170 2200
2171 case PACKET_ID_RECEIPT: {
2172 uint32_t msgid;
2173
2174 if (data_length < sizeof(msgid))
2175 break;
2176
2177 memcpy(&msgid, data, sizeof(msgid));
2178 msgid = ntohl(msgid);
2179
2180 if (m->read_receipt)
2181 (*m->read_receipt)(m, i, msgid, m->read_receipt_userdata);
2182
2183 break;
2184 }
2185
2186 case PACKET_ID_INVITE_GROUPCHAT: { 2201 case PACKET_ID_INVITE_GROUPCHAT: {
2187 if (data_length == 0) 2202 if (data_length == 0)
2188 break; 2203 break;
@@ -2346,6 +2361,7 @@ void do_friends(Messenger *m)
2346 } 2361 }
2347 2362
2348 check_friend_tcp_udp(m, i); 2363 check_friend_tcp_udp(m, i);
2364 do_receipts(m, i);
2349 } 2365 }
2350 } 2366 }
2351} 2367}
diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h
index da1bbe9f..0a613c0b 100644
--- a/toxcore/Messenger.h
+++ b/toxcore/Messenger.h
@@ -52,7 +52,6 @@
52#define PACKET_ID_AVATAR_DATA_CONTROL 54 52#define PACKET_ID_AVATAR_DATA_CONTROL 54
53#define PACKET_ID_AVATAR_DATA_START 55 53#define PACKET_ID_AVATAR_DATA_START 55
54#define PACKET_ID_AVATAR_DATA_PUSH 56 54#define PACKET_ID_AVATAR_DATA_PUSH 56
55#define PACKET_ID_RECEIPT 63
56#define PACKET_ID_MESSAGE 64 55#define PACKET_ID_MESSAGE 64
57#define PACKET_ID_ACTION 65 56#define PACKET_ID_ACTION 65
58#define PACKET_ID_MSI 69 57#define PACKET_ID_MSI 69
@@ -78,6 +77,13 @@ typedef struct {
78 TCP_Proxy_Info proxy_info; 77 TCP_Proxy_Info proxy_info;
79} Messenger_Options; 78} Messenger_Options;
80 79
80
81struct Receipts {
82 uint32_t packet_num;
83 uint32_t msg_id;
84 struct Receipts *next;
85};
86
81/* Status definitions. */ 87/* Status definitions. */
82enum { 88enum {
83 NOFRIEND, 89 NOFRIEND,
@@ -217,7 +223,6 @@ typedef struct {
217 uint8_t is_typing; 223 uint8_t is_typing;
218 uint16_t info_size; // Length of the info. 224 uint16_t info_size; // Length of the info.
219 uint32_t message_id; // a semi-unique id used in read receipts. 225 uint32_t message_id; // a semi-unique id used in read receipts.
220 uint8_t receives_read_receipts; // shall we send read receipts to this person?
221 uint32_t friendrequest_nospam; // The nospam number used in the friend request. 226 uint32_t friendrequest_nospam; // The nospam number used in the friend request.
222 uint64_t ping_lastrecv;//TODO remove 227 uint64_t ping_lastrecv;//TODO remove
223 uint64_t share_relays_lastsent; 228 uint64_t share_relays_lastsent;
@@ -237,6 +242,9 @@ typedef struct {
237 int (*function)(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint32_t len, void *object); 242 int (*function)(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint32_t len, void *object);
238 void *object; 243 void *object;
239 } lossless_packethandlers[PACKET_ID_LOSSLESS_RANGE_SIZE]; 244 } lossless_packethandlers[PACKET_ID_LOSSLESS_RANGE_SIZE];
245
246 struct Receipts *receipts_start;
247 struct Receipts *receipts_end;
240} Friend; 248} Friend;
241 249
242 250
@@ -400,12 +408,8 @@ int m_friend_exists(const Messenger *m, int32_t friendnumber);
400 * 408 *
401 * You will want to retain the return value, it will be passed to your read_receipt callback 409 * You will want to retain the return value, it will be passed to your read_receipt callback
402 * if one is received. 410 * if one is received.
403 * m_sendmessage_withid will send a message with the id of your choosing,
404 * however we can generate an id for you by calling plain m_sendmessage.
405 */ 411 */
406uint32_t m_sendmessage(Messenger *m, int32_t friendnumber, const uint8_t *message, uint32_t length); 412uint32_t m_sendmessage(Messenger *m, int32_t friendnumber, const uint8_t *message, uint32_t length);
407uint32_t m_sendmessage_withid(Messenger *m, int32_t friendnumber, uint32_t theid, const uint8_t *message,
408 uint32_t length);
409 413
410/* Send an action to an online friend. 414/* Send an action to an online friend.
411 * 415 *
@@ -414,12 +418,8 @@ uint32_t m_sendmessage_withid(Messenger *m, int32_t friendnumber, uint32_t theid
414 * 418 *
415 * You will want to retain the return value, it will be passed to your read_receipt callback 419 * You will want to retain the return value, it will be passed to your read_receipt callback
416 * if one is received. 420 * if one is received.
417 * m_sendaction_withid will send an action message with the id of your choosing,
418 * however we can generate an id for you by calling plain m_sendaction.
419 */ 421 */
420uint32_t m_sendaction(Messenger *m, int32_t friendnumber, const uint8_t *action, uint32_t length); 422uint32_t m_sendaction(Messenger *m, int32_t friendnumber, const uint8_t *action, uint32_t length);
421uint32_t m_sendaction_withid(const Messenger *m, int32_t friendnumber, uint32_t theid, const uint8_t *action,
422 uint32_t length);
423 423
424/* Set the name and name_length of a friend. 424/* Set the name and name_length of a friend.
425 * name must be a string of maximum MAX_NAME_LENGTH length. 425 * name must be a string of maximum MAX_NAME_LENGTH length.
@@ -626,11 +626,6 @@ int m_set_usertyping(Messenger *m, int32_t friendnumber, uint8_t is_typing);
626 */ 626 */
627int m_get_istyping(const Messenger *m, int32_t friendnumber); 627int m_get_istyping(const Messenger *m, int32_t friendnumber);
628 628
629/* Sets whether we send read receipts for friendnumber.
630 * This function is not lazy, and it will fail if yesno is not (0 or 1).
631 */
632void m_set_sends_receipts(Messenger *m, int32_t friendnumber, int yesno);
633
634/* Set the function that will be executed when a friend request is received. 629/* Set the function that will be executed when a friend request is received.
635 * Function format is function(uint8_t * public_key, uint8_t * data, size_t length) 630 * Function format is function(uint8_t * public_key, uint8_t * data, size_t length)
636 */ 631 */
diff --git a/toxcore/tox.h b/toxcore/tox.h
index 2506779e..2acc70ea 100644
--- a/toxcore/tox.h
+++ b/toxcore/tox.h
@@ -238,7 +238,7 @@ bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch);
238/** 238/**
239 * Maximum length of a single message after which it should be split. 239 * Maximum length of a single message after which it should be split.
240 */ 240 */
241#define TOX_MAX_MESSAGE_LENGTH 1368 241#define TOX_MAX_MESSAGE_LENGTH 1372
242 242
243/** 243/**
244 * Maximum size of custom packets. TODO: should be LENGTH? 244 * Maximum size of custom packets. TODO: should be LENGTH?