summaryrefslogtreecommitdiff
path: root/toxav/msi.c
diff options
context:
space:
mode:
Diffstat (limited to 'toxav/msi.c')
-rw-r--r--toxav/msi.c153
1 files changed, 82 insertions, 71 deletions
diff --git a/toxav/msi.c b/toxav/msi.c
index ee7a95f3..a74f8a58 100644
--- a/toxav/msi.c
+++ b/toxav/msi.c
@@ -544,25 +544,25 @@ typedef struct _Timer {
544 void *func_args; 544 void *func_args;
545 uint64_t timeout; 545 uint64_t timeout;
546 size_t idx; 546 size_t idx;
547 547
548} Timer; 548} Timer;
549 549
550typedef struct _TimerHandler { 550typedef struct _TimerHandler {
551 Timer **timers; 551 Timer **timers;
552 pthread_mutex_t mutex; 552 pthread_mutex_t mutex;
553 553
554 size_t max_capacity; 554 size_t max_capacity;
555 size_t size; 555 size_t size;
556 uint64_t resolution; 556 uint64_t resolution;
557 557
558 _Bool running; 558 _Bool running;
559 559
560} TimerHandler; 560} TimerHandler;
561 561
562 562
563/** 563/**
564 * @brief Allocate timer in array 564 * @brief Allocate timer in array
565 * 565 *
566 * @param timers_container Handler 566 * @param timers_container Handler
567 * @param func Function to be executed 567 * @param func Function to be executed
568 * @param arg Its args 568 * @param arg Its args
@@ -572,50 +572,52 @@ typedef struct _TimerHandler {
572int timer_alloc ( TimerHandler *timers_container, void *(func)(void *), void *arg, unsigned timeout) 572int timer_alloc ( TimerHandler *timers_container, void *(func)(void *), void *arg, unsigned timeout)
573{ 573{
574 pthread_mutex_lock(&timers_container->mutex); 574 pthread_mutex_lock(&timers_container->mutex);
575 575
576 int i = 0; 576 int i = 0;
577
577 for (; i < timers_container->max_capacity && timers_container->timers[i]; i ++); 578 for (; i < timers_container->max_capacity && timers_container->timers[i]; i ++);
578 579
579 if (i == timers_container->max_capacity) { 580 if (i == timers_container->max_capacity) {
580 LOGGER_WARNING("Maximum capacity reached!"); 581 LOGGER_WARNING("Maximum capacity reached!");
581 pthread_mutex_unlock(&timers_container->mutex); 582 pthread_mutex_unlock(&timers_container->mutex);
582 return -1; 583 return -1;
583 } 584 }
584 585
585 Timer* timer = timers_container->timers[i] = calloc(sizeof(Timer), 1); 586 Timer *timer = timers_container->timers[i] = calloc(sizeof(Timer), 1);
586 587
587 if (timer == NULL) { 588 if (timer == NULL) {
588 LOGGER_ERROR("Failed to allocate timer!"); 589 LOGGER_ERROR("Failed to allocate timer!");
589 pthread_mutex_unlock(&timers_container->mutex); 590 pthread_mutex_unlock(&timers_container->mutex);
590 return -1; 591 return -1;
591 } 592 }
592 593
593 timers_container->size ++; 594 timers_container->size ++;
594 595
595 timer->func = func; 596 timer->func = func;
596 timer->func_args = arg; 597 timer->func_args = arg;
597 timer->timeout = timeout + current_time_monotonic(); /* In ms */ 598 timer->timeout = timeout + current_time_monotonic(); /* In ms */
598 timer->idx = i; 599 timer->idx = i;
599 600
600 /* reorder */ 601 /* reorder */
601 if (i) { 602 if (i) {
602 int j = i - 1; 603 int j = i - 1;
604
603 for (; j >= 0 && timeout < timers_container->timers[j]->timeout; j--) { 605 for (; j >= 0 && timeout < timers_container->timers[j]->timeout; j--) {
604 Timer* tmp = timers_container->timers[j]; 606 Timer *tmp = timers_container->timers[j];
605 timers_container->timers[j] = timer; 607 timers_container->timers[j] = timer;
606 timers_container->timers[j+1] = tmp; 608 timers_container->timers[j + 1] = tmp;
607 } 609 }
608 } 610 }
609 611
610 pthread_mutex_unlock(&timers_container->mutex); 612 pthread_mutex_unlock(&timers_container->mutex);
611 613
612 LOGGER_DEBUG("Allocated timer index: %d timeout: %d, current size: %d", i, timeout, timers_container->size); 614 LOGGER_DEBUG("Allocated timer index: %d timeout: %d, current size: %d", i, timeout, timers_container->size);
613 return i; 615 return i;
614} 616}
615 617
616/** 618/**
617 * @brief Remove timer from array 619 * @brief Remove timer from array
618 * 620 *
619 * @param timers_container handler 621 * @param timers_container handler
620 * @param idx index 622 * @param idx index
621 * @return int 623 * @return int
@@ -623,133 +625,142 @@ int timer_alloc ( TimerHandler *timers_container, void *(func)(void *), void *ar
623int timer_release ( TimerHandler *timers_container, int idx ) 625int timer_release ( TimerHandler *timers_container, int idx )
624{ 626{
625 int rc = pthread_mutex_trylock(&timers_container->mutex); 627 int rc = pthread_mutex_trylock(&timers_container->mutex);
626 628
627 Timer **timed_events = timers_container->timers; 629 Timer **timed_events = timers_container->timers;
628 630
629 if (!timed_events[idx]) { 631 if (!timed_events[idx]) {
630 LOGGER_WARNING("No event under index: %d", idx); 632 LOGGER_WARNING("No event under index: %d", idx);
633
631 if ( rc != EBUSY ) pthread_mutex_unlock(&timers_container->mutex); 634 if ( rc != EBUSY ) pthread_mutex_unlock(&timers_container->mutex);
635
632 return -1; 636 return -1;
633 } 637 }
634 638
635 free(timed_events[idx]); 639 free(timed_events[idx]);
636 640
637 timed_events[idx] = NULL; 641 timed_events[idx] = NULL;
638 642
639 int i = idx + 1; 643 int i = idx + 1;
644
640 for (; i < timers_container->max_capacity && timed_events[i]; i ++) { 645 for (; i < timers_container->max_capacity && timed_events[i]; i ++) {
641 timed_events[i-1] = timed_events[i]; 646 timed_events[i - 1] = timed_events[i];
642 timed_events[i] = NULL; 647 timed_events[i] = NULL;
643 } 648 }
644 649
645 timers_container->size--; 650 timers_container->size--;
646 651
647 LOGGER_DEBUG("Popped index: %d, current size: %d ", idx, timers_container->size); 652 LOGGER_DEBUG("Popped index: %d, current size: %d ", idx, timers_container->size);
648 653
649 if ( rc != EBUSY ) pthread_mutex_unlock(&timers_container->mutex); 654 if ( rc != EBUSY ) pthread_mutex_unlock(&timers_container->mutex);
655
650 return 0; 656 return 0;
651} 657}
652 658
653/** 659/**
654 * @brief Main poll for timer execution 660 * @brief Main poll for timer execution
655 * 661 *
656 * @param arg ... 662 * @param arg ...
657 * @return void* 663 * @return void*
658 */ 664 */
659void *timer_poll( void *arg ) 665void *timer_poll( void *arg )
660{ 666{
661 TimerHandler *handler = arg; 667 TimerHandler *handler = arg;
662 668
663 while ( handler->running ) { 669 while ( handler->running ) {
664 670
665 pthread_mutex_lock(&handler->mutex); 671 pthread_mutex_lock(&handler->mutex);
666 672
667 if ( handler->running ) { 673 if ( handler->running ) {
668 674
669 uint64_t time = current_time_monotonic(); 675 uint64_t time = current_time_monotonic();
670 676
671 while ( handler->timers[0] && handler->timers[0]->timeout < time ) { 677 while ( handler->timers[0] && handler->timers[0]->timeout < time ) {
672 678
673 pthread_t _tid; 679 pthread_t _tid;
674 if ( 0 != pthread_create(&_tid, NULL, handler->timers[0]->func, handler->timers[0]->func_args) || 680
675 0 != pthread_detach(_tid) ) 681 if ( 0 != pthread_create(&_tid, NULL, handler->timers[0]->func, handler->timers[0]->func_args) ||
682 0 != pthread_detach(_tid) )
676 LOGGER_ERROR("Failed to execute timer at: %d!", handler->timers[0]->timeout); 683 LOGGER_ERROR("Failed to execute timer at: %d!", handler->timers[0]->timeout);
677 684
678 else LOGGER_DEBUG("Exectued timer assigned at: %d", handler->timers[0]->timeout); 685 else LOGGER_DEBUG("Exectued timer assigned at: %d", handler->timers[0]->timeout);
679 686
680 timer_release(handler, 0); 687 timer_release(handler, 0);
681 } 688 }
682 689
683 } 690 }
684 691
685 pthread_mutex_unlock(&handler->mutex); 692 pthread_mutex_unlock(&handler->mutex);
686 693
687 usleep(handler->resolution); 694 usleep(handler->resolution);
688 } 695 }
689 696
690 pthread_exit(NULL); 697 pthread_exit(NULL);
691} 698}
692 699
693/** 700/**
694 * @brief Start timer poll and return handler 701 * @brief Start timer poll and return handler
695 * 702 *
696 * @param max_capacity capacity 703 * @param max_capacity capacity
697 * @param resolution ... 704 * @param resolution ...
698 * @return TimerHandler* 705 * @return TimerHandler*
699 */ 706 */
700TimerHandler* timer_init_session (int max_capacity, int resolution) 707TimerHandler *timer_init_session (int max_capacity, int resolution)
701{ 708{
702 TimerHandler* handler = calloc(1, sizeof(TimerHandler)); 709 TimerHandler *handler = calloc(1, sizeof(TimerHandler));
710
703 if (handler == NULL) { 711 if (handler == NULL) {
704 LOGGER_ERROR("Failed to allocate memory, program might misbehave!"); 712 LOGGER_ERROR("Failed to allocate memory, program might misbehave!");
705 return NULL; 713 return NULL;
706 } 714 }
707 715
708 handler->timers = calloc(max_capacity, sizeof(Timer*)); 716 handler->timers = calloc(max_capacity, sizeof(Timer *));
717
709 if (handler->timers == NULL) { 718 if (handler->timers == NULL) {
710 LOGGER_ERROR("Failed to allocate %d timed events!", max_capacity); 719 LOGGER_ERROR("Failed to allocate %d timed events!", max_capacity);
711 free(handler); 720 free(handler);
712 return NULL; 721 return NULL;
713 } 722 }
714 723
715 handler->max_capacity = max_capacity; 724 handler->max_capacity = max_capacity;
716 handler->running = 1; 725 handler->running = 1;
717 handler->resolution = resolution; 726 handler->resolution = resolution;
718 727
719 pthread_mutex_init(&handler->mutex, NULL); 728 pthread_mutex_init(&handler->mutex, NULL);
720 729
721 730
722 pthread_t _tid; 731 pthread_t _tid;
723 if ( 0 != pthread_create(&_tid, NULL, timer_poll, handler) || 0 != pthread_detach(_tid) ){ 732
733 if ( 0 != pthread_create(&_tid, NULL, timer_poll, handler) || 0 != pthread_detach(_tid) ) {
724 LOGGER_ERROR("Failed to start timer poll thread!"); 734 LOGGER_ERROR("Failed to start timer poll thread!");
725 free(handler->timers); 735 free(handler->timers);
726 free(handler); 736 free(handler);
727 return NULL; 737 return NULL;
728 } 738 }
729 739
730 return handler; 740 return handler;
731} 741}
732 742
733/** 743/**
734 * @brief Terminate timer session 744 * @brief Terminate timer session
735 * 745 *
736 * @param handler The timer handler 746 * @param handler The timer handler
737 * @return void 747 * @return void
738 */ 748 */
739void timer_terminate_session(TimerHandler* handler) 749void timer_terminate_session(TimerHandler *handler)
740{ 750{
741 pthread_mutex_lock(&handler->mutex); 751 pthread_mutex_lock(&handler->mutex);
742 752
743 handler->running = 0; 753 handler->running = 0;
744 754
745 pthread_mutex_unlock(&handler->mutex); 755 pthread_mutex_unlock(&handler->mutex);
746 756
747 int i = 0; 757 int i = 0;
758
748 for (; i < handler->max_capacity; i ++) 759 for (; i < handler->max_capacity; i ++)
749 free(handler->timers[i]); 760 free(handler->timers[i]);
750 761
751 free(handler->timers); 762 free(handler->timers);
752 763
753 pthread_mutex_destroy( &handler->mutex ); 764 pthread_mutex_destroy( &handler->mutex );
754} 765}
755 766
@@ -946,8 +957,8 @@ MSICall *find_call ( MSISession *session, uint8_t *call_id )
946 957
947 for (; i < session->max_calls; i ++ ) 958 for (; i < session->max_calls; i ++ )
948 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 ) {
949 LOGGER_SCOPE( 960 LOGGER_SCOPE(
950 char tmp[CALL_ID_LEN+1] = {'\0'}; 961 char tmp[CALL_ID_LEN + 1] = {'\0'};
951 memcpy(tmp, session->calls[i]->id, CALL_ID_LEN); 962 memcpy(tmp, session->calls[i]->id, CALL_ID_LEN);
952 LOGGER_DEBUG("Found call id: %s", tmp); 963 LOGGER_DEBUG("Found call id: %s", tmp);
953 ); 964 );
@@ -1587,8 +1598,8 @@ MSISession *msi_init_session ( Messenger *messenger, int32_t max_calls )
1587 return NULL; 1598 return NULL;
1588 } 1599 }
1589 1600
1590 TimerHandler* handler = timer_init_session(max_calls * 10, 10000); 1601 TimerHandler *handler = timer_init_session(max_calls * 10, 10000);
1591 1602
1592 if ( !max_calls || !handler ) { 1603 if ( !max_calls || !handler ) {
1593 LOGGER_WARNING("Invalid max call treshold or timer handler initialization failed!"); 1604 LOGGER_WARNING("Invalid max call treshold or timer handler initialization failed!");
1594 return NULL; 1605 return NULL;
@@ -1604,7 +1615,7 @@ MSISession *msi_init_session ( Messenger *messenger, int32_t max_calls )
1604 _retu->messenger_handle = messenger; 1615 _retu->messenger_handle = messenger;
1605 _retu->agent_handler = NULL; 1616 _retu->agent_handler = NULL;
1606 _retu->timer_handler = handler; 1617 _retu->timer_handler = handler;
1607 1618
1608 if (!(_retu->calls = calloc( sizeof (MSICall *), max_calls ))) { 1619 if (!(_retu->calls = calloc( sizeof (MSICall *), max_calls ))) {
1609 LOGGER_ERROR("Allocation failed! Program might misbehave!"); 1620 LOGGER_ERROR("Allocation failed! Program might misbehave!");
1610 free(_retu); 1621 free(_retu);
@@ -1661,9 +1672,9 @@ int msi_terminate_session ( MSISession *session )
1661 } 1672 }
1662 1673
1663 timer_terminate_session(session->timer_handler); 1674 timer_terminate_session(session->timer_handler);
1664 1675
1665 pthread_mutex_destroy(&session->mutex); 1676 pthread_mutex_destroy(&session->mutex);
1666 1677
1667 LOGGER_DEBUG("Terminated session: %p", session); 1678 LOGGER_DEBUG("Terminated session: %p", session);
1668 free ( session ); 1679 free ( session );
1669 return _status; 1680 return _status;
@@ -1764,7 +1775,7 @@ int msi_hangup ( MSISession *session, int32_t call_index )
1764 1775
1765 free_message ( _msg_end ); 1776 free_message ( _msg_end );
1766 1777
1767 session->calls[call_index]->request_timer_id = 1778 session->calls[call_index]->request_timer_id =
1768 timer_alloc ( session->timer_handler, handle_timeout, session->calls[call_index], m_deftout ); 1779 timer_alloc ( session->timer_handler, handle_timeout, session->calls[call_index], m_deftout );
1769 1780
1770 pthread_mutex_unlock(&session->mutex); 1781 pthread_mutex_unlock(&session->mutex);
@@ -1877,7 +1888,7 @@ int msi_reject ( MSISession *session, int32_t call_index, const uint8_t *reason
1877 1888
1878 session->calls[call_index]->state = call_hanged_up; 1889 session->calls[call_index]->state = call_hanged_up;
1879 1890
1880 session->calls[call_index]->request_timer_id = 1891 session->calls[call_index]->request_timer_id =
1881 timer_alloc ( session->timer_handler, handle_timeout, session->calls[call_index], m_deftout ); 1892 timer_alloc ( session->timer_handler, handle_timeout, session->calls[call_index], m_deftout );
1882 1893
1883 pthread_mutex_unlock(&session->mutex); 1894 pthread_mutex_unlock(&session->mutex);