Merge branch 'mannol1-master'

This commit is contained in:
irungentoo 2014-07-03 11:13:11 -04:00
commit aa1194ab3e
No known key found for this signature in database
GPG Key ID: 10349DC9BED89E98
8 changed files with 364 additions and 508 deletions

View File

@ -4,9 +4,7 @@ lib_LTLIBRARIES += libtoxav.la
libtoxav_la_include_HEADERS = ../toxav/toxav.h
libtoxav_la_includedir = $(includedir)/tox
libtoxav_la_SOURCES = ../toxav/event.h \
../toxav/event.c \
../toxav/rtp.h \
libtoxav_la_SOURCES = ../toxav/rtp.h \
../toxav/rtp.c \
../toxav/msi.h \
../toxav/msi.c \

View File

@ -1,4 +1,4 @@
/** media.c
/** codec.c
*
* Audio and video codec intitialization, encoding/decoding and playback
*
@ -212,7 +212,7 @@ int init_video_encoder(CodecState *cs, uint16_t width, uint16_t height, uint32_t
vpx_codec_enc_cfg_t cfg;
int rc = vpx_codec_enc_config_default(VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0);
if (rc) {
if (rc != VPX_CODEC_OK) {
LOGGER_ERROR("Failed to get config: %s", vpx_codec_err_to_string(rc));
return -1;
}
@ -234,6 +234,12 @@ int init_video_encoder(CodecState *cs, uint16_t width, uint16_t height, uint32_t
}
rc = vpx_codec_control(&cs->v_encoder, VP8E_SET_CPUUSED, 7);
if ( rc != VPX_CODEC_OK) {
LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc));
return -1;
}
return 0;
}

View File

@ -1,4 +1,4 @@
/** media.h
/** codec.h
*
* Audio and video codec intitialization, encoding/decoding and playback
*

View File

@ -1,380 +0,0 @@
/** event.c
*
* Copyright (C) 2013 Tox project All Rights Reserved.
*
* This file is part of Tox.
*
* Tox is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tox is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tox. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <stdlib.h>
#include "../toxcore/network.h" /* current_time_monotonic() */
#include "event.h"
#define _GNU_SOURCE
#include <assert.h>
#include <unistd.h>
#include <stddef.h>
#include <inttypes.h>
#include <pthread.h>
#include <stdio.h>
#define RUN_IN_THREAD(func, args) { pthread_t _tid; \
pthread_create(&_tid, NULL, func, args); assert( pthread_detach(_tid) == 0 ); }
#define LOCK(event_handler) pthread_mutex_lock (&event_handler->mutex)
#define UNLOCK(event_handler) pthread_mutex_unlock(&event_handler->mutex)
#define FREQUENCY 10000
#define inline__ inline __attribute__((always_inline))
typedef struct _EventContainer {
void *(*func)(void *);
void *func_args;
unsigned timeout;
long long id;
} EventContainer;
typedef struct _EventHandler {
EventContainer *timed_events;
size_t timed_events_count;
int running;
pthread_mutex_t mutex;
} EventHandler;
int throw_event( void *(func)(void *), void *arg );
int reset_timer_event ( int id, uint32_t timeout );
int throw_timer_event ( void *(func)(void *), void *arg, unsigned timeout);
int cancel_timer_event ( int id );
int execute_timer_event ( int id );
struct _Event event = {
throw_event,
/* reset_timer_event */ NULL,
throw_timer_event,
cancel_timer_event,
/*execute_timer_event*/ NULL
};
/*
* Random functions used by this file
*/
void clear_events (EventContainer **event_container, size_t *counter)
{
free(*event_container );
*event_container = NULL;
*counter = 0;
}
int pop_id ( EventContainer **event_container, size_t *counter, int id )
{
if ( !*event_container || !*counter || !id )
return -1;
EventContainer *_it = *event_container;
int i;
for ( i = *counter; i; -- i ) {
if ( _it->id == id ) { /* Hit! */
break;
}
++_it;
}
if ( i ) {
for ( ; i; -- i ) {
*_it = *(_it + 1);
++_it;
}
-- (*counter );
if ( !(*counter)) { /* Free and set to NULL */
free(*event_container);
*event_container = NULL;
} else {
void *_result = realloc(*event_container, sizeof(EventContainer) * (*counter )); /* resize */
if ( _result != NULL ) {
*event_container = _result;
return 0;
} else {
/* Not sure what would happen next so abort execution.
*/
fprintf(stderr, "CRITICAL! Failed to reallocate memory in %s():%d, aborting...", __func__, __LINE__);
abort();
return -1;
}
}
}
/* not found here */
return -1;
}
void push_event ( EventContainer **container, size_t *counter, void *(func)(void *), void *arg )
{
EventContainer *_new = realloc((*container ), sizeof(EventContainer) * ((*counter ) + 1));
if ( _new == NULL ) {
/* Not sure what would happen next so abort execution.
* TODO: This could notice the calling function
* about realloc failing.
*/
fprintf(stderr, "CRITICAL! Failed to reallocate memory in %s():%d, aborting...", __func__, __LINE__);
abort();
}
_new[*counter].func = func;
_new[*counter].func_args = arg;
_new[*counter].timeout = 0;
_new[*counter].id = 0;
(*container) = _new;
(*counter )++;
}
void reorder_events ( size_t counter, EventContainer *container, unsigned timeout )
{
if ( counter > 1 ) {
int i = counter - 1;
/* start from behind excluding last added member */
EventContainer *_it = &container[i - 1];
EventContainer _last_added = container[i];
for ( ; i; --i ) {
if ( _it->timeout > timeout ) {
*(_it + 1) = *_it;
*_it = _last_added;
-- _it;
}
}
}
}
/* ============================================= */
/* main poll for event execution */
void *event_poll( void *arg )
{
EventHandler *_event_handler = arg;
while ( _event_handler->running ) {
LOCK( _event_handler );
if ( _event_handler->timed_events ) {
uint32_t _time = ((uint32_t)current_time_monotonic());
if ( _event_handler->timed_events[0].timeout < _time ) {
RUN_IN_THREAD ( _event_handler->timed_events[0].func,
_event_handler->timed_events[0].func_args );
pop_id(&_event_handler->timed_events,
&_event_handler->timed_events_count,
_event_handler->timed_events[0].id);
}
}
UNLOCK( _event_handler );
usleep(FREQUENCY);
}
LOCK( _event_handler );
clear_events(&_event_handler->timed_events, &_event_handler->timed_events_count);
UNLOCK( _event_handler );
_event_handler->running = -1;
pthread_exit(NULL);
}
int throw_event( void *(func)(void *), void *arg )
{
pthread_t _tid;
int _rc =
pthread_create(&_tid, NULL, func, arg );
return (0 != _rc ) ? _rc : pthread_detach(_tid);
}
EventHandler event_handler;
/* Place and order array of timers */
int throw_timer_event ( void *(func)(void *), void *arg, unsigned timeout)
{
static int _unique_id = 1;
push_event(&event_handler.timed_events, &(event_handler.timed_events_count), func, arg );
size_t _counter = event_handler.timed_events_count;
event_handler.timed_events[_counter - 1].timeout = timeout + ((uint32_t)current_time_monotonic());
event_handler.timed_events[_counter - 1].id = _unique_id;
++_unique_id;
/* reorder */
reorder_events(_counter, event_handler.timed_events, timeout );
return _unique_id - 1;
}
int execute_timer_event ( int id )
{
int _status;
LOCK((&event_handler));
EventContainer *_it = event_handler.timed_events;
int _i = event_handler.timed_events_count;
/* Find it and execute */
for ( ; _i; _i-- ) {
if ( _it->id == id ) {
RUN_IN_THREAD ( _it->func, _it->func_args );
break;
}
++_it;
}
/* Now remove it from the queue */
if ( _i ) {
for ( ; _i; -- _i ) {
*_it = *(_it + 1);
++_it;
}
-- event_handler.timed_events_count;
if ( !event_handler.timed_events_count ) { /* Free and set to null */
free(event_handler.timed_events);
event_handler.timed_events = NULL;
} else {
void *_result = realloc(event_handler.timed_events,
sizeof(EventContainer) * event_handler.timed_events_count); /* resize */
if ( _result != NULL ) {
event_handler.timed_events = _result;
} else {
/* Not sure what would happen next so abort execution.
*/
fprintf(stderr, "CRITICAL! Failed to reallocate memory in %s():%d, aborting...", __func__, __LINE__);
abort();
return -1;
}
}
_status = 0;
} else _status = -1;
UNLOCK((&event_handler));
return _status;
}
int reset_timer_event ( int id, uint32_t timeout )
{
int _status;
LOCK((&event_handler));
EventContainer *_it = event_handler.timed_events;
int _i = event_handler.timed_events_count;
/* Find it and change */
for ( ; _i; _i-- ) {
if ( _it->id == id ) {
_it->timeout = timeout + ((uint32_t)current_time_monotonic());
break;
}
++_it;
}
_status = _i ? -1 : 0;
UNLOCK((&event_handler));
return _status;
}
/* Remove timer from array */
inline__ int cancel_timer_event ( int id )
{
return pop_id (&event_handler.timed_events, &event_handler.timed_events_count, id );
}
/* Initialization and termination of event polls
* This will be run at the beginning and the end of the program execution.
* I think that's the best way to do it.
*/
void __attribute__((constructor)) init_event_poll ()
{
event_handler.timed_events = NULL;
event_handler.timed_events_count = 0;
event_handler.running = 1;
pthread_mutex_init(&event_handler.mutex, NULL);
RUN_IN_THREAD(event_poll, &event_handler);
}
/* NOTE: Do we need this? */
void __attribute__((destructor)) terminate_event_poll()
{
/* Exit thread */
event_handler.running = 0;
/* Give it enought time to exit */
usleep(FREQUENCY * 2);
pthread_mutex_destroy( &event_handler.mutex );
}

