From 30524bf41513a334f0e32117b85aad2f661eed2b Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 27 Aug 2014 15:13:44 -0400 Subject: [PATCH] Changed how receipts work. Messages now have a maximum length of 1372. Receipt packets have been removed, instead net_crypto tells us if the other peer has received the packets or not. --- toxcore/Messenger.c | 222 +++++++++++++++++++++++--------------------- toxcore/Messenger.h | 25 ++--- toxcore/tox.h | 2 +- 3 files changed, 128 insertions(+), 121 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index fd7527e4..eff845cf 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -42,6 +42,7 @@ static void set_friend_status(Messenger *m, int32_t friendnumber, uint8_t status); static int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_t packet_id, const uint8_t *data, uint32_t length); +static int clear_receipts(Messenger *m, int32_t friendnumber); // friend_not_valid determines if the friendnumber passed is valid in the Messenger object static uint8_t friend_not_valid(const Messenger *m, int32_t friendnumber) @@ -251,7 +252,6 @@ int32_t m_addfriend(Messenger *m, const uint8_t *address, const uint8_t *data, u memcpy(m->friendlist[i].info, data, length); m->friendlist[i].info_size = length; m->friendlist[i].message_id = 0; - m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */ memcpy(&(m->friendlist[i].friendrequest_nospam), address + crypto_box_PUBLICKEYBYTES, sizeof(uint32_t)); recv_tcp_relay_handler(m->onion_c, onion_friendnum, &tcp_relay_node_callback, m, i); @@ -301,7 +301,6 @@ int32_t m_addfriend_norequest(Messenger *m, const uint8_t *client_id) m->friendlist[i].userstatus = USERSTATUS_NONE; m->friendlist[i].is_typing = 0; m->friendlist[i].message_id = 0; - m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */ recv_tcp_relay_handler(m->onion_c, onion_friendnum, &tcp_relay_node_callback, m, i); if (m->numfriends == i) @@ -330,6 +329,7 @@ int m_delfriend(Messenger *m, int32_t friendnumber) onion_delfriend(m->onion_c, m->friendlist[friendnumber].onion_friendnum); crypto_kill(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id); free(m->friendlist[friendnumber].statusmessage); + clear_receipts(m, friendnumber); remove_request_received(&(m->fr), m->friendlist[friendnumber].client_id); memset(&(m->friendlist[friendnumber]), 0, sizeof(Friend)); uint32_t i; @@ -363,6 +363,106 @@ int m_friend_exists(const Messenger *m, int32_t friendnumber) return m->friendlist[friendnumber].status > NOFRIEND; } +static int clear_receipts(Messenger *m, int32_t friendnumber) +{ + if (friend_not_valid(m, friendnumber)) + return -1; + + struct Receipts *receipts = m->friendlist[friendnumber].receipts_start; + + while (receipts) { + struct Receipts *temp_r = receipts->next; + free(receipts); + receipts = temp_r; + } + + m->friendlist[friendnumber].receipts_start = NULL; + m->friendlist[friendnumber].receipts_end = NULL; + return 0; +} + +static int add_receipt(Messenger *m, int32_t friendnumber, uint32_t packet_num, uint32_t msg_id) +{ + if (friend_not_valid(m, friendnumber)) + return -1; + + struct Receipts *new = calloc(1, sizeof(struct Receipts)); + + if (!new) + return -1; + + new->packet_num = packet_num; + new->msg_id = msg_id; + + if (!m->friendlist[friendnumber].receipts_start) { + m->friendlist[friendnumber].receipts_start = new; + } else { + m->friendlist[friendnumber].receipts_end->next = new; + } + + m->friendlist[friendnumber].receipts_end = new; + new->next = NULL; + return 0; +} + +static int do_receipts(Messenger *m, int32_t friendnumber) +{ + if (friend_not_valid(m, friendnumber)) + return -1; + + struct Receipts *receipts = m->friendlist[friendnumber].receipts_start; + + while (receipts) { + struct Receipts *temp_r = receipts->next; + + if (cryptpacket_received(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id, receipts->packet_num) == -1) + break; + + if (m->read_receipt) + (*m->read_receipt)(m, friendnumber, receipts->msg_id, m->read_receipt_userdata); + + free(receipts); + m->friendlist[friendnumber].receipts_start = temp_r; + receipts = temp_r; + } + + if (!m->friendlist[friendnumber].receipts_start) + m->friendlist[friendnumber].receipts_end = NULL; + + return 0; +} + +static uint32_t send_message_generic(Messenger *m, int32_t friendnumber, const uint8_t *message, uint32_t length, + uint8_t packet_id) +{ + if (friend_not_valid(m, friendnumber)) + return 0; + + if (length >= MAX_CRYPTO_DATA_SIZE || m->friendlist[friendnumber].status != FRIEND_ONLINE) + return 0; + + uint8_t packet[length + 1]; + packet[0] = packet_id; + + if (length != 0) + memcpy(packet + 1, message, length); + + int64_t packet_num = write_cryptpacket(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id, packet, + length + 1); + + if (packet_num == -1) + return 0; + + uint32_t msg_id = ++m->friendlist[friendnumber].message_id; + + if (msg_id == 0) { + msg_id = ++m->friendlist[friendnumber].message_id; // Otherwise, false error + } + + add_receipt(m, friendnumber, packet_num, msg_id); + return msg_id; +} + /* Send a text chat message to an online friend. * * return the message id if packet was successfully put into the send queue. @@ -370,32 +470,7 @@ int m_friend_exists(const Messenger *m, int32_t friendnumber) */ uint32_t m_sendmessage(Messenger *m, int32_t friendnumber, const uint8_t *message, uint32_t length) { - if (friend_not_valid(m, friendnumber)) - return 0; - - uint32_t msgid = ++m->friendlist[friendnumber].message_id; - - if (msgid == 0) - msgid = 1; // Otherwise, false error - - if (m_sendmessage_withid(m, friendnumber, msgid, message, length)) { - return msgid; - } - - return 0; -} - -uint32_t m_sendmessage_withid(Messenger *m, int32_t friendnumber, uint32_t theid, const uint8_t *message, - uint32_t length) -{ - if (length >= (MAX_CRYPTO_DATA_SIZE - sizeof(theid)) || length == 0) - return 0; - - uint8_t temp[sizeof(theid) + length]; - theid = htonl(theid); - memcpy(temp, &theid, sizeof(theid)); - memcpy(temp + sizeof(theid), message, length); - return write_cryptpacket_id(m, friendnumber, PACKET_ID_MESSAGE, temp, sizeof(temp)); + return send_message_generic(m, friendnumber, message, length, PACKET_ID_MESSAGE); } /* Send an action to an online friend. @@ -405,32 +480,7 @@ uint32_t m_sendmessage_withid(Messenger *m, int32_t friendnumber, uint32_t theid */ uint32_t m_sendaction(Messenger *m, int32_t friendnumber, const uint8_t *action, uint32_t length) { - if (friend_not_valid(m, friendnumber)) - return 0; - - uint32_t msgid = ++m->friendlist[friendnumber].message_id; - - if (msgid == 0) - msgid = 1; // Otherwise, false error - - if (m_sendaction_withid(m, friendnumber, msgid, action, length)) { - return msgid; - } - - return 0; -} - -uint32_t m_sendaction_withid(const Messenger *m, int32_t friendnumber, uint32_t theid, const uint8_t *action, - uint32_t length) -{ - if (length >= (MAX_CRYPTO_DATA_SIZE - sizeof(theid)) || length == 0) - return 0; - - uint8_t temp[sizeof(theid) + length]; - theid = htonl(theid); - memcpy(temp, &theid, sizeof(theid)); - memcpy(temp + sizeof(theid), action, length); - return write_cryptpacket_id(m, friendnumber, PACKET_ID_ACTION, temp, sizeof(temp)); + return send_message_generic(m, friendnumber, action, length, PACKET_ID_ACTION); } /* Send a name packet to friendnumber. @@ -725,18 +775,6 @@ static void set_friend_typing(const Messenger *m, int32_t friendnumber, uint8_t m->friendlist[friendnumber].is_typing = is_typing; } -/* Sets whether we send read receipts for friendnumber. */ -void m_set_sends_receipts(Messenger *m, int32_t friendnumber, int yesno) -{ - if (yesno != 0 && yesno != 1) - return; - - if (friend_not_valid(m, friendnumber)) - return; - - m->friendlist[friendnumber].receives_read_receipts = yesno; -} - /* static void (*friend_request)(uint8_t *, uint8_t *, uint16_t); */ /* Set the function that will be executed when a friend request is received. */ void m_callback_friendrequest(Messenger *m, void (*function)(Messenger *m, const uint8_t *, const uint8_t *, uint16_t, @@ -821,6 +859,7 @@ static void check_friend_connectionstatus(Messenger *m, int32_t friendnumber, ui if (was_online) { break_files(m, friendnumber); remove_online_friend(m, friendnumber); + clear_receipts(m, friendnumber); } else { add_online_friend(m, friendnumber); } @@ -842,8 +881,8 @@ void set_friend_status(Messenger *m, int32_t friendnumber, uint8_t status) m->friendlist[friendnumber].status = status; } -int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_t packet_id, const uint8_t *data, - uint32_t length) +static int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_t packet_id, const uint8_t *data, + uint32_t length) { if (friend_not_valid(m, friendnumber)) return 0; @@ -1916,8 +1955,8 @@ void kill_messenger(Messenger *m) kill_networking(m->net); for (i = 0; i < m->numfriends; ++i) { - if (m->friendlist[i].statusmessage) - free(m->friendlist[i].statusmessage); + clear_receipts(m, i); + free(m->friendlist[i].statusmessage); } free(m->friendlist); @@ -2051,24 +2090,17 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) } case PACKET_ID_MESSAGE: { - const uint8_t *message_id = data; - uint8_t message_id_length = 4; - - if (data_length <= message_id_length) + if (data_length == 0) break; - const uint8_t *message = data + message_id_length; - uint16_t message_length = data_length - message_id_length; + const uint8_t *message = data; + uint16_t message_length = data_length; /* Make sure the NULL terminator is present. */ uint8_t message_terminated[message_length + 1]; memcpy(message_terminated, message, message_length); message_terminated[message_length] = 0; - if (m->friendlist[i].receives_read_receipts) { - write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length); - } - if (m->friend_message) (*m->friend_message)(m, i, message_terminated, message_length, m->friend_message_userdata); @@ -2076,24 +2108,17 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) } case PACKET_ID_ACTION: { - const uint8_t *message_id = data; - uint8_t message_id_length = 4; - - if (data_length <= message_id_length) + if (data_length == 0) break; - const uint8_t *action = data + message_id_length; - uint16_t action_length = data_length - message_id_length; + const uint8_t *action = data; + uint16_t action_length = data_length; /* Make sure the NULL terminator is present. */ uint8_t action_terminated[action_length + 1]; memcpy(action_terminated, action, action_length); action_terminated[action_length] = 0; - if (m->friendlist[i].receives_read_receipts) { - write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length); - } - if (m->friend_action) (*m->friend_action)(m, i, action_terminated, action_length, m->friend_action_userdata); @@ -2101,21 +2126,6 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) break; } - case PACKET_ID_RECEIPT: { - uint32_t msgid; - - if (data_length < sizeof(msgid)) - break; - - memcpy(&msgid, data, sizeof(msgid)); - msgid = ntohl(msgid); - - if (m->read_receipt) - (*m->read_receipt)(m, i, msgid, m->read_receipt_userdata); - - break; - } - case PACKET_ID_INVITE_GROUPCHAT: { if (data_length != crypto_box_PUBLICKEYBYTES) break; @@ -2348,6 +2358,8 @@ void do_friends(Messenger *m) if (m->friendlist[i].share_relays_lastsent + FRIEND_SHARE_RELAYS_INTERVAL < temp_time) { send_relays(m, i); } + + do_receipts(m, i); } } } diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index c45eaff9..c9f3cf88 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -46,7 +46,6 @@ #define PACKET_ID_STATUSMESSAGE 49 #define PACKET_ID_USERSTATUS 50 #define PACKET_ID_TYPING 51 -#define PACKET_ID_RECEIPT 63 #define PACKET_ID_MESSAGE 64 #define PACKET_ID_ACTION 65 #define PACKET_ID_MSI 69 @@ -74,6 +73,13 @@ typedef struct { TCP_Proxy_Info proxy_info; } Messenger_Options; + +struct Receipts { + uint32_t packet_num; + uint32_t msg_id; + struct Receipts *next; +}; + /* Status definitions. */ enum { NOFRIEND, @@ -168,7 +174,6 @@ typedef struct { uint8_t is_typing; uint16_t info_size; // Length of the info. uint32_t message_id; // a semi-unique id used in read receipts. - uint8_t receives_read_receipts; // shall we send read receipts to this person? uint32_t friendrequest_nospam; // The nospam number used in the friend request. uint64_t ping_lastrecv; uint64_t ping_lastsent; @@ -187,6 +192,9 @@ typedef struct { int (*function)(void *object, const uint8_t *data, uint32_t len); void *object; } lossless_packethandlers[PACKET_ID_LOSSLESS_RANGE_SIZE]; + + struct Receipts *receipts_start; + struct Receipts *receipts_end; } Friend; @@ -335,12 +343,8 @@ int m_friend_exists(const Messenger *m, int32_t friendnumber); * * You will want to retain the return value, it will be passed to your read_receipt callback * if one is received. - * m_sendmessage_withid will send a message with the id of your choosing, - * however we can generate an id for you by calling plain m_sendmessage. */ uint32_t m_sendmessage(Messenger *m, int32_t friendnumber, const uint8_t *message, uint32_t length); -uint32_t m_sendmessage_withid(Messenger *m, int32_t friendnumber, uint32_t theid, const uint8_t *message, - uint32_t length); /* Send an action to an online friend. * @@ -349,12 +353,8 @@ uint32_t m_sendmessage_withid(Messenger *m, int32_t friendnumber, uint32_t theid * * You will want to retain the return value, it will be passed to your read_receipt callback * if one is received. - * m_sendaction_withid will send an action message with the id of your choosing, - * however we can generate an id for you by calling plain m_sendaction. */ uint32_t m_sendaction(Messenger *m, int32_t friendnumber, const uint8_t *action, uint32_t length); -uint32_t m_sendaction_withid(const Messenger *m, int32_t friendnumber, uint32_t theid, const uint8_t *action, - uint32_t length); /* Set the name and name_length of a friend. * name must be a string of maximum MAX_NAME_LENGTH length. @@ -453,11 +453,6 @@ int m_set_usertyping(Messenger *m, int32_t friendnumber, uint8_t is_typing); */ uint8_t m_get_istyping(const Messenger *m, int32_t friendnumber); -/* Sets whether we send read receipts for friendnumber. - * This function is not lazy, and it will fail if yesno is not (0 or 1). - */ -void m_set_sends_receipts(Messenger *m, int32_t friendnumber, int yesno); - /* Set the function that will be executed when a friend request is received. * Function format is function(uint8_t * public_key, uint8_t * data, uint16_t length) */ diff --git a/toxcore/tox.h b/toxcore/tox.h index 550600f9..08c2b3a2 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -34,7 +34,7 @@ extern "C" { #define TOX_MAX_NAME_LENGTH 128 /* Maximum length of single messages after which they should be split. */ -#define TOX_MAX_MESSAGE_LENGTH 1368 +#define TOX_MAX_MESSAGE_LENGTH 1372 #define TOX_MAX_STATUSMESSAGE_LENGTH 1007 #define TOX_CLIENT_ID_SIZE 32