From 105e2fa4a38de07493f9388ab23acba2b2969458 Mon Sep 17 00:00:00 2001 From: Sebastian Stal Date: Wed, 7 Aug 2013 09:53:52 -0700 Subject: [PATCH] Add read receipts using packet ID 65. --- core/Messenger.c | 52 ++++++++++++++++++++++++++++++++++++++++++------ core/Messenger.h | 14 ++++++++++--- 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/core/Messenger.c b/core/Messenger.c index d8bf3413..a4195d58 100644 --- a/core/Messenger.c +++ b/core/Messenger.c @@ -37,6 +37,8 @@ typedef struct { uint8_t userstatus_sent; USERSTATUS_KIND userstatus_kind; 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? */ } Friend; uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; @@ -128,6 +130,8 @@ int m_addfriend(uint8_t *client_id, uint8_t *data, uint16_t length) friendlist[i].userstatus_kind = USERSTATUS_KIND_OFFLINE; memcpy(friendlist[i].info, data, length); friendlist[i].info_size = length; + friendlist[i].message_id = 0; + friendlist[i].receives_read_receipts = 1; /* default: YES */ ++numfriends; return i; @@ -150,6 +154,8 @@ int m_addfriend_norequest(uint8_t * client_id) memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE); friendlist[i].userstatus = calloc(1, 1); friendlist[i].userstatus_length = 1; + friendlist[i].message_id = 0; + friendlist[i].receives_read_receipts = 1; /* default: YES */ numfriends++; return i; } @@ -193,19 +199,30 @@ int m_friendstatus(int friendnumber) } /* send a text chat message to an online friend - return 1 if packet was successfully put into the send queue + return the message id if packet was successfully put into the send queue return 0 if it was not */ -int m_sendmessage(int friendnumber, uint8_t *message, uint32_t length) +uint32_t m_sendmessage(int friendnumber, uint8_t *message, uint32_t length) { if (friendnumber < 0 || friendnumber >= numfriends) return 0; - if (length >= MAX_DATA_SIZE || friendlist[friendnumber].status != FRIEND_ONLINE) + return m_sendmessage_withid(friendnumber, friendlist[friendnumber].message_id++, message, length); +} + +uint32_t m_sendmessage_withid(int friendnumber, uint32_t theid, uint8_t *message, uint32_t length) +{ + if (friendnumber < 0 || friendnumber >= numfriends) + return 0; + if (length >= (MAX_DATA_SIZE - 4) || friendlist[friendnumber].status != FRIEND_ONLINE) /* this does not mean the maximum message length is MAX_DATA_SIZE - 1, it is actually 17 bytes less. */ return 0; uint8_t temp[MAX_DATA_SIZE]; temp[0] = PACKET_ID_MESSAGE; - memcpy(temp + 1, message, length); - return write_cryptpacket(friendlist[friendnumber].crypt_connection_id, temp, length + 1); + temp[1] = theid >> 24; + temp[2] = theid >> 16; + temp[3] = theid >> 8; + temp[4] = theid; + memcpy(temp + 5, message, length); + return write_cryptpacket(friendlist[friendnumber].crypt_connection_id, temp, length + 5); } /* send a name packet to friendnumber @@ -408,6 +425,14 @@ void m_callback_userstatus(void (*function)(int, USERSTATUS_KIND, uint8_t *, uin friend_statuschange_isset = 1; } +static void (*read_receipt)(int, uint32_t); +static uint8_t read_receipt_isset = 0; +void m_callback_read_receipt(void (*function)(int, uint32_t)) +{ + read_receipt = function; + read_receipt_isset = 1; +} + #define PORT 33445 /* run this at startup */ int initMessenger(void) @@ -499,8 +524,23 @@ static void doFriends(void) break; } case PACKET_ID_MESSAGE: { + if (friendlist[i].receives_read_receipts) { + uint8_t *thepacket = malloc(5); + thepacket[0] = PACKET_ID_RECEIPT; + memcpy(thepacket + 1, temp + 1, 4); + write_cryptpacket(friendlist[i].crypt_connection_id, thepacket, 5); + free(thepacket); + } if (friend_message_isset) - (*friend_message)(i, temp + 1, len - 1); + (*friend_message)(i, temp + 5, len - 5); + break; + } + case PACKET_ID_RECEIPT: { + if (len < 5) + break; + uint32_t msgid = (temp[1] << 24) | (temp[2] << 16) | (temp[3] << 8) | temp[4]; + if (read_receipt_isset) + (*read_receipt)(i, msgid); break; } } diff --git a/core/Messenger.h b/core/Messenger.h index 8940aadd..0e4eabe0 100644 --- a/core/Messenger.h +++ b/core/Messenger.h @@ -40,6 +40,7 @@ extern "C" { #define PACKET_ID_NICKNAME 48 #define PACKET_ID_USERSTATUS 49 +#define PACKET_ID_RECEIPT 65 #define PACKET_ID_MESSAGE 64 /* status definitions */ @@ -117,9 +118,14 @@ int m_delfriend(int friendnumber); int m_friendstatus(int friendnumber); /* send a text chat message to an online friend - returns 1 if packet was successfully put into the send queue - return 0 if it was not */ -int m_sendmessage(int friendnumber, uint8_t *message, uint32_t length); + returns the message id if packet was successfully put into the send queue + return 0 if it was not + 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(int friendnumber, uint8_t *message, uint32_t length); +uint32_t m_sendmessage_withid(int friendnumber, uint32_t theid, uint8_t *message, uint32_t length); /* Set our nickname name must be a string of maximum MAX_NAME_LENGTH length. @@ -183,6 +189,8 @@ void m_callback_namechange(void (*function)(int, uint8_t *, uint16_t)); you are not responsible for freeing newstatus */ void m_callback_userstatus(void (*function)(int, USERSTATUS_KIND, uint8_t *, uint16_t)); +void m_callback_read_receipt(void (*function)(int, uint32_t)); + /* run this at startup returns 0 if no connection problems returns -1 if there are problems */