View File

@ -1,47 +0,0 @@
/** event.h
*
* Copyright (C) 2013 Tox project All Rights Reserved.
*
* This file is part of Tox.
*
* Tox is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tox is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tox. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef __TOXEVENT
#define __TOXEVENT
/**
* - Events are, in fact, ran in their own threads upon execution.
* - Event handler is initialized at the start, before the main() function
* and terminated after it's execution.
* - Timers are checked for timeout every ~10000 ns.
* - Timers can be canceled or ran immediately via
* timer_release() or timer_now() functions.
* - Timeout is measured in milliseconds.
*
* NOTE: timer_reset () and timer_now() are not tested nor usable atm
*
*/
extern struct _Event {
int (*rise) (void *( func ) ( void *), void *arg);
int (*timer_reset ) ( int id, unsigned timeout );
int (*timer_alloc) (void *( func ) ( void *), void *arg, unsigned timeout);
int (*timer_release) (int id);
int (*timer_now) ( int id );
} event;
#endif /* _MSI__EVENT_H_ */

View File

@ -115,7 +115,6 @@ static struct _Callbacks {
inline__ void invoke_callback(int32_t call_index, MSICallbackID id)
{
/*if ( callbacks[id].function ) event.rise ( callbacks[id].function, callbacks[id].data );*/
if ( callbacks[id].function ) {
LOGGER_DEBUG("Invoking callback function: %d", id);
callbacks[id].function ( call_index, callbacks[id].data );
@ -220,7 +219,7 @@ if ( *iterator != value_byte || size_con <= type_size_const) { return -1; } size
iterator ++; if(size_con <= 3) {return -1;} size_con -= 3; \
uint16_t _value_size; memcpy(&_value_size, iterator, sizeof(_value_size)); _value_size = ntohs(_value_size);\
if(size_con < _value_size) { return -1; } size_con -= _value_size; \
if ( !(header.header_value = calloc(sizeof(uint8_t), _value_size)) ); \
if ( !(header.header_value = calloc(sizeof(uint8_t), _value_size)) ) \
LOGGER_ERROR("Allocation failed! Program might misbehave!"); \
header.size = _value_size; \
memcpy(header.header_value, iterator + 2, _value_size);\
@ -538,6 +537,233 @@ GENERIC_SETTER_DEFINITION ( info )
GENERIC_SETTER_DEFINITION ( callid )
typedef struct _Timer {
void *(*func)(void *);
void *func_args;
uint64_t timeout;
size_t idx;
} Timer;
typedef struct _TimerHandler {
Timer **timers;
pthread_mutex_t mutex;
size_t max_capacity;
size_t size;
uint64_t resolution;
_Bool running;
} TimerHandler;
/**
* @brief Allocate timer in array
*
* @param timers_container Handler
* @param func Function to be executed
* @param arg Its args
* @param timeout Timeout in ms
* @return int
*/
int timer_alloc ( TimerHandler *timers_container, void *(func)(void *), void *arg, unsigned timeout)
{
pthread_mutex_lock(&timers_container->mutex);
int i = 0;
for (; i < timers_container->max_capacity && timers_container->timers[i]; i ++);
if (i == timers_container->max_capacity) {
LOGGER_WARNING("Maximum capacity reached!");
pthread_mutex_unlock(&timers_container->mutex);
return -1;
}
Timer *timer = timers_container->timers[i] = calloc(sizeof(Timer), 1);
if (timer == NULL) {
LOGGER_ERROR("Failed to allocate timer!");
pthread_mutex_unlock(&timers_container->mutex);
return -1;
}
timers_container->size ++;
timer->func = func;
timer->func_args = arg;
timer->timeout = timeout + current_time_monotonic(); /* In ms */
timer->idx = i;
/* reorder */
if (i) {
int j = i - 1;
for (; j >= 0 && timeout < timers_container->timers[j]->timeout; j--) {
Timer *tmp = timers_container->timers[j];
timers_container->timers[j] = timer;
timers_container->timers[j + 1] = tmp;
}
}
pthread_mutex_unlock(&timers_container->mutex);
LOGGER_DEBUG("Allocated timer index: %d timeout: %d, current size: %d", i, timeout, timers_container->size);
return i;
}
/**
* @brief Remove timer from array
*
* @param timers_container handler
* @param idx index
* @return int
*/
int timer_release ( TimerHandler *timers_container, int idx )
{
int rc = pthread_mutex_trylock(&timers_container->mutex);
Timer **timed_events = timers_container->timers;
if (!timed_events[idx]) {
LOGGER_WARNING("No event under index: %d", idx);
if ( rc != EBUSY ) pthread_mutex_unlock(&timers_container->mutex);
return -1;
}
free(timed_events[idx]);
timed_events[idx] = NULL;
int i = idx + 1;
for (; i < timers_container->max_capacity && timed_events[i]; i ++) {
timed_events[i - 1] = timed_events[i];
timed_events[i] = NULL;
}
timers_container->size--;
LOGGER_DEBUG("Popped index: %d, current size: %d ", idx, timers_container->size);
if ( rc != EBUSY ) pthread_mutex_unlock(&timers_container->mutex);
return 0;
}
/**
* @brief Main poll for timer execution
*
* @param arg ...
* @return void*
*/
void *timer_poll( void *arg )
{
TimerHandler *handler = arg;
while ( handler->running ) {
pthread_mutex_lock(&handler->mutex);
if ( handler->running ) {
uint64_t time = current_time_monotonic();
while ( handler->timers[0] && handler->timers[0]->timeout < time ) {
pthread_t _tid;
if ( 0 != pthread_create(&_tid, NULL, handler->timers[0]->func, handler->timers[0]->func_args) ||
0 != pthread_detach(_tid) )
LOGGER_ERROR("Failed to execute timer at: %d!", handler->timers[0]->timeout);
else LOGGER_DEBUG("Exectued timer assigned at: %d", handler->timers[0]->timeout);
timer_release(handler, 0);
}
}
pthread_mutex_unlock(&handler->mutex);
usleep(handler->resolution);
}
pthread_exit(NULL);
}
/**
* @brief Start timer poll and return handler
*
* @param max_capacity capacity
* @param resolution ...
* @return TimerHandler*
*/
TimerHandler *timer_init_session (int max_capacity, int resolution)
{
TimerHandler *handler = calloc(1, sizeof(TimerHandler));
if (handler == NULL) {
LOGGER_ERROR("Failed to allocate memory, program might misbehave!");
return NULL;
}
handler->timers = calloc(max_capacity, sizeof(Timer *));
if (handler->timers == NULL) {
LOGGER_ERROR("Failed to allocate %d timed events!", max_capacity);
free(handler);
return NULL;
}
handler->max_capacity = max_capacity;
handler->running = 1;
handler->resolution = resolution;
pthread_mutex_init(&handler->mutex, NULL);
pthread_t _tid;
if ( 0 != pthread_create(&_tid, NULL, timer_poll, handler) || 0 != pthread_detach(_tid) ) {
LOGGER_ERROR("Failed to start timer poll thread!");
free(handler->timers);
free(handler);
return NULL;
}
return handler;
}
/**
* @brief Terminate timer session
*
* @param handler The timer handler
* @return void
*/
void timer_terminate_session(TimerHandler *handler)
{
pthread_mutex_lock(&handler->mutex);
handler->running = 0;
pthread_mutex_unlock(&handler->mutex);
int i = 0;
for (; i < handler->max_capacity; i ++)
free(handler->timers[i]);
free(handler->timers);
pthread_mutex_destroy( &handler->mutex );
}
/**
* @brief Generate _random_ alphanumerical string.
*
@ -731,7 +957,11 @@ MSICall *find_call ( MSISession *session, uint8_t *call_id )
for (; i < session->max_calls; i ++ )
if ( session->calls[i] && memcmp(session->calls[i]->id, call_id, CALL_ID_LEN) == 0 ) {
LOGGER_DEBUG("Found call id: %s", session->calls[i]->id);
LOGGER_SCOPE(
char tmp[CALL_ID_LEN + 1] = {'\0'};
memcpy(tmp, session->calls[i]->id, CALL_ID_LEN);
LOGGER_DEBUG("Found call id: %s", tmp);
);
return session->calls[i];
}
@ -883,8 +1113,8 @@ int terminate_call ( MSISession *session, MSICall *call )
* NOTE: This has to be done before possibly
* locking the mutex the second time
*/
event.timer_release ( call->request_timer_id );
event.timer_release ( call->ringing_timer_id );
timer_release ( session->timer_handler, call->request_timer_id );
timer_release ( session->timer_handler, call->ringing_timer_id );
/* Get a handle */
pthread_mutex_lock ( &call->mutex );
@ -1055,10 +1285,6 @@ int handle_recv_reject ( MSISession *session, MSICall *call, MSIMessage *msg )
pthread_mutex_unlock(&session->mutex);
invoke_callback(call->call_idx, MSI_OnReject);
/*
event.timer_release ( session->call->request_timer_id );
session->call->request_timer_id = event.timer_alloc ( handle_timeout, session, m_deftout );
*/
terminate_call(session, call);
return 1;
@ -1123,7 +1349,7 @@ int handle_recv_ringing ( MSISession *session, MSICall *call, MSIMessage *msg )
LOGGER_DEBUG("Session: %p Handling 'ringing' on call: %s", session, call->id );
call->ringing_timer_id = event.timer_alloc ( handle_timeout, call, call->ringing_tout_ms );
call->ringing_timer_id = timer_alloc ( session->timer_handler, handle_timeout, call, call->ringing_tout_ms );
pthread_mutex_unlock(&session->mutex);
@ -1150,7 +1376,7 @@ int handle_recv_starting ( MSISession *session, MSICall *call, MSIMessage *msg )
flush_peer_type ( call, msg, 0 );
event.timer_release ( call->ringing_timer_id );
timer_release ( session->timer_handler, call->ringing_timer_id );
pthread_mutex_unlock(&session->mutex);
invoke_callback(call->call_idx, MSI_OnStarting);
@ -1168,7 +1394,7 @@ int handle_recv_ending ( MSISession *session, MSICall *call, MSIMessage *msg )
LOGGER_DEBUG("Session: %p Handling 'ending' on call: %s", session, call->id );
/* Stop timer */
event.timer_release ( call->request_timer_id );
timer_release ( session->timer_handler, call->request_timer_id );
pthread_mutex_unlock(&session->mutex);
@ -1246,89 +1472,88 @@ void msi_handle_packet ( Messenger *messenger, int source, const uint8_t *data,
/* Unused */
(void)messenger;
MSISession *_session = object;
MSIMessage *_msg;
MSISession *session = object;
MSIMessage *msg;
if ( !length ) {
LOGGER_WARNING("Lenght param negative");
return;
}
_msg = parse_message ( data, length );
msg = parse_message ( data, length );
if ( !_msg ) {
if ( !msg ) {
LOGGER_WARNING("Error parsing message");
return;
} else {
LOGGER_DEBUG("Successfully parsed message");
}
_msg->friend_id = source;
msg->friend_id = source;
/* Find what call */
MSICall *_call = _msg->callid.header_value ? find_call(_session, _msg->callid.header_value ) : NULL;
MSICall *call = msg->callid.header_value ? find_call(session, msg->callid.header_value ) : NULL;
/* Now handle message */
if ( _msg->request.header_value ) { /* Handle request */
if ( msg->request.header_value ) { /* Handle request */
if ( _msg->response.size > 32 ) {
if ( msg->response.size > 32 ) {
LOGGER_WARNING("Header size too big");
goto free_end;
}
uint8_t _request_value[32];
memcpy(_request_value, _msg->request.header_value, _msg->request.size);
_request_value[_msg->request.size] = '\0';
memcpy(_request_value, msg->request.header_value, msg->request.size);
_request_value[msg->request.size] = '\0';
if ( same ( _request_value, stringify_request ( invite ) ) ) {
handle_recv_invite ( _session, _call, _msg );
handle_recv_invite ( session, call, msg );
} else if ( same ( _request_value, stringify_request ( start ) ) ) {
handle_recv_start ( _session, _call, _msg );
handle_recv_start ( session, call, msg );
} else if ( same ( _request_value, stringify_request ( cancel ) ) ) {
handle_recv_cancel ( _session, _call, _msg );
handle_recv_cancel ( session, call, msg );
} else if ( same ( _request_value, stringify_request ( reject ) ) ) {
handle_recv_reject ( _session, _call, _msg );
handle_recv_reject ( session, call, msg );
} else if ( same ( _request_value, stringify_request ( end ) ) ) {
handle_recv_end ( _session, _call, _msg );
handle_recv_end ( session, call, msg );
} else {
LOGGER_WARNING("Uknown request");
goto free_end;
}
} else if ( _msg->response.header_value ) { /* Handle response */
} else if ( msg->response.header_value ) { /* Handle response */
if ( _msg->response.size > 32 ) {
if ( msg->response.size > 32 ) {
LOGGER_WARNING("Header size too big");
goto free_end;
}
/* Got response so cancel timer */
if ( _call )
event.timer_release ( _call->request_timer_id );
if ( call ) timer_release ( session->timer_handler, call->request_timer_id );
uint8_t _response_value[32];
memcpy(_response_value, _msg->response.header_value, _msg->response.size);
_response_value[_msg->response.size] = '\0';
memcpy(_response_value, msg->response.header_value, msg->response.size);
_response_value[msg->response.size] = '\0';
if ( same ( _response_value, stringify_response ( ringing ) ) ) {
handle_recv_ringing ( _session, _call, _msg );
handle_recv_ringing ( session, call, msg );
} else if ( same ( _response_value, stringify_response ( starting ) ) ) {
handle_recv_starting ( _session, _call, _msg );
handle_recv_starting ( session, call, msg );
} else if ( same ( _response_value, stringify_response ( ending ) ) ) {
handle_recv_ending ( _session, _call, _msg );
handle_recv_ending ( session, call, msg );
} else if ( same ( _response_value, stringify_response ( error ) ) ) {
handle_recv_error ( _session, _call, _msg );
handle_recv_error ( session, call, msg );
} else {
LOGGER_WARNING("Uknown response");
@ -1340,7 +1565,7 @@ void msi_handle_packet ( Messenger *messenger, int source, const uint8_t *data,
}
free_end:
free_message ( _msg );
free_message ( msg );
}
@ -1373,7 +1598,12 @@ MSISession *msi_init_session ( Messenger *messenger, int32_t max_calls )
return NULL;
}
if ( !max_calls) return NULL;
TimerHandler *handler = timer_init_session(max_calls * 10, 10000);
if ( !max_calls || !handler ) {
LOGGER_WARNING("Invalid max call treshold or timer handler initialization failed!");
return NULL;
}
MSISession *_retu = calloc ( sizeof ( MSISession ), 1 );
@ -1384,6 +1614,7 @@ MSISession *msi_init_session ( Messenger *messenger, int32_t max_calls )
_retu->messenger_handle = messenger;
_retu->agent_handler = NULL;
_retu->timer_handler = handler;
if (!(_retu->calls = calloc( sizeof (MSICall *), max_calls ))) {
LOGGER_ERROR("Allocation failed! Program might misbehave!");
@ -1440,6 +1671,7 @@ int msi_terminate_session ( MSISession *session )
msi_cancel ( session, idx, session->calls[idx]->peers [_it], "MSI session terminated!" );
}
timer_terminate_session(session->timer_handler);
pthread_mutex_destroy(&session->mutex);
@ -1495,7 +1727,7 @@ int msi_invite ( MSISession *session, int32_t *call_index, MSICallType call_type
_call->state = call_inviting;
_call->request_timer_id = event.timer_alloc ( handle_timeout, _call, m_deftout );
_call->request_timer_id = timer_alloc ( session->timer_handler, handle_timeout, _call, m_deftout );
LOGGER_DEBUG("Invite sent");
@ -1543,8 +1775,8 @@ int msi_hangup ( MSISession *session, int32_t call_index )
free_message ( _msg_end );
session->calls[call_index]->request_timer_id = event.timer_alloc ( handle_timeout, session->calls[call_index],
m_deftout );
session->calls[call_index]->request_timer_id =
timer_alloc ( session->timer_handler, handle_timeout, session->calls[call_index], m_deftout );
pthread_mutex_unlock(&session->mutex);
return 0;
@ -1620,7 +1852,7 @@ int msi_cancel ( MSISession *session, int32_t call_index, uint32_t peer, const c
free_message ( _msg_cancel );
/*session->calls[call_index]->state = call_hanged_up;
session->calls[call_index]->request_timer_id = event.timer_alloc ( handle_timeout, session->calls[call_index], m_deftout );*/
session->calls[call_index]->request_timer_id = timer_alloc ( handle_timeout, session->calls[call_index], m_deftout );*/
terminate_call ( session, session->calls[call_index] );
pthread_mutex_unlock(&session->mutex);
@ -1656,8 +1888,8 @@ int msi_reject ( MSISession *session, int32_t call_index, const uint8_t *reason
session->calls[call_index]->state = call_hanged_up;
session->calls[call_index]->request_timer_id = event.timer_alloc ( handle_timeout, session->calls[call_index],
m_deftout );
session->calls[call_index]->request_timer_id =
timer_alloc ( session->timer_handler, handle_timeout, session->calls[call_index], m_deftout );
pthread_mutex_unlock(&session->mutex);
return 0;

View File

@ -105,6 +105,8 @@ typedef struct _MSISession {
uint32_t call_timeout; /* Time of the timeout for some action to end; 0 if infinite */
pthread_mutex_t mutex;
void *timer_handler;
} MSISession;

View File

@ -66,6 +66,8 @@ typedef struct _CallSpecific {
uint32_t frame_limit; /* largest address written to in frame_buf for current input frame*/
uint8_t frame_id, frame_outid; /* id of input and output video frame */
void *frame_buf; /* buffer for split video payloads */
_Bool call_active;
} CallSpecific;
@ -296,8 +298,9 @@ int toxav_stop_call ( ToxAv *av, int32_t call_index )
*/
int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, ToxAvCodecSettings *codec_settings, int support_video )
{
if ( !av->msi_session || cii(call_index, av->msi_session) || !av->msi_session->calls[call_index] ) {
LOGGER_ERROR("Error while starting audio RTP session: invalid call!\n");
if ( !av->msi_session || cii(call_index, av->msi_session) ||
!av->msi_session->calls[call_index] || av->calls[call_index].call_active) {
LOGGER_ERROR("Error while starting RTP session: invalid call!\n");
return ErrorInternal;
}
@ -320,6 +323,8 @@ int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, ToxAvCodecSettin
if ( !call->crtps[video_index] ) {
LOGGER_ERROR("Error while starting video RTP session!\n");
rtp_terminate_session(call->crtps[audio_index], av->messenger);
return ErrorStartingVideoRtp;
}
@ -330,23 +335,40 @@ int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, ToxAvCodecSettin
call->frame_buf = calloc(MAX_VIDEOFRAME_SIZE, 1);
if (!call->frame_buf) {
rtp_terminate_session(call->crtps[audio_index], av->messenger);
rtp_terminate_session(call->crtps[video_index], av->messenger);
LOGGER_WARNING("Frame buffer allocation failed!");
return ErrorInternal;
}
}
if ( !(call->j_buf = create_queue(codec_settings->jbuf_capacity)) ) return ErrorInternal;
if ( !(call->j_buf = create_queue(codec_settings->jbuf_capacity)) ) {
rtp_terminate_session(call->crtps[audio_index], av->messenger);
rtp_terminate_session(call->crtps[video_index], av->messenger);
free(call->frame_buf);
LOGGER_WARNING("Jitter buffer creaton failed!");
return ErrorInternal;
}
call->cs = codec_init_session(codec_settings->audio_bitrate,
codec_settings->audio_frame_duration,
codec_settings->audio_sample_rate,
codec_settings->audio_channels,
codec_settings->audio_VAD_tolerance,
codec_settings->video_width,
codec_settings->video_height,
codec_settings->video_bitrate);
if ( (call->cs = codec_init_session(codec_settings->audio_bitrate,
codec_settings->audio_frame_duration,
codec_settings->audio_sample_rate,
codec_settings->audio_channels,
codec_settings->audio_VAD_tolerance,
codec_settings->video_width,
codec_settings->video_height,
codec_settings->video_bitrate) )) {
call->call_active = 1;
return ErrorNone;
}
return call->cs ? ErrorNone : ErrorInternal;
rtp_terminate_session(call->crtps[audio_index], av->messenger);
rtp_terminate_session(call->crtps[video_index], av->messenger);
free(call->frame_buf);
terminate_queue(call->j_buf);
return ErrorInternal;
}
/**
@ -359,22 +381,24 @@ int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, ToxAvCodecSettin
*/
int toxav_kill_transmission ( ToxAv *av, int32_t call_index )
{
if (cii(call_index, av->msi_session)) return ErrorNoCall;
if (cii(call_index, av->msi_session) || !av->calls[call_index].call_active) {
LOGGER_WARNING("Action on inactive call: %d", call_index);
return ErrorNoCall;
}
CallSpecific *call = &av->calls[call_index];
call->call_active = 0;
if ( call->crtps[audio_index] && -1 == rtp_terminate_session(call->crtps[audio_index], av->messenger) ) {
LOGGER_ERROR("Error while terminating audio RTP session!\n");
return ErrorTerminatingAudioRtp;
}
/*return ErrorTerminatingAudioRtp;*/
} else call->crtps[audio_index] = NULL;
if ( call->crtps[video_index] && -1 == rtp_terminate_session(call->crtps[video_index], av->messenger) ) {
LOGGER_ERROR("Error while terminating video RTP session!\n");
return ErrorTerminatingVideoRtp;
}
call->crtps[audio_index] = NULL;
call->crtps[video_index] = NULL;
/*return ErrorTerminatingVideoRtp;*/
} else call->crtps[video_index] = NULL;
if ( call->j_buf ) {
terminate_queue(call->j_buf);
@ -388,6 +412,7 @@ int toxav_kill_transmission ( ToxAv *av, int32_t call_index )
LOGGER_DEBUG("Terminated codec session");
} else LOGGER_DEBUG("No codec session");
return ErrorNone;
}
@ -406,8 +431,6 @@ int toxav_kill_transmission ( ToxAv *av, int32_t call_index )
inline__ int toxav_send_rtp_payload ( ToxAv *av, int32_t call_index, ToxAvCallType type, const uint8_t *payload,
unsigned int length )
{
if (cii(call_index, av->msi_session)) return ErrorNoCall;
#define send(data, len) rtp_send_msg(av->calls[call_index].crtps[type - TypeAudio], av->msi_session->messenger_handle, data, len)
if (av->calls[call_index].crtps[type - TypeAudio]) {
@ -465,8 +488,6 @@ inline__ int toxav_recv_rtp_payload ( ToxAv *av, int32_t call_index, ToxAvCallTy
{
if ( !dest ) return ErrorInternal;
if (cii(call_index, av->msi_session)) return ErrorNoCall;
CallSpecific *call = &av->calls[call_index];
if ( !call->crtps[type - TypeAudio] ) return ErrorNoRtpSession;
@ -518,7 +539,11 @@ inline__ int toxav_recv_video ( ToxAv *av, int32_t call_index, vpx_image_t **out
{
if ( !output ) return ErrorInternal;
if (cii(call_index, av->msi_session)) return ErrorNoCall;
if (cii(call_index, av->msi_session) || !av->calls[call_index].call_active) {
LOGGER_WARNING("Action on inactive call: %d", call_index);
return ErrorNoCall;
}
uint8_t packet [RTP_PAYLOAD_SIZE];
CallSpecific *call = &av->calls[call_index];
@ -586,7 +611,11 @@ inline__ int toxav_recv_video ( ToxAv *av, int32_t call_index, vpx_image_t **out
*/
inline__ int toxav_send_video ( ToxAv *av, int32_t call_index, const uint8_t *frame, int frame_size)
{
if (cii(call_index, av->msi_session)) return ErrorNoCall;
if (cii(call_index, av->msi_session) || !av->calls[call_index].call_active) {
LOGGER_WARNING("Action on inactive call: %d", call_index);
return ErrorNoCall;
}
return toxav_send_rtp_payload(av, call_index, TypeVideo, frame, frame_size);
}
@ -604,7 +633,11 @@ inline__ int toxav_send_video ( ToxAv *av, int32_t call_index, const uint8_t *fr
*/
inline__ int toxav_prepare_video_frame(ToxAv *av, int32_t call_index, uint8_t *dest, int dest_max, vpx_image_t *input)
{
if (cii(call_index, av->msi_session)) return ErrorNoCall;
if (cii(call_index, av->msi_session) || !av->calls[call_index].call_active) {
LOGGER_WARNING("Action on inactive call: %d", call_index);
return ErrorNoCall;
}
CallSpecific *call = &av->calls[call_index];
@ -649,7 +682,11 @@ inline__ int toxav_recv_audio ( ToxAv *av, int32_t call_index, int frame_size, i
{
if ( !dest ) return ErrorInternal;
if (cii(call_index, av->msi_session)) return ErrorNoCall;
if (cii(call_index, av->msi_session) || !av->calls[call_index].call_active) {
LOGGER_WARNING("Action on inactive call: %d", call_index);
return ErrorNoCall;
}
CallSpecific *call = &av->calls[call_index];
@ -690,7 +727,11 @@ inline__ int toxav_recv_audio ( ToxAv *av, int32_t call_index, int frame_size, i
*/
inline__ int toxav_send_audio ( ToxAv *av, int32_t call_index, const uint8_t *frame, int frame_size)
{
if (cii(call_index, av->msi_session)) return ErrorNoCall;
if (cii(call_index, av->msi_session) || !av->calls[call_index].call_active) {
LOGGER_WARNING("Action on inactive call: %d", call_index);
return ErrorNoCall;
}
return toxav_send_rtp_payload(av, call_index, TypeAudio, frame, frame_size);
}
@ -710,7 +751,11 @@ inline__ int toxav_send_audio ( ToxAv *av, int32_t call_index, const uint8_t *fr
inline__ int toxav_prepare_audio_frame ( ToxAv *av, int32_t call_index, uint8_t *dest, int dest_max,
const int16_t *frame, int frame_size)
{
if (cii(call_index, av->msi_session)) return ErrorNoCall;
if (cii(call_index, av->msi_session) || !av->calls[call_index].call_active) {
LOGGER_WARNING("Action on inactive call: %d", call_index);
return ErrorNoCall;
}
int32_t rc = opus_encode(av->calls[call_index].cs->audio_encoder, frame, frame_size, dest, dest_max);