diff options
Diffstat (limited to 'toxav/msi.c')
-rw-r--r-- | toxav/msi.c | 153 |
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 | ||
550 | typedef struct _TimerHandler { | 550 | typedef 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 { | |||
572 | int timer_alloc ( TimerHandler *timers_container, void *(func)(void *), void *arg, unsigned timeout) | 572 | int 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 | |||
623 | int timer_release ( TimerHandler *timers_container, int idx ) | 625 | int 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 | */ |
659 | void *timer_poll( void *arg ) | 665 | void *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 | */ |
700 | TimerHandler* timer_init_session (int max_capacity, int resolution) | 707 | TimerHandler *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 | */ |
739 | void timer_terminate_session(TimerHandler* handler) | 749 | void 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); |