summaryrefslogtreecommitdiff
path: root/toxav/msi.c
diff options
context:
space:
mode:
Diffstat (limited to 'toxav/msi.c')
-rw-r--r--toxav/msi.c322
1 files changed, 277 insertions, 45 deletions
diff --git a/toxav/msi.c b/toxav/msi.c
index 1d3a406b..a74f8a58 100644
--- a/toxav/msi.c
+++ b/toxav/msi.c
@@ -115,7 +115,6 @@ static struct _Callbacks {
115 115
116inline__ void invoke_callback(int32_t call_index, MSICallbackID id) 116inline__ void invoke_callback(int32_t call_index, MSICallbackID id)
117{ 117{
118 /*if ( callbacks[id].function ) event.rise ( callbacks[id].function, callbacks[id].data );*/
119 if ( callbacks[id].function ) { 118 if ( callbacks[id].function ) {
120 LOGGER_DEBUG("Invoking callback function: %d", id); 119 LOGGER_DEBUG("Invoking callback function: %d", id);
121 callbacks[id].function ( call_index, callbacks[id].data ); 120 callbacks[id].function ( call_index, callbacks[id].data );
@@ -220,7 +219,7 @@ if ( *iterator != value_byte || size_con <= type_size_const) { return -1; } size
220iterator ++; if(size_con <= 3) {return -1;} size_con -= 3; \ 219iterator ++; if(size_con <= 3) {return -1;} size_con -= 3; \
221uint16_t _value_size; memcpy(&_value_size, iterator, sizeof(_value_size)); _value_size = ntohs(_value_size);\ 220uint16_t _value_size; memcpy(&_value_size, iterator, sizeof(_value_size)); _value_size = ntohs(_value_size);\
222if(size_con < _value_size) { return -1; } size_con -= _value_size; \ 221if(size_con < _value_size) { return -1; } size_con -= _value_size; \
223if ( !(header.header_value = calloc(sizeof(uint8_t), _value_size)) ); \ 222if ( !(header.header_value = calloc(sizeof(uint8_t), _value_size)) ) \
224LOGGER_ERROR("Allocation failed! Program might misbehave!"); \ 223LOGGER_ERROR("Allocation failed! Program might misbehave!"); \
225header.size = _value_size; \ 224header.size = _value_size; \
226memcpy(header.header_value, iterator + 2, _value_size);\ 225memcpy(header.header_value, iterator + 2, _value_size);\
@@ -538,6 +537,233 @@ GENERIC_SETTER_DEFINITION ( info )
538GENERIC_SETTER_DEFINITION ( callid ) 537GENERIC_SETTER_DEFINITION ( callid )
539 538
540 539
540
541
542typedef struct _Timer {
543 void *(*func)(void *);
544 void *func_args;
545 uint64_t timeout;
546 size_t idx;
547
548} Timer;
549
550typedef struct _TimerHandler {
551 Timer **timers;
552 pthread_mutex_t mutex;
553
554 size_t max_capacity;
555 size_t size;
556 uint64_t resolution;
557
558 _Bool running;
559
560} TimerHandler;
561
562
563/**
564 * @brief Allocate timer in array
565 *
566 * @param timers_container Handler
567 * @param func Function to be executed
568 * @param arg Its args
569 * @param timeout Timeout in ms
570 * @return int
571 */
572int timer_alloc ( TimerHandler *timers_container, void *(func)(void *), void *arg, unsigned timeout)
573{
574 pthread_mutex_lock(&timers_container->mutex);
575
576 int i = 0;
577
578 for (; i < timers_container->max_capacity && timers_container->timers[i]; i ++);
579
580 if (i == timers_container->max_capacity) {
581 LOGGER_WARNING("Maximum capacity reached!");
582 pthread_mutex_unlock(&timers_container->mutex);
583 return -1;
584 }
585
586 Timer *timer = timers_container->timers[i] = calloc(sizeof(Timer), 1);
587
588 if (timer == NULL) {
589 LOGGER_ERROR("Failed to allocate timer!");
590 pthread_mutex_unlock(&timers_container->mutex);
591 return -1;
592 }
593
594 timers_container->size ++;
595
596 timer->func = func;
597 timer->func_args = arg;
598 timer->timeout = timeout + current_time_monotonic(); /* In ms */
599 timer->idx = i;
600
601 /* reorder */
602 if (i) {
603 int j = i - 1;
604
605 for (; j >= 0 && timeout < timers_container->timers[j]->timeout; j--) {
606 Timer *tmp = timers_container->timers[j];
607 timers_container->timers[j] = timer;
608 timers_container->timers[j + 1] = tmp;
609 }
610 }
611
612 pthread_mutex_unlock(&timers_container->mutex);
613
614 LOGGER_DEBUG("Allocated timer index: %d timeout: %d, current size: %d", i, timeout, timers_container->size);
615 return i;
616}
617
618/**
619 * @brief Remove timer from array
620 *
621 * @param timers_container handler
622 * @param idx index
623 * @return int
624 */
625int timer_release ( TimerHandler *timers_container, int idx )
626{
627 int rc = pthread_mutex_trylock(&timers_container->mutex);
628
629 Timer **timed_events = timers_container->timers;
630
631 if (!timed_events[idx]) {
632 LOGGER_WARNING("No event under index: %d", idx);
633
634 if ( rc != EBUSY ) pthread_mutex_unlock(&timers_container->mutex);
635
636 return -1;
637 }
638
639 free(timed_events[idx]);
640
641 timed_events[idx] = NULL;
642
643 int i = idx + 1;
644
645 for (; i < timers_container->max_capacity && timed_events[i]; i ++) {
646 timed_events[i - 1] = timed_events[i];
647 timed_events[i] = NULL;
648 }
649
650 timers_container->size--;
651
652 LOGGER_DEBUG("Popped index: %d, current size: %d ", idx, timers_container->size);
653
654 if ( rc != EBUSY ) pthread_mutex_unlock(&timers_container->mutex);
655
656 return 0;
657}
658
659/**
660 * @brief Main poll for timer execution
661 *
662 * @param arg ...
663 * @return void*
664 */
665void *timer_poll( void *arg )
666{
667 TimerHandler *handler = arg;
668
669 while ( handler->running ) {
670
671 pthread_mutex_lock(&handler->mutex);
672
673 if ( handler->running ) {
674
675 uint64_t time = current_time_monotonic();
676
677 while ( handler->timers[0] && handler->timers[0]->timeout < time ) {
678
679 pthread_t _tid;
680
681 if ( 0 != pthread_create(&_tid, NULL, handler->timers[0]->func, handler->timers[0]->func_args) ||
682 0 != pthread_detach(_tid) )
683 LOGGER_ERROR("Failed to execute timer at: %d!", handler->timers[0]->timeout);
684
685 else LOGGER_DEBUG("Exectued timer assigned at: %d", handler->timers[0]->timeout);
686
687 timer_release(handler, 0);
688 }
689
690 }
691
692 pthread_mutex_unlock(&handler->mutex);
693
694 usleep(handler->resolution);
695 }
696
697 pthread_exit(NULL);
698}
699
700/**
701 * @brief Start timer poll and return handler
702 *
703 * @param max_capacity capacity
704 * @param resolution ...
705 * @return TimerHandler*
706 */
707TimerHandler *timer_init_session (int max_capacity, int resolution)
708{
709 TimerHandler *handler = calloc(1, sizeof(TimerHandler));
710
711 if (handler == NULL) {
712 LOGGER_ERROR("Failed to allocate memory, program might misbehave!");
713 return NULL;
714 }
715
716 handler->timers = calloc(max_capacity, sizeof(Timer *));
717
718 if (handler->timers == NULL) {
719 LOGGER_ERROR("Failed to allocate %d timed events!", max_capacity);
720 free(handler);
721 return NULL;
722 }
723
724 handler->max_capacity = max_capacity;
725 handler->running = 1;
726 handler->resolution = resolution;
727
728 pthread_mutex_init(&handler->mutex, NULL);
729
730
731 pthread_t _tid;
732
733 if ( 0 != pthread_create(&_tid, NULL, timer_poll, handler) || 0 != pthread_detach(_tid) ) {
734 LOGGER_ERROR("Failed to start timer poll thread!");
735 free(handler->timers);
736 free(handler);
737 return NULL;
738 }
739
740 return handler;
741}
742
743/**
744 * @brief Terminate timer session
745 *
746 * @param handler The timer handler
747 * @return void
748 */
749void timer_terminate_session(TimerHandler *handler)
750{
751 pthread_mutex_lock(&handler->mutex);
752
753 handler->running = 0;
754
755 pthread_mutex_unlock(&handler->mutex);
756
757 int i = 0;
758
759 for (; i < handler->max_capacity; i ++)
760 free(handler->timers[i]);
761
762 free(handler->timers);
763
764 pthread_mutex_destroy( &handler->mutex );
765}
766
541/** 767/**
542 * @brief Generate _random_ alphanumerical string. 768 * @brief Generate _random_ alphanumerical string.
543 * 769 *
@@ -731,7 +957,11 @@ MSICall *find_call ( MSISession *session, uint8_t *call_id )
731 957
732 for (; i < session->max_calls; i ++ ) 958 for (; i < session->max_calls; i ++ )
733 if ( session->calls[i] && memcmp(session->calls[i]->id, call_id, CALL_ID_LEN) == 0 ) { 959 if ( session->calls[i] && memcmp(session->calls[i]->id, call_id, CALL_ID_LEN) == 0 ) {
734 LOGGER_DEBUG("Found call id: %s", session->calls[i]->id); 960 LOGGER_SCOPE(
961 char tmp[CALL_ID_LEN + 1] = {'\0'};
962 memcpy(tmp, session->calls[i]->id, CALL_ID_LEN);
963 LOGGER_DEBUG("Found call id: %s", tmp);
964 );
735 return session->calls[i]; 965 return session->calls[i];
736 } 966 }
737 967
@@ -883,8 +1113,8 @@ int terminate_call ( MSISession *session, MSICall *call )
883 * NOTE: This has to be done before possibly 1113 * NOTE: This has to be done before possibly
884 * locking the mutex the second time 1114 * locking the mutex the second time
885 */ 1115 */
886 event.timer_release ( call->request_timer_id ); 1116 timer_release ( session->timer_handler, call->request_timer_id );
887 event.timer_release ( call->ringing_timer_id ); 1117 timer_release ( session->timer_handler, call->ringing_timer_id );
888 1118
889 /* Get a handle */ 1119 /* Get a handle */
890 pthread_mutex_lock ( &call->mutex ); 1120 pthread_mutex_lock ( &call->mutex );
@@ -1055,10 +1285,6 @@ int handle_recv_reject ( MSISession *session, MSICall *call, MSIMessage *msg )
1055 pthread_mutex_unlock(&session->mutex); 1285 pthread_mutex_unlock(&session->mutex);
1056 1286
1057 invoke_callback(call->call_idx, MSI_OnReject); 1287 invoke_callback(call->call_idx, MSI_OnReject);
1058 /*
1059 event.timer_release ( session->call->request_timer_id );
1060 session->call->request_timer_id = event.timer_alloc ( handle_timeout, session, m_deftout );
1061 */
1062 1288
1063 terminate_call(session, call); 1289 terminate_call(session, call);
1064 return 1; 1290 return 1;
@@ -1123,7 +1349,7 @@ int handle_recv_ringing ( MSISession *session, MSICall *call, MSIMessage *msg )
1123 1349
1124 LOGGER_DEBUG("Session: %p Handling 'ringing' on call: %s", session, call->id ); 1350 LOGGER_DEBUG("Session: %p Handling 'ringing' on call: %s", session, call->id );
1125 1351
1126 call->ringing_timer_id = event.timer_alloc ( handle_timeout, call, call->ringing_tout_ms ); 1352 call->ringing_timer_id = timer_alloc ( session->timer_handler, handle_timeout, call, call->ringing_tout_ms );
1127 1353
1128 pthread_mutex_unlock(&session->mutex); 1354 pthread_mutex_unlock(&session->mutex);
1129 1355
@@ -1150,7 +1376,7 @@ int handle_recv_starting ( MSISession *session, MSICall *call, MSIMessage *msg )
1150 flush_peer_type ( call, msg, 0 ); 1376 flush_peer_type ( call, msg, 0 );
1151 1377
1152 1378
1153 event.timer_release ( call->ringing_timer_id ); 1379 timer_release ( session->timer_handler, call->ringing_timer_id );
1154 pthread_mutex_unlock(&session->mutex); 1380 pthread_mutex_unlock(&session->mutex);
1155 1381
1156 invoke_callback(call->call_idx, MSI_OnStarting); 1382 invoke_callback(call->call_idx, MSI_OnStarting);
@@ -1168,7 +1394,7 @@ int handle_recv_ending ( MSISession *session, MSICall *call, MSIMessage *msg )
1168 LOGGER_DEBUG("Session: %p Handling 'ending' on call: %s", session, call->id ); 1394 LOGGER_DEBUG("Session: %p Handling 'ending' on call: %s", session, call->id );
1169 1395
1170 /* Stop timer */ 1396 /* Stop timer */
1171 event.timer_release ( call->request_timer_id ); 1397 timer_release ( session->timer_handler, call->request_timer_id );
1172 1398
1173 pthread_mutex_unlock(&session->mutex); 1399 pthread_mutex_unlock(&session->mutex);
1174 1400
@@ -1246,89 +1472,88 @@ void msi_handle_packet ( Messenger *messenger, int source, const uint8_t *data,
1246 /* Unused */ 1472 /* Unused */
1247 (void)messenger; 1473 (void)messenger;
1248 1474
1249 MSISession *_session = object; 1475 MSISession *session = object;
1250 MSIMessage *_msg; 1476 MSIMessage *msg;
1251 1477
1252 if ( !length ) { 1478 if ( !length ) {
1253 LOGGER_WARNING("Lenght param negative"); 1479 LOGGER_WARNING("Lenght param negative");
1254 return; 1480 return;
1255 } 1481 }
1256 1482
1257 _msg = parse_message ( data, length ); 1483 msg = parse_message ( data, length );
1258 1484
1259 if ( !_msg ) { 1485 if ( !msg ) {
1260 LOGGER_WARNING("Error parsing message"); 1486 LOGGER_WARNING("Error parsing message");
1261 return; 1487 return;
1262 } else { 1488 } else {
1263 LOGGER_DEBUG("Successfully parsed message"); 1489 LOGGER_DEBUG("Successfully parsed message");
1264 } 1490 }
1265 1491
1266 _msg->friend_id = source; 1492 msg->friend_id = source;
1267 1493
1268 1494
1269 /* Find what call */ 1495 /* Find what call */
1270 MSICall *_call = _msg->callid.header_value ? find_call(_session, _msg->callid.header_value ) : NULL; 1496 MSICall *call = msg->callid.header_value ? find_call(session, msg->callid.header_value ) : NULL;
1271 1497
1272 /* Now handle message */ 1498 /* Now handle message */
1273 1499
1274 if ( _msg->request.header_value ) { /* Handle request */ 1500 if ( msg->request.header_value ) { /* Handle request */
1275 1501
1276 if ( _msg->response.size > 32 ) { 1502 if ( msg->response.size > 32 ) {
1277 LOGGER_WARNING("Header size too big"); 1503 LOGGER_WARNING("Header size too big");
1278 goto free_end; 1504 goto free_end;
1279 } 1505 }
1280 1506
1281 uint8_t _request_value[32]; 1507 uint8_t _request_value[32];
1282 1508
1283 memcpy(_request_value, _msg->request.header_value, _msg->request.size); 1509 memcpy(_request_value, msg->request.header_value, msg->request.size);
1284 _request_value[_msg->request.size] = '\0'; 1510 _request_value[msg->request.size] = '\0';
1285 1511
1286 if ( same ( _request_value, stringify_request ( invite ) ) ) { 1512 if ( same ( _request_value, stringify_request ( invite ) ) ) {
1287 handle_recv_invite ( _session, _call, _msg ); 1513 handle_recv_invite ( session, call, msg );
1288 1514
1289 } else if ( same ( _request_value, stringify_request ( start ) ) ) { 1515 } else if ( same ( _request_value, stringify_request ( start ) ) ) {
1290 handle_recv_start ( _session, _call, _msg ); 1516 handle_recv_start ( session, call, msg );
1291 1517
1292 } else if ( same ( _request_value, stringify_request ( cancel ) ) ) { 1518 } else if ( same ( _request_value, stringify_request ( cancel ) ) ) {
1293 handle_recv_cancel ( _session, _call, _msg ); 1519 handle_recv_cancel ( session, call, msg );
1294 1520
1295 } else if ( same ( _request_value, stringify_request ( reject ) ) ) { 1521 } else if ( same ( _request_value, stringify_request ( reject ) ) ) {
1296 handle_recv_reject ( _session, _call, _msg ); 1522 handle_recv_reject ( session, call, msg );
1297 1523
1298 } else if ( same ( _request_value, stringify_request ( end ) ) ) { 1524 } else if ( same ( _request_value, stringify_request ( end ) ) ) {
1299 handle_recv_end ( _session, _call, _msg ); 1525 handle_recv_end ( session, call, msg );
1300 } else { 1526 } else {
1301 LOGGER_WARNING("Uknown request"); 1527 LOGGER_WARNING("Uknown request");
1302 goto free_end; 1528 goto free_end;
1303 } 1529 }
1304 1530
1305 } else if ( _msg->response.header_value ) { /* Handle response */ 1531 } else if ( msg->response.header_value ) { /* Handle response */
1306 1532
1307 if ( _msg->response.size > 32 ) { 1533 if ( msg->response.size > 32 ) {
1308 LOGGER_WARNING("Header size too big"); 1534 LOGGER_WARNING("Header size too big");
1309 goto free_end; 1535 goto free_end;
1310 } 1536 }
1311 1537
1312 /* Got response so cancel timer */ 1538 /* Got response so cancel timer */
1313 if ( _call ) 1539 if ( call ) timer_release ( session->timer_handler, call->request_timer_id );
1314 event.timer_release ( _call->request_timer_id );
1315 1540
1316 uint8_t _response_value[32]; 1541 uint8_t _response_value[32];
1317 1542
1318 memcpy(_response_value, _msg->response.header_value, _msg->response.size); 1543 memcpy(_response_value, msg->response.header_value, msg->response.size);
1319 _response_value[_msg->response.size] = '\0'; 1544 _response_value[msg->response.size] = '\0';
1320 1545
1321 if ( same ( _response_value, stringify_response ( ringing ) ) ) { 1546 if ( same ( _response_value, stringify_response ( ringing ) ) ) {
1322 handle_recv_ringing ( _session, _call, _msg ); 1547 handle_recv_ringing ( session, call, msg );
1323 1548
1324 } else if ( same ( _response_value, stringify_response ( starting ) ) ) { 1549 } else if ( same ( _response_value, stringify_response ( starting ) ) ) {
1325 handle_recv_starting ( _session, _call, _msg ); 1550 handle_recv_starting ( session, call, msg );
1326 1551
1327 } else if ( same ( _response_value, stringify_response ( ending ) ) ) { 1552 } else if ( same ( _response_value, stringify_response ( ending ) ) ) {
1328 handle_recv_ending ( _session, _call, _msg ); 1553 handle_recv_ending ( session, call, msg );
1329 1554
1330 } else if ( same ( _response_value, stringify_response ( error ) ) ) { 1555 } else if ( same ( _response_value, stringify_response ( error ) ) ) {
1331 handle_recv_error ( _session, _call, _msg ); 1556 handle_recv_error ( session, call, msg );
1332 1557
1333 } else { 1558 } else {
1334 LOGGER_WARNING("Uknown response"); 1559 LOGGER_WARNING("Uknown response");
@@ -1340,7 +1565,7 @@ void msi_handle_packet ( Messenger *messenger, int source, const uint8_t *data,
1340 } 1565 }
1341 1566
1342free_end: 1567free_end:
1343 free_message ( _msg ); 1568 free_message ( msg );
1344} 1569}
1345 1570
1346 1571
@@ -1373,7 +1598,12 @@ MSISession *msi_init_session ( Messenger *messenger, int32_t max_calls )
1373 return NULL; 1598 return NULL;
1374 } 1599 }
1375 1600
1376 if ( !max_calls) return NULL; 1601 TimerHandler *handler = timer_init_session(max_calls * 10, 10000);
1602
1603 if ( !max_calls || !handler ) {
1604 LOGGER_WARNING("Invalid max call treshold or timer handler initialization failed!");
1605 return NULL;
1606 }
1377 1607
1378 MSISession *_retu = calloc ( sizeof ( MSISession ), 1 ); 1608 MSISession *_retu = calloc ( sizeof ( MSISession ), 1 );
1379 1609
@@ -1384,6 +1614,7 @@ MSISession *msi_init_session ( Messenger *messenger, int32_t max_calls )
1384 1614
1385 _retu->messenger_handle = messenger; 1615 _retu->messenger_handle = messenger;
1386 _retu->agent_handler = NULL; 1616 _retu->agent_handler = NULL;
1617 _retu->timer_handler = handler;
1387 1618
1388 if (!(_retu->calls = calloc( sizeof (MSICall *), max_calls ))) { 1619 if (!(_retu->calls = calloc( sizeof (MSICall *), max_calls ))) {
1389 LOGGER_ERROR("Allocation failed! Program might misbehave!"); 1620 LOGGER_ERROR("Allocation failed! Program might misbehave!");
@@ -1440,6 +1671,7 @@ int msi_terminate_session ( MSISession *session )
1440 msi_cancel ( session, idx, session->calls[idx]->peers [_it], "MSI session terminated!" ); 1671 msi_cancel ( session, idx, session->calls[idx]->peers [_it], "MSI session terminated!" );
1441 } 1672 }
1442 1673
1674 timer_terminate_session(session->timer_handler);
1443 1675
1444 pthread_mutex_destroy(&session->mutex); 1676 pthread_mutex_destroy(&session->mutex);
1445 1677
@@ -1495,7 +1727,7 @@ int msi_invite ( MSISession *session, int32_t *call_index, MSICallType call_type
1495 1727
1496 _call->state = call_inviting; 1728 _call->state = call_inviting;
1497 1729
1498 _call->request_timer_id = event.timer_alloc ( handle_timeout, _call, m_deftout ); 1730 _call->request_timer_id = timer_alloc ( session->timer_handler, handle_timeout, _call, m_deftout );
1499 1731
1500 LOGGER_DEBUG("Invite sent"); 1732 LOGGER_DEBUG("Invite sent");
1501 1733
@@ -1543,8 +1775,8 @@ int msi_hangup ( MSISession *session, int32_t call_index )
1543 1775
1544 free_message ( _msg_end ); 1776 free_message ( _msg_end );
1545 1777
1546 session->calls[call_index]->request_timer_id = event.timer_alloc ( handle_timeout, session->calls[call_index], 1778 session->calls[call_index]->request_timer_id =
1547 m_deftout ); 1779 timer_alloc ( session->timer_handler, handle_timeout, session->calls[call_index], m_deftout );
1548 1780
1549 pthread_mutex_unlock(&session->mutex); 1781 pthread_mutex_unlock(&session->mutex);
1550 return 0; 1782 return 0;
@@ -1620,7 +1852,7 @@ int msi_cancel ( MSISession *session, int32_t call_index, uint32_t peer, const c
1620 free_message ( _msg_cancel ); 1852 free_message ( _msg_cancel );
1621 1853
1622 /*session->calls[call_index]->state = call_hanged_up; 1854 /*session->calls[call_index]->state = call_hanged_up;
1623 session->calls[call_index]->request_timer_id = event.timer_alloc ( handle_timeout, session->calls[call_index], m_deftout );*/ 1855 session->calls[call_index]->request_timer_id = timer_alloc ( handle_timeout, session->calls[call_index], m_deftout );*/
1624 terminate_call ( session, session->calls[call_index] ); 1856 terminate_call ( session, session->calls[call_index] );
1625 pthread_mutex_unlock(&session->mutex); 1857 pthread_mutex_unlock(&session->mutex);
1626 1858
@@ -1656,8 +1888,8 @@ int msi_reject ( MSISession *session, int32_t call_index, const uint8_t *reason
1656 1888
1657 session->calls[call_index]->state = call_hanged_up; 1889 session->calls[call_index]->state = call_hanged_up;
1658 1890
1659 session->calls[call_index]->request_timer_id = event.timer_alloc ( handle_timeout, session->calls[call_index], 1891 session->calls[call_index]->request_timer_id =
1660 m_deftout ); 1892 timer_alloc ( session->timer_handler, handle_timeout, session->calls[call_index], m_deftout );
1661 1893
1662 pthread_mutex_unlock(&session->mutex); 1894 pthread_mutex_unlock(&session->mutex);
1663 return 0; 1895 return 0;