summaryrefslogtreecommitdiff
path: root/toxav
diff options
context:
space:
mode:
authormannol <eniz_vukovic@hotmail.com>2014-07-03 16:58:00 +0200
committermannol <eniz_vukovic@hotmail.com>2014-07-03 16:58:00 +0200
commitd3560a3a77dea199d25d0209288e07aeb5909abb (patch)
treebbf908194bebc0b28e7d62d21fe4e83b68ccdd2e /toxav
parentaeaf997ca57052a1589699c8ddfd9a75ca398180 (diff)
Removed redundant code and fixed toxav codec actions being called when call inactive
Diffstat (limited to 'toxav')
-rw-r--r--toxav/Makefile.inc4
-rw-r--r--toxav/codec.c10
-rw-r--r--toxav/codec.h2
-rw-r--r--toxav/event.c380
-rw-r--r--toxav/event.h47
-rw-r--r--toxav/msi.c315
-rw-r--r--toxav/msi.h2
-rw-r--r--toxav/toxav.c95
8 files changed, 352 insertions, 503 deletions
diff --git a/toxav/Makefile.inc b/toxav/Makefile.inc
index fdd20a26..de8ef8ff 100644
--- a/toxav/Makefile.inc
+++ b/toxav/Makefile.inc
@@ -4,9 +4,7 @@ lib_LTLIBRARIES += libtoxav.la
4libtoxav_la_include_HEADERS = ../toxav/toxav.h 4libtoxav_la_include_HEADERS = ../toxav/toxav.h
5libtoxav_la_includedir = $(includedir)/tox 5libtoxav_la_includedir = $(includedir)/tox
6 6
7libtoxav_la_SOURCES = ../toxav/event.h \ 7libtoxav_la_SOURCES = ../toxav/rtp.h \
8 ../toxav/event.c \
9 ../toxav/rtp.h \
10 ../toxav/rtp.c \ 8 ../toxav/rtp.c \
11 ../toxav/msi.h \ 9 ../toxav/msi.h \
12 ../toxav/msi.c \ 10 ../toxav/msi.c \
diff --git a/toxav/codec.c b/toxav/codec.c
index 9ca9a50c..33fe5627 100644
--- a/toxav/codec.c
+++ b/toxav/codec.c
@@ -1,4 +1,4 @@
1/** media.c 1/** codec.c
2 * 2 *
3 * Audio and video codec intitialization, encoding/decoding and playback 3 * Audio and video codec intitialization, encoding/decoding and playback
4 * 4 *
@@ -212,7 +212,7 @@ int init_video_encoder(CodecState *cs, uint16_t width, uint16_t height, uint32_t
212 vpx_codec_enc_cfg_t cfg; 212 vpx_codec_enc_cfg_t cfg;
213 int rc = vpx_codec_enc_config_default(VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0); 213 int rc = vpx_codec_enc_config_default(VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0);
214 214
215 if (rc) { 215 if (rc != VPX_CODEC_OK) {
216 LOGGER_ERROR("Failed to get config: %s", vpx_codec_err_to_string(rc)); 216 LOGGER_ERROR("Failed to get config: %s", vpx_codec_err_to_string(rc));
217 return -1; 217 return -1;
218 } 218 }
@@ -234,6 +234,12 @@ int init_video_encoder(CodecState *cs, uint16_t width, uint16_t height, uint32_t
234 } 234 }
235 235
236 rc = vpx_codec_control(&cs->v_encoder, VP8E_SET_CPUUSED, 7); 236 rc = vpx_codec_control(&cs->v_encoder, VP8E_SET_CPUUSED, 7);
237
238 if ( rc != VPX_CODEC_OK) {
239 LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc));
240 return -1;
241 }
242
237 return 0; 243 return 0;
238} 244}
239 245
diff --git a/toxav/codec.h b/toxav/codec.h
index d48e252c..7ddf2943 100644
--- a/toxav/codec.h
+++ b/toxav/codec.h
@@ -1,4 +1,4 @@
1/** media.h 1/** codec.h
2 * 2 *
3 * Audio and video codec intitialization, encoding/decoding and playback 3 * Audio and video codec intitialization, encoding/decoding and playback
4 * 4 *
diff --git a/toxav/event.c b/toxav/event.c
deleted file mode 100644
index 3916b744..00000000
--- a/toxav/event.c
+++ /dev/null
@@ -1,380 +0,0 @@
1/** event.c
2 *
3 * Copyright (C) 2013 Tox project All Rights Reserved.
4 *
5 * This file is part of Tox.
6 *
7 * Tox is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * Tox is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif /* HAVE_CONFIG_H */
26
27#include <stdlib.h>
28#include "../toxcore/network.h" /* current_time_monotonic() */
29#include "event.h"
30
31#define _GNU_SOURCE
32
33#include <assert.h>
34#include <unistd.h>
35#include <stddef.h>
36#include <inttypes.h>
37#include <pthread.h>
38#include <stdio.h>
39
40#define RUN_IN_THREAD(func, args) { pthread_t _tid; \
41pthread_create(&_tid, NULL, func, args); assert( pthread_detach(_tid) == 0 ); }
42
43#define LOCK(event_handler) pthread_mutex_lock (&event_handler->mutex)
44#define UNLOCK(event_handler) pthread_mutex_unlock(&event_handler->mutex)
45
46#define FREQUENCY 10000
47
48#define inline__ inline __attribute__((always_inline))
49
50
51typedef struct _EventContainer {
52 void *(*func)(void *);
53 void *func_args;
54 unsigned timeout;
55 long long id;
56
57} EventContainer;
58
59typedef struct _EventHandler {
60 EventContainer *timed_events;
61 size_t timed_events_count;
62
63 int running;
64
65 pthread_mutex_t mutex;
66
67} EventHandler;
68
69int throw_event( void *(func)(void *), void *arg );
70int reset_timer_event ( int id, uint32_t timeout );
71int throw_timer_event ( void *(func)(void *), void *arg, unsigned timeout);
72int cancel_timer_event ( int id );
73int execute_timer_event ( int id );
74
75struct _Event event = {
76 throw_event,
77 /* reset_timer_event */ NULL,
78 throw_timer_event,
79 cancel_timer_event,
80 /*execute_timer_event*/ NULL
81};
82
83/*
84 * Random functions used by this file
85 */
86void clear_events (EventContainer **event_container, size_t *counter)
87{
88 free(*event_container );
89
90 *event_container = NULL;
91 *counter = 0;
92}
93
94int pop_id ( EventContainer **event_container, size_t *counter, int id )
95{
96 if ( !*event_container || !*counter || !id )
97 return -1;
98
99 EventContainer *_it = *event_container;
100 int i;
101
102 for ( i = *counter; i; -- i ) {
103 if ( _it->id == id ) { /* Hit! */
104 break;
105 }
106
107 ++_it;
108 }
109
110 if ( i ) {
111 for ( ; i; -- i ) {
112 *_it = *(_it + 1);
113 ++_it;
114 }
115
116 -- (*counter );
117
118 if ( !(*counter)) { /* Free and set to NULL */
119 free(*event_container);
120 *event_container = NULL;
121 } else {
122 void *_result = realloc(*event_container, sizeof(EventContainer) * (*counter )); /* resize */
123
124
125 if ( _result != NULL ) {
126 *event_container = _result;
127 return 0;
128 } else {
129 /* Not sure what would happen next so abort execution.
130 */
131 fprintf(stderr, "CRITICAL! Failed to reallocate memory in %s():%d, aborting...", __func__, __LINE__);
132 abort();
133 return -1;
134 }
135 }
136 }
137
138 /* not found here */
139
140 return -1;
141}
142
143void push_event ( EventContainer **container, size_t *counter, void *(func)(void *), void *arg )
144{
145 EventContainer *_new = realloc((*container ), sizeof(EventContainer) * ((*counter ) + 1));
146
147 if ( _new == NULL ) {
148 /* Not sure what would happen next so abort execution.
149 * TODO: This could notice the calling function
150 * about realloc failing.
151 */
152 fprintf(stderr, "CRITICAL! Failed to reallocate memory in %s():%d, aborting...", __func__, __LINE__);
153 abort();
154 }
155
156 _new[*counter].func = func;
157 _new[*counter].func_args = arg;
158 _new[*counter].timeout = 0;
159 _new[*counter].id = 0;
160
161 (*container) = _new;
162
163 (*counter )++;
164}
165
166void reorder_events ( size_t counter, EventContainer *container, unsigned timeout )
167{
168 if ( counter > 1 ) {
169
170 int i = counter - 1;
171
172 /* start from behind excluding last added member */
173 EventContainer *_it = &container[i - 1];
174
175 EventContainer _last_added = container[i];
176
177 for ( ; i; --i ) {
178 if ( _it->timeout > timeout ) {
179 *(_it + 1) = *_it;
180 *_it = _last_added;
181 -- _it;
182 }
183 }
184
185 }
186}
187
188/* ============================================= */
189
190/* main poll for event execution */
191void *event_poll( void *arg )
192{
193 EventHandler *_event_handler = arg;
194
195 while ( _event_handler->running ) {
196
197 LOCK( _event_handler );
198
199 if ( _event_handler->timed_events ) {
200
201 uint32_t _time = ((uint32_t)current_time_monotonic());
202
203 if ( _event_handler->timed_events[0].timeout < _time ) {
204
205 RUN_IN_THREAD ( _event_handler->timed_events[0].func,
206 _event_handler->timed_events[0].func_args );
207
208 pop_id(&_event_handler->timed_events,
209 &_event_handler->timed_events_count,
210 _event_handler->timed_events[0].id);
211
212 }
213
214 }
215
216 UNLOCK( _event_handler );
217
218 usleep(FREQUENCY);
219 }
220
221 LOCK( _event_handler );
222
223 clear_events(&_event_handler->timed_events, &_event_handler->timed_events_count);
224
225 UNLOCK( _event_handler );
226
227 _event_handler->running = -1;
228 pthread_exit(NULL);
229}
230
231int throw_event( void *(func)(void *), void *arg )
232{
233 pthread_t _tid;
234 int _rc =
235 pthread_create(&_tid, NULL, func, arg );
236
237 return (0 != _rc ) ? _rc : pthread_detach(_tid);
238}
239
240EventHandler event_handler;
241
242/* Place and order array of timers */
243int throw_timer_event ( void *(func)(void *), void *arg, unsigned timeout)
244{
245 static int _unique_id = 1;
246
247 push_event(&event_handler.timed_events, &(event_handler.timed_events_count), func, arg );
248
249 size_t _counter = event_handler.timed_events_count;
250
251 event_handler.timed_events[_counter - 1].timeout = timeout + ((uint32_t)current_time_monotonic());
252 event_handler.timed_events[_counter - 1].id = _unique_id;
253 ++_unique_id;
254
255
256 /* reorder */
257
258 reorder_events(_counter, event_handler.timed_events, timeout );
259
260 return _unique_id - 1;
261}
262
263int execute_timer_event ( int id )
264{
265 int _status;
266
267 LOCK((&event_handler));
268 EventContainer *_it = event_handler.timed_events;
269
270 int _i = event_handler.timed_events_count;
271
272 /* Find it and execute */
273 for ( ; _i; _i-- ) {
274 if ( _it->id == id ) {
275 RUN_IN_THREAD ( _it->func, _it->func_args );
276 break;
277 }
278
279 ++_it;
280 }
281
282 /* Now remove it from the queue */
283
284 if ( _i ) {
285 for ( ; _i; -- _i ) {
286 *_it = *(_it + 1);
287 ++_it;
288 }
289
290 -- event_handler.timed_events_count;
291
292 if ( !event_handler.timed_events_count ) { /* Free and set to null */
293 free(event_handler.timed_events);
294 event_handler.timed_events = NULL;
295 } else {
296 void *_result = realloc(event_handler.timed_events,
297 sizeof(EventContainer) * event_handler.timed_events_count); /* resize */
298
299 if ( _result != NULL ) {
300 event_handler.timed_events = _result;
301 } else {
302 /* Not sure what would happen next so abort execution.
303 */
304 fprintf(stderr, "CRITICAL! Failed to reallocate memory in %s():%d, aborting...", __func__, __LINE__);
305 abort();
306 return -1;
307 }
308 }
309
310 _status = 0;
311
312 } else _status = -1;
313
314 UNLOCK((&event_handler));
315
316 return _status;
317}
318
319int reset_timer_event ( int id, uint32_t timeout )
320{
321 int _status;
322
323 LOCK((&event_handler));
324
325 EventContainer *_it = event_handler.timed_events;
326
327 int _i = event_handler.timed_events_count;
328
329 /* Find it and change */
330 for ( ; _i; _i-- ) {
331 if ( _it->id == id ) {
332 _it->timeout = timeout + ((uint32_t)current_time_monotonic());
333 break;
334 }
335
336 ++_it;
337 }
338
339 _status = _i ? -1 : 0;
340
341 UNLOCK((&event_handler));
342
343 return _status;
344}
345
346/* Remove timer from array */
347inline__ int cancel_timer_event ( int id )
348{
349 return pop_id (&event_handler.timed_events, &event_handler.timed_events_count, id );
350}
351
352
353/* Initialization and termination of event polls
354 * This will be run at the beginning and the end of the program execution.
355 * I think that's the best way to do it.
356 */
357
358void __attribute__((constructor)) init_event_poll ()
359{
360 event_handler.timed_events = NULL;
361 event_handler.timed_events_count = 0;
362
363 event_handler.running = 1;
364
365 pthread_mutex_init(&event_handler.mutex, NULL);
366
367 RUN_IN_THREAD(event_poll, &event_handler);
368}
369
370/* NOTE: Do we need this? */
371void __attribute__((destructor)) terminate_event_poll()
372{
373 /* Exit thread */
374 event_handler.running = 0;
375
376 /* Give it enought time to exit */
377 usleep(FREQUENCY * 2);
378
379 pthread_mutex_destroy( &event_handler.mutex );
380} \ No newline at end of file
diff --git a/toxav/event.h b/toxav/event.h
deleted file mode 100644
index e8bc5e37..00000000
--- a/toxav/event.h
+++ /dev/null
@@ -1,47 +0,0 @@
1/** event.h
2 *
3 * Copyright (C) 2013 Tox project All Rights Reserved.
4 *
5 * This file is part of Tox.
6 *
7 * Tox is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * Tox is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22
23#ifndef __TOXEVENT
24#define __TOXEVENT
25
26
27/**
28 * - Events are, in fact, ran in their own threads upon execution.
29 * - Event handler is initialized at the start, before the main() function
30 * and terminated after it's execution.
31 * - Timers are checked for timeout every ~10000 ns.
32 * - Timers can be canceled or ran immediately via
33 * timer_release() or timer_now() functions.
34 * - Timeout is measured in milliseconds.
35 *
36 * NOTE: timer_reset () and timer_now() are not tested nor usable atm
37 *
38 */
39extern struct _Event {
40 int (*rise) (void *( func ) ( void *), void *arg);
41 int (*timer_reset ) ( int id, unsigned timeout );
42 int (*timer_alloc) (void *( func ) ( void *), void *arg, unsigned timeout);
43 int (*timer_release) (int id);
44 int (*timer_now) ( int id );
45} event;
46
47#endif /* _MSI__EVENT_H_ */
diff --git a/toxav/msi.c b/toxav/msi.c
index 136daf93..9695029a 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,222 @@ 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 for (; i < timers_container->max_capacity && timers_container->timers[i]; i ++);
578
579 if (i == timers_container->max_capacity) {
580 LOGGER_WARNING("Maximum capacity reached!");
581 pthread_mutex_unlock(&timers_container->mutex);
582 return -1;
583 }
584
585 Timer* timer = timers_container->timers[i] = calloc(sizeof(Timer), 1);
586
587 if (timer == NULL) {
588 LOGGER_ERROR("Failed to allocate timer!");
589 pthread_mutex_unlock(&timers_container->mutex);
590 return -1;
591 }
592
593 timers_container->size ++;
594
595 timer->func = func;
596 timer->func_args = arg;
597 timer->timeout = timeout + current_time_monotonic(); /* In ms */
598 timer->idx = i;
599
600 /* reorder */
601 if (i) {
602 int j = i - 1;
603 for (; j >= 0 && timeout < timers_container->timers[j]->timeout; j--) {
604 Timer* tmp = timers_container->timers[j];
605 timers_container->timers[j] = timer;
606 timers_container->timers[j+1] = tmp;
607 }
608 }
609
610 pthread_mutex_unlock(&timers_container->mutex);
611
612 LOGGER_DEBUG("Allocated timer index: %d timeout: %d, current size: %d", i, timeout, timers_container->size);
613 return i;
614}
615
616/**
617 * @brief Remove timer from array
618 *
619 * @param timers_container handler
620 * @param idx index
621 * @return int
622 */
623int timer_release ( TimerHandler *timers_container, int idx )
624{
625 int rc = pthread_mutex_trylock(&timers_container->mutex);
626
627 Timer **timed_events = timers_container->timers;
628
629 if (!timed_events[idx]) {
630 LOGGER_WARNING("No event under index: %d", idx);
631 if ( rc != EBUSY ) pthread_mutex_unlock(&timers_container->mutex);
632 return -1;
633 }
634
635 free(timed_events[idx]);
636
637 timed_events[idx] = NULL;
638
639 int i = idx + 1;
640 for (; i < timers_container->max_capacity && timed_events[i]; i ++) {
641 timed_events[i-1] = timed_events[i];
642 timed_events[i] = NULL;
643 }
644
645 timers_container->size--;
646
647 LOGGER_DEBUG("Popped index: %d, current size: %d ", idx, timers_container->size);
648
649 if ( rc != EBUSY ) pthread_mutex_unlock(&timers_container->mutex);
650 return 0;
651}
652
653/**
654 * @brief Main poll for timer execution
655 *
656 * @param arg ...
657 * @return void*
658 */
659void *timer_poll( void *arg )
660{
661 TimerHandler *handler = arg;
662
663 while ( handler->running ) {
664
665 pthread_mutex_lock(&handler->mutex);
666
667 if ( handler->running ) {
668
669 uint64_t time = current_time_monotonic();
670
671 while ( handler->timers[0] && handler->timers[0]->timeout < time ) {
672
673 pthread_t _tid;
674 if ( 0 != pthread_create(&_tid, NULL, handler->timers[0]->func, handler->timers[0]->func_args) ||
675 0 != pthread_detach(_tid) )
676 LOGGER_ERROR("Failed to execute timer at: %d!", handler->timers[0]->timeout);
677
678 else LOGGER_DEBUG("Exectued timer assigned at: %d", handler->timers[0]->timeout);
679
680 timer_release(handler, 0);
681 }
682
683 }
684
685 pthread_mutex_unlock(&handler->mutex);
686
687 usleep(handler->resolution);
688 }
689
690 pthread_exit(NULL);
691}
692
693/**
694 * @brief Start timer poll and return handler
695 *
696 * @param max_capacity capacity
697 * @param resolution ...
698 * @return TimerHandler*
699 */
700TimerHandler* timer_init_session (int max_capacity, int resolution)
701{
702 TimerHandler* handler = calloc(1, sizeof(TimerHandler));
703 if (handler == NULL) {
704 LOGGER_ERROR("Failed to allocate memory, program might misbehave!");
705 return NULL;
706 }
707
708 handler->timers = calloc(max_capacity, sizeof(Timer*));
709 if (handler->timers == NULL) {
710 LOGGER_ERROR("Failed to allocate %d timed events!", max_capacity);
711 free(handler);
712 return NULL;
713 }
714
715 handler->max_capacity = max_capacity;
716 handler->running = 1;
717 handler->resolution = resolution;
718
719 pthread_mutex_init(&handler->mutex, NULL);
720
721
722 pthread_t _tid;
723 if ( 0 != pthread_create(&_tid, NULL, timer_poll, handler) || 0 != pthread_detach(_tid) ){
724 LOGGER_ERROR("Failed to start timer poll thread!");
725 free(handler->timers);
726 free(handler);
727 return NULL;
728 }
729
730 return handler;
731}
732
733/**
734 * @brief Terminate timer session
735 *
736 * @param handler The timer handler
737 * @return void
738 */
739void timer_terminate_session(TimerHandler* handler)
740{
741 pthread_mutex_lock(&handler->mutex);
742
743 handler->running = 0;
744
745 pthread_mutex_unlock(&handler->mutex);
746
747 int i = 0;
748 for (; i < handler->max_capacity; i ++)
749 free(handler->timers[i]);
750
751 free(handler->timers);
752
753 pthread_mutex_destroy( &handler->mutex );
754}
755
541/** 756/**
542 * @brief Generate _random_ alphanumerical string. 757 * @brief Generate _random_ alphanumerical string.
543 * 758 *
@@ -731,7 +946,11 @@ MSICall *find_call ( MSISession *session, uint8_t *call_id )
731 946
732 for (; i < session->max_calls; i ++ ) 947 for (; i < session->max_calls; i ++ )
733 if ( session->calls[i] && memcmp(session->calls[i]->id, call_id, CALL_ID_LEN) == 0 ) { 948 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); 949 LOGGER_SCOPE(
950 char tmp[CALL_ID_LEN+1] = {'\0'};
951 memcpy(tmp, session->calls[i]->id, CALL_ID_LEN);
952 LOGGER_DEBUG("Found call id: %s", tmp);
953 );
735 return session->calls[i]; 954 return session->calls[i];
736 } 955 }
737 956
@@ -883,8 +1102,8 @@ int terminate_call ( MSISession *session, MSICall *call )
883 * NOTE: This has to be done before possibly 1102 * NOTE: This has to be done before possibly
884 * locking the mutex the second time 1103 * locking the mutex the second time
885 */ 1104 */
886 event.timer_release ( call->request_timer_id ); 1105 timer_release ( session->timer_handler, call->request_timer_id );
887 event.timer_release ( call->ringing_timer_id ); 1106 timer_release ( session->timer_handler, call->ringing_timer_id );
888 1107
889 /* Get a handle */ 1108 /* Get a handle */
890 pthread_mutex_lock ( &call->mutex ); 1109 pthread_mutex_lock ( &call->mutex );
@@ -1055,10 +1274,6 @@ int handle_recv_reject ( MSISession *session, MSICall *call, MSIMessage *msg )
1055 pthread_mutex_unlock(&session->mutex); 1274 pthread_mutex_unlock(&session->mutex);
1056 1275
1057 invoke_callback(call->call_idx, MSI_OnReject); 1276 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 1277
1063 terminate_call(session, call); 1278 terminate_call(session, call);
1064 return 1; 1279 return 1;
@@ -1123,7 +1338,7 @@ int handle_recv_ringing ( MSISession *session, MSICall *call, MSIMessage *msg )
1123 1338
1124 LOGGER_DEBUG("Session: %p Handling 'ringing' on call: %s", session, call->id ); 1339 LOGGER_DEBUG("Session: %p Handling 'ringing' on call: %s", session, call->id );
1125 1340
1126 call->ringing_timer_id = event.timer_alloc ( handle_timeout, call, call->ringing_tout_ms ); 1341 call->ringing_timer_id = timer_alloc ( session->timer_handler, handle_timeout, call, call->ringing_tout_ms );
1127 1342
1128 pthread_mutex_unlock(&session->mutex); 1343 pthread_mutex_unlock(&session->mutex);
1129 1344
@@ -1150,7 +1365,7 @@ int handle_recv_starting ( MSISession *session, MSICall *call, MSIMessage *msg )
1150 flush_peer_type ( call, msg, 0 ); 1365 flush_peer_type ( call, msg, 0 );
1151 1366
1152 1367
1153 event.timer_release ( call->ringing_timer_id ); 1368 timer_release ( session->timer_handler, call->ringing_timer_id );
1154 pthread_mutex_unlock(&session->mutex); 1369 pthread_mutex_unlock(&session->mutex);
1155 1370
1156 invoke_callback(call->call_idx, MSI_OnStarting); 1371 invoke_callback(call->call_idx, MSI_OnStarting);
@@ -1168,7 +1383,7 @@ int handle_recv_ending ( MSISession *session, MSICall *call, MSIMessage *msg )
1168 LOGGER_DEBUG("Session: %p Handling 'ending' on call: %s", session, call->id ); 1383 LOGGER_DEBUG("Session: %p Handling 'ending' on call: %s", session, call->id );
1169 1384
1170 /* Stop timer */ 1385 /* Stop timer */
1171 event.timer_release ( call->request_timer_id ); 1386 timer_release ( session->timer_handler, call->request_timer_id );
1172 1387
1173 pthread_mutex_unlock(&session->mutex); 1388 pthread_mutex_unlock(&session->mutex);
1174 1389
@@ -1246,89 +1461,88 @@ void msi_handle_packet ( Messenger *messenger, int source, uint8_t *data, uint16
1246 /* Unused */ 1461 /* Unused */
1247 (void)messenger; 1462 (void)messenger;
1248 1463
1249 MSISession *_session = object; 1464 MSISession *session = object;
1250 MSIMessage *_msg; 1465 MSIMessage *msg;
1251 1466
1252 if ( !length ) { 1467 if ( !length ) {
1253 LOGGER_WARNING("Lenght param negative"); 1468 LOGGER_WARNING("Lenght param negative");
1254 return; 1469 return;
1255 } 1470 }
1256 1471
1257 _msg = parse_message ( data, length ); 1472 msg = parse_message ( data, length );
1258 1473
1259 if ( !_msg ) { 1474 if ( !msg ) {
1260 LOGGER_WARNING("Error parsing message"); 1475 LOGGER_WARNING("Error parsing message");
1261 return; 1476 return;
1262 } else { 1477 } else {
1263 LOGGER_DEBUG("Successfully parsed message"); 1478 LOGGER_DEBUG("Successfully parsed message");
1264 } 1479 }
1265 1480
1266 _msg->friend_id = source; 1481 msg->friend_id = source;
1267 1482
1268 1483
1269 /* Find what call */ 1484 /* Find what call */
1270 MSICall *_call = _msg->callid.header_value ? find_call(_session, _msg->callid.header_value ) : NULL; 1485 MSICall *call = msg->callid.header_value ? find_call(session, msg->callid.header_value ) : NULL;
1271 1486
1272 /* Now handle message */ 1487 /* Now handle message */
1273 1488
1274 if ( _msg->request.header_value ) { /* Handle request */ 1489 if ( msg->request.header_value ) { /* Handle request */
1275 1490
1276 if ( _msg->response.size > 32 ) { 1491 if ( msg->response.size > 32 ) {
1277 LOGGER_WARNING("Header size too big"); 1492 LOGGER_WARNING("Header size too big");
1278 goto free_end; 1493 goto free_end;
1279 } 1494 }
1280 1495
1281 uint8_t _request_value[32]; 1496 uint8_t _request_value[32];
1282 1497
1283 memcpy(_request_value, _msg->request.header_value, _msg->request.size); 1498 memcpy(_request_value, msg->request.header_value, msg->request.size);
1284 _request_value[_msg->request.size] = '\0'; 1499 _request_value[msg->request.size] = '\0';
1285 1500
1286 if ( same ( _request_value, stringify_request ( invite ) ) ) { 1501 if ( same ( _request_value, stringify_request ( invite ) ) ) {
1287 handle_recv_invite ( _session, _call, _msg ); 1502 handle_recv_invite ( session, call, msg );
1288 1503
1289 } else if ( same ( _request_value, stringify_request ( start ) ) ) { 1504 } else if ( same ( _request_value, stringify_request ( start ) ) ) {
1290 handle_recv_start ( _session, _call, _msg ); 1505 handle_recv_start ( session, call, msg );
1291 1506
1292 } else if ( same ( _request_value, stringify_request ( cancel ) ) ) { 1507 } else if ( same ( _request_value, stringify_request ( cancel ) ) ) {
1293 handle_recv_cancel ( _session, _call, _msg ); 1508 handle_recv_cancel ( session, call, msg );
1294 1509
1295 } else if ( same ( _request_value, stringify_request ( reject ) ) ) { 1510 } else if ( same ( _request_value, stringify_request ( reject ) ) ) {
1296 handle_recv_reject ( _session, _call, _msg ); 1511 handle_recv_reject ( session, call, msg );
1297 1512
1298 } else if ( same ( _request_value, stringify_request ( end ) ) ) { 1513 } else if ( same ( _request_value, stringify_request ( end ) ) ) {
1299 handle_recv_end ( _session, _call, _msg ); 1514 handle_recv_end ( session, call, msg );
1300 } else { 1515 } else {
1301 LOGGER_WARNING("Uknown request"); 1516 LOGGER_WARNING("Uknown request");
1302 goto free_end; 1517 goto free_end;
1303 } 1518 }
1304 1519
1305 } else if ( _msg->response.header_value ) { /* Handle response */ 1520 } else if ( msg->response.header_value ) { /* Handle response */
1306 1521
1307 if ( _msg->response.size > 32 ) { 1522 if ( msg->response.size > 32 ) {
1308 LOGGER_WARNING("Header size too big"); 1523 LOGGER_WARNING("Header size too big");
1309 goto free_end; 1524 goto free_end;
1310 } 1525 }
1311 1526
1312 /* Got response so cancel timer */ 1527 /* Got response so cancel timer */
1313 if ( _call ) 1528 if ( call ) timer_release ( session->timer_handler, call->request_timer_id );
1314 event.timer_release ( _call->request_timer_id );
1315 1529
1316 uint8_t _response_value[32]; 1530 uint8_t _response_value[32];
1317 1531
1318 memcpy(_response_value, _msg->response.header_value, _msg->response.size); 1532 memcpy(_response_value, msg->response.header_value, msg->response.size);
1319 _response_value[_msg->response.size] = '\0'; 1533 _response_value[msg->response.size] = '\0';
1320 1534
1321 if ( same ( _response_value, stringify_response ( ringing ) ) ) { 1535 if ( same ( _response_value, stringify_response ( ringing ) ) ) {
1322 handle_recv_ringing ( _session, _call, _msg ); 1536 handle_recv_ringing ( session, call, msg );
1323 1537
1324 } else if ( same ( _response_value, stringify_response ( starting ) ) ) { 1538 } else if ( same ( _response_value, stringify_response ( starting ) ) ) {
1325 handle_recv_starting ( _session, _call, _msg ); 1539 handle_recv_starting ( session, call, msg );
1326 1540
1327 } else if ( same ( _response_value, stringify_response ( ending ) ) ) { 1541 } else if ( same ( _response_value, stringify_response ( ending ) ) ) {
1328 handle_recv_ending ( _session, _call, _msg ); 1542 handle_recv_ending ( session, call, msg );
1329 1543
1330 } else if ( same ( _response_value, stringify_response ( error ) ) ) { 1544 } else if ( same ( _response_value, stringify_response ( error ) ) ) {
1331 handle_recv_error ( _session, _call, _msg ); 1545 handle_recv_error ( session, call, msg );
1332 1546
1333 } else { 1547 } else {
1334 LOGGER_WARNING("Uknown response"); 1548 LOGGER_WARNING("Uknown response");
@@ -1340,7 +1554,7 @@ void msi_handle_packet ( Messenger *messenger, int source, uint8_t *data, uint16
1340 } 1554 }
1341 1555
1342free_end: 1556free_end:
1343 free_message ( _msg ); 1557 free_message ( msg );
1344} 1558}
1345 1559
1346 1560
@@ -1373,7 +1587,12 @@ MSISession *msi_init_session ( Messenger *messenger, int32_t max_calls )
1373 return NULL; 1587 return NULL;
1374 } 1588 }
1375 1589
1376 if ( !max_calls) return NULL; 1590 TimerHandler* handler = timer_init_session(max_calls * 10, 10000);
1591
1592 if ( !max_calls || !handler ) {
1593 LOGGER_WARNING("Invalid max call treshold or timer handler initialization failed!");
1594 return NULL;
1595 }
1377 1596
1378 MSISession *_retu = calloc ( sizeof ( MSISession ), 1 ); 1597 MSISession *_retu = calloc ( sizeof ( MSISession ), 1 );
1379 1598
@@ -1384,6 +1603,7 @@ MSISession *msi_init_session ( Messenger *messenger, int32_t max_calls )
1384 1603
1385 _retu->messenger_handle = messenger; 1604 _retu->messenger_handle = messenger;
1386 _retu->agent_handler = NULL; 1605 _retu->agent_handler = NULL;
1606 _retu->timer_handler = handler;
1387 1607
1388 if (!(_retu->calls = calloc( sizeof (MSICall *), max_calls ))) { 1608 if (!(_retu->calls = calloc( sizeof (MSICall *), max_calls ))) {
1389 LOGGER_ERROR("Allocation failed! Program might misbehave!"); 1609 LOGGER_ERROR("Allocation failed! Program might misbehave!");
@@ -1440,9 +1660,12 @@ int msi_terminate_session ( MSISession *session )
1440 msi_cancel ( session, idx, session->calls[idx]->peers [_it], "MSI session terminated!" ); 1660 msi_cancel ( session, idx, session->calls[idx]->peers [_it], "MSI session terminated!" );
1441 } 1661 }
1442 1662
1443 1663 timer_terminate_session(session->timer_handler);
1664
1444 pthread_mutex_destroy(&session->mutex); 1665 pthread_mutex_destroy(&session->mutex);
1445 1666
1667// timer_terminate_session();
1668
1446 LOGGER_DEBUG("Terminated session: %p", session); 1669 LOGGER_DEBUG("Terminated session: %p", session);
1447 free ( session ); 1670 free ( session );
1448 return _status; 1671 return _status;
@@ -1495,7 +1718,7 @@ int msi_invite ( MSISession *session, int32_t *call_index, MSICallType call_type
1495 1718
1496 _call->state = call_inviting; 1719 _call->state = call_inviting;
1497 1720
1498 _call->request_timer_id = event.timer_alloc ( handle_timeout, _call, m_deftout ); 1721 _call->request_timer_id = timer_alloc ( session->timer_handler, handle_timeout, _call, m_deftout );
1499 1722
1500 LOGGER_DEBUG("Invite sent"); 1723 LOGGER_DEBUG("Invite sent");
1501 1724
@@ -1543,8 +1766,8 @@ int msi_hangup ( MSISession *session, int32_t call_index )
1543 1766
1544 free_message ( _msg_end ); 1767 free_message ( _msg_end );
1545 1768
1546 session->calls[call_index]->request_timer_id = event.timer_alloc ( handle_timeout, session->calls[call_index], 1769 session->calls[call_index]->request_timer_id =
1547 m_deftout ); 1770 timer_alloc ( session->timer_handler, handle_timeout, session->calls[call_index], m_deftout );
1548 1771
1549 pthread_mutex_unlock(&session->mutex); 1772 pthread_mutex_unlock(&session->mutex);
1550 return 0; 1773 return 0;
@@ -1620,7 +1843,7 @@ int msi_cancel ( MSISession *session, int32_t call_index, uint32_t peer, const c
1620 free_message ( _msg_cancel ); 1843 free_message ( _msg_cancel );
1621 1844
1622 /*session->calls[call_index]->state = call_hanged_up; 1845 /*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 );*/ 1846 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] ); 1847 terminate_call ( session, session->calls[call_index] );
1625 pthread_mutex_unlock(&session->mutex); 1848 pthread_mutex_unlock(&session->mutex);
1626 1849
@@ -1656,8 +1879,8 @@ int msi_reject ( MSISession *session, int32_t call_index, const uint8_t *reason
1656 1879
1657 session->calls[call_index]->state = call_hanged_up; 1880 session->calls[call_index]->state = call_hanged_up;
1658 1881
1659 session->calls[call_index]->request_timer_id = event.timer_alloc ( handle_timeout, session->calls[call_index], 1882 session->calls[call_index]->request_timer_id =
1660 m_deftout ); 1883 timer_alloc ( session->timer_handler, handle_timeout, session->calls[call_index], m_deftout );
1661 1884
1662 pthread_mutex_unlock(&session->mutex); 1885 pthread_mutex_unlock(&session->mutex);
1663 return 0; 1886 return 0;
diff --git a/toxav/msi.h b/toxav/msi.h
index 02432daf..fbef46f2 100644
--- a/toxav/msi.h
+++ b/toxav/msi.h
@@ -105,6 +105,8 @@ typedef struct _MSISession {
105 uint32_t call_timeout; /* Time of the timeout for some action to end; 0 if infinite */ 105 uint32_t call_timeout; /* Time of the timeout for some action to end; 0 if infinite */
106 106
107 pthread_mutex_t mutex; 107 pthread_mutex_t mutex;
108
109 void* timer_handler;
108} MSISession; 110} MSISession;
109 111
110 112
diff --git a/toxav/toxav.c b/toxav/toxav.c
index ad8e651f..02c5a970 100644
--- a/toxav/toxav.c
+++ b/toxav/toxav.c
@@ -66,6 +66,8 @@ typedef struct _CallSpecific {
66 uint32_t frame_limit; /* largest address written to in frame_buf for current input frame*/ 66 uint32_t frame_limit; /* largest address written to in frame_buf for current input frame*/
67 uint8_t frame_id, frame_outid; /* id of input and output video frame */ 67 uint8_t frame_id, frame_outid; /* id of input and output video frame */
68 void *frame_buf; /* buffer for split video payloads */ 68 void *frame_buf; /* buffer for split video payloads */
69
70 _Bool call_active;
69} CallSpecific; 71} CallSpecific;
70 72
71 73
@@ -296,8 +298,9 @@ int toxav_stop_call ( ToxAv *av, int32_t call_index )
296 */ 298 */
297int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, ToxAvCodecSettings *codec_settings, int support_video ) 299int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, ToxAvCodecSettings *codec_settings, int support_video )
298{ 300{
299 if ( !av->msi_session || cii(call_index, av->msi_session) || !av->msi_session->calls[call_index] ) { 301 if ( !av->msi_session || cii(call_index, av->msi_session) ||
300 LOGGER_ERROR("Error while starting audio RTP session: invalid call!\n"); 302 !av->msi_session->calls[call_index] || av->calls[call_index].call_active) {
303 LOGGER_ERROR("Error while starting RTP session: invalid call!\n");
301 return ErrorInternal; 304 return ErrorInternal;
302 } 305 }
303 306
@@ -320,6 +323,8 @@ int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, ToxAvCodecSettin
320 323
321 if ( !call->crtps[video_index] ) { 324 if ( !call->crtps[video_index] ) {
322 LOGGER_ERROR("Error while starting video RTP session!\n"); 325 LOGGER_ERROR("Error while starting video RTP session!\n");
326
327 rtp_terminate_session(call->crtps[audio_index], av->messenger);
323 return ErrorStartingVideoRtp; 328 return ErrorStartingVideoRtp;
324 } 329 }
325 330
@@ -330,23 +335,40 @@ int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, ToxAvCodecSettin
330 call->frame_buf = calloc(MAX_VIDEOFRAME_SIZE, 1); 335 call->frame_buf = calloc(MAX_VIDEOFRAME_SIZE, 1);
331 336
332 if (!call->frame_buf) { 337 if (!call->frame_buf) {
338 rtp_terminate_session(call->crtps[audio_index], av->messenger);
339 rtp_terminate_session(call->crtps[video_index], av->messenger);
340 LOGGER_WARNING("Frame buffer allocation failed!");
333 return ErrorInternal; 341 return ErrorInternal;
334 } 342 }
335 343
336 } 344 }
337 345
338 if ( !(call->j_buf = create_queue(codec_settings->jbuf_capacity)) ) return ErrorInternal; 346 if ( !(call->j_buf = create_queue(codec_settings->jbuf_capacity)) ) {
347 rtp_terminate_session(call->crtps[audio_index], av->messenger);
348 rtp_terminate_session(call->crtps[video_index], av->messenger);
349 free(call->frame_buf);
350 LOGGER_WARNING("Jitter buffer creaton failed!");
351 return ErrorInternal;
352 }
339 353
340 call->cs = codec_init_session(codec_settings->audio_bitrate, 354 if ( (call->cs = codec_init_session(codec_settings->audio_bitrate,
341 codec_settings->audio_frame_duration, 355 codec_settings->audio_frame_duration,
342 codec_settings->audio_sample_rate, 356 codec_settings->audio_sample_rate,
343 codec_settings->audio_channels, 357 codec_settings->audio_channels,
344 codec_settings->audio_VAD_tolerance, 358 codec_settings->audio_VAD_tolerance,
345 codec_settings->video_width, 359 codec_settings->video_width,
346 codec_settings->video_height, 360 codec_settings->video_height,
347 codec_settings->video_bitrate); 361 codec_settings->video_bitrate) )) {
348 362 call->call_active = 1;
349 return call->cs ? ErrorNone : ErrorInternal; 363 return ErrorNone;
364 }
365
366 rtp_terminate_session(call->crtps[audio_index], av->messenger);
367 rtp_terminate_session(call->crtps[video_index], av->messenger);
368 free(call->frame_buf);
369 terminate_queue(call->j_buf);
370
371 return ErrorInternal;
350} 372}
351 373
352/** 374/**
@@ -359,22 +381,26 @@ int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, ToxAvCodecSettin
359 */ 381 */
360int toxav_kill_transmission ( ToxAv *av, int32_t call_index ) 382int toxav_kill_transmission ( ToxAv *av, int32_t call_index )
361{ 383{
362 if (cii(call_index, av->msi_session)) return ErrorNoCall; 384 if (cii(call_index, av->msi_session) || !av->calls[call_index].call_active) {
363 385 LOGGER_WARNING("Action on inactive call: %d", call_index);
386 return ErrorNoCall;
387 }
388
364 CallSpecific *call = &av->calls[call_index]; 389 CallSpecific *call = &av->calls[call_index];
365 390
391 call->call_active = 0;
392
366 if ( call->crtps[audio_index] && -1 == rtp_terminate_session(call->crtps[audio_index], av->messenger) ) { 393 if ( call->crtps[audio_index] && -1 == rtp_terminate_session(call->crtps[audio_index], av->messenger) ) {
367 LOGGER_ERROR("Error while terminating audio RTP session!\n"); 394 LOGGER_ERROR("Error while terminating audio RTP session!\n");
368 return ErrorTerminatingAudioRtp; 395 /*return ErrorTerminatingAudioRtp;*/
369 } 396 }
397 else call->crtps[audio_index] = NULL;
370 398
371 if ( call->crtps[video_index] && -1 == rtp_terminate_session(call->crtps[video_index], av->messenger) ) { 399 if ( call->crtps[video_index] && -1 == rtp_terminate_session(call->crtps[video_index], av->messenger) ) {
372 LOGGER_ERROR("Error while terminating video RTP session!\n"); 400 LOGGER_ERROR("Error while terminating video RTP session!\n");
373 return ErrorTerminatingVideoRtp; 401 /*return ErrorTerminatingVideoRtp;*/
374 } 402 }
375 403 else call->crtps[video_index] = NULL;
376 call->crtps[audio_index] = NULL;
377 call->crtps[video_index] = NULL;
378 404
379 if ( call->j_buf ) { 405 if ( call->j_buf ) {
380 terminate_queue(call->j_buf); 406 terminate_queue(call->j_buf);
@@ -388,6 +414,7 @@ int toxav_kill_transmission ( ToxAv *av, int32_t call_index )
388 LOGGER_DEBUG("Terminated codec session"); 414 LOGGER_DEBUG("Terminated codec session");
389 } else LOGGER_DEBUG("No codec session"); 415 } else LOGGER_DEBUG("No codec session");
390 416
417
391 return ErrorNone; 418 return ErrorNone;
392} 419}
393 420
@@ -406,8 +433,6 @@ int toxav_kill_transmission ( ToxAv *av, int32_t call_index )
406inline__ int toxav_send_rtp_payload ( ToxAv *av, int32_t call_index, ToxAvCallType type, const uint8_t *payload, 433inline__ int toxav_send_rtp_payload ( ToxAv *av, int32_t call_index, ToxAvCallType type, const uint8_t *payload,
407 unsigned int length ) 434 unsigned int length )
408{ 435{
409 if (cii(call_index, av->msi_session)) return ErrorNoCall;
410
411#define send(data, len) rtp_send_msg(av->calls[call_index].crtps[type - TypeAudio], av->msi_session->messenger_handle, data, len) 436#define send(data, len) rtp_send_msg(av->calls[call_index].crtps[type - TypeAudio], av->msi_session->messenger_handle, data, len)
412 437
413 if (av->calls[call_index].crtps[type - TypeAudio]) { 438 if (av->calls[call_index].crtps[type - TypeAudio]) {
@@ -465,8 +490,6 @@ inline__ int toxav_recv_rtp_payload ( ToxAv *av, int32_t call_index, ToxAvCallTy
465{ 490{
466 if ( !dest ) return ErrorInternal; 491 if ( !dest ) return ErrorInternal;
467 492
468 if (cii(call_index, av->msi_session)) return ErrorNoCall;
469
470 CallSpecific *call = &av->calls[call_index]; 493 CallSpecific *call = &av->calls[call_index];
471 494
472 if ( !call->crtps[type - TypeAudio] ) return ErrorNoRtpSession; 495 if ( !call->crtps[type - TypeAudio] ) return ErrorNoRtpSession;
@@ -518,7 +541,11 @@ inline__ int toxav_recv_video ( ToxAv *av, int32_t call_index, vpx_image_t **out
518{ 541{
519 if ( !output ) return ErrorInternal; 542 if ( !output ) return ErrorInternal;
520 543
521 if (cii(call_index, av->msi_session)) return ErrorNoCall; 544 if (cii(call_index, av->msi_session) || !av->calls[call_index].call_active) {
545 LOGGER_WARNING("Action on inactive call: %d", call_index);
546 return ErrorNoCall;
547 }
548
522 549
523 uint8_t packet [RTP_PAYLOAD_SIZE]; 550 uint8_t packet [RTP_PAYLOAD_SIZE];
524 CallSpecific *call = &av->calls[call_index]; 551 CallSpecific *call = &av->calls[call_index];
@@ -584,7 +611,11 @@ inline__ int toxav_recv_video ( ToxAv *av, int32_t call_index, vpx_image_t **out
584 */ 611 */
585inline__ int toxav_send_video ( ToxAv *av, int32_t call_index, const uint8_t *frame, int frame_size) 612inline__ int toxav_send_video ( ToxAv *av, int32_t call_index, const uint8_t *frame, int frame_size)
586{ 613{
587 if (cii(call_index, av->msi_session)) return ErrorNoCall; 614 if (cii(call_index, av->msi_session) || !av->calls[call_index].call_active) {
615 LOGGER_WARNING("Action on inactive call: %d", call_index);
616 return ErrorNoCall;
617 }
618
588 619
589 return toxav_send_rtp_payload(av, call_index, TypeVideo, frame, frame_size); 620 return toxav_send_rtp_payload(av, call_index, TypeVideo, frame, frame_size);
590} 621}
@@ -602,7 +633,11 @@ inline__ int toxav_send_video ( ToxAv *av, int32_t call_index, const uint8_t *fr
602 */ 633 */
603inline__ int toxav_prepare_video_frame(ToxAv *av, int32_t call_index, uint8_t *dest, int dest_max, vpx_image_t *input) 634inline__ int toxav_prepare_video_frame(ToxAv *av, int32_t call_index, uint8_t *dest, int dest_max, vpx_image_t *input)
604{ 635{
605 if (cii(call_index, av->msi_session)) return ErrorNoCall; 636 if (cii(call_index, av->msi_session) || !av->calls[call_index].call_active) {
637 LOGGER_WARNING("Action on inactive call: %d", call_index);
638 return ErrorNoCall;
639 }
640
606 641
607 CallSpecific *call = &av->calls[call_index]; 642 CallSpecific *call = &av->calls[call_index];
608 643
@@ -647,7 +682,11 @@ inline__ int toxav_recv_audio ( ToxAv *av, int32_t call_index, int frame_size, i
647{ 682{
648 if ( !dest ) return ErrorInternal; 683 if ( !dest ) return ErrorInternal;
649 684
650 if (cii(call_index, av->msi_session)) return ErrorNoCall; 685 if (cii(call_index, av->msi_session) || !av->calls[call_index].call_active) {
686 LOGGER_WARNING("Action on inactive call: %d", call_index);
687 return ErrorNoCall;
688 }
689
651 690
652 CallSpecific *call = &av->calls[call_index]; 691 CallSpecific *call = &av->calls[call_index];
653 692
@@ -688,7 +727,11 @@ inline__ int toxav_recv_audio ( ToxAv *av, int32_t call_index, int frame_size, i
688 */ 727 */
689inline__ int toxav_send_audio ( ToxAv *av, int32_t call_index, const uint8_t *frame, int frame_size) 728inline__ int toxav_send_audio ( ToxAv *av, int32_t call_index, const uint8_t *frame, int frame_size)
690{ 729{
691 if (cii(call_index, av->msi_session)) return ErrorNoCall; 730 if (cii(call_index, av->msi_session) || !av->calls[call_index].call_active) {
731 LOGGER_WARNING("Action on inactive call: %d", call_index);
732 return ErrorNoCall;
733 }
734
692 735
693 return toxav_send_rtp_payload(av, call_index, TypeAudio, frame, frame_size); 736 return toxav_send_rtp_payload(av, call_index, TypeAudio, frame, frame_size);
694} 737}
@@ -708,7 +751,11 @@ inline__ int toxav_send_audio ( ToxAv *av, int32_t call_index, const uint8_t *fr
708inline__ int toxav_prepare_audio_frame ( ToxAv *av, int32_t call_index, uint8_t *dest, int dest_max, 751inline__ int toxav_prepare_audio_frame ( ToxAv *av, int32_t call_index, uint8_t *dest, int dest_max,
709 const int16_t *frame, int frame_size) 752 const int16_t *frame, int frame_size)
710{ 753{
711 if (cii(call_index, av->msi_session)) return ErrorNoCall; 754 if (cii(call_index, av->msi_session) || !av->calls[call_index].call_active) {
755 LOGGER_WARNING("Action on inactive call: %d", call_index);
756 return ErrorNoCall;
757 }
758
712 759
713 int32_t rc = opus_encode(av->calls[call_index].cs->audio_encoder, frame, frame_size, dest, dest_max); 760 int32_t rc = opus_encode(av->calls[call_index].cs->audio_encoder, frame, frame_size, dest, dest_max);
714 761