Add read receipts using packet ID 65.

This commit is contained in:
Sebastian Stal 2013-08-07 09:53:52 -07:00
parent 39a213a58c
commit 105e2fa4a3
2 changed files with 57 additions and 9 deletions

View File

@ -37,6 +37,8 @@ typedef struct {
uint8_t userstatus_sent; uint8_t userstatus_sent;
USERSTATUS_KIND userstatus_kind; USERSTATUS_KIND userstatus_kind;
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 */
uint8_t receives_read_receipts; /* shall we send read receipts to this person? */
} Friend; } Friend;
uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; 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; friendlist[i].userstatus_kind = USERSTATUS_KIND_OFFLINE;
memcpy(friendlist[i].info, data, length); memcpy(friendlist[i].info, data, length);
friendlist[i].info_size = length; friendlist[i].info_size = length;
friendlist[i].message_id = 0;
friendlist[i].receives_read_receipts = 1; /* default: YES */
++numfriends; ++numfriends;
return i; return i;
@ -150,6 +154,8 @@ int m_addfriend_norequest(uint8_t * client_id)
memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE); memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE);
friendlist[i].userstatus = calloc(1, 1); friendlist[i].userstatus = calloc(1, 1);
friendlist[i].userstatus_length = 1; friendlist[i].userstatus_length = 1;
friendlist[i].message_id = 0;
friendlist[i].receives_read_receipts = 1; /* default: YES */
numfriends++; numfriends++;
return i; return i;
} }
@ -193,19 +199,30 @@ int m_friendstatus(int friendnumber)
} }
/* send a text chat message to an online friend /* 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 */ 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) if (friendnumber < 0 || friendnumber >= numfriends)
return 0; 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. */ /* this does not mean the maximum message length is MAX_DATA_SIZE - 1, it is actually 17 bytes less. */
return 0; return 0;
uint8_t temp[MAX_DATA_SIZE]; uint8_t temp[MAX_DATA_SIZE];
temp[0] = PACKET_ID_MESSAGE; temp[0] = PACKET_ID_MESSAGE;
memcpy(temp + 1, message, length); temp[1] = theid >> 24;
return write_cryptpacket(friendlist[friendnumber].crypt_connection_id, temp, length + 1); 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 /* 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; 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 #define PORT 33445
/* run this at startup */ /* run this at startup */
int initMessenger(void) int initMessenger(void)
@ -499,8 +524,23 @@ static void doFriends(void)
break; break;
} }
case PACKET_ID_MESSAGE: { 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) 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; break;
} }
} }

View File

@ -40,6 +40,7 @@ extern "C" {
#define PACKET_ID_NICKNAME 48 #define PACKET_ID_NICKNAME 48
#define PACKET_ID_USERSTATUS 49 #define PACKET_ID_USERSTATUS 49
#define PACKET_ID_RECEIPT 65
#define PACKET_ID_MESSAGE 64 #define PACKET_ID_MESSAGE 64
/* status definitions */ /* status definitions */
@ -117,9 +118,14 @@ int m_delfriend(int friendnumber);
int m_friendstatus(int friendnumber); int m_friendstatus(int friendnumber);
/* send a text chat message to an online friend /* send a text chat message to an online friend
returns 1 if packet was successfully put into the send queue returns the message id if packet was successfully put into the send queue
return 0 if it was not */ return 0 if it was not
int m_sendmessage(int friendnumber, uint8_t *message, uint32_t length); 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 /* Set our nickname
name must be a string of maximum MAX_NAME_LENGTH length. 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 */ you are not responsible for freeing newstatus */
void m_callback_userstatus(void (*function)(int, USERSTATUS_KIND, uint8_t *, uint16_t)); 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 /* run this at startup
returns 0 if no connection problems returns 0 if no connection problems
returns -1 if there are problems */ returns -1 if there are problems */