Merge branch 'fixed-receipts' into new_api

This commit is contained in:
irungentoo 2015-02-20 16:39:33 -05:00
commit af881e820a
No known key found for this signature in database
GPG Key ID: 10349DC9BED89E98
3 changed files with 123 additions and 112 deletions

View File

@ -214,7 +214,6 @@ static int32_t init_new_friend(Messenger *m, const uint8_t *real_pk, uint8_t sta
m->friendlist[i].avatar_send_data.last_reset = 0; m->friendlist[i].avatar_send_data.last_reset = 0;
m->friendlist[i].is_typing = 0; m->friendlist[i].is_typing = 0;
m->friendlist[i].message_id = 0; m->friendlist[i].message_id = 0;
m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */
friend_connection_callbacks(m->fr_c, friendcon_id, MESSENGER_CALLBACK_INDEX, &handle_status, &handle_packet, friend_connection_callbacks(m->fr_c, friendcon_id, MESSENGER_CALLBACK_INDEX, &handle_status, &handle_packet,
&handle_custom_lossy_packet, m, i); &handle_custom_lossy_packet, m, i);
@ -315,6 +314,75 @@ int32_t m_addfriend_norequest(Messenger *m, const uint8_t *real_pk)
return init_new_friend(m, real_pk, FRIEND_CONFIRMED); return init_new_friend(m, real_pk, FRIEND_CONFIRMED);
} }
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, friend_connection_crypt_connection_id(m->fr_c, m->friendlist[friendnumber].friendcon_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;
}
/* Remove a friend. /* Remove a friend.
* *
* return 0 if success. * return 0 if success.
@ -329,6 +397,7 @@ int m_delfriend(Messenger *m, int32_t friendnumber)
remove_online_friend(m, friendnumber); remove_online_friend(m, friendnumber);
free(m->friendlist[friendnumber].avatar_recv_data); free(m->friendlist[friendnumber].avatar_recv_data);
clear_receipts(m, friendnumber);
remove_request_received(&(m->fr), m->friendlist[friendnumber].real_pk); remove_request_received(&(m->fr), m->friendlist[friendnumber].real_pk);
friend_connection_callbacks(m->fr_c, m->friendlist[friendnumber].friendcon_id, MESSENGER_CALLBACK_INDEX, 0, 0, 0, 0, 0); friend_connection_callbacks(m->fr_c, m->friendlist[friendnumber].friendcon_id, MESSENGER_CALLBACK_INDEX, 0, 0, 0, 0, 0);
kill_friend_connection(m->fr_c, m->friendlist[friendnumber].friendcon_id); kill_friend_connection(m->fr_c, m->friendlist[friendnumber].friendcon_id);
@ -381,6 +450,37 @@ int m_friend_exists(const Messenger *m, int32_t friendnumber)
return 1; return 1;
} }
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, friend_connection_crypt_connection_id(m->fr_c, m->friendlist[friendnumber].friendcon_id), packet, length + 1, 0);
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. /* Send a text chat message to an online friend.
* *
* return the message id if packet was successfully put into the send queue. * return the message id if packet was successfully put into the send queue.
@ -388,32 +488,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) uint32_t m_sendmessage(Messenger *m, int32_t friendnumber, const uint8_t *message, uint32_t length)
{ {
if (friend_not_valid(m, friendnumber)) return send_message_generic(m, friendnumber, message, length, PACKET_ID_MESSAGE);
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), 0);
} }
/* Send an action to an online friend. /* Send an action to an online friend.
@ -423,32 +498,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) uint32_t m_sendaction(Messenger *m, int32_t friendnumber, const uint8_t *action, uint32_t length)
{ {
if (friend_not_valid(m, friendnumber)) return send_message_generic(m, friendnumber, action, length, PACKET_ID_ACTION);
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), 0);
} }
/* Send a name packet to friendnumber. /* Send a name packet to friendnumber.
@ -886,18 +936,6 @@ static void set_friend_typing(const Messenger *m, int32_t friendnumber, uint8_t
m->friendlist[friendnumber].is_typing = is_typing; 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;
}
/* Set the function that will be executed when a friend request is received. */ /* 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 *, size_t, void m_callback_friendrequest(Messenger *m, void (*function)(Messenger *m, const uint8_t *, const uint8_t *, size_t,
void *), void *userdata) void *), void *userdata)
@ -1011,6 +1049,7 @@ static void check_friend_connectionstatus(Messenger *m, int32_t friendnumber, ui
if (was_online) { if (was_online) {
break_files(m, friendnumber); break_files(m, friendnumber);
remove_online_friend(m, friendnumber); remove_online_friend(m, friendnumber);
clear_receipts(m, friendnumber);
} else { } else {
add_online_friend(m, friendnumber); add_online_friend(m, friendnumber);
} }
@ -1660,6 +1699,7 @@ void kill_messenger(Messenger *m)
for (i = 0; i < m->numfriends; ++i) { for (i = 0; i < m->numfriends; ++i) {
free(m->friendlist[i].avatar_recv_data); free(m->friendlist[i].avatar_recv_data);
clear_receipts(m, i);
} }
free(m->avatar_data); free(m->avatar_data);
@ -2083,23 +2123,18 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len)
case PACKET_ID_MESSAGE: { case PACKET_ID_MESSAGE: {
const uint8_t *message_id = data; const uint8_t *message_id = data;
uint8_t message_id_length = 4;
if (data_length <= message_id_length) if (data_length == 0)
break; break;
const uint8_t *message = data + message_id_length; const uint8_t *message = data;
uint16_t message_length = data_length - message_id_length; uint16_t message_length = data_length;
/* Make sure the NULL terminator is present. */ /* Make sure the NULL terminator is present. */
uint8_t message_terminated[message_length + 1]; uint8_t message_terminated[message_length + 1];
memcpy(message_terminated, message, message_length); memcpy(message_terminated, message, message_length);
message_terminated[message_length] = 0; 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, 0);
}
if (m->friend_message) if (m->friend_message)
(*m->friend_message)(m, i, message_terminated, message_length, m->friend_message_userdata); (*m->friend_message)(m, i, message_terminated, message_length, m->friend_message_userdata);
@ -2108,23 +2143,18 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len)
case PACKET_ID_ACTION: { case PACKET_ID_ACTION: {
const uint8_t *message_id = data; const uint8_t *message_id = data;
uint8_t message_id_length = 4;
if (data_length <= message_id_length) if (data_length == 0)
break; break;
const uint8_t *action = data + message_id_length; const uint8_t *action = data;
uint16_t action_length = data_length - message_id_length; uint16_t action_length = data_length;
/* Make sure the NULL terminator is present. */ /* Make sure the NULL terminator is present. */
uint8_t action_terminated[action_length + 1]; uint8_t action_terminated[action_length + 1];
memcpy(action_terminated, action, action_length); memcpy(action_terminated, action, action_length);
action_terminated[action_length] = 0; 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, 0);
}
if (m->friend_action) if (m->friend_action)
(*m->friend_action)(m, i, action_terminated, action_length, m->friend_action_userdata); (*m->friend_action)(m, i, action_terminated, action_length, m->friend_action_userdata);
@ -2168,21 +2198,6 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len)
break; 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: { case PACKET_ID_INVITE_GROUPCHAT: {
if (data_length == 0) if (data_length == 0)
break; break;
@ -2346,6 +2361,7 @@ void do_friends(Messenger *m)
} }
check_friend_tcp_udp(m, i); check_friend_tcp_udp(m, i);
do_receipts(m, i);
} }
} }
} }

