From 105e2fa4a38de07493f9388ab23acba2b2969458 Mon Sep 17 00:00:00 2001 From: Sebastian Stal Date: Wed, 7 Aug 2013 09:53:52 -0700 Subject: 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 */ -- cgit v1.2.3 From 9f6262f3ddb7be3cbb9a12c9b4a2e1f96c5dcfbf Mon Sep 17 00:00:00 2001 From: Sebastian Stal Date: Wed, 7 Aug 2013 09:57:23 -0700 Subject: Check for correct error value in toxic. --- testing/toxic/chat.c | 2 +- testing/toxic/prompt.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/testing/toxic/chat.c b/testing/toxic/chat.c index 7262e722..bad4cbfa 100644 --- a/testing/toxic/chat.c +++ b/testing/toxic/chat.c @@ -127,7 +127,7 @@ static void chat_onKey(ToxWindow* self, int key) { wattroff(ctx->history, COLOR_PAIR(1)); wprintw(ctx->history, "%s\n", ctx->line); } - if(m_sendmessage(ctx->friendnum, (uint8_t*) ctx->line, strlen(ctx->line)+1) < 0) { + if(m_sendmessage(ctx->friendnum, (uint8_t*) ctx->line, strlen(ctx->line)+1) == 0) { wattron(ctx->history, COLOR_PAIR(3)); wprintw(ctx->history, " * Failed to send message.\n"); wattroff(ctx->history, COLOR_PAIR(3)); diff --git a/testing/toxic/prompt.c b/testing/toxic/prompt.c index 20f6b480..670a93a2 100644 --- a/testing/toxic/prompt.c +++ b/testing/toxic/prompt.c @@ -45,7 +45,7 @@ static void execute(ToxWindow* self, char* u_cmd) { int i; int newlines = 0; char cmd[256] = {0}; - for(i = 0; i < strlen(prompt_buf); i++) + for(i = 0; i < strlen(prompt_buf); i++) { if (u_cmd[i] == '\n') ++newlines; @@ -260,7 +260,7 @@ static void execute(ToxWindow* self, char* u_cmd) { msg[0] = 0; msg++; - if(m_sendmessage(atoi(id), (uint8_t*) msg, strlen(msg)+1) < 0) { + if(m_sendmessage(atoi(id), (uint8_t*) msg, strlen(msg)+1) == 0) { wprintw(self->window, "Error occurred while sending message.\n"); } else { @@ -338,7 +338,7 @@ static void print_usage(ToxWindow* self) { wprintw(self->window, " myid : Print your ID\n"); wprintw(self->window, " quit/exit : Exit program\n"); wprintw(self->window, " help : Print this message again\n"); - wprintw(self->window, " clear : Clear this window\n"); + wprintw(self->window, " clear : Clear this window\n"); wattron(self->window, A_BOLD); wprintw(self->window, "TIP: Use the TAB key to navigate through the tabs.\n\n"); -- cgit v1.2.3 From c0828667e70fdd92fd01c581ce04dfc451e01860 Mon Sep 17 00:00:00 2001 From: Sebastian Stal Date: Wed, 7 Aug 2013 10:06:07 -0700 Subject: Document functions, and fix bug. --- core/Messenger.c | 15 ++++++++++++++- core/Messenger.h | 11 +++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/core/Messenger.c b/core/Messenger.c index a4195d58..353ce603 100644 --- a/core/Messenger.c +++ b/core/Messenger.c @@ -205,7 +205,10 @@ uint32_t m_sendmessage(int friendnumber, uint8_t *message, uint32_t length) { if (friendnumber < 0 || friendnumber >= numfriends) return 0; - return m_sendmessage_withid(friendnumber, friendlist[friendnumber].message_id++, message, length); + uint32_t msgid = ++friendlist[friendnumber].message_id; + if (msgid == 0) + msgid = 1; /* otherwise, false error */ + return m_sendmessage_withid(friendnumber, msgid, message, length); } uint32_t m_sendmessage_withid(int friendnumber, uint32_t theid, uint8_t *message, uint32_t length) @@ -391,6 +394,16 @@ static void set_friend_userstatus_kind(int friendnumber, USERSTATUS_KIND k) friendlist[friendnumber].userstatus_kind = k; } +/* Sets whether we send read receipts for friendnumber. */ +void m_set_sends_receipts(int friendnumber, int yesno) +{ + if (yesno < 0 || yesno > 1) + return; + if (friendnumber >= numfriends || friendnumber < 0) + return; + friendlist[friendnumber].receives_read_receipts = yesno; +} + /* static void (*friend_request)(uint8_t *, uint8_t *, uint16_t); static uint8_t friend_request_isset = 0; */ /* set the function that will be executed when a friend request is received. */ diff --git a/core/Messenger.h b/core/Messenger.h index 0e4eabe0..f0444b91 100644 --- a/core/Messenger.h +++ b/core/Messenger.h @@ -171,6 +171,10 @@ int m_copy_self_userstatus(uint8_t *buf, uint32_t maxlen); USERSTATUS_KIND m_get_userstatus_kind(int friendnumber); USERSTATUS_KIND m_get_self_userstatus_kind(void); +/* 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(int 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) */ void m_callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t)); @@ -189,6 +193,13 @@ 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)); +/* set the callback for read receipts + function(int friendnumber, uint32_t receipt) + if you are keeping a record of returns from m_sendmessage, + receipt might be one of those values, and that means the message + has been received on the other side. since core doesn't + track ids for you, receipt may not correspond to any message + in that case, you should discard it. */ void m_callback_read_receipt(void (*function)(int, uint32_t)); /* run this at startup -- cgit v1.2.3