diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/Messenger.c | 65 | ||||
-rw-r--r-- | core/Messenger.h | 25 |
2 files changed, 81 insertions, 9 deletions
diff --git a/core/Messenger.c b/core/Messenger.c index 4e994a15..b29bd1f1 100644 --- a/core/Messenger.c +++ b/core/Messenger.c | |||
@@ -37,6 +37,8 @@ typedef struct { | |||
37 | uint8_t userstatus_sent; | 37 | uint8_t userstatus_sent; |
38 | USERSTATUS_KIND userstatus_kind; | 38 | USERSTATUS_KIND userstatus_kind; |
39 | uint16_t info_size; /* length of the info */ | 39 | uint16_t info_size; /* length of the info */ |
40 | uint32_t message_id; /* a semi-unique id used in read receipts */ | ||
41 | uint8_t receives_read_receipts; /* shall we send read receipts to this person? */ | ||
40 | } Friend; | 42 | } Friend; |
41 | 43 | ||
42 | uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; | 44 | 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) | |||
128 | friendlist[i].userstatus_kind = USERSTATUS_KIND_OFFLINE; | 130 | friendlist[i].userstatus_kind = USERSTATUS_KIND_OFFLINE; |
129 | memcpy(friendlist[i].info, data, length); | 131 | memcpy(friendlist[i].info, data, length); |
130 | friendlist[i].info_size = length; | 132 | friendlist[i].info_size = length; |
133 | friendlist[i].message_id = 0; | ||
134 | friendlist[i].receives_read_receipts = 1; /* default: YES */ | ||
131 | 135 | ||
132 | ++numfriends; | 136 | ++numfriends; |
133 | return i; | 137 | return i; |
@@ -150,6 +154,8 @@ int m_addfriend_norequest(uint8_t * client_id) | |||
150 | memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE); | 154 | memcpy(friendlist[i].client_id, client_id, CLIENT_ID_SIZE); |
151 | friendlist[i].userstatus = calloc(1, 1); | 155 | friendlist[i].userstatus = calloc(1, 1); |
152 | friendlist[i].userstatus_length = 1; | 156 | friendlist[i].userstatus_length = 1; |
157 | friendlist[i].message_id = 0; | ||
158 | friendlist[i].receives_read_receipts = 1; /* default: YES */ | ||
153 | numfriends++; | 159 | numfriends++; |
154 | return i; | 160 | return i; |
155 | } | 161 | } |
@@ -193,19 +199,31 @@ int m_friendstatus(int friendnumber) | |||
193 | } | 199 | } |
194 | 200 | ||
195 | /* send a text chat message to an online friend | 201 | /* send a text chat message to an online friend |
196 | return 1 if packet was successfully put into the send queue | 202 | return the message id if packet was successfully put into the send queue |
197 | return 0 if it was not */ | 203 | return 0 if it was not */ |
198 | int m_sendmessage(int friendnumber, uint8_t *message, uint32_t length) | 204 | uint32_t m_sendmessage(int friendnumber, uint8_t *message, uint32_t length) |
199 | { | 205 | { |
200 | if (friendnumber < 0 || friendnumber >= numfriends) | 206 | if (friendnumber < 0 || friendnumber >= numfriends) |
201 | return 0; | 207 | return 0; |
202 | if (length >= MAX_DATA_SIZE || friendlist[friendnumber].status != FRIEND_ONLINE) | 208 | uint32_t msgid = ++friendlist[friendnumber].message_id; |
209 | if (msgid == 0) | ||
210 | msgid = 1; /* otherwise, false error */ | ||
211 | return m_sendmessage_withid(friendnumber, msgid, message, length); | ||
212 | } | ||
213 | |||
214 | uint32_t m_sendmessage_withid(int friendnumber, uint32_t theid, uint8_t *message, uint32_t length) | ||
215 | { | ||
216 | if (friendnumber < 0 || friendnumber >= numfriends) | ||
217 | return 0; | ||
218 | if (length >= (MAX_DATA_SIZE - sizeof(theid)) || friendlist[friendnumber].status != FRIEND_ONLINE) | ||
203 | /* this does not mean the maximum message length is MAX_DATA_SIZE - 1, it is actually 17 bytes less. */ | 219 | /* this does not mean the maximum message length is MAX_DATA_SIZE - 1, it is actually 17 bytes less. */ |
204 | return 0; | 220 | return 0; |
205 | uint8_t temp[MAX_DATA_SIZE]; | 221 | uint8_t temp[MAX_DATA_SIZE]; |
206 | temp[0] = PACKET_ID_MESSAGE; | 222 | temp[0] = PACKET_ID_MESSAGE; |
207 | memcpy(temp + 1, message, length); | 223 | theid = htonl(theid); |
208 | return write_cryptpacket(friendlist[friendnumber].crypt_connection_id, temp, length + 1); | 224 | memcpy(temp + 1, &theid, sizeof(theid)); |
225 | memcpy(temp + 1 + sizeof(theid), message, length); | ||
226 | return write_cryptpacket(friendlist[friendnumber].crypt_connection_id, temp, length + 1 + sizeof(theid)); | ||
209 | } | 227 | } |
210 | 228 | ||
211 | /* send a name packet to friendnumber | 229 | /* send a name packet to friendnumber |
@@ -374,6 +392,16 @@ static void set_friend_userstatus_kind(int friendnumber, USERSTATUS_KIND k) | |||
374 | friendlist[friendnumber].userstatus_kind = k; | 392 | friendlist[friendnumber].userstatus_kind = k; |
375 | } | 393 | } |
376 | 394 | ||
395 | /* Sets whether we send read receipts for friendnumber. */ | ||
396 | void m_set_sends_receipts(int friendnumber, int yesno) | ||
397 | { | ||
398 | if (yesno != 0 || yesno != 1) | ||
399 | return; | ||
400 | if (friendnumber >= numfriends || friendnumber < 0) | ||
401 | return; | ||
402 | friendlist[friendnumber].receives_read_receipts = yesno; | ||
403 | } | ||
404 | |||
377 | /* static void (*friend_request)(uint8_t *, uint8_t *, uint16_t); | 405 | /* static void (*friend_request)(uint8_t *, uint8_t *, uint16_t); |
378 | static uint8_t friend_request_isset = 0; */ | 406 | static uint8_t friend_request_isset = 0; */ |
379 | /* set the function that will be executed when a friend request is received. */ | 407 | /* set the function that will be executed when a friend request is received. */ |
@@ -408,6 +436,14 @@ void m_callback_userstatus(void (*function)(int, USERSTATUS_KIND, uint8_t *, uin | |||
408 | friend_statuschange_isset = 1; | 436 | friend_statuschange_isset = 1; |
409 | } | 437 | } |
410 | 438 | ||
439 | static void (*read_receipt)(int, uint32_t); | ||
440 | static uint8_t read_receipt_isset = 0; | ||
441 | void m_callback_read_receipt(void (*function)(int, uint32_t)) | ||
442 | { | ||
443 | read_receipt = function; | ||
444 | read_receipt_isset = 1; | ||
445 | } | ||
446 | |||
411 | #define PORT 33445 | 447 | #define PORT 33445 |
412 | /* run this at startup */ | 448 | /* run this at startup */ |
413 | int initMessenger(void) | 449 | int initMessenger(void) |
@@ -499,8 +535,25 @@ static void doFriends(void) | |||
499 | break; | 535 | break; |
500 | } | 536 | } |
501 | case PACKET_ID_MESSAGE: { | 537 | case PACKET_ID_MESSAGE: { |
538 | if (friendlist[i].receives_read_receipts) { | ||
539 | uint8_t *thepacket = malloc(5); | ||
540 | thepacket[0] = PACKET_ID_RECEIPT; | ||
541 | memcpy(thepacket + 1, temp + 1, 4); | ||
542 | write_cryptpacket(friendlist[i].crypt_connection_id, thepacket, 5); | ||
543 | free(thepacket); | ||
544 | } | ||
502 | if (friend_message_isset) | 545 | if (friend_message_isset) |
503 | (*friend_message)(i, temp + 1, len - 1); | 546 | (*friend_message)(i, temp + 5, len - 5); |
547 | break; | ||
548 | } | ||
549 | case PACKET_ID_RECEIPT: { | ||
550 | uint32_t msgid; | ||
551 | if (len < 1 + sizeof(msgid)) | ||
552 | break; | ||
553 | memcpy(&msgid, temp + 1, sizeof(msgid)); | ||
554 | msgid = ntohl(msgid); | ||
555 | if (read_receipt_isset) | ||
556 | (*read_receipt)(i, msgid); | ||
504 | break; | 557 | break; |
505 | } | 558 | } |
506 | } | 559 | } |
diff --git a/core/Messenger.h b/core/Messenger.h index 8940aadd..f0444b91 100644 --- a/core/Messenger.h +++ b/core/Messenger.h | |||
@@ -40,6 +40,7 @@ extern "C" { | |||
40 | 40 | ||
41 | #define PACKET_ID_NICKNAME 48 | 41 | #define PACKET_ID_NICKNAME 48 |
42 | #define PACKET_ID_USERSTATUS 49 | 42 | #define PACKET_ID_USERSTATUS 49 |
43 | #define PACKET_ID_RECEIPT 65 | ||
43 | #define PACKET_ID_MESSAGE 64 | 44 | #define PACKET_ID_MESSAGE 64 |
44 | 45 | ||
45 | /* status definitions */ | 46 | /* status definitions */ |
@@ -117,9 +118,14 @@ int m_delfriend(int friendnumber); | |||
117 | int m_friendstatus(int friendnumber); | 118 | int m_friendstatus(int friendnumber); |
118 | 119 | ||
119 | /* send a text chat message to an online friend | 120 | /* send a text chat message to an online friend |
120 | returns 1 if packet was successfully put into the send queue | 121 | returns the message id if packet was successfully put into the send queue |
121 | return 0 if it was not */ | 122 | return 0 if it was not |
122 | int m_sendmessage(int friendnumber, uint8_t *message, uint32_t length); | 123 | you will want to retain the return value, it will be passed to your read receipt callback |
124 | if one is received. | ||
125 | m_sendmessage_withid will send a message with the id of your choosing, | ||
126 | however we can generate an id for you by calling plain m_sendmessage. */ | ||
127 | uint32_t m_sendmessage(int friendnumber, uint8_t *message, uint32_t length); | ||
128 | uint32_t m_sendmessage_withid(int friendnumber, uint32_t theid, uint8_t *message, uint32_t length); | ||
123 | 129 | ||
124 | /* Set our nickname | 130 | /* Set our nickname |
125 | name must be a string of maximum MAX_NAME_LENGTH length. | 131 | name must be a string of maximum MAX_NAME_LENGTH length. |
@@ -165,6 +171,10 @@ int m_copy_self_userstatus(uint8_t *buf, uint32_t maxlen); | |||
165 | USERSTATUS_KIND m_get_userstatus_kind(int friendnumber); | 171 | USERSTATUS_KIND m_get_userstatus_kind(int friendnumber); |
166 | USERSTATUS_KIND m_get_self_userstatus_kind(void); | 172 | USERSTATUS_KIND m_get_self_userstatus_kind(void); |
167 | 173 | ||
174 | /* Sets whether we send read receipts for friendnumber. | ||
175 | * This function is not lazy, and it will fail if yesno is not (0 or 1).*/ | ||
176 | void m_set_sends_receipts(int friendnumber, int yesno); | ||
177 | |||
168 | /* set the function that will be executed when a friend request is received. | 178 | /* set the function that will be executed when a friend request is received. |
169 | function format is function(uint8_t * public_key, uint8_t * data, uint16_t length) */ | 179 | function format is function(uint8_t * public_key, uint8_t * data, uint16_t length) */ |
170 | void m_callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t)); | 180 | void m_callback_friendrequest(void (*function)(uint8_t *, uint8_t *, uint16_t)); |
@@ -183,6 +193,15 @@ void m_callback_namechange(void (*function)(int, uint8_t *, uint16_t)); | |||
183 | you are not responsible for freeing newstatus */ | 193 | you are not responsible for freeing newstatus */ |
184 | void m_callback_userstatus(void (*function)(int, USERSTATUS_KIND, uint8_t *, uint16_t)); | 194 | void m_callback_userstatus(void (*function)(int, USERSTATUS_KIND, uint8_t *, uint16_t)); |
185 | 195 | ||
196 | /* set the callback for read receipts | ||
197 | function(int friendnumber, uint32_t receipt) | ||
198 | if you are keeping a record of returns from m_sendmessage, | ||
199 | receipt might be one of those values, and that means the message | ||
200 | has been received on the other side. since core doesn't | ||
201 | track ids for you, receipt may not correspond to any message | ||
202 | in that case, you should discard it. */ | ||
203 | void m_callback_read_receipt(void (*function)(int, uint32_t)); | ||
204 | |||
186 | /* run this at startup | 205 | /* run this at startup |
187 | returns 0 if no connection problems | 206 | returns 0 if no connection problems |
188 | returns -1 if there are problems */ | 207 | returns -1 if there are problems */ |