View File

@ -52,7 +52,6 @@
#define PACKET_ID_AVATAR_DATA_CONTROL 54 #define PACKET_ID_AVATAR_DATA_CONTROL 54
#define PACKET_ID_AVATAR_DATA_START 55 #define PACKET_ID_AVATAR_DATA_START 55
#define PACKET_ID_AVATAR_DATA_PUSH 56 #define PACKET_ID_AVATAR_DATA_PUSH 56
#define PACKET_ID_RECEIPT 63
#define PACKET_ID_MESSAGE 64 #define PACKET_ID_MESSAGE 64
#define PACKET_ID_ACTION 65 #define PACKET_ID_ACTION 65
#define PACKET_ID_MSI 69 #define PACKET_ID_MSI 69
@ -78,6 +77,13 @@ typedef struct {
TCP_Proxy_Info proxy_info; TCP_Proxy_Info proxy_info;
} Messenger_Options; } Messenger_Options;
struct Receipts {
uint32_t packet_num;
uint32_t msg_id;
struct Receipts *next;
};
/* Status definitions. */ /* Status definitions. */
enum { enum {
NOFRIEND, NOFRIEND,
@ -217,7 +223,6 @@ typedef struct {
uint8_t is_typing; uint8_t is_typing;
uint16_t info_size; // Length of the info. uint16_t info_size; // Length of the info.
uint32_t message_id; // a semi-unique id used in read receipts. 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. uint32_t friendrequest_nospam; // The nospam number used in the friend request.
uint64_t ping_lastrecv;//TODO remove uint64_t ping_lastrecv;//TODO remove
uint64_t share_relays_lastsent; uint64_t share_relays_lastsent;
@ -237,6 +242,9 @@ typedef struct {
int (*function)(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint32_t len, void *object); int (*function)(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint32_t len, void *object);
void *object; void *object;
} lossless_packethandlers[PACKET_ID_LOSSLESS_RANGE_SIZE]; } lossless_packethandlers[PACKET_ID_LOSSLESS_RANGE_SIZE];
struct Receipts *receipts_start;
struct Receipts *receipts_end;
} Friend; } Friend;
@ -400,12 +408,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 * You will want to retain the return value, it will be passed to your read_receipt callback
* if one is received. * 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(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. /* Send an action to an online friend.
* *
@ -414,12 +418,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 * You will want to retain the return value, it will be passed to your read_receipt callback
* if one is received. * 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(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. /* Set the name and name_length of a friend.
* name must be a string of maximum MAX_NAME_LENGTH length. * 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);
*/ */
int m_get_istyping(const Messenger *m, int32_t friendnumber); int 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. /* Set the function that will be executed when a friend request is received.
* Function format is function(uint8_t * public_key, uint8_t * data, size_t length) * Function format is function(uint8_t * public_key, uint8_t * data, size_t length)
*/ */

View File

@ -238,7 +238,7 @@ bool tox_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch);
/** /**
* Maximum length of a single message after which it should be split. * Maximum length of a single message after which it should be split.
*/ */
#define TOX_MAX_MESSAGE_LENGTH 1368 #define TOX_MAX_MESSAGE_LENGTH 1372
/** /**
* Maximum size of custom packets. TODO: should be LENGTH? * Maximum size of custom packets. TODO: should be LENGTH?