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