summaryrefslogtreecommitdiff
path: root/toxav/msi.c
diff options
context:
space:
mode:
Diffstat (limited to 'toxav/msi.c')
-rw-r--r--toxav/msi.c105
1 files changed, 63 insertions, 42 deletions
diff --git a/toxav/msi.c b/toxav/msi.c
index dd9f5fba..41f33c7f 100644
--- a/toxav/msi.c
+++ b/toxav/msi.c
@@ -40,33 +40,37 @@
40 * |id [1 byte]| |size [1 byte]| |data [$size bytes]| |...{repeat}| |0 {end byte}| 40 * |id [1 byte]| |size [1 byte]| |data [$size bytes]| |...{repeat}| |0 {end byte}|
41 */ 41 */
42 42
43typedef enum { 43typedef enum MSIHeaderID {
44 ID_REQUEST = 1, 44 ID_REQUEST = 1,
45 ID_ERROR, 45 ID_ERROR,
46 ID_CAPABILITIES, 46 ID_CAPABILITIES,
47} MSIHeaderID; 47} MSIHeaderID;
48 48
49 49
50typedef enum { 50typedef enum MSIRequest {
51 REQU_INIT, 51 REQU_INIT,
52 REQU_PUSH, 52 REQU_PUSH,
53 REQU_POP, 53 REQU_POP,
54} MSIRequest; 54} MSIRequest;
55 55
56 56
57#define GENERIC_HEADER(header, val_type) \ 57typedef struct MSIHeaderRequest {
58typedef struct { \ 58 MSIRequest value;
59 val_type value; \ 59 bool exists;
60 bool exists; \ 60} MSIHeaderRequest;
61} MSIHeader##header
62 61
62typedef struct MSIHeaderError {
63 MSIError value;
64 bool exists;
65} MSIHeaderError;
63 66
64GENERIC_HEADER(Request, MSIRequest); 67typedef struct MSIHeaderCapabilities {
65GENERIC_HEADER(Error, MSIError); 68 uint8_t value;
66GENERIC_HEADER(Capabilities, uint8_t); 69 bool exists;
70} MSIHeaderCapabilities;
67 71
68 72
69typedef struct { 73typedef struct MSIMessage {
70 MSIHeaderRequest request; 74 MSIHeaderRequest request;
71 MSIHeaderError error; 75 MSIHeaderError error;
72 MSIHeaderCapabilities capabilities; 76 MSIHeaderCapabilities capabilities;
@@ -185,14 +189,14 @@ int msi_invite(MSISession *session, MSICall **call, uint32_t friend_number, uint
185 return -1; 189 return -1;
186 } 190 }
187 191
188 (*call) = new_call(session, friend_number); 192 MSICall *temp = new_call(session, friend_number);
189 193
190 if (*call == nullptr) { 194 if (temp == nullptr) {
191 pthread_mutex_unlock(session->mutex); 195 pthread_mutex_unlock(session->mutex);
192 return -1; 196 return -1;
193 } 197 }
194 198
195 (*call)->self_capabilities = capabilities; 199 temp->self_capabilities = capabilities;
196 200
197 MSIMessage msg; 201 MSIMessage msg;
198 msg_init(&msg, REQU_INIT); 202 msg_init(&msg, REQU_INIT);
@@ -200,9 +204,11 @@ int msi_invite(MSISession *session, MSICall **call, uint32_t friend_number, uint
200 msg.capabilities.exists = true; 204 msg.capabilities.exists = true;
201 msg.capabilities.value = capabilities; 205 msg.capabilities.value = capabilities;
202 206
203 send_message((*call)->session->messenger, (*call)->friend_number, &msg); 207 send_message(temp->session->messenger, temp->friend_number, &msg);
204 208
205 (*call)->state = MSI_CALL_REQUESTING; 209 temp->state = MSI_CALL_REQUESTING;
210
211 *call = temp;
206 212
207 LOGGER_DEBUG(session->messenger->log, "Invite sent"); 213 LOGGER_DEBUG(session->messenger->log, "Invite sent");
208 pthread_mutex_unlock(session->mutex); 214 pthread_mutex_unlock(session->mutex);
@@ -328,18 +334,27 @@ int msg_parse_in(const Logger *log, MSIMessage *dest, const uint8_t *data, uint1
328{ 334{
329 /* Parse raw data received from socket into MSIMessage struct */ 335 /* Parse raw data received from socket into MSIMessage struct */
330 336
331#define CHECK_SIZE(bytes, constraint, size) \ 337#define CHECK_SIZE(bytes, constraint, size) \
332 if ((constraint -= (2 + size)) < 1) { LOGGER_ERROR(log, "Read over length!"); return -1; } \ 338 do { \
333 if (bytes[1] != size) { LOGGER_ERROR(log, "Invalid data size!"); return -1; } 339 constraint -= 2 + size; \
334 340 if (constraint < 1) { \
335#define CHECK_ENUM_HIGH(bytes, enum_high) /* Assumes size == 1 */ \ 341 LOGGER_ERROR(log, "Read over length!"); \
336 if (bytes[2] > enum_high) { LOGGER_ERROR(log, "Failed enum high limit!"); return -1; } 342 return -1; \
337 343 } \
338#define SET_UINT8(type, bytes, header) do { \ 344 if (bytes[1] != size) { \
339 header.value = (type)bytes[2]; \ 345 LOGGER_ERROR(log, "Invalid data size!"); \
340 header.exists = true; \ 346 return -1; \
341 bytes += 3; \ 347 } \
342 } while(0) 348 } while (0)
349
350 /* Assumes size == 1 */
351#define CHECK_ENUM_HIGH(bytes, enum_high) \
352 do { \
353 if (bytes[2] > enum_high) { \
354 LOGGER_ERROR(log, "Failed enum high limit!"); \
355 return -1; \
356 } \
357 } while (0)
343 358
344 assert(dest); 359 assert(dest);
345 360
@@ -358,18 +373,24 @@ int msg_parse_in(const Logger *log, MSIMessage *dest, const uint8_t *data, uint1
358 case ID_REQUEST: 373 case ID_REQUEST:
359 CHECK_SIZE(it, size_constraint, 1); 374 CHECK_SIZE(it, size_constraint, 1);
360 CHECK_ENUM_HIGH(it, REQU_POP); 375 CHECK_ENUM_HIGH(it, REQU_POP);
361 SET_UINT8(MSIRequest, it, dest->request); 376 dest->request.value = (MSIRequest)it[2];
377 dest->request.exists = true;
378 it += 3;
362 break; 379 break;
363 380
364 case ID_ERROR: 381 case ID_ERROR:
365 CHECK_SIZE(it, size_constraint, 1); 382 CHECK_SIZE(it, size_constraint, 1);
366 CHECK_ENUM_HIGH(it, MSI_E_UNDISCLOSED); 383 CHECK_ENUM_HIGH(it, MSI_E_UNDISCLOSED);
367 SET_UINT8(MSIError, it, dest->error); 384 dest->error.value = (MSIError)it[2];
385 dest->error.exists = true;
386 it += 3;
368 break; 387 break;
369 388
370 case ID_CAPABILITIES: 389 case ID_CAPABILITIES:
371 CHECK_SIZE(it, size_constraint, 1); 390 CHECK_SIZE(it, size_constraint, 1);
372 SET_UINT8(uint8_t, it, dest->capabilities); 391 dest->capabilities.value = it[2];
392 dest->capabilities.exists = true;
393 it += 3;
373 break; 394 break;
374 395
375 default: 396 default:
@@ -383,11 +404,10 @@ int msg_parse_in(const Logger *log, MSIMessage *dest, const uint8_t *data, uint1
383 return -1; 404 return -1;
384 } 405 }
385 406
386 return 0;
387
388#undef CHECK_SIZE
389#undef CHECK_ENUM_HIGH 407#undef CHECK_ENUM_HIGH
390#undef SET_UINT8 408#undef CHECK_SIZE
409
410 return 0;
391} 411}
392uint8_t *msg_parse_header_out(MSIHeaderID id, uint8_t *dest, const void *value, uint8_t value_len, uint16_t *length) 412uint8_t *msg_parse_header_out(MSIHeaderID id, uint8_t *dest, const void *value, uint8_t value_len, uint16_t *length)
393{ 413{
@@ -397,9 +417,9 @@ uint8_t *msg_parse_header_out(MSIHeaderID id, uint8_t *dest, const void *value,
397 assert(value_len); 417 assert(value_len);
398 418
399 *dest = id; 419 *dest = id;
400 dest ++; 420 ++dest;
401 *dest = value_len; 421 *dest = value_len;
402 dest ++; 422 ++dest;
403 423
404 memcpy(dest, value, value_len); 424 memcpy(dest, value, value_len);
405 425
@@ -443,7 +463,7 @@ int send_message(Messenger *m, uint32_t friend_number, const MSIMessage *msg)
443 } 463 }
444 464
445 *it = 0; 465 *it = 0;
446 size ++; 466 ++size;
447 467
448 if (m_msi_packet(m, friend_number, parsed, size)) { 468 if (m_msi_packet(m, friend_number, parsed, size)) {
449 LOGGER_DEBUG(m->log, "Sent message"); 469 LOGGER_DEBUG(m->log, "Sent message");
@@ -526,7 +546,8 @@ MSICall *new_call(MSISession *session, uint32_t friend_number)
526 return nullptr; 546 return nullptr;
527 } 547 }
528 548
529 session->calls_tail = session->calls_head = friend_number; 549 session->calls_tail = friend_number;
550 session->calls_head = friend_number;
530 } else if (session->calls_tail < friend_number) { /* Appending */ 551 } else if (session->calls_tail < friend_number) { /* Appending */
531 MSICall **tmp = (MSICall **)realloc(session->calls, sizeof(MSICall *) * (friend_number + 1)); 552 MSICall **tmp = (MSICall **)realloc(session->calls, sizeof(MSICall *) * (friend_number + 1));
532 553
@@ -540,7 +561,7 @@ MSICall *new_call(MSISession *session, uint32_t friend_number)
540 /* Set fields in between to null */ 561 /* Set fields in between to null */
541 uint32_t i = session->calls_tail + 1; 562 uint32_t i = session->calls_tail + 1;
542 563
543 for (; i < friend_number; i ++) { 564 for (; i < friend_number; ++i) {
544 session->calls[i] = nullptr; 565 session->calls[i] = nullptr;
545 } 566 }
546 567
@@ -592,14 +613,14 @@ void kill_call(MSICall *call)
592 return; 613 return;
593 614
594CLEAR_CONTAINER: 615CLEAR_CONTAINER:
595 session->calls_head = session->calls_tail = 0; 616 session->calls_head = 0;
617 session->calls_tail = 0;
596 free(session->calls); 618 free(session->calls);
597 free(call); 619 free(call);
598 session->calls = nullptr; 620 session->calls = nullptr;
599} 621}
600void on_peer_status(Messenger *m, uint32_t friend_number, uint8_t status, void *data) 622void on_peer_status(Messenger *m, uint32_t friend_number, uint8_t status, void *data)
601{ 623{
602 (void)m;
603 MSISession *session = (MSISession *)data; 624 MSISession *session = (MSISession *)data;
604 625
605 switch (status) { 626 switch (status) {