diff --git a/toxav/event.c b/toxav/event.c old mode 100755 new mode 100644 index 9efe4be4..f79fd60e --- a/toxav/event.c +++ b/toxav/event.c @@ -1,5 +1,5 @@ /** event.c - * + * * Copyright (C) 2013 Tox project All Rights Reserved. * * This file is part of Tox. @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with Tox. If not, see . * - * + * * Report bugs/suggestions at #tox-dev @ freenode.net:6667 */ @@ -53,31 +53,30 @@ pthread_create(&_tid, NULL, func, args); assert( pthread_detach(_tid) == 0 ); } typedef struct _EventContainer { - void* (*func)(void*); - void* func_args; + void *(*func)(void *); + void *func_args; unsigned timeout; long long id; - + } EventContainer; typedef struct _EventHandler { - EventContainer* timed_events; + EventContainer *timed_events; size_t timed_events_count; - + int running; - + pthread_mutex_t mutex; - + } EventHandler; -int throw_event( void* (func)(void*), void* arg ); +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 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 = -{ +struct _Event event = { throw_event, /* reset_timer_event */ NULL, throw_timer_event, @@ -88,62 +87,68 @@ struct _Event event = /* * Random functions used by this file */ -void clear_events (EventContainer** event_container, size_t* counter) +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 ) +int pop_id ( EventContainer **event_container, size_t *counter, int id ) { if ( !*event_container || !*counter || !id ) return -1; - - EventContainer* _it = *event_container; + + EventContainer *_it = *event_container; int i; - - for ( i = *counter; i; -- i ){ + + for ( i = *counter; i; -- i ) { if ( _it->id == id ) { /* Hit! */ break; } + ++_it; } - + if ( i ) { - for ( ; i; -- i ){ *_it = *(_it + 1); ++_it; } + 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 { + } 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; + return -1; } } } - + /* not found here */ - + return -1; } -void push_event ( EventContainer** container, size_t* counter, void* (func)(void*), void* arg ) +void push_event ( EventContainer **container, size_t *counter, void * (func)(void *), void *arg ) { - EventContainer* _new = realloc((*container ), sizeof(EventContainer) * ((*counter ) + 1)); - - if ( _new == NULL ) { + 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. @@ -151,188 +156,194 @@ void push_event ( EventContainer** container, size_t* counter, void* (func)(void 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 ) +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 *_it = &container[i - 1]; + EventContainer _last_added = container[i]; - + for ( ; i; --i ) { - if ( _it->timeout > timeout ){ + if ( _it->timeout > timeout ) { *(_it + 1) = *_it; - *_it = _last_added; -- _it; + *_it = _last_added; + -- _it; } } - + } } /* ============================================= */ /* main poll for event execution */ -void* event_poll( void* arg ) +void *event_poll( void *arg ) { - EventHandler* _event_handler = arg; - - while ( _event_handler->running ) - { - + EventHandler *_event_handler = arg; + + while ( _event_handler->running ) { + LOCK( _event_handler ); - - if ( _event_handler->timed_events ){ - + + if ( _event_handler->timed_events ) { + uint32_t _time = ((uint32_t)(current_time() / 1000)); - + 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 ) +int throw_event( void * (func)(void *), void *arg ) { pthread_t _tid; int _rc = - pthread_create(&_tid, NULL, func, arg ); - + 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) +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() / 1000)); - event_handler.timed_events[_counter - 1].id = _unique_id; ++_unique_id; - - + 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; - + 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; } - + 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 { + } 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; - } + return -1; + } } - + _status = 0; - - } - else _status = -1; - + + } 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; - + + 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() / 1000)); break; } + ++_it; } - + _status = _i ? -1 : 0; - + UNLOCK((&event_handler)); - + return _status; } @@ -352,11 +363,11 @@ 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); } @@ -365,9 +376,9 @@ void __attribute__((destructor)) terminate_event_poll() { /* Exit thread */ event_handler.running = 0; - + /* Give it enought time to exit */ - usleep(FREQUENCY*2); - + usleep(FREQUENCY * 2); + pthread_mutex_destroy( &event_handler.mutex ); } \ No newline at end of file diff --git a/toxav/event.h b/toxav/event.h old mode 100755 new mode 100644 index 17dadbd5..0fb2d120 --- a/toxav/event.h +++ b/toxav/event.h @@ -1,5 +1,5 @@ /** event.h - * + * * Copyright (C) 2013 Tox project All Rights Reserved. * * This file is part of Tox. @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with Tox. If not, see . * - * + * * Report bugs/suggestions at #tox-dev @ freenode.net:6667 */ @@ -36,13 +36,12 @@ * - 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); +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_alloc) (void * ( func ) ( void * ), void *arg, unsigned timeout); int (*timer_release) (int id); int (*timer_now) ( int id ); } event; diff --git a/toxav/media.c b/toxav/media.c index c4894076..2594f99a 100644 --- a/toxav/media.c +++ b/toxav/media.c @@ -1,5 +1,5 @@ /** media.c - * + * * Audio and video codec intitialization, encoding/decoding and playback * * Copyright (C) 2013 Tox project All Rights Reserved. @@ -50,8 +50,8 @@ struct jitter_buffer { struct jitter_buffer *create_queue(int capacity) { struct jitter_buffer *q; - q = (struct jitter_buffer *)calloc(sizeof(struct jitter_buffer),1); - q->queue = (RTPMessage **)calloc(sizeof(RTPMessage*), capacity); + q = (struct jitter_buffer *)calloc(sizeof(struct jitter_buffer), 1); + q->queue = (RTPMessage **)calloc(sizeof(RTPMessage *), capacity); int i = 0; for (i = 0; i < capacity; ++i) { @@ -200,7 +200,8 @@ int queue(struct jitter_buffer *q, RTPMessage *pk) int init_video_decoder(CodecState *cs) { - if (vpx_codec_dec_init_ver(&cs->v_decoder, VIDEO_CODEC_DECODER_INTERFACE, NULL, 0, VPX_DECODER_ABI_VERSION) != VPX_CODEC_OK) { + if (vpx_codec_dec_init_ver(&cs->v_decoder, VIDEO_CODEC_DECODER_INTERFACE, NULL, 0, + VPX_DECODER_ABI_VERSION) != VPX_CODEC_OK) { fprintf(stderr, "Init video_decoder failed!\n"); return -1; } @@ -211,13 +212,13 @@ int init_video_decoder(CodecState *cs) int init_audio_decoder(CodecState *cs, uint32_t audio_channels) { int rc; - cs->audio_decoder = opus_decoder_create(cs->audio_sample_rate, audio_channels, &rc ); - - if ( rc != OPUS_OK ){ + cs->audio_decoder = opus_decoder_create(cs->audio_sample_rate, audio_channels, &rc ); + + if ( rc != OPUS_OK ) { fprintf(stderr, "Error while starting audio decoder!\n"); return -1; - } - + } + return 0; } @@ -226,18 +227,22 @@ int init_video_encoder(CodecState *cs, uint16_t width, uint16_t height, uint32_t { vpx_codec_enc_cfg_t cfg; int res = vpx_codec_enc_config_default(VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0); - if(res) { + + if (res) { printf("Failed to get config: %s\n", vpx_codec_err_to_string(res)); return -1; } - + cfg.rc_target_bitrate = video_bitrate; cfg.g_w = width; cfg.g_h = height; - if(vpx_codec_enc_init_ver(&cs->v_encoder, VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0, VPX_ENCODER_ABI_VERSION) != VPX_CODEC_OK) { + + if (vpx_codec_enc_init_ver(&cs->v_encoder, VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0, + VPX_ENCODER_ABI_VERSION) != VPX_CODEC_OK) { fprintf(stderr, "Failed to initialize encoder\n"); return -1; } + return 0; } @@ -247,57 +252,57 @@ int init_audio_encoder(CodecState *cs, uint32_t audio_channels) cs->audio_encoder = opus_encoder_create(cs->audio_sample_rate, audio_channels, OPUS_APPLICATION_AUDIO, &err); err = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_BITRATE(cs->audio_bitrate)); err = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_COMPLEXITY(10)); - - + + return err == OPUS_OK ? 0 : -1; } -CodecState* codec_init_session ( uint32_t audio_bitrate, - uint16_t audio_frame_duration, - uint32_t audio_sample_rate, - uint32_t audio_channels, +CodecState *codec_init_session ( uint32_t audio_bitrate, + uint16_t audio_frame_duration, + uint32_t audio_sample_rate, + uint32_t audio_channels, uint16_t video_width, uint16_t video_height, uint32_t video_bitrate ) { - CodecState* _retu = calloc(sizeof(CodecState), 1); + CodecState *_retu = calloc(sizeof(CodecState), 1); assert(_retu); _retu->audio_bitrate = audio_bitrate; _retu->audio_sample_rate = audio_sample_rate; - + /* Encoders */ if (!video_width || !video_height) { video_width = 320; video_height = 240; } - - if ( 0 == init_video_encoder(_retu, video_width, video_height, video_bitrate) ) + + if ( 0 == init_video_encoder(_retu, video_width, video_height, video_bitrate) ) printf("Video encoder initialized!\n"); - - if ( 0 == init_audio_encoder(_retu, audio_channels) ) + + if ( 0 == init_audio_encoder(_retu, audio_channels) ) printf("Audio encoder initialized!\n"); - - + + /* Decoders */ if ( 0 == init_video_decoder(_retu) ) printf("Video decoder initialized!\n"); - + if ( 0 == init_audio_decoder(_retu, audio_channels) ) printf("Audio decoder initialized!\n"); - - + + return _retu; } -void codec_terminate_session ( CodecState* cs ) +void codec_terminate_session ( CodecState *cs ) { if ( cs->audio_encoder ) { opus_encoder_destroy(cs->audio_encoder); printf("Terminated encoder!\n"); } - + if ( cs->audio_decoder ) { opus_decoder_destroy(cs->audio_decoder); printf("Terminated decoder!\n"); diff --git a/toxav/media.h b/toxav/media.h index 030a36ac..aed57ea2 100644 --- a/toxav/media.h +++ b/toxav/media.h @@ -1,5 +1,5 @@ /** media.h - * + * * Audio and video codec intitialization, encoding/decoding and playback * * Copyright (C) 2013 Tox project All Rights Reserved. @@ -39,7 +39,7 @@ #include -typedef struct _CodecState{ +typedef struct _CodecState { /* video encoding */ vpx_codec_ctx_t v_encoder; @@ -67,14 +67,14 @@ int queue(struct jitter_buffer *q, RTPMessage *pk); RTPMessage *dequeue(struct jitter_buffer *q, int *success); -CodecState* codec_init_session ( uint32_t audio_bitrate, - uint16_t audio_frame_duration, - uint32_t audio_sample_rate, - uint32_t audio_channels, +CodecState *codec_init_session ( uint32_t audio_bitrate, + uint16_t audio_frame_duration, + uint32_t audio_sample_rate, + uint32_t audio_channels, uint16_t video_width, uint16_t video_height, uint32_t video_bitrate ); -void codec_terminate_session(CodecState* cs); +void codec_terminate_session(CodecState *cs); #endif diff --git a/toxav/msi.c b/toxav/msi.c index 84ab973f..8f69d942 100644 --- a/toxav/msi.c +++ b/toxav/msi.c @@ -1,5 +1,5 @@ /** toxmsi.c - * + * * Copyright (C) 2013 Tox project All Rights Reserved. * * This file is part of Tox. @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with Tox. If not, see . * - * + * * Report bugs/suggestions at #tox-dev @ freenode.net:6667 */ @@ -46,7 +46,7 @@ #define TYPE_REQUEST 1 #define TYPE_RESPONSE 2 -unsigned char* VERSION_STRING = (unsigned char*)"0.3.1"; +unsigned char *VERSION_STRING = (unsigned char *)"0.3.1"; #define VERSION_STRLEN 5 #define CT_AUDIO_HEADER_VALUE "AUDIO" @@ -95,10 +95,10 @@ GENERIC_HEADER ( Nonce ) /** * @brief This is the message structure. It contains all of the headers and * destination/source of the message stored in friend_id. - * + * */ typedef struct _MSIMessage { - + MSIHeaderVersion version; MSIHeaderRequest request; MSIHeaderResponse response; @@ -109,11 +109,11 @@ typedef struct _MSIMessage { MSIHeaderCallId callid; MSIHeaderCryptoKey cryptokey; MSIHeaderNonce nonce; - - struct _MSIMessage* next; - - int friend_id; - + + struct _MSIMessage *next; + + int friend_id; + } MSIMessage; @@ -145,23 +145,24 @@ typedef enum { cancel, reject, end, - + } MSIRequest; /** * @brief Get string value for request. - * + * * @param request The request. * @return const uint8_t* The string */ -static inline const uint8_t *stringify_request ( MSIRequest request ) { - static const uint8_t* strings[] = { - ( uint8_t* ) "INVITE", - ( uint8_t* ) "START", - ( uint8_t* ) "CANCEL", - ( uint8_t* ) "REJECT", - ( uint8_t* ) "END" +static inline const uint8_t *stringify_request ( MSIRequest request ) +{ + static const uint8_t *strings[] = { + ( uint8_t * ) "INVITE", + ( uint8_t * ) "START", + ( uint8_t * ) "CANCEL", + ( uint8_t * ) "REJECT", + ( uint8_t * ) "END" }; return strings[request]; @@ -179,16 +180,17 @@ typedef enum { /** * @brief Get string value for response. - * + * * @param response The response. * @return const uint8_t* The string */ -static inline const uint8_t *stringify_response ( MSIResponse response ) { - static const uint8_t* strings[] = { - ( uint8_t* ) "ringing", - ( uint8_t* ) "starting", - ( uint8_t* ) "ending", - ( uint8_t* ) "error" +static inline const uint8_t *stringify_response ( MSIResponse response ) +{ + static const uint8_t *strings[] = { + ( uint8_t * ) "ringing", + ( uint8_t * ) "starting", + ( uint8_t * ) "ending", + ( uint8_t * ) "error" }; return strings[response]; @@ -212,78 +214,80 @@ static inline const uint8_t *stringify_response ( MSIResponse response ) { * @brief Parse raw 'data' received from socket into MSIMessage struct. * Every message has to have end value of 'end_byte' or _undefined_ behavior * occures. The best practice is to check the end of the message at the handle_packet. - * + * * @param msg Container. * @param data The data. * @return int * @retval -1 Error occured. * @retval 0 Success. */ -int parse_raw_data ( MSIMessage* msg, const uint8_t* data, uint16_t length ) { +int parse_raw_data ( MSIMessage *msg, const uint8_t *data, uint16_t length ) +{ assert ( msg ); if ( data[length - 1] ) /* End byte must have value 0 */ return -1; - - const uint8_t* _it = data; + + const uint8_t *_it = data; while ( *_it ) {/* until end_byte is hit */ - + uint16_t itedlen = (_it - data) + 2; - + if ( *_it == field_byte && itedlen < length ) { - + uint16_t _size = ( uint16_t ) * ( _it + 1 ) << 8 | ( uint16_t ) * ( _it + 2 ); if ( itedlen + _size > length ) return -1; - + _it += 3; /* place it at the field value beginning */ switch ( _size ) { /* Compare the size of the hardcoded values ( vary fast and convenient ) */ - case 4: { /* INFO header */ - if ON_HEADER ( _it, msg->info, INFO_FIELD, 4 ) - } - break; - - case 5: { /* NONCE header */ - if ON_HEADER ( _it, msg->nonce, NONCE_FIELD, 5 ) - } - break; - - case 6: { /* Reason header */ - if ON_HEADER ( _it, msg->reason, REASON_FIELD, 6 ) - } - break; - - case 7: { /* Version, Request, Call-id headers */ - if ON_HEADER ( _it, msg->version, VERSION_FIELD, 7 ) - else if ON_HEADER ( _it, msg->request, REQUEST_FIELD, 7 ) - else if ON_HEADER ( _it, msg->callid, CALLID_FIELD, 7 ) - } - break; - - case 8: { /* Response header */ - if ON_HEADER ( _it, msg->response, RESPONSE_FIELD, 8 ) - } - break; - - case 9: { /* Call-type header */ - if ON_HEADER ( _it, msg->calltype, CALLTYPE_FIELD, 9 ) - } - break; - - case 10: { /* User-agent, Crypto-key headers */ - if ON_HEADER ( _it, msg->useragent, USERAGENT_FIELD, 10 ) - else if ON_HEADER ( _it, msg->cryptokey, CRYPTOKEY_FIELD, 10 ) + case 4: { /* INFO header */ + if ON_HEADER ( _it, msg->info, INFO_FIELD, 4 ) } - break; + break; - default: - return -1; + case 5: { /* NONCE header */ + if ON_HEADER ( _it, msg->nonce, NONCE_FIELD, 5 ) + } + break; + + case 6: { /* Reason header */ + if ON_HEADER ( _it, msg->reason, REASON_FIELD, 6 ) + } + break; + + case 7: { /* Version, Request, Call-id headers */ + if ON_HEADER ( _it, msg->version, VERSION_FIELD, 7 ) + else if ON_HEADER ( _it, msg->request, REQUEST_FIELD, 7 ) + else if ON_HEADER ( _it, msg->callid, CALLID_FIELD, 7 ) + } + break; + + case 8: { /* Response header */ + if ON_HEADER ( _it, msg->response, RESPONSE_FIELD, 8 ) + } + break; + + case 9: { /* Call-type header */ + if ON_HEADER ( _it, msg->calltype, CALLTYPE_FIELD, 9 ) + } + break; + + case 10: { /* User-agent, Crypto-key headers */ + if ON_HEADER ( _it, msg->useragent, USERAGENT_FIELD, 10 ) + else if ON_HEADER ( _it, msg->cryptokey, CRYPTOKEY_FIELD, 10 ) + } + break; + + default: + return -1; } } else return -1; + /* If it's anything else return failure as the message is invalid */ } @@ -300,11 +304,12 @@ var.size = t_size; /** * @brief Speaks for it self. - * + * * @param msg The message. * @return void */ -void free_message ( MSIMessage* msg ) { +void free_message ( MSIMessage *msg ) +{ assert ( msg ); free ( msg->calltype.header_value ); @@ -323,29 +328,30 @@ void free_message ( MSIMessage* msg ) { /** - * @brief Create the message. - * + * @brief Create the message. + * * @param type Request or response. * @param type_id Type of request/response. * @return MSIMessage* Created message. * @retval NULL Error occured. */ -MSIMessage* msi_new_message ( uint8_t type, const uint8_t* type_id ) { - MSIMessage* _retu = calloc ( sizeof ( MSIMessage ), 1 ); +MSIMessage *msi_new_message ( uint8_t type, const uint8_t *type_id ) +{ + MSIMessage *_retu = calloc ( sizeof ( MSIMessage ), 1 ); assert ( _retu ); if ( type == TYPE_REQUEST ) { - ALLOCATE_HEADER ( _retu->request, type_id, strlen ( (const char*)type_id ) ) + ALLOCATE_HEADER ( _retu->request, type_id, strlen ( (const char *)type_id ) ) } else if ( type == TYPE_RESPONSE ) { - ALLOCATE_HEADER ( _retu->response, type_id, strlen ( (const char*)type_id ) ) + ALLOCATE_HEADER ( _retu->response, type_id, strlen ( (const char *)type_id ) ) } else { free_message ( _retu ); return NULL; } - ALLOCATE_HEADER ( _retu->version, VERSION_STRING, strlen ( (const char*)VERSION_STRING ) ) + ALLOCATE_HEADER ( _retu->version, VERSION_STRING, strlen ( (const char *)VERSION_STRING ) ) return _retu; } @@ -353,15 +359,16 @@ MSIMessage* msi_new_message ( uint8_t type, const uint8_t* type_id ) { /** * @brief Parse data from handle_packet. - * + * * @param data The data. * @return MSIMessage* Parsed message. * @retval NULL Error occured. */ -MSIMessage* parse_message ( const uint8_t* data, uint16_t length ) { +MSIMessage *parse_message ( const uint8_t *data, uint16_t length ) +{ assert ( data ); - MSIMessage* _retu = calloc ( sizeof ( MSIMessage ), 1 ); + MSIMessage *_retu = calloc ( sizeof ( MSIMessage ), 1 ); assert ( _retu ); memset ( _retu, 0, sizeof ( MSIMessage ) ); @@ -386,7 +393,7 @@ MSIMessage* parse_message ( const uint8_t* data, uint16_t length ) { /** * @brief Speaks for it self. - * + * * @param dest Container. * @param header_field Field. * @param header_value Field value. @@ -394,45 +401,53 @@ MSIMessage* parse_message ( const uint8_t* data, uint16_t length ) { * @param length Pointer to container length. * @return uint8_t* Iterated container. */ -uint8_t* append_header_to_string ( - uint8_t* dest, - const uint8_t* header_field, - const uint8_t* header_value, +uint8_t *append_header_to_string ( + uint8_t *dest, + const uint8_t *header_field, + const uint8_t *header_value, uint16_t value_len, - uint16_t* length ) + uint16_t *length ) { assert ( dest ); assert ( header_value ); assert ( header_field ); - const uint8_t* _hvit = header_value; + const uint8_t *_hvit = header_value; uint16_t _total = 6 + value_len; /* 6 is known plus header value len + field len*/ *dest = field_byte; /* Set the first byte */ - uint8_t* _getback_byte = dest + 1; /* remeber the byte we were on */ + uint8_t *_getback_byte = dest + 1; /* remeber the byte we were on */ dest += 3; /* swith to 4th byte where field value starts */ /* Now set the field value and calculate it's length */ uint16_t _i = 0; + for ( ; header_field[_i]; ++_i ) { *dest = header_field[_i]; ++dest; }; + _total += _i; /* Now set the length of the field byte */ *_getback_byte = ( uint8_t ) _i >> 8; + _getback_byte++; + *_getback_byte = ( uint8_t ) _i; /* for value part do it regulary */ *dest = value_byte; + dest++; *dest = ( uint8_t ) value_len >> 8; + dest++; + *dest = ( uint8_t ) value_len; + dest++; for ( _i = value_len; _i; --_i ) { @@ -452,16 +467,17 @@ if ( header.header_value ) { var = append_header_to_string(var, (const uint8_t*) /** * @brief Convert MSIMessage struct to _sendable_ string. - * + * * @param msg The message. * @param dest Destination. * @return uint16_t It's final size. */ -uint16_t message_to_string ( MSIMessage* msg, uint8_t* dest ) { +uint16_t message_to_string ( MSIMessage *msg, uint8_t *dest ) +{ assert ( msg ); assert ( dest ); - uint8_t* _iterated = dest; + uint8_t *_iterated = dest; uint16_t _size = 0; CLEAN_ASSIGN ( _size, _iterated, VERSION_FIELD, msg->version ); @@ -499,12 +515,13 @@ GENERIC_SETTER_DEFINITION ( nonce ) /** * @brief Generate _random_ alphanumerical string. - * + * * @param str Destination. * @param size Size of string. * @return void */ -void t_randomstr ( uint8_t* str, size_t size ) { +void t_randomstr ( uint8_t *str, size_t size ) +{ assert ( str ); static const uint8_t _bytes[] = @@ -535,19 +552,20 @@ typedef enum { /** * @brief Stringify error code. - * + * * @param error_code The code. * @return const uint8_t* The string. */ -static inline const uint8_t *stringify_error ( MSICallError error_code ) { - static const uint8_t* strings[] = { - ( uint8_t* ) "", - ( uint8_t* ) "Using dead call", - ( uint8_t* ) "Call id not set to any call", - ( uint8_t* ) "Call id not available", - ( uint8_t* ) "No active call in session", - ( uint8_t* ) "No Crypto-key set", - ( uint8_t* ) "Callee busy" +static inline const uint8_t *stringify_error ( MSICallError error_code ) +{ + static const uint8_t *strings[] = { + ( uint8_t * ) "", + ( uint8_t * ) "Using dead call", + ( uint8_t * ) "Call id not set to any call", + ( uint8_t * ) "Call id not available", + ( uint8_t * ) "No active call in session", + ( uint8_t * ) "No Crypto-key set", + ( uint8_t * ) "Callee busy" }; return strings[error_code]; @@ -556,19 +574,20 @@ static inline const uint8_t *stringify_error ( MSICallError error_code ) { /** * @brief Convert error_code into string. - * + * * @param error_code The code. * @return const uint8_t* The string. */ -static inline const uint8_t *stringify_error_code ( MSICallError error_code ) { - static const uint8_t* strings[] = { - ( uint8_t* ) "", - ( uint8_t* ) "1", - ( uint8_t* ) "2", - ( uint8_t* ) "3", - ( uint8_t* ) "4", - ( uint8_t* ) "5", - ( uint8_t* ) "6" +static inline const uint8_t *stringify_error_code ( MSICallError error_code ) +{ + static const uint8_t *strings[] = { + ( uint8_t * ) "", + ( uint8_t * ) "1", + ( uint8_t * ) "2", + ( uint8_t * ) "3", + ( uint8_t * ) "4", + ( uint8_t * ) "5", + ( uint8_t * ) "6" }; return strings[error_code]; @@ -577,7 +596,7 @@ static inline const uint8_t *stringify_error_code ( MSICallError error_code ) { /** * @brief Speaks for it self. - * + * * @param session Control session. * @param msg The message. * @param to Where to. @@ -585,73 +604,76 @@ static inline const uint8_t *stringify_error_code ( MSICallError error_code ) { * @retval -1 Error occured. * @retval 0 Success. */ -int send_message ( MSISession* session, MSIMessage* msg, uint32_t to ) +int send_message ( MSISession *session, MSIMessage *msg, uint32_t to ) { msi_msg_set_callid ( msg, session->call->id, CALL_ID_LEN ); - + uint8_t _msg_string_final [MSI_MAXMSG_SIZE]; uint16_t _length = message_to_string ( msg, _msg_string_final ); - + return m_msi_packet(session->messenger_handle, to, _msg_string_final, _length) ? 0 : -1; } /** * @brief Speaks for it self. - * + * * @param session Control session. * @param msg The message. * @param peer_id The peer. * @return void */ -void flush_peer_type ( MSISession* session, MSIMessage* msg, int peer_id ) { +void flush_peer_type ( MSISession *session, MSIMessage *msg, int peer_id ) +{ if ( msg->calltype.header_value ) { - if ( strcmp ( ( const char* ) msg->calltype.header_value, CT_AUDIO_HEADER_VALUE ) == 0 ) { + if ( strcmp ( ( const char * ) msg->calltype.header_value, CT_AUDIO_HEADER_VALUE ) == 0 ) { session->call->type_peer[peer_id] = type_audio; - } else if ( strcmp ( ( const char* ) msg->calltype.header_value, CT_VIDEO_HEADER_VALUE ) == 0 ) { + } else if ( strcmp ( ( const char * ) msg->calltype.header_value, CT_VIDEO_HEADER_VALUE ) == 0 ) { session->call->type_peer[peer_id] = type_video; } else {} /* Error */ } else {} /* Error */ } -void handle_remote_connection_change(Messenger* messenger, int friend_num, uint8_t status, void* session_p) +void handle_remote_connection_change(Messenger *messenger, int friend_num, uint8_t status, void *session_p) { - MSISession* session = session_p; - - switch ( status ) - { - case 0: /* Went offline */ - { + MSISession *session = session_p; + + switch ( status ) { + case 0: { /* Went offline */ if ( session->call ) { int i = 0; - for ( ; i < session->call->peer_count; i ++ ) + + for ( ; i < session->call->peer_count; i ++ ) if ( session->call->peers[i] == friend_num ) { - msi_stopcall(session); /* Stop the call for now */ + msi_stopcall(session); /* Stop the call for now */ return; } } - } break; - - default: break; + } + break; + + default: + break; } } /** * @brief Sends error response to peer. - * + * * @param session The session. * @param errid The id. * @param to Where to? * @return int * @retval 0 It's always success. */ -int handle_error ( MSISession* session, MSICallError errid, uint32_t to ) { - MSIMessage* _msg_error = msi_new_message ( TYPE_RESPONSE, stringify_response ( error ) ); +int handle_error ( MSISession *session, MSICallError errid, uint32_t to ) +{ + MSIMessage *_msg_error = msi_new_message ( TYPE_RESPONSE, stringify_response ( error ) ); - const uint8_t* _error_code_str = stringify_error_code ( errid ); + const uint8_t *_error_code_str = stringify_error_code ( errid ); - msi_msg_set_reason ( _msg_error, _error_code_str, strlen ( ( const char* ) _error_code_str ) ); + msi_msg_set_reason ( _msg_error, _error_code_str, strlen ( ( const char * ) _error_code_str ) ); send_message ( session, _msg_error, to ); free_message ( _msg_error ); @@ -666,14 +688,15 @@ int handle_error ( MSISession* session, MSICallError errid, uint32_t to ) { /** * @brief Determine the error if any. - * + * * @param session Control session. * @param msg The message. * @return int * @retval -1 No error. * @retval 0 Error occured and response sent. */ -int has_call_error ( MSISession* session, MSIMessage* msg ) { +int has_call_error ( MSISession *session, MSIMessage *msg ) +{ if ( !msg->callid.header_value ) { return handle_error ( session, error_no_callid, msg->friend_id ); @@ -691,28 +714,29 @@ int has_call_error ( MSISession* session, MSIMessage* msg ) { /** * @brief Function called at request timeout. - * + * * @param arg Control session * @return void* */ -void* handle_timeout ( void* arg ) +void *handle_timeout ( void *arg ) { /* Send hangup either way */ - MSISession* _session = arg; - + MSISession *_session = arg; + if ( _session && _session->call ) { - - uint32_t* _peers = _session->call->peers; + + uint32_t *_peers = _session->call->peers; uint16_t _peer_count = _session->call->peer_count; - - + + /* Cancel all? */ uint16_t _it = 0; + for ( ; _it < _peer_count; _it++ ) - msi_cancel ( arg, _peers[_it], (const uint8_t*)"Timeout" ); - + msi_cancel ( arg, _peers[_it], (const uint8_t *)"Timeout" ); + } - + ( *callbacks[MSI_OnRequestTimeout] ) ( _session->agent_handler ); ( *callbacks[MSI_OnEnding ] ) ( _session->agent_handler ); @@ -722,38 +746,39 @@ void* handle_timeout ( void* arg ) /** * @brief Add peer to peer list. - * + * * @param call What call. * @param peer_id Its id. * @return void */ -void add_peer( MSICall* call, int peer_id ) +void add_peer( MSICall *call, int peer_id ) { if ( !call->peers ) { call->peers = calloc(sizeof(int), 1); call->peer_count = 1; - } else{ + } else { call->peer_count ++; call->peers = realloc( call->peers, sizeof(int) * call->peer_count); - } - + } + call->peers[call->peer_count - 1] = peer_id; } /** * @brief Speaks for it self. - * + * * @param session Control session. * @param peers Amount of peers. (Currently it only supports 1) * @param ringing_timeout Ringing timeout. * @return MSICall* The created call. */ -MSICall* init_call ( MSISession* session, int peers, int ringing_timeout ) { +MSICall *init_call ( MSISession *session, int peers, int ringing_timeout ) +{ assert ( session ); assert ( peers ); - MSICall* _call = calloc ( sizeof ( MSICall ), 1 ); + MSICall *_call = calloc ( sizeof ( MSICall ), 1 ); _call->type_peer = calloc ( sizeof ( MSICallType ), peers ); assert ( _call ); @@ -779,13 +804,14 @@ MSICall* init_call ( MSISession* session, int peers, int ringing_timeout ) { /** * @brief Terminate the call. - * + * * @param session Control session. * @return int * @retval -1 Error occured. * @retval 0 Success. */ -int terminate_call ( MSISession* session ) { +int terminate_call ( MSISession *session ) +{ assert ( session ); if ( !session->call ) @@ -802,7 +828,7 @@ int terminate_call ( MSISession* session ) { /* Get a handle */ pthread_mutex_lock ( &session->call->mutex ); - MSICall* _call = session->call; + MSICall *_call = session->call; session->call = NULL; free ( _call->type_peer ); @@ -816,19 +842,21 @@ int terminate_call ( MSISession* session ) { pthread_mutex_destroy ( &_call->mutex ); free ( _call ); - + return 0; } /********** Request handlers **********/ -int handle_recv_invite ( MSISession* session, MSIMessage* msg ) { +int handle_recv_invite ( MSISession *session, MSIMessage *msg ) +{ assert ( session ); if ( session->call ) { handle_error ( session, error_busy, msg->friend_id ); return 0; } + if ( !msg->callid.header_value ) { handle_error ( session, error_no_callid, msg->friend_id ); return 0; @@ -837,12 +865,12 @@ int handle_recv_invite ( MSISession* session, MSIMessage* msg ) { session->call = init_call ( session, 1, 0 ); memcpy ( session->call->id, msg->callid.header_value, CALL_ID_LEN ); session->call->state = call_starting; - + add_peer( session->call, msg->friend_id); - + flush_peer_type ( session, msg, 0 ); - MSIMessage* _msg_ringing = msi_new_message ( TYPE_RESPONSE, stringify_response ( ringing ) ); + MSIMessage *_msg_ringing = msi_new_message ( TYPE_RESPONSE, stringify_response ( ringing ) ); send_message ( session, _msg_ringing, msg->friend_id ); free_message ( _msg_ringing ); @@ -850,7 +878,8 @@ int handle_recv_invite ( MSISession* session, MSIMessage* msg ) { return 1; } -int handle_recv_start ( MSISession* session, MSIMessage* msg ) { +int handle_recv_start ( MSISession *session, MSIMessage *msg ) +{ assert ( session ); if ( has_call_error ( session, msg ) == 0 ) @@ -873,14 +902,15 @@ int handle_recv_start ( MSISession* session, MSIMessage* msg ) { return 1; } -int handle_recv_reject ( MSISession* session, MSIMessage* msg ) { +int handle_recv_reject ( MSISession *session, MSIMessage *msg ) +{ assert ( session ); if ( has_call_error ( session, msg ) == 0 ) return 0; - MSIMessage* _msg_end = msi_new_message ( TYPE_REQUEST, stringify_request ( end ) ); + MSIMessage *_msg_end = msi_new_message ( TYPE_REQUEST, stringify_request ( end ) ); send_message ( session, _msg_end, msg->friend_id ); free_message ( _msg_end ); @@ -890,7 +920,8 @@ int handle_recv_reject ( MSISession* session, MSIMessage* msg ) { return 1; } -int handle_recv_cancel ( MSISession* session, MSIMessage* msg ) { +int handle_recv_cancel ( MSISession *session, MSIMessage *msg ) +{ assert ( session ); if ( has_call_error ( session, msg ) == 0 ) @@ -903,14 +934,15 @@ int handle_recv_cancel ( MSISession* session, MSIMessage* msg ) { return 1; } -int handle_recv_end ( MSISession* session, MSIMessage* msg ) { +int handle_recv_end ( MSISession *session, MSIMessage *msg ) +{ assert ( session ); if ( has_call_error ( session, msg ) == 0 ) return 0; - MSIMessage* _msg_ending = msi_new_message ( TYPE_RESPONSE, stringify_response ( ending ) ); + MSIMessage *_msg_ending = msi_new_message ( TYPE_RESPONSE, stringify_response ( ending ) ); send_message ( session, _msg_ending, msg->friend_id ); free_message ( _msg_ending ); @@ -922,7 +954,8 @@ int handle_recv_end ( MSISession* session, MSIMessage* msg ) { } /********** Response handlers **********/ -int handle_recv_ringing ( MSISession* session, MSIMessage* msg ) { +int handle_recv_ringing ( MSISession *session, MSIMessage *msg ) +{ assert ( session ); if ( has_call_error ( session, msg ) == 0 ) @@ -933,7 +966,8 @@ int handle_recv_ringing ( MSISession* session, MSIMessage* msg ) { return 1; } -int handle_recv_starting ( MSISession* session, MSIMessage* msg ) { +int handle_recv_starting ( MSISession *session, MSIMessage *msg ) +{ assert ( session ); if ( has_call_error ( session, msg ) == 0 ) @@ -959,7 +993,7 @@ int handle_recv_starting ( MSISession* session, MSIMessage* msg ) { session->call->state = call_active; - MSIMessage* _msg_start = msi_new_message ( TYPE_REQUEST, stringify_request ( start ) ); + MSIMessage *_msg_start = msi_new_message ( TYPE_REQUEST, stringify_request ( start ) ); msi_msg_set_cryptokey ( _msg_start, session->call->key_local, crypto_secretbox_KEYBYTES ); msi_msg_set_nonce ( _msg_start, session->call->nonce_local, crypto_box_NONCEBYTES ); send_message ( session, _msg_start, msg->friend_id ); @@ -972,7 +1006,8 @@ int handle_recv_starting ( MSISession* session, MSIMessage* msg ) { return 1; } -int handle_recv_ending ( MSISession* session, MSIMessage* msg ) { +int handle_recv_ending ( MSISession *session, MSIMessage *msg ) +{ assert ( session ); if ( has_call_error ( session, msg ) == 0 ) @@ -985,13 +1020,14 @@ int handle_recv_ending ( MSISession* session, MSIMessage* msg ) { return 1; } -int handle_recv_error ( MSISession* session, MSIMessage* msg ) { +int handle_recv_error ( MSISession *session, MSIMessage *msg ) +{ assert ( session ); assert ( session->call ); /* Handle error accordingly */ if ( msg->reason.header_value ) { - session->last_error_id = atoi ( ( const char* ) msg->reason.header_value ); + session->last_error_id = atoi ( ( const char * ) msg->reason.header_value ); session->last_error_str = stringify_error ( session->last_error_id ); } @@ -1035,92 +1071,92 @@ int handle_recv_error ( MSISession* session, MSIMessage* msg ) { * * */ -void msi_handle_packet ( Messenger* messenger, int source, uint8_t* data, uint16_t length, void* object ) +void msi_handle_packet ( Messenger *messenger, int source, uint8_t *data, uint16_t length, void *object ) { /* Unused */ (void)messenger; - - MSISession* _session = object; - MSIMessage* _msg; - + + MSISession *_session = object; + MSIMessage *_msg; + if ( !length ) return; - + _msg = parse_message ( data, length ); - + if ( !_msg ) return; - + _msg->friend_id = source; - - + + /* Now handle message */ - + if ( _msg->request.header_value ) { /* Handle request */ - - const uint8_t* _request_value = _msg->request.header_value; - + + const uint8_t *_request_value = _msg->request.header_value; + if ( same ( _request_value, stringify_request ( invite ) ) ) { handle_recv_invite ( _session, _msg ); - + } else if ( same ( _request_value, stringify_request ( start ) ) ) { handle_recv_start ( _session, _msg ); - + } else if ( same ( _request_value, stringify_request ( cancel ) ) ) { handle_recv_cancel ( _session, _msg ); - + } else if ( same ( _request_value, stringify_request ( reject ) ) ) { handle_recv_reject ( _session, _msg ); - + } else if ( same ( _request_value, stringify_request ( end ) ) ) { handle_recv_end ( _session, _msg ); } - + else { free_message ( _msg ); return; } - + } else if ( _msg->response.header_value ) { /* Handle response */ - - const uint8_t* _response_value = _msg->response.header_value; - + + const uint8_t *_response_value = _msg->response.header_value; + if ( same ( _response_value, stringify_response ( ringing ) ) ) { handle_recv_ringing ( _session, _msg ); - + } else if ( same ( _response_value, stringify_response ( starting ) ) ) { handle_recv_starting ( _session, _msg ); - + } else if ( same ( _response_value, stringify_response ( ending ) ) ) { handle_recv_ending ( _session, _msg ); - + } else if ( same ( _response_value, stringify_response ( error ) ) ) { handle_recv_error ( _session, _msg ); } else { free_message ( _msg ); return; } - + /* Got response so cancel timer */ if ( _session->call ) event.timer_release ( _session->call->request_timer_id ); - + } - + free_message ( _msg ); } -/******************************************************************************************************************** +/******************************************************************************************************************** * ******************************************************************************************************************* ******************************************************************************************************************** ******************************************************************************************************************** ******************************************************************************************************************** - * - * - * + * + * + * * PUBLIC API FUNCTIONS IMPLEMENTATIONS - * - * - * + * + * + * ******************************************************************************************************************** ******************************************************************************************************************** ******************************************************************************************************************** @@ -1136,12 +1172,12 @@ void msi_handle_packet ( Messenger* messenger, int source, uint8_t* data, uint16 /** * @brief Callback setter. - * + * * @param callback The callback. * @param id The id. * @return void */ -void msi_register_callback ( MSICallback callback, MSICallbackID id ) +void msi_register_callback ( MSICallback callback, MSICallbackID id ) { callbacks[id] = callback; } @@ -1149,54 +1185,56 @@ void msi_register_callback ( MSICallback callback, MSICallbackID id ) /** * @brief Start the control session. - * + * * @param messenger Tox* object. * @param user_agent User agent, i.e. 'Venom'; 'QT-gui' * @return MSISession* The created session. * @retval NULL Error occured. */ -MSISession* msi_init_session ( Messenger* messenger, const uint8_t* ua_name ) { +MSISession *msi_init_session ( Messenger *messenger, const uint8_t *ua_name ) +{ assert ( messenger ); - - MSISession* _retu = calloc ( sizeof ( MSISession ), 1 ); + + MSISession *_retu = calloc ( sizeof ( MSISession ), 1 ); assert ( _retu ); - + _retu->ua_name = ua_name; _retu->messenger_handle = messenger; _retu->agent_handler = NULL; - + _retu->call = NULL; - + _retu->frequ = 10000; /* default value? */ _retu->call_timeout = 30000; /* default value? */ - - + + m_callback_msi_packet(messenger, msi_handle_packet, _retu ); - + /* This is called when remote terminates session */ m_callback_connectionstatus_internal_av(messenger, handle_remote_connection_change, _retu); - + return _retu; } /** * @brief Terminate control session. - * + * * @param session The session * @return int */ -int msi_terminate_session ( MSISession* session ) { +int msi_terminate_session ( MSISession *session ) +{ assert ( session ); - + int _status = 0; - + terminate_call ( session ); - m_callback_msi_packet((struct Messenger*) session->messenger_handle, NULL, NULL); - - + m_callback_msi_packet((struct Messenger *) session->messenger_handle, NULL, NULL); + + /* TODO: Clean it up more? */ - + free ( session ); return _status; } @@ -1204,32 +1242,33 @@ int msi_terminate_session ( MSISession* session ) { /** * @brief Send invite request to friend_id. - * + * * @param session Control session. * @param call_type Type of the call. Audio or Video(both audio and video) * @param rngsec Ringing timeout. * @param friend_id The friend. * @return int */ -int msi_invite ( MSISession* session, MSICallType call_type, uint32_t rngsec, uint32_t friend_id ) { +int msi_invite ( MSISession *session, MSICallType call_type, uint32_t rngsec, uint32_t friend_id ) +{ assert ( session ); - MSIMessage* _msg_invite = msi_new_message ( TYPE_REQUEST, stringify_request ( invite ) ); + MSIMessage *_msg_invite = msi_new_message ( TYPE_REQUEST, stringify_request ( invite ) ); session->call = init_call ( session, 1, rngsec ); /* Just one for now */ t_randomstr ( session->call->id, CALL_ID_LEN ); - + add_peer(session->call, friend_id ); - + session->call->type_local = call_type; /* Do whatever with message */ if ( call_type == type_audio ) { msi_msg_set_calltype - ( _msg_invite, ( const uint8_t* ) CT_AUDIO_HEADER_VALUE, strlen ( CT_AUDIO_HEADER_VALUE ) ); + ( _msg_invite, ( const uint8_t * ) CT_AUDIO_HEADER_VALUE, strlen ( CT_AUDIO_HEADER_VALUE ) ); } else { msi_msg_set_calltype - ( _msg_invite, ( const uint8_t* ) CT_VIDEO_HEADER_VALUE, strlen ( CT_VIDEO_HEADER_VALUE ) ); + ( _msg_invite, ( const uint8_t * ) CT_VIDEO_HEADER_VALUE, strlen ( CT_VIDEO_HEADER_VALUE ) ); } send_message ( session, _msg_invite, friend_id ); @@ -1245,26 +1284,28 @@ int msi_invite ( MSISession* session, MSICallType call_type, uint32_t rngsec, ui /** * @brief Hangup active call. - * + * * @param session Control session. - * @return int + * @return int * @retval -1 Error occured. * @retval 0 Success. */ -int msi_hangup ( MSISession* session ) { +int msi_hangup ( MSISession *session ) +{ assert ( session ); if ( !session->call || session->call->state != call_active ) return -1; - MSIMessage* _msg_ending = msi_new_message ( TYPE_REQUEST, stringify_request ( end ) ); - + MSIMessage *_msg_ending = msi_new_message ( TYPE_REQUEST, stringify_request ( end ) ); + /* hangup for each peer */ int _it = 0; + for ( ; _it < session->call->peer_count; _it ++ ) send_message ( session, _msg_ending, session->call->peers[_it] ); - - + + free_message ( _msg_ending ); session->call->request_timer_id = event.timer_alloc ( handle_timeout, session, m_deftout ); @@ -1275,23 +1316,24 @@ int msi_hangup ( MSISession* session ) { /** * @brief Answer active call request. - * + * * @param session Control session. * @param call_type Answer with Audio or Video(both). * @return int */ -int msi_answer ( MSISession* session, MSICallType call_type ) { +int msi_answer ( MSISession *session, MSICallType call_type ) +{ assert ( session ); - MSIMessage* _msg_starting = msi_new_message ( TYPE_RESPONSE, stringify_response ( starting ) ); + MSIMessage *_msg_starting = msi_new_message ( TYPE_RESPONSE, stringify_response ( starting ) ); session->call->type_local = call_type; if ( call_type == type_audio ) { msi_msg_set_calltype - ( _msg_starting, ( const uint8_t* ) CT_AUDIO_HEADER_VALUE, strlen ( CT_AUDIO_HEADER_VALUE ) ); + ( _msg_starting, ( const uint8_t * ) CT_AUDIO_HEADER_VALUE, strlen ( CT_AUDIO_HEADER_VALUE ) ); } else { msi_msg_set_calltype - ( _msg_starting, ( const uint8_t* ) CT_VIDEO_HEADER_VALUE, strlen ( CT_VIDEO_HEADER_VALUE ) ); + ( _msg_starting, ( const uint8_t * ) CT_VIDEO_HEADER_VALUE, strlen ( CT_VIDEO_HEADER_VALUE ) ); } /* Now set the local encryption key and pass it with STARTING message */ @@ -1316,18 +1358,19 @@ int msi_answer ( MSISession* session, MSICallType call_type ) { /** * @brief Cancel request. - * + * * @param session Control session. * @param reason Set optional reason header. Pass NULL if none. * @return int */ -int msi_cancel ( MSISession* session, uint32_t peer, const uint8_t* reason ) { +int msi_cancel ( MSISession *session, uint32_t peer, const uint8_t *reason ) +{ assert ( session ); - MSIMessage* _msg_cancel = msi_new_message ( TYPE_REQUEST, stringify_request ( cancel ) ); - - if ( reason ) msi_msg_set_reason(_msg_cancel, reason, strlen((const char*)reason)); - + MSIMessage *_msg_cancel = msi_new_message ( TYPE_REQUEST, stringify_request ( cancel ) ); + + if ( reason ) msi_msg_set_reason(_msg_cancel, reason, strlen((const char *)reason)); + send_message ( session, _msg_cancel, peer ); free_message ( _msg_cancel ); @@ -1339,17 +1382,18 @@ int msi_cancel ( MSISession* session, uint32_t peer, const uint8_t* reason ) { /** * @brief Reject request. - * + * * @param session Control session. * @return int */ -int msi_reject ( MSISession* session, const uint8_t* reason ) { +int msi_reject ( MSISession *session, const uint8_t *reason ) +{ assert ( session ); - MSIMessage* _msg_reject = msi_new_message ( TYPE_REQUEST, stringify_request ( reject ) ); - - if ( reason ) msi_msg_set_reason(_msg_reject, reason, strlen((const char*)reason) + 1); - + MSIMessage *_msg_reject = msi_new_message ( TYPE_REQUEST, stringify_request ( reject ) ); + + if ( reason ) msi_msg_set_reason(_msg_reject, reason, strlen((const char *)reason) + 1); + send_message ( session, _msg_reject, session->call->peers[session->call->peer_count - 1] ); free_message ( _msg_reject ); @@ -1361,18 +1405,19 @@ int msi_reject ( MSISession* session, const uint8_t* reason ) { /** * @brief Terminate the current call. - * + * * @param session Control session. * @return int */ -int msi_stopcall ( MSISession* session ) { +int msi_stopcall ( MSISession *session ) +{ assert ( session ); if ( !session->call ) return -1; /* just terminate it */ - + terminate_call ( session ); return 0; diff --git a/toxav/msi.h b/toxav/msi.h index 5b693da4..84a30f63 100644 --- a/toxav/msi.h +++ b/toxav/msi.h @@ -1,5 +1,5 @@ /** toxmsi.h - * + * * Copyright (C) 2013 Tox project All Rights Reserved. * * This file is part of Tox. @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with Tox. If not, see . * - * + * * Report bugs/suggestions at #tox-dev @ freenode.net:6667 */ @@ -33,7 +33,7 @@ #define CALL_ID_LEN 12 -typedef void* ( *MSICallback ) ( void* arg ); +typedef void *( *MSICallback ) ( void *arg ); /** @@ -60,21 +60,21 @@ typedef enum { /** * @brief The call struct. - * + * */ typedef struct _MSICall { /* Call info structure */ MSICallState state; MSICallType type_local; /* Type of payload user is ending */ - MSICallType* type_peer; /* Type of payload others are sending */ + MSICallType *type_peer; /* Type of payload others are sending */ uint8_t id[CALL_ID_LEN]; /* Random value identifying the call */ - uint8_t* key_local; /* The key for encryption */ - uint8_t* key_peer; /* The key for decryption */ + uint8_t *key_local; /* The key for encryption */ + uint8_t *key_peer; /* The key for decryption */ - uint8_t* nonce_local; /* Local nonce */ - uint8_t* nonce_peer; /* Peer nonce */ + uint8_t *nonce_local; /* Local nonce */ + uint8_t *nonce_peer; /* Peer nonce */ int ringing_tout_ms; /* Ringing timeout in ms */ @@ -84,39 +84,39 @@ typedef struct _MSICall { /* Call info structure */ pthread_mutex_t mutex; /* It's to be assumed that call will have * seperate thread so add mutex */ - uint32_t* peers; - uint16_t peer_count; - - + uint32_t *peers; + uint16_t peer_count; + + } MSICall; /** * @brief Control session struct - * + * */ typedef struct _MSISession { /* Call handler */ - struct _MSICall* call; + struct _MSICall *call; int last_error_id; /* Determine the last error */ - const uint8_t* last_error_str; + const uint8_t *last_error_str; - const uint8_t* ua_name; + const uint8_t *ua_name; + + void *agent_handler; /* Pointer to an object that is handling msi */ + Messenger *messenger_handle; - void* agent_handler; /* Pointer to an object that is handling msi */ - Messenger* messenger_handle; - uint32_t frequ; uint32_t call_timeout; /* Time of the timeout for some action to end; 0 if infinite */ - + } MSISession; -/** - * @brief Callbacks ids that handle the states +/** + * @brief Callbacks ids that handle the states */ typedef enum { /* Requests */ @@ -140,7 +140,7 @@ typedef enum { /** * @brief Callback setter. - * + * * @param callback The callback. * @param id The id. * @return void @@ -150,84 +150,84 @@ void msi_register_callback(MSICallback callback, MSICallbackID id); /** * @brief Start the control session. - * + * * @param messenger Tox* object. * @param user_agent User agent, i.e. 'Venom'; 'QT-gui' * @return MSISession* The created session. * @retval NULL Error occured. */ -MSISession* msi_init_session ( Messenger* messenger, const uint8_t* ua_name ); +MSISession *msi_init_session ( Messenger *messenger, const uint8_t *ua_name ); /** * @brief Terminate control session. - * + * * @param session The session * @return int */ -int msi_terminate_session ( MSISession* session ); +int msi_terminate_session ( MSISession *session ); /** * @brief Send invite request to friend_id. - * + * * @param session Control session. * @param call_type Type of the call. Audio or Video(both audio and video) * @param rngsec Ringing timeout. * @param friend_id The friend. * @return int */ -int msi_invite ( MSISession* session, MSICallType call_type, uint32_t rngsec, uint32_t friend_id ); +int msi_invite ( MSISession *session, MSICallType call_type, uint32_t rngsec, uint32_t friend_id ); /** * @brief Hangup active call. - * + * * @param session Control session. - * @return int + * @return int * @retval -1 Error occured. * @retval 0 Success. */ -int msi_hangup ( MSISession* session ); +int msi_hangup ( MSISession *session ); /** * @brief Answer active call request. - * + * * @param session Control session. * @param call_type Answer with Audio or Video(both). * @return int */ -int msi_answer ( MSISession* session, MSICallType call_type ); +int msi_answer ( MSISession *session, MSICallType call_type ); /** * @brief Cancel request. - * + * * @param session Control session. * @param peer To which peer. * @param reason Set optional reason header. Pass NULL if none. * @return int */ -int msi_cancel ( MSISession* session, uint32_t peer, const uint8_t* reason ); +int msi_cancel ( MSISession *session, uint32_t peer, const uint8_t *reason ); /** * @brief Reject request. - * + * * @param session Control session. * @param reason Set optional reason header. Pass NULL if none. * @return int */ -int msi_reject ( MSISession* session, const uint8_t* reason ); +int msi_reject ( MSISession *session, const uint8_t *reason ); /** * @brief Terminate the current call. - * + * * @param session Control session. * @return int */ -int msi_stopcall ( MSISession* session ); +int msi_stopcall ( MSISession *session ); #endif /* __TOXMSI */ diff --git a/toxav/phone.c b/toxav/phone.c old mode 100755 new mode 100644 index 161275d9..ec7dd143 --- a/toxav/phone.c +++ b/toxav/phone.c @@ -1,16 +1,16 @@ /** phone.c * - * NOTE NOTE NOTE NOTE NOTE NOTE - * + * NOTE NOTE NOTE NOTE NOTE NOTE + * * This file is for testing/reference purposes only, hence - * it is _poorly_ designed and it does not fully reflect the - * quaility of msi nor rtp. Although toxmsi* and toxrtp* are tested - * there is always possiblity of crashes. If crash occures, - * contact me ( mannol ) on either irc channel #tox-dev @ freenode.net:6667 + * it is _poorly_ designed and it does not fully reflect the + * quaility of msi nor rtp. Although toxmsi* and toxrtp* are tested + * there is always possiblity of crashes. If crash occures, + * contact me ( mannol ) on either irc channel #tox-dev @ freenode.net:6667 * or eniz_vukovic@hotmail.com - * - * NOTE NOTE NOTE NOTE NOTE NOTE - * + * + * NOTE NOTE NOTE NOTE NOTE NOTE + * * Copyright (C) 2013 Tox project All Rights Reserved. * * This file is part of Tox. @@ -97,25 +97,25 @@ typedef struct av_friend_s { typedef struct av_session_s { /* Encoding/decoding/capturing/playing */ - ToxAv* av; - - VideoPicture video_picture; + ToxAv *av; + + VideoPicture video_picture; struct ALCdevice *audio_capture_device; - + /* context for converting image format to something SDL can use*/ struct SwsContext *sws_SDL_r_ctx; - + /* context for converting webcam image format to something the video encoder can use */ struct SwsContext *sws_ctx; - + /* Thread running control */ - int running_decaud, running_encaud, + int running_decaud, running_encaud, running_decvid, running_encvid; - + pthread_mutex_t _mutex; - - Tox* _messenger; - av_friend_t* _friends; + + Tox *_messenger; + av_friend_t *_friends; int _friend_cout; char _my_public_id[200]; #ifdef TOX_FFMPEG @@ -128,43 +128,44 @@ typedef struct av_session_s { } av_session_t; -void av_allocate_friend(av_session_t* _phone, int _id, int _active) +void av_allocate_friend(av_session_t *_phone, int _id, int _active) { static int _new_id = 0; - + if ( !_phone->_friends ) { _phone->_friends = calloc(sizeof(av_friend_t), 1); _phone->_friend_cout = 1; - } else{ + } else { _phone->_friend_cout ++; _phone->_friends = realloc(_phone->_friends, sizeof(av_friend_t) * _phone->_friend_cout); } - + if ( _id == -1 ) { _phone->_friends->_id = _new_id; _new_id ++; } else _phone->_friends->_id = _id; - + _phone->_friends->_active = _active; } -av_friend_t* av_get_friend(av_session_t* _phone, int _id) +av_friend_t *av_get_friend(av_session_t *_phone, int _id) { - av_friend_t* _friends = _phone->_friends; - + av_friend_t *_friends = _phone->_friends; + if ( !_friends ) return NULL; - + int _it = 0; + for (; _it < _phone->_friend_cout; _it ++) - if ( _friends[_it]._id == _id ) + if ( _friends[_it]._id == _id ) return _friends + _it; - + return NULL; } /***************** MISC *****************/ -void INFO (const char* _format, ...) +void INFO (const char *_format, ...) { printf("\r[!] "); va_list _arg; @@ -180,44 +181,44 @@ unsigned char *hex_string_to_bin(char hex_string[]) size_t i, len = strlen(hex_string); unsigned char *val = calloc(sizeof(unsigned char), len); char *pos = hex_string; - + for (i = 0; i < len; ++i, pos += 2) sscanf(pos, "%2hhx", &val[i]); - + return val; } -int getinput( char* _buff, size_t _limit, int* _len ) +int getinput( char *_buff, size_t _limit, int *_len ) { if ( fgets(_buff, _limit, stdin) == NULL ) return -1; - + *_len = strlen(_buff) - 1; - + /* Get rid of newline */ _buff[*_len] = '\0'; - + return 0; } -char* trim_spaces ( char* buff ) +char *trim_spaces ( char *buff ) { - + int _i = 0, _len = strlen(buff); - - char* container = calloc(sizeof(char), _len); + + char *container = calloc(sizeof(char), _len); int _ci = 0; - + for ( ; _i < _len; _i++ ) { while ( _i < _len && buff[_i] == ' ' ) _i++; - - if ( _i < _len ){ + + if ( _i < _len ) { container[_ci] = buff[_i]; _ci ++; } } - + memcpy( buff, container, _ci ); buff[_ci] = '\0'; free(container); @@ -227,26 +228,26 @@ char* trim_spaces ( char* buff ) #define FRADDR_TOSTR_CHUNK_LEN 8 static void fraddr_to_str(uint8_t *id_bin, char *id_str) -{ +{ uint i, delta = 0, pos_extra = 0, sum_extra = 0; - + for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; i++) { sprintf(&id_str[2 * i + delta], "%02hhX", id_bin[i]); - + if ((i + 1) == TOX_CLIENT_ID_SIZE) pos_extra = 2 * (i + 1) + delta; - + if (i >= TOX_CLIENT_ID_SIZE) sum_extra |= id_bin[i]; - + if (!((i + 1) % FRADDR_TOSTR_CHUNK_LEN)) { id_str[2 * (i + 1) + delta] = ' '; delta++; } } - + id_str[2 * i + delta] = 0; - + if (!sum_extra) id_str[pos_extra] = 0; } @@ -262,8 +263,8 @@ static void fraddr_to_str(uint8_t *id_bin, char *id_str) */ -/* - * How av stuff _should_ look like +/* + * How av stuff _should_ look like */ /* int display_received_frame(av_session_t* _phone, vpx_image_t *image) @@ -271,7 +272,7 @@ int display_received_frame(av_session_t* _phone, vpx_image_t *image) CodecState* cs = get_cs_temp(_phone->av); AVPicture pict; SDL_LockYUVOverlay(_phone->video_picture.bmp); - + pict.data[0] = _phone->video_picture.bmp->pixels[0]; pict.data[1] = _phone->video_picture.bmp->pixels[2]; pict.data[2] = _phone->video_picture.bmp->pixels[1]; @@ -279,18 +280,18 @@ int display_received_frame(av_session_t* _phone, vpx_image_t *image) pict.linesize[1] = _phone->video_picture.bmp->pitches[2]; pict.linesize[2] = _phone->video_picture.bmp->pitches[1]; */ - /* Convert the image into YUV format that SDL uses *//* - sws_scale(_phone->sws_SDL_r_ctx, (uint8_t const * const *)r_video_frame->data, r_video_frame->linesize, 0, - cs->video_decoder_ctx->height, pict.data, pict.linesize ); - - SDL_UnlockYUVOverlay(_phone->video_picture.bmp); - SDL_Rect rect; - rect.x = 0; - rect.y = 0; - rect.w = cs->video_decoder_ctx->width; - rect.h = cs->video_decoder_ctx->height; - SDL_DisplayYUVOverlay(_phone->video_picture.bmp, &rect); - return 1; +/* Convert the image into YUV format that SDL uses *//* +sws_scale(_phone->sws_SDL_r_ctx, (uint8_t const * const *)r_video_frame->data, r_video_frame->linesize, 0, + cs->video_decoder_ctx->height, pict.data, pict.linesize ); + +SDL_UnlockYUVOverlay(_phone->video_picture.bmp); +SDL_Rect rect; +rect.x = 0; +rect.y = 0; +rect.w = cs->video_decoder_ctx->width; +rect.h = cs->video_decoder_ctx->height; +SDL_DisplayYUVOverlay(_phone->video_picture.bmp, &rect); +return 1; } */ #ifdef TOX_FFMPEG @@ -298,8 +299,8 @@ void *encode_video_thread(void *arg) { INFO("Started encode video thread!"); - av_session_t* _phone = arg; - + av_session_t *_phone = arg; + _phone->running_encvid = 1; //CodecState *cs = get_cs_temp(_phone->av); AVPacket pkt1, *packet = &pkt1; @@ -311,40 +312,41 @@ void *encode_video_thread(void *arg) s_video_frame = avcodec_alloc_frame(); webcam_frame = avcodec_alloc_frame(); //AVPacket enc_video_packet; - + uint8_t *buffer; int numBytes; /* Determine required buffer size and allocate buffer */ numBytes = avpicture_get_size(PIX_FMT_YUV420P, _phone->webcam_decoder_ctx->width, _phone->webcam_decoder_ctx->height); - buffer = (uint8_t *)av_calloc(numBytes * sizeof(uint8_t),1); + buffer = (uint8_t *)av_calloc(numBytes * sizeof(uint8_t), 1); avpicture_fill((AVPicture *)s_video_frame, buffer, PIX_FMT_YUV420P, _phone->webcam_decoder_ctx->width, _phone->webcam_decoder_ctx->height); _phone->sws_ctx = sws_getContext(_phone->webcam_decoder_ctx->width, _phone->webcam_decoder_ctx->height, - _phone->webcam_decoder_ctx->pix_fmt, _phone->webcam_decoder_ctx->width, _phone->webcam_decoder_ctx->height, PIX_FMT_YUV420P, - SWS_BILINEAR, NULL, NULL, NULL); - - - vpx_image_t *image = - vpx_img_alloc(NULL, VPX_IMG_FMT_I420, _phone->webcam_decoder_ctx->width, _phone->webcam_decoder_ctx->height, 1); - + _phone->webcam_decoder_ctx->pix_fmt, _phone->webcam_decoder_ctx->width, _phone->webcam_decoder_ctx->height, + PIX_FMT_YUV420P, + SWS_BILINEAR, NULL, NULL, NULL); + + + vpx_image_t *image = + vpx_img_alloc(NULL, VPX_IMG_FMT_I420, _phone->webcam_decoder_ctx->width, _phone->webcam_decoder_ctx->height, 1); + //uint32_t frame_counter = 0; while (_phone->running_encvid) { - + if (av_read_frame(_phone->video_format_ctx, packet) < 0) { printf("error reading frame\n"); - + if (_phone->video_format_ctx->pb->error != 0) break; - + continue; } - + if (packet->stream_index == _phone->video_stream) { if (avcodec_decode_video2(_phone->webcam_decoder_ctx, webcam_frame, &video_frame_finished, packet) < 0) { printf("couldn't decode\n"); continue; } - + av_free_packet(packet); sws_scale(_phone->sws_ctx, (uint8_t const * const *)webcam_frame->data, webcam_frame->linesize, 0, _phone->webcam_decoder_ctx->height, s_video_frame->data, s_video_frame->linesize); @@ -352,7 +354,7 @@ void *encode_video_thread(void *arg) //++p; /* if (p == 60) { - + s_video_frame->pict_type = AV_PICTURE_TYPE_BI ; } else if (p == 61) { s_video_frame->pict_type = AV_PICTURE_TYPE_I ; @@ -360,11 +362,14 @@ void *encode_video_thread(void *arg) } else { s_video_frame->pict_type = AV_PICTURE_TYPE_P ; }*/ - + if (video_frame_finished) { - memcpy(image->planes[VPX_PLANE_Y], s_video_frame->data[0], s_video_frame->linesize[0] * _phone->webcam_decoder_ctx->height); - memcpy(image->planes[VPX_PLANE_U], s_video_frame->data[1], s_video_frame->linesize[1] * _phone->webcam_decoder_ctx->height / 2); - memcpy(image->planes[VPX_PLANE_V], s_video_frame->data[2], s_video_frame->linesize[2] * _phone->webcam_decoder_ctx->height / 2); + memcpy(image->planes[VPX_PLANE_Y], s_video_frame->data[0], + s_video_frame->linesize[0] * _phone->webcam_decoder_ctx->height); + memcpy(image->planes[VPX_PLANE_U], s_video_frame->data[1], + s_video_frame->linesize[1] * _phone->webcam_decoder_ctx->height / 2); + memcpy(image->planes[VPX_PLANE_V], s_video_frame->data[2], + s_video_frame->linesize[2] * _phone->webcam_decoder_ctx->height / 2); toxav_send_video (_phone->av, image); //if (avcodec_encode_video2(cs->video_encoder_ctx, &enc_video_packet, s_video_frame, &got_packet) < 0) { /*if (vpx_codec_encode(&cs->v_encoder, image, frame_counter, 1, 0, 0) != VPX_CODEC_OK) { @@ -372,7 +377,7 @@ void *encode_video_thread(void *arg) continue; } ++frame_counter; - + vpx_codec_iter_t iter = NULL; vpx_codec_cx_pkt_t *pkt; while( (pkt = vpx_codec_get_cx_data(&cs->v_encoder, &iter)) ) { @@ -382,20 +387,20 @@ void *encode_video_thread(void *arg) //if (!got_packet) { // continue; //} - + //if (!enc_video_packet.data) fprintf(stderr, "video packet data is NULL\n"); - + //toxav_send_rtp_payload(_phone->av, TypeVideo, enc_video_packet.data, enc_video_packet.size); - + //av_free_packet(&enc_video_packet); } } else { av_free_packet(packet); } } - + vpx_img_free(image); - + /* clean up codecs */ //pthread_mutex_lock(&cs->ctrl_mutex); av_free(buffer); @@ -405,9 +410,9 @@ void *encode_video_thread(void *arg) //avcodec_close(webcam_decoder_ctx); //avcodec_close(cs->video_encoder_ctx); //pthread_mutex_unlock(&cs->ctrl_mutex); - + _phone->running_encvid = -1; - + pthread_exit ( NULL ); } #endif @@ -415,23 +420,23 @@ void *encode_video_thread(void *arg) void *encode_audio_thread(void *arg) { INFO("Started encode audio thread!"); - av_session_t* _phone = arg; + av_session_t *_phone = arg; _phone->running_encaud = 1; int ret = 0; int16_t frame[4096]; int frame_size = AUDIO_FRAME_SIZE; ALint sample = 0; - alcCaptureStart((ALCdevice*)_phone->audio_capture_device); - + alcCaptureStart((ALCdevice *)_phone->audio_capture_device); + while (_phone->running_encaud) { - alcGetIntegerv((ALCdevice*)_phone->audio_capture_device, ALC_CAPTURE_SAMPLES, (ALCsizei)sizeof(ALint), &sample); - + alcGetIntegerv((ALCdevice *)_phone->audio_capture_device, ALC_CAPTURE_SAMPLES, (ALCsizei)sizeof(ALint), &sample); + if (sample >= frame_size) { - alcCaptureSamples((ALCdevice*)_phone->audio_capture_device, frame, frame_size); - + alcCaptureSamples((ALCdevice *)_phone->audio_capture_device, frame, frame_size); + ret = toxav_send_audio(_phone->av, frame, frame_size); - + if (ret < 0) printf("Could not encode or send audio packet\n"); @@ -439,28 +444,29 @@ void *encode_audio_thread(void *arg) usleep(1000); } } - + /* clean up codecs * pthread_mutex_lock(&cs->ctrl_mutex);* / alcCaptureStop((ALCdevice*)_phone->audio_capture_device); - alcCaptureCloseDevice((ALCdevice*)_phone->audio_capture_device); + alcCaptureCloseDevice((ALCdevice*)_phone->audio_capture_device); / *pthread_mutex_unlock(&cs->ctrl_mutex);*/ _phone->running_encaud = -1; - pthread_exit ( NULL ); + pthread_exit ( NULL ); } void convert_to_rgb(vpx_image_t *img, unsigned char *out) { const int w = img->d_w; - const int w2 = w/2; - const int pstride = w*3; + const int w2 = w / 2; + const int pstride = w * 3; const int h = img->d_h; - const int h2 = h/2; - + const int h2 = h / 2; + const int strideY = img->stride[0]; const int strideU = img->stride[1]; const int strideV = img->stride[2]; int posy, posx; + for (posy = 0; posy < h2; posy++) { unsigned char *dst = out + pstride * (posy * 2); unsigned char *dst2 = out + pstride * (posy * 2 + 1); @@ -468,36 +474,61 @@ void convert_to_rgb(vpx_image_t *img, unsigned char *out) const unsigned char *srcY2 = img->planes[0] + strideY * (posy * 2 + 1); const unsigned char *srcU = img->planes[1] + strideU * posy; const unsigned char *srcV = img->planes[2] + strideV * posy; - + for (posx = 0; posx < w2; posx++) { - unsigned char Y,U,V; - short R,G,B; - short iR,iG,iB; - - U = *(srcU++); V = *(srcV++); - iR = (351 * (V-128)) / 256; - iG = - (179 * (V-128)) / 256 - (86 * (U-128)) / 256; - iB = (444 * (U-128)) / 256; - - Y = *(srcY++); - R = Y + iR ; G = Y + iG ; B = Y + iB ; - R = (R<0?0:(R>255?255:R)); G = (G<0?0:(G>255?255:G)); B = (B<0?0:(B>255?255:B)); - *(dst++) = R; *(dst++) = G; *(dst++) = B; - + unsigned char Y, U, V; + short R, G, B; + short iR, iG, iB; + + U = *(srcU++); + V = *(srcV++); + iR = (351 * (V - 128)) / 256; + iG = - (179 * (V - 128)) / 256 - (86 * (U - 128)) / 256; + iB = (444 * (U - 128)) / 256; + + Y = *(srcY++); + R = Y + iR ; + G = Y + iG ; + B = Y + iB ; + R = (R < 0 ? 0 : (R > 255 ? 255 : R)); + G = (G < 0 ? 0 : (G > 255 ? 255 : G)); + B = (B < 0 ? 0 : (B > 255 ? 255 : B)); + *(dst++) = R; + *(dst++) = G; + *(dst++) = B; + Y = *(srcY2++); - R = Y + iR ; G = Y + iG ; B = Y + iB ; - R = (R<0?0:(R>255?255:R)); G = (G<0?0:(G>255?255:G)); B = (B<0?0:(B>255?255:B)); - *(dst2++) = R; *(dst2++) = G; *(dst2++) = B; - + R = Y + iR ; + G = Y + iG ; + B = Y + iB ; + R = (R < 0 ? 0 : (R > 255 ? 255 : R)); + G = (G < 0 ? 0 : (G > 255 ? 255 : G)); + B = (B < 0 ? 0 : (B > 255 ? 255 : B)); + *(dst2++) = R; + *(dst2++) = G; + *(dst2++) = B; + Y = *(srcY++) ; - R = Y + iR ; G = Y + iG ; B = Y + iB ; - R = (R<0?0:(R>255?255:R)); G = (G<0?0:(G>255?255:G)); B = (B<0?0:(B>255?255:B)); - *(dst++) = R; *(dst++) = G; *(dst++) = B; - + R = Y + iR ; + G = Y + iG ; + B = Y + iB ; + R = (R < 0 ? 0 : (R > 255 ? 255 : R)); + G = (G < 0 ? 0 : (G > 255 ? 255 : G)); + B = (B < 0 ? 0 : (B > 255 ? 255 : B)); + *(dst++) = R; + *(dst++) = G; + *(dst++) = B; + Y = *(srcY2++); - R = Y + iR ; G = Y + iG ; B = Y + iB ; - R = (R<0?0:(R>255?255:R)); G = (G<0?0:(G>255?255:G)); B = (B<0?0:(B>255?255:B)); - *(dst2++) = R; *(dst2++) = G; *(dst2++) = B; + R = Y + iR ; + G = Y + iG ; + B = Y + iB ; + R = (R < 0 ? 0 : (R > 255 ? 255 : R)); + G = (G < 0 ? 0 : (G > 255 ? 255 : G)); + B = (B < 0 ? 0 : (B > 255 ? 255 : B)); + *(dst2++) = R; + *(dst2++) = G; + *(dst2++) = B; } } } @@ -507,15 +538,15 @@ void convert_to_rgb(vpx_image_t *img, unsigned char *out) void *decode_video_thread(void *arg) { INFO("Started decode video thread!"); - av_session_t* _phone = arg; + av_session_t *_phone = arg; _phone->running_decvid = 1; - + //CodecState *cs = get_cs_temp(_phone->av); //cs->video_stream = 0; - + //int recved_size; //uint8_t dest[RTP_PAYLOAD_SIZE]; - + //int dec_frame_finished; //AVFrame *r_video_frame; //r_video_frame = avcodec_alloc_frame(); @@ -523,89 +554,95 @@ void *decode_video_thread(void *arg) //av_new_packet (&dec_video_packet, 65536); int width = 0; int height = 0; - + while (_phone->running_decvid) { //recved_size = toxav_recv_rtp_payload(_phone->av, TypeVideo, dest); //if (recved_size) { vpx_image_t *image; + if (toxav_recv_video(_phone->av, &image) == 0) { //memcpy(dec_video_packet.data, dest, recved_size); //dec_video_packet.size = recved_size; - + //avcodec_decode_video2(cs->video_decoder_ctx, r_video_frame, &dec_frame_finished, &dec_video_packet); - + //if (dec_frame_finished) { - - /* Check if size has changed */ - if (image->d_w != width || image->d_h != height) { - - width = image->d_w; - height = image->d_h; - - printf("w: %d h: %d \n", width, height); - - screen = SDL_SetVideoMode(width, height, 0, 0); - - //if (_phone->video_picture.bmp) - // SDL_FreeYUVOverlay(_phone->video_picture.bmp); - - //_phone->video_picture.bmp = SDL_CreateYUVOverlay(width, height, SDL_YV12_OVERLAY, screen); - // _phone->sws_SDL_r_ctx = sws_getContext(width, height, cs->video_decoder_ctx->pix_fmt, width, height, PIX_FMT_YUV420P, - // SWS_BILINEAR, NULL, NULL, NULL); - } - uint8_t *rgb_image = malloc(width*height*3); - convert_to_rgb(image, rgb_image); - SDL_Surface* img_surface = SDL_CreateRGBSurfaceFrom(rgb_image, width, height, 24, width * 3, mask32(0), mask32(1), mask32(2), 0); - if(SDL_BlitSurface(img_surface, NULL, screen, NULL) == 0) - SDL_UpdateRect(screen, 0, 0, 0, 0); - /* - SDL_LockYUVOverlay(_phone->video_picture.bmp); - memcpy(_phone->video_picture.bmp->pixels[0], image->planes[VPX_PLANE_Y], _phone->video_picture.bmp->pitches[0] * height); - memcpy(_phone->video_picture.bmp->pixels[1], image->planes[VPX_PLANE_V], _phone->video_picture.bmp->pitches[1] * height / 2); - memcpy(_phone->video_picture.bmp->pixels[2], image->planes[VPX_PLANE_U], _phone->video_picture.bmp->pitches[2] * height / 2); - - SDL_Rect rect; - rect.x = 0; - rect.y = 0; - rect.w = width; - rect.h = height; - SDL_DisplayYUVOverlay(_phone->video_picture.bmp, &rect);*/ - free(rgb_image); - //display_received_frame(_phone, image); - - } //else { - /* TODO: request the sender to create a new i-frame immediatly */ - //printf("Bad video packet\n"); - //} + + /* Check if size has changed */ + if (image->d_w != width || image->d_h != height) { + + width = image->d_w; + height = image->d_h; + + printf("w: %d h: %d \n", width, height); + + screen = SDL_SetVideoMode(width, height, 0, 0); + + //if (_phone->video_picture.bmp) + // SDL_FreeYUVOverlay(_phone->video_picture.bmp); + + //_phone->video_picture.bmp = SDL_CreateYUVOverlay(width, height, SDL_YV12_OVERLAY, screen); + // _phone->sws_SDL_r_ctx = sws_getContext(width, height, cs->video_decoder_ctx->pix_fmt, width, height, PIX_FMT_YUV420P, + // SWS_BILINEAR, NULL, NULL, NULL); + } + + uint8_t *rgb_image = malloc(width * height * 3); + convert_to_rgb(image, rgb_image); + SDL_Surface *img_surface = SDL_CreateRGBSurfaceFrom(rgb_image, width, height, 24, width * 3, mask32(0), mask32(1), + mask32(2), 0); + + if (SDL_BlitSurface(img_surface, NULL, screen, NULL) == 0) + SDL_UpdateRect(screen, 0, 0, 0, 0); + + /* + SDL_LockYUVOverlay(_phone->video_picture.bmp); + memcpy(_phone->video_picture.bmp->pixels[0], image->planes[VPX_PLANE_Y], _phone->video_picture.bmp->pitches[0] * height); + memcpy(_phone->video_picture.bmp->pixels[1], image->planes[VPX_PLANE_V], _phone->video_picture.bmp->pitches[1] * height / 2); + memcpy(_phone->video_picture.bmp->pixels[2], image->planes[VPX_PLANE_U], _phone->video_picture.bmp->pitches[2] * height / 2); + + SDL_Rect rect; + rect.x = 0; + rect.y = 0; + rect.w = width; + rect.h = height; + SDL_DisplayYUVOverlay(_phone->video_picture.bmp, &rect);*/ + free(rgb_image); + //display_received_frame(_phone, image); + + } //else { + + /* TODO: request the sender to create a new i-frame immediatly */ + //printf("Bad video packet\n"); //} - + //} + usleep(1000); } - + /* clean up codecs */ //av_free(r_video_frame); - + //pthread_mutex_lock(&cs->ctrl_mutex); //avcodec_close(cs->video_decoder_ctx); //pthread_mutex_unlock(&cs->ctrl_mutex); - + _phone->running_decvid = -1; - + pthread_exit ( NULL ); } void *decode_audio_thread(void *arg) { INFO("Started decode audio thread!"); - av_session_t* _phone = arg; + av_session_t *_phone = arg; _phone->running_decaud = 1; - + //int recved_size; //uint8_t dest [RTP_PAYLOAD_SIZE]; - + int frame_size = AUDIO_FRAME_SIZE; //int data_size; - + ALCdevice *dev; ALCcontext *ctx; ALuint source, *buffers; @@ -613,72 +650,74 @@ void *decode_audio_thread(void *arg) ctx = alcCreateContext(dev, NULL); alcMakeContextCurrent(ctx); int openal_buffers = 5; - - buffers = calloc(sizeof(ALuint) * openal_buffers,1); + + buffers = calloc(sizeof(ALuint) * openal_buffers, 1); alGenBuffers(openal_buffers, buffers); alGenSources((ALuint)1, &source); alSourcei(source, AL_LOOPING, AL_FALSE); - + ALuint buffer; ALint ready; - + uint16_t zeros[frame_size]; memset(zeros, 0, frame_size); int16_t PCM[frame_size]; - + int i; + for (i = 0; i < openal_buffers; ++i) { alBufferData(buffers[i], AL_FORMAT_MONO16, zeros, frame_size, 48000); } - + alSourceQueueBuffers(source, openal_buffers, buffers); alSourcePlay(source); - + if (alGetError() != AL_NO_ERROR) { fprintf(stderr, "Error starting audio\n"); goto ending; } - - int dec_frame_len = 0; - + + int dec_frame_len = 0; + while (_phone->running_decaud) { - + alGetSourcei(source, AL_BUFFERS_PROCESSED, &ready); + if (ready <= 0) continue; - dec_frame_len = toxav_recv_audio(_phone->av, frame_size, PCM); + dec_frame_len = toxav_recv_audio(_phone->av, frame_size, PCM); /* Play the packet */ if (dec_frame_len > 0) { alSourceUnqueueBuffers(source, 1, &buffer); alBufferData(buffer, AL_FORMAT_MONO16, PCM, dec_frame_len * 2 * 1, 48000); int error = alGetError(); - + if (error != AL_NO_ERROR) { fprintf(stderr, "Error setting buffer %d\n", error); break; } - + alSourceQueueBuffers(source, 1, &buffer); - + if (alGetError() != AL_NO_ERROR) { fprintf(stderr, "Error: could not buffer audio\n"); break; } - + alGetSourcei(source, AL_SOURCE_STATE, &ready); - + if (ready != AL_PLAYING) alSourcePlay(source); - } - + } + usleep(1000); } - - + + ending: /* clean up codecs */ - //pthread_mutex_lock(&cs->ctrl_mutex); + //pthread_mutex_lock(&cs->ctrl_mutex); /* alDeleteSources(1, &source); alDeleteBuffers(openal_buffers, buffers); @@ -687,9 +726,9 @@ ending: alcCloseDevice(dev); */ //pthread_mutex_unlock(&cs->ctrl_mutex); - + _phone->running_decaud = -1; - + pthread_exit ( NULL ); } @@ -697,48 +736,47 @@ ending: -int phone_startmedia_loop ( ToxAv* arg ) +int phone_startmedia_loop ( ToxAv *arg ) { - if ( !arg ){ + if ( !arg ) { return -1; } - + toxav_prepare_transmission(arg); - - /* + + /* * Rise all threads */ #ifdef TOX_FFMPEG + /* Only checks for last peer */ - if ( toxav_get_peer_transmission_type(arg, 0) == TypeVideo && - 0 > event.rise(encode_video_thread, toxav_get_agent_handler(arg)) ) - { + if ( toxav_get_peer_transmission_type(arg, 0) == TypeVideo && + 0 > event.rise(encode_video_thread, toxav_get_agent_handler(arg)) ) { INFO("Error while starting encode_video_thread()"); return -1; } + #endif + /* Always send audio */ - if ( 0 > event.rise(encode_audio_thread, toxav_get_agent_handler(arg)) ) - { + if ( 0 > event.rise(encode_audio_thread, toxav_get_agent_handler(arg)) ) { INFO("Error while starting encode_audio_thread()"); return -1; } - + /* Only checks for last peer */ - if ( toxav_get_peer_transmission_type(arg, 0) == TypeVideo && - 0 > event.rise(decode_video_thread, toxav_get_agent_handler(arg)) ) - { + if ( toxav_get_peer_transmission_type(arg, 0) == TypeVideo && + 0 > event.rise(decode_video_thread, toxav_get_agent_handler(arg)) ) { INFO("Error while starting decode_video_thread()"); return -1; } - - if ( 0 > event.rise(decode_audio_thread, toxav_get_agent_handler(arg)) ) - { + + if ( 0 > event.rise(decode_audio_thread, toxav_get_agent_handler(arg)) ) { INFO("Error while starting decode_audio_thread()"); return -1; } - - + + return 0; } @@ -760,58 +798,60 @@ int phone_startmedia_loop ( ToxAv* arg ) /* Some example callbacks */ -void* callback_recv_invite ( void* _arg ) +void *callback_recv_invite ( void *_arg ) { assert(_arg); - - switch ( toxav_get_peer_transmission_type(_arg, 0) ){ - case TypeAudio: - INFO( "Incoming audio call!"); - break; - case TypeVideo: - INFO( "Incoming video call!"); - break; + + switch ( toxav_get_peer_transmission_type(_arg, 0) ) { + case TypeAudio: + INFO( "Incoming audio call!"); + break; + + case TypeVideo: + INFO( "Incoming video call!"); + break; } pthread_exit(NULL); } -void* callback_recv_ringing ( void* _arg ) +void *callback_recv_ringing ( void *_arg ) { INFO ( "Ringing!" ); pthread_exit(NULL); } -void* callback_recv_starting ( void* _arg ) +void *callback_recv_starting ( void *_arg ) { - if ( 0 != phone_startmedia_loop(_arg) ){ + if ( 0 != phone_startmedia_loop(_arg) ) { INFO("Starting call failed!"); } else { INFO ("Call started! ( press h to hangup )"); } + pthread_exit(NULL); } -void* callback_recv_ending ( void* _arg ) +void *callback_recv_ending ( void *_arg ) { - av_session_t* _phone = toxav_get_agent_handler(_arg); - + av_session_t *_phone = toxav_get_agent_handler(_arg); + _phone->running_encaud = 0; _phone->running_decaud = 0; _phone->running_encvid = 0; _phone->running_decvid = 0; - + /* Wait until all threads are done */ - - while ( _phone->running_encaud != -1 || + + while ( _phone->running_encaud != -1 || _phone->running_decaud != -1 || _phone->running_encvid != -1 || _phone->running_decvid != -1 ) - - usleep(10000000); - + + usleep(10000000); + INFO ( "Call ended!" ); pthread_exit(NULL); } -void* callback_recv_error ( void* _arg ) +void *callback_recv_error ( void *_arg ) { /*MSISession* _session = _arg; @@ -819,79 +859,79 @@ void* callback_recv_error ( void* _arg ) pthread_exit(NULL); } -void* callback_call_started ( void* _arg ) +void *callback_call_started ( void *_arg ) { - if ( 0 != phone_startmedia_loop(_arg) ){ + if ( 0 != phone_startmedia_loop(_arg) ) { INFO("Starting call failed!"); } else { INFO ("Call started! ( press h to hangup )"); } - + pthread_exit(NULL); } -void* callback_call_canceled ( void* _arg ) +void *callback_call_canceled ( void *_arg ) { INFO ( "Call canceled!" ); pthread_exit(NULL); } -void* callback_call_rejected ( void* _arg ) +void *callback_call_rejected ( void *_arg ) { INFO ( "Call rejected!" ); pthread_exit(NULL); } -void* callback_call_ended ( void* _arg ) +void *callback_call_ended ( void *_arg ) { - av_session_t* _phone = toxav_get_agent_handler(_arg); - + av_session_t *_phone = toxav_get_agent_handler(_arg); + _phone->running_encaud = 0; _phone->running_decaud = 0; _phone->running_encvid = 0; _phone->running_decvid = 0; - + /* Wait until all threads are done */ - - while ( _phone->running_encaud != -1 || + + while ( _phone->running_encaud != -1 || _phone->running_decaud != -1 || _phone->running_encvid != -1 || _phone->running_decvid != -1 ) - + usleep(10000000); - + toxav_kill_transmission(_phone->av); INFO ( "Call ended!" ); pthread_exit(NULL); } -void* callback_requ_timeout ( void* _arg ) +void *callback_requ_timeout ( void *_arg ) { INFO( "No answer! " ); pthread_exit(NULL); } -av_session_t* av_init_session() +av_session_t *av_init_session() { - av_session_t* _retu = malloc(sizeof(av_session_t)); - + av_session_t *_retu = malloc(sizeof(av_session_t)); + /* Initialize our mutex */ pthread_mutex_init ( &_retu->_mutex, NULL ); _retu->_messenger = tox_new(1); - + if ( !_retu->_messenger ) { fprintf ( stderr, "tox_new() failed!\n" ); return NULL; } _retu->_friends = NULL; - - + + const ALchar *_device_list = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER); int i = 0; const ALchar *device_names[20]; - + if ( _device_list ) { INFO("\nAvailable Capture Devices are:"); - + while (*_device_list ) { device_names[i] = _device_list; INFO("%d) %s", i, device_names[i]); @@ -899,32 +939,33 @@ av_session_t* av_init_session() ++i; } } - + INFO("Enter capture device number"); - - char dev[2]; char* left; - char* warned_ = fgets(dev, 2, stdin); + + char dev[2]; + char *left; + char *warned_ = fgets(dev, 2, stdin); (void)warned_; long selection = strtol(dev, &left, 10); - + if ( *left ) { printf("'%s' is not a number!", dev); fflush(stdout); exit(EXIT_FAILURE); - } - else { + } else { INFO("Selected: %d ( %s )", selection, device_names[selection]); } - - _retu->audio_capture_device = - (struct ALCdevice*)alcCaptureOpenDevice( + + _retu->audio_capture_device = + (struct ALCdevice *)alcCaptureOpenDevice( device_names[selection], AUDIO_SAMPLE_RATE, AL_FORMAT_MONO16, AUDIO_FRAME_SIZE * 4); - - - if (alcGetError((ALCdevice*)_retu->audio_capture_device) != AL_NO_ERROR) { - printf("Could not start capture device! %d\n", alcGetError((ALCdevice*)_retu->audio_capture_device)); + + + if (alcGetError((ALCdevice *)_retu->audio_capture_device) != AL_NO_ERROR) { + printf("Could not start capture device! %d\n", alcGetError((ALCdevice *)_retu->audio_capture_device)); return 0; } + uint16_t height = 0, width = 0; #ifdef TOX_FFMPEG avdevice_register_all(); @@ -932,6 +973,7 @@ av_session_t* av_init_session() av_register_all(); _retu->video_input_format = av_find_input_format(VIDEO_DRIVER); + if (avformat_open_input(&_retu->video_format_ctx, DEFAULT_WEBCAM, _retu->video_input_format, NULL) != 0) { fprintf(stderr, "Opening video_input_format failed!\n"); //return -1; @@ -968,51 +1010,53 @@ av_session_t* av_init_session() //return -1; return NULL; } + width = _retu->webcam_decoder_ctx->width; height = _retu->webcam_decoder_ctx->height; #endif uint8_t _byte_address[TOX_FRIEND_ADDRESS_SIZE]; tox_get_address(_retu->_messenger, _byte_address ); fraddr_to_str( _byte_address, _retu->_my_public_id ); - + _retu->av = toxav_new(_retu->_messenger, _retu, _USERAGENT, width, height); /* ------------------ */ - + toxav_register_callstate_callback(callback_call_started, OnStart); toxav_register_callstate_callback(callback_call_canceled, OnCancel); toxav_register_callstate_callback(callback_call_rejected, OnReject); toxav_register_callstate_callback(callback_call_ended, OnEnd); toxav_register_callstate_callback(callback_recv_invite, OnInvite); - + toxav_register_callstate_callback(callback_recv_ringing, OnRinging); toxav_register_callstate_callback(callback_recv_starting, OnStarting); toxav_register_callstate_callback(callback_recv_ending, OnEnding); - + toxav_register_callstate_callback(callback_recv_error, OnError); toxav_register_callstate_callback(callback_requ_timeout, OnRequestTimeout); - + /* ------------------ */ return _retu; } -int av_terminate_session(av_session_t* _phone) +int av_terminate_session(av_session_t *_phone) { toxav_hangup(_phone->av); - + free(_phone->_friends); pthread_mutex_destroy ( &_phone->_mutex ); - - Tox* _p = _phone->_messenger; - _phone->_messenger = NULL; usleep(100000); /* Wait for tox_poll to end */ - + + Tox *_p = _phone->_messenger; + _phone->_messenger = NULL; + usleep(100000); /* Wait for tox_poll to end */ + tox_kill(_p); toxav_kill(_phone->av); - + free(_phone); - + printf("\r[i] Quit!\n"); return 0; } @@ -1022,65 +1066,65 @@ int av_terminate_session(av_session_t* _phone) /* Auto accept friend request */ void av_friend_requ(uint8_t *_public_key, uint8_t *_data, uint16_t _length, void *_userdata) { - av_session_t* _phone = _userdata; + av_session_t *_phone = _userdata; av_allocate_friend (_phone, -1, 0); - + INFO("Got friend request with message: %s", _data); - + tox_add_friend_norequest(_phone->_messenger, _public_key); - + INFO("Auto-accepted! Friend id: %d", _phone->_friends->_id ); } void av_friend_active(Tox *_messenger, int _friendnumber, uint8_t *_string, uint16_t _length, void *_userdata) { - av_session_t* _phone = _userdata; + av_session_t *_phone = _userdata; INFO("Friend no. %d is online", _friendnumber); - - av_friend_t* _this_friend = av_get_friend(_phone, _friendnumber); - + + av_friend_t *_this_friend = av_get_friend(_phone, _friendnumber); + if ( !_this_friend ) { INFO("But it's not registered!"); return; } - + (*_this_friend)._active = 1; } -int av_add_friend(av_session_t* _phone, char* _friend_hash) -{ +int av_add_friend(av_session_t *_phone, char *_friend_hash) +{ trim_spaces(_friend_hash); - + unsigned char *_bin_string = hex_string_to_bin(_friend_hash); - int _number = tox_add_friend(_phone->_messenger, _bin_string, (uint8_t *)"Tox phone "_USERAGENT, sizeof("Tox phone "_USERAGENT)); + int _number = tox_add_friend(_phone->_messenger, _bin_string, (uint8_t *)"Tox phone "_USERAGENT, + sizeof("Tox phone "_USERAGENT)); free(_bin_string); - + if ( _number >= 0) { INFO("Added friend as %d", _number ); av_allocate_friend(_phone, _number, 0); - } - else + } else INFO("Unknown error %i", _number ); - + return _number; } -int av_connect_to_dht(av_session_t* _phone, char* _dht_key, const char* _dht_addr, unsigned short _dht_port) +int av_connect_to_dht(av_session_t *_phone, char *_dht_key, const char *_dht_addr, unsigned short _dht_port) { unsigned char *_binary_string = hex_string_to_bin(_dht_key); - + uint16_t _port = htons(_dht_port); - + int _if = tox_bootstrap_from_address(_phone->_messenger, _dht_addr, 1, _port, _binary_string ); - + free(_binary_string); - + return _if ? 0 : -1; } /*********************************/ -void do_phone ( av_session_t* _phone ) +void do_phone ( av_session_t *_phone ) { INFO("Welcome to tox_phone version: " _USERAGENT "\n" "Usage: \n" @@ -1091,218 +1135,218 @@ void do_phone ( av_session_t* _phone ) "r (reject incoming call)\n" "q (quit)\n" "================================================================================" - ); - - while ( 1 ) - { + ); + + while ( 1 ) { char _line [ 1500 ]; int _len; - - if ( -1 == getinput(_line, 1500, &_len) ){ - printf(" >> "); + + if ( -1 == getinput(_line, 1500, &_len) ) { + printf(" >> "); fflush(stdout); continue; } - - if ( _len > 1 && _line[1] != ' ' && _line[1] != '\n' ){ + + if ( _len > 1 && _line[1] != ' ' && _line[1] != '\n' ) { INFO("Invalid input!"); continue; } - switch (_line[0]){ + switch (_line[0]) { - case 'f': - { - char _id [128]; - strncpy(_id, _line + 2, 128); - - av_add_friend(_phone, _id); - - } break; - case 'c': - { - ToxAvCallType _ctype; - - if ( _len < 5 ){ - INFO("Invalid input; usage: c a/v [friend]"); - break; - } - else if ( _line[2] == 'a' || _line[2] != 'v' ){ /* default and audio */ - _ctype = TypeAudio; - } - else { /* video */ - _ctype = TypeVideo; - } - - char* _end; - int _friend = strtol(_line + 4, &_end, 10); - - if ( *_end ){ - INFO("Friend num has to be numerical value"); - break; - } - - if ( toxav_call(_phone->av, _friend, _ctype, 30) == ErrorAlreadyInCall ){ - INFO("Already in a call"); - break; - } - else INFO("Calling friend: %d!", _friend); + case 'f': { + char _id [128]; + strncpy(_id, _line + 2, 128); - } break; - case 'h': - { - if ( toxav_hangup(_phone->av) == ErrorNoCall ) { - INFO("No call!"); - break; - } - else INFO("Hung up..."); + av_add_friend(_phone, _id); - } break; - case 'a': - { - ToxAvError rc; - - if ( _len > 1 && _line[2] == 'v' ) { - rc = toxav_answer(_phone->av, TypeVideo); - } else - rc = toxav_answer(_phone->av, TypeAudio); - - if ( rc == ErrorInvalidState ) { - INFO("No call to answer!"); + } + break; + + case 'c': { + ToxAvCallType _ctype; + + if ( _len < 5 ) { + INFO("Invalid input; usage: c a/v [friend]"); + break; + } else if ( _line[2] == 'a' || _line[2] != 'v' ) { /* default and audio */ + _ctype = TypeAudio; + } else { /* video */ + _ctype = TypeVideo; + } + + char *_end; + int _friend = strtol(_line + 4, &_end, 10); + + if ( *_end ) { + INFO("Friend num has to be numerical value"); + break; + } + + if ( toxav_call(_phone->av, _friend, _ctype, 30) == ErrorAlreadyInCall ) { + INFO("Already in a call"); + break; + } else INFO("Calling friend: %d!", _friend); + + } + break; + + case 'h': { + if ( toxav_hangup(_phone->av) == ErrorNoCall ) { + INFO("No call!"); + break; + } else INFO("Hung up..."); + + } + break; + + case 'a': { + ToxAvError rc; + + if ( _len > 1 && _line[2] == 'v' ) { + rc = toxav_answer(_phone->av, TypeVideo); + } else + rc = toxav_answer(_phone->av, TypeAudio); + + if ( rc == ErrorInvalidState ) { + INFO("No call to answer!"); + } + + } + break; + + case 'r': { + if ( toxav_reject(_phone->av, "User action") == ErrorInvalidState ) + INFO("No state to cancel!"); + else INFO("Call Rejected..."); + + } + break; + + case 'q': { + INFO("Quitting!"); + return; } - } break; - case 'r': - { - if ( toxav_reject(_phone->av, "User action") == ErrorInvalidState ) - INFO("No state to cancel!"); - else INFO("Call Rejected..."); + case '\n': { + } - } break; - case 'q': - { - INFO("Quitting!"); - return; - } - case '\n': - { - } - default: - { - } break; + default: { + } break; } } } -void* tox_poll (void* _messenger_p) +void *tox_poll (void *_messenger_p) { - Tox** _messenger = _messenger_p; - while( *_messenger ) { - tox_do(*_messenger); + Tox **_messenger = _messenger_p; + + while ( *_messenger ) { + tox_do(*_messenger); usleep(10000); } - + pthread_exit(NULL); } -int av_wait_dht(av_session_t* _phone, int _wait_seconds, const char* _ip, char* _key, unsigned short _port) +int av_wait_dht(av_session_t *_phone, int _wait_seconds, const char *_ip, char *_key, unsigned short _port) { if ( !_wait_seconds ) return -1; - + int _waited = 0; - - while( !tox_isconnected(_phone->_messenger) ) { - - if ( -1 == av_connect_to_dht(_phone, _key, _ip, _port) ) - { + + while ( !tox_isconnected(_phone->_messenger) ) { + + if ( -1 == av_connect_to_dht(_phone, _key, _ip, _port) ) { INFO("Could not connect to: %s", _ip); av_terminate_session(_phone); return -1; } - + if ( _waited >= _wait_seconds ) return 0; - + printf("."); fflush(stdout); - + _waited ++; usleep(1000000); } - + int _r = _wait_seconds - _waited; return _r ? _r : 1; } /* ---------------------- */ -int print_help ( const char* _name ) +int print_help ( const char *_name ) { - printf ( "Usage: %s [IP] [PORT] [KEY]\n" - "\t[IP] (DHT ip)\n" - "\t[PORT] (DHT port)\n" - "\t[KEY] (DHT public key)\n" - "P.S. Friends and key are stored in ./tox_phone.conf\n" - ,_name ); + printf ( "Usage: %s [IP] [PORT] [KEY]\n" + "\t[IP] (DHT ip)\n" + "\t[PORT] (DHT port)\n" + "\t[KEY] (DHT public key)\n" + "P.S. Friends and key are stored in ./tox_phone.conf\n" + , _name ); return 1; } -int main ( int argc, char* argv [] ) +int main ( int argc, char *argv [] ) { if ( argc < 1 || argc < 4 ) - return print_help(argv[0]); - - char* _convertable; - - - const char* _ip = argv[1]; - char* _key = argv[3]; + return print_help(argv[0]); + + char *_convertable; + + + const char *_ip = argv[1]; + char *_key = argv[3]; unsigned short _port = strtol(argv[2], &_convertable, 10); - + if ( *_convertable ) { - printf("Invalid port: cannot convert string to long: %s", _convertable); - return 1; + printf("Invalid port: cannot convert string to long: %s", _convertable); + return 1; } - - av_session_t* _phone = av_init_session(); - + + av_session_t *_phone = av_init_session(); + tox_callback_friend_request(_phone->_messenger, av_friend_requ, _phone); tox_callback_status_message(_phone->_messenger, av_friend_active, _phone); - + INFO("\r================================================================================\n" "[!] Trying dht@%s:%d" , _ip, _port); - + /* Start tox protocol */ event.rise( tox_poll, &_phone->_messenger ); - + /* Just clean one line */ printf("\r \r"); fflush(stdout); - + int _r; int _wait_seconds = 5; + for ( _r = 0; _r == 0; _r = av_wait_dht(_phone, _wait_seconds, _ip, _key, _port) ) _wait_seconds --; - - + + if ( -1 == _r ) { INFO("Error while connecting to dht: %s:%d", _ip, _port); av_terminate_session(_phone); return 1; } - + INFO("CONNECTED!\n" "================================================================================\n" "%s\n" "================================================================================" , _phone->_my_public_id ); - + do_phone (_phone); - + av_terminate_session(_phone); - + return 0; } diff --git a/toxav/rtp.c b/toxav/rtp.c index 2543c509..dbaecbb6 100644 --- a/toxav/rtp.c +++ b/toxav/rtp.c @@ -1,5 +1,5 @@ /** toxrtp.c - * + * * Copyright (C) 2013 Tox project All Rights Reserved. * * This file is part of Tox. @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with Tox. If not, see . * - * + * * Report bugs/suggestions at #tox-dev @ freenode.net:6667 */ @@ -55,56 +55,56 @@ /** * @brief Converts 4 bytes to uint32_t - * + * * @param dest Where to convert * @param bytes What bytes * @return void */ -inline__ void bytes_to_U32(uint32_t* dest, const uint8_t* bytes) +inline__ void bytes_to_U32(uint32_t *dest, const uint8_t *bytes) { - *dest = -#ifdef WORDS_BIGENDIAN - ( ( uint32_t ) * bytes ) | - ( ( uint32_t ) * ( bytes + 1 ) << 8 ) | - ( ( uint32_t ) * ( bytes + 2 ) << 16 ) | - ( ( uint32_t ) * ( bytes + 3 ) << 24 ) ; + *dest = +#ifdef WORDS_BIGENDIAN + ( ( uint32_t ) * bytes ) | + ( ( uint32_t ) * ( bytes + 1 ) << 8 ) | + ( ( uint32_t ) * ( bytes + 2 ) << 16 ) | + ( ( uint32_t ) * ( bytes + 3 ) << 24 ) ; #else - ( ( uint32_t ) * bytes << 24 ) | - ( ( uint32_t ) * ( bytes + 1 ) << 16 ) | - ( ( uint32_t ) * ( bytes + 2 ) << 8 ) | - ( ( uint32_t ) * ( bytes + 3 ) ) ; -#endif + ( ( uint32_t ) * bytes << 24 ) | + ( ( uint32_t ) * ( bytes + 1 ) << 16 ) | + ( ( uint32_t ) * ( bytes + 2 ) << 8 ) | + ( ( uint32_t ) * ( bytes + 3 ) ) ; +#endif } /** * @brief Converts 2 bytes to uint16_t - * + * * @param dest Where to convert * @param bytes What bytes * @return void */ -inline__ void bytes_to_U16(uint16_t* dest, const uint8_t* bytes) -{ - *dest = -#ifdef WORDS_BIGENDIAN - ( ( uint16_t ) * bytes ) | - ( ( uint16_t ) * ( bytes + 1 ) << 8 ); +inline__ void bytes_to_U16(uint16_t *dest, const uint8_t *bytes) +{ + *dest = +#ifdef WORDS_BIGENDIAN + ( ( uint16_t ) * bytes ) | + ( ( uint16_t ) * ( bytes + 1 ) << 8 ); #else - ( ( uint16_t ) * bytes << 8 ) | - ( ( uint16_t ) * ( bytes + 1 ) ); -#endif + ( ( uint16_t ) * bytes << 8 ) | + ( ( uint16_t ) * ( bytes + 1 ) ); +#endif } /** * @brief Convert uint32_t to byte string of size 4 - * + * * @param dest Where to convert * @param value The value * @return void */ -inline__ void U32_to_bytes(uint8_t* dest, uint32_t value) -{ -#ifdef WORDS_BIGENDIAN +inline__ void U32_to_bytes(uint8_t *dest, uint32_t value) +{ +#ifdef WORDS_BIGENDIAN *(dest) = ( value ); *(dest + 1) = ( value >> 8 ); *(dest + 2) = ( value >> 16 ); @@ -114,43 +114,43 @@ inline__ void U32_to_bytes(uint8_t* dest, uint32_t value) *(dest + 1) = ( value >> 16 ); *(dest + 2) = ( value >> 8 ); *(dest + 3) = ( value ); -#endif +#endif } /** * @brief Convert uint16_t to byte string of size 2 - * + * * @param dest Where to convert * @param value The value * @return void */ -inline__ void U16_to_bytes(uint8_t* dest, uint16_t value) +inline__ void U16_to_bytes(uint8_t *dest, uint16_t value) { -#ifdef WORDS_BIGENDIAN +#ifdef WORDS_BIGENDIAN *(dest) = ( value ); *(dest + 1) = ( value >> 8 ); #else *(dest) = ( value >> 8 ); *(dest + 1) = ( value ); -#endif +#endif } /** * @brief Checks if message came in late. - * + * * @param session Control session. * @param msg The message. * @return int * @retval -1 The message came in order. * @retval 0 The message came late. */ -inline__ int check_late_message (RTPSession* session, RTPMessage* msg) +inline__ int check_late_message (RTPSession *session, RTPMessage *msg) { /* * Check Sequence number. If this new msg has lesser number then the session->rsequnum * it shows that the message came in late. Also check timestamp to be 100% certain. - * + * */ return ( msg->header->sequnum < session->rsequnum && msg->header->timestamp < session->timestamp ) ? 0 : -1; } @@ -158,12 +158,12 @@ inline__ int check_late_message (RTPSession* session, RTPMessage* msg) /** * @brief Increases nonce value by 'target' - * + * * @param nonce The nonce * @param target The target * @return void */ -inline__ void increase_nonce(uint8_t* nonce, uint16_t target) +inline__ void increase_nonce(uint8_t *nonce, uint16_t target) { uint16_t _nonce_counter; @@ -176,29 +176,29 @@ inline__ void increase_nonce(uint8_t* nonce, uint16_t target) /* Check overflow */ if (_nonce_counter > UINT16_MAX - target ) { /* 2 bytes are not long enough */ uint8_t _it = 3; + while ( _it <= crypto_box_NONCEBYTES ) _it += ++nonce[crypto_box_NONCEBYTES - _it] ? crypto_box_NONCEBYTES : 1; - + _nonce_counter = _nonce_counter - (UINT16_MAX - target ); /* Assign the rest of it */ } else { /* Increase nonce */ - - _nonce_counter+= target; + + _nonce_counter += target; } - + /* Assign the last bytes */ - + U16_to_bytes( _reverse_bytes, _nonce_counter); nonce [crypto_box_NONCEBYTES - 1] = _reverse_bytes[0]; nonce [crypto_box_NONCEBYTES - 2] = _reverse_bytes[1]; - + } /** * @brief Speaks for it self. - * + * */ -static const uint32_t payload_table[] = -{ +static const uint32_t payload_table[] = { 8000, 8000, 8000, 8000, 8000, 8000, 16000, 8000, 8000, 8000, /* 0-9 */ 44100, 44100, 0, 0, 90000, 8000, 11025, 22050, 0, 0, /* 10-19 */ 0, 0, 0, 0, 0, 90000, 90000, 0, 90000, 0, /* 20-29 */ @@ -217,208 +217,227 @@ static const uint32_t payload_table[] = /** * @brief Extracts header from payload. - * + * * @param payload The payload. * @param length The size of payload. * @return RTPHeader* Extracted header. * @retval NULL Error occurred while extracting header. */ -RTPHeader* extract_header ( const uint8_t* payload, int length ) +RTPHeader *extract_header ( const uint8_t *payload, int length ) { if ( !payload || !length ) { return NULL; } - - const uint8_t* _it = payload; - - RTPHeader* _retu = calloc(1, sizeof (RTPHeader)); + + const uint8_t *_it = payload; + + RTPHeader *_retu = calloc(1, sizeof (RTPHeader)); assert(_retu); - - _retu->flags = *_it; ++_it; - + + _retu->flags = *_it; + ++_it; + /* This indicates if the first 2 bits are valid. * Now it may happen that this is out of order but * it cuts down chances of parsing some invalid value */ - - if ( GET_FLAG_VERSION(_retu) != RTP_VERSION ){ + + if ( GET_FLAG_VERSION(_retu) != RTP_VERSION ) { /* Deallocate */ free(_retu); return NULL; } - + /* * Added a check for the size of the header little sooner so * I don't need to parse the other stuff if it's bad */ - uint8_t _cc = GET_FLAG_CSRCC ( _retu ); + uint8_t _cc = GET_FLAG_CSRCC ( _retu ); uint32_t _length = 12 /* Minimum header len */ + ( _cc * 4 ); - + if ( length < _length ) { /* Deallocate */ free(_retu); return NULL; } - + if ( _cc > 0 ) { _retu->csrc = calloc (_cc, sizeof (uint32_t)); assert(_retu->csrc); - + } else { /* But this should not happen ever */ /* Deallocate */ free(_retu); return NULL; } - - - _retu->marker_payloadt = *_it; ++_it; + + + _retu->marker_payloadt = *_it; + ++_it; _retu->length = _length; - - - bytes_to_U32(&_retu->timestamp, _it); _it += 4; + + + bytes_to_U32(&_retu->timestamp, _it); + _it += 4; bytes_to_U32(&_retu->ssrc, _it); - + uint8_t _x; + for ( _x = 0; _x < _cc; _x++ ) { - _it += 4; bytes_to_U32(&(_retu->csrc[_x]), _it); + _it += 4; + bytes_to_U32(&(_retu->csrc[_x]), _it); } - + return _retu; } /** * @brief Extracts external header from payload. Must be called AFTER extract_header()! - * + * * @param payload The ITERATED payload. * @param length The size of payload. * @return RTPExtHeader* Extracted extension header. * @retval NULL Error occurred while extracting extension header. */ -RTPExtHeader* extract_ext_header ( const uint8_t* payload, uint16_t length ) +RTPExtHeader *extract_ext_header ( const uint8_t *payload, uint16_t length ) { - const uint8_t* _it = payload; - - RTPExtHeader* _retu = calloc(1, sizeof (RTPExtHeader)); + const uint8_t *_it = payload; + + RTPExtHeader *_retu = calloc(1, sizeof (RTPExtHeader)); assert(_retu); - - uint16_t _ext_length; - bytes_to_U16(&_ext_length, _it); _it += 2; - - + + uint16_t _ext_length; + bytes_to_U16(&_ext_length, _it); + _it += 2; + + if ( length < ( _ext_length * sizeof(uint32_t) ) ) { free(_retu); return NULL; } - + _retu->length = _ext_length; - bytes_to_U16(&_retu->type, _it); _it += 2; - + bytes_to_U16(&_retu->type, _it); + _it += 2; + _retu->table = calloc(_ext_length, sizeof (uint32_t)); assert(_retu->table); - + uint16_t _x; + for ( _x = 0; _x < _ext_length; _x++ ) { - _it += 4; bytes_to_U32(&(_retu->table[_x]), _it); + _it += 4; + bytes_to_U32(&(_retu->table[_x]), _it); } - + return _retu; } /** * @brief Adds header to payload. Make sure _payload_ has enough space. - * + * * @param header The header. * @param payload The payload. * @return uint8_t* Iterated position. */ -uint8_t* add_header ( RTPHeader* header, uint8_t* payload ) +uint8_t *add_header ( RTPHeader *header, uint8_t *payload ) { uint8_t _cc = GET_FLAG_CSRCC ( header ); - - uint8_t* _it = payload; - - + + uint8_t *_it = payload; + + /* Add sequence number first */ - U16_to_bytes(_it, header->sequnum); _it += 2; - - *_it = header->flags; ++_it; - *_it = header->marker_payloadt; ++_it; - - - U32_to_bytes( _it, header->timestamp); _it+=4; + U16_to_bytes(_it, header->sequnum); + _it += 2; + + *_it = header->flags; + ++_it; + *_it = header->marker_payloadt; + ++_it; + + + U32_to_bytes( _it, header->timestamp); + _it += 4; U32_to_bytes( _it, header->ssrc); - + if ( header->csrc ) { uint8_t _x; + for ( _x = 0; _x < _cc; _x++ ) { - _it+=4; U32_to_bytes( _it, header->csrc[_x]); + _it += 4; + U32_to_bytes( _it, header->csrc[_x]); } } - + return _it + 4; } /** * @brief Adds extension header to payload. Make sure _payload_ has enough space. - * + * * @param header The header. * @param payload The payload. * @return uint8_t* Iterated position. */ -uint8_t* add_ext_header ( RTPExtHeader* header, uint8_t* payload ) +uint8_t *add_ext_header ( RTPExtHeader *header, uint8_t *payload ) { - uint8_t* _it = payload; - - U16_to_bytes(_it, header->length); _it+=2; - U16_to_bytes(_it, header->type); _it-=2; /* Return to 0 position */ - + uint8_t *_it = payload; + + U16_to_bytes(_it, header->length); + _it += 2; + U16_to_bytes(_it, header->type); + _it -= 2; /* Return to 0 position */ + if ( header->table ) { uint16_t _x; + for ( _x = 0; _x < header->length; _x++ ) { - _it+=4; U32_to_bytes(_it, header->table[_x]); + _it += 4; + U32_to_bytes(_it, header->table[_x]); } } - + return _it + 4; } /** * @brief Builds header from control session values. - * + * * @param session Control session. * @return RTPHeader* Created header. */ -RTPHeader* build_header ( RTPSession* session ) +RTPHeader *build_header ( RTPSession *session ) { - RTPHeader* _retu = calloc ( 1, sizeof (RTPHeader) ); + RTPHeader *_retu = calloc ( 1, sizeof (RTPHeader) ); assert(_retu); - + ADD_FLAG_VERSION ( _retu, session->version ); ADD_FLAG_PADDING ( _retu, session->padding ); ADD_FLAG_EXTENSION ( _retu, session->extension ); ADD_FLAG_CSRCC ( _retu, session->cc ); ADD_SETTING_MARKER ( _retu, session->marker ); ADD_SETTING_PAYLOAD ( _retu, session->payload_type ); - + _retu->sequnum = session->sequnum; _retu->timestamp = ((uint32_t)(current_time() / 1000)); /* micro to milli */ _retu->ssrc = session->ssrc; - + if ( session->cc > 0 ) { _retu->csrc = calloc(session->cc, sizeof (uint32_t)); assert(_retu->csrc); - + int i; - + for ( i = 0; i < session->cc; i++ ) { _retu->csrc[i] = session->csrc[i]; } } else { _retu->csrc = NULL; } - + _retu->length = 12 /* Minimum header len */ + ( session->cc * size_32 ); - + return _retu; } @@ -427,7 +446,7 @@ RTPHeader* build_header ( RTPSession* session ) * @brief Parses data into RTPMessage struct. Stores headers separately from the payload data * and so the length variable is set accordingly. _sequnum_ argument is * passed by the handle_packet() since it's parsed already. - * + * * @param session Control session. * @param sequnum Sequence number that's parsed from payload in handle_packet() * @param data Payload data. @@ -435,26 +454,28 @@ RTPHeader* build_header ( RTPSession* session ) * @return RTPMessage* * @retval NULL Error occurred. */ -RTPMessage* msg_parse ( uint16_t sequnum, const uint8_t* data, int length ) -{ - RTPMessage* _retu = calloc(1, sizeof (RTPMessage)); - +RTPMessage *msg_parse ( uint16_t sequnum, const uint8_t *data, int length ) +{ + RTPMessage *_retu = calloc(1, sizeof (RTPMessage)); + _retu->header = extract_header ( data, length ); /* It allocates memory and all */ - - if ( !_retu->header ){ + + if ( !_retu->header ) { free(_retu); return NULL; } + _retu->header->sequnum = sequnum; - + _retu->length = length - _retu->header->length; - + uint16_t _from_pos = _retu->header->length - 2 /* Since sequ num is excluded */ ; - - + + if ( GET_FLAG_EXTENSION ( _retu->header ) ) { _retu->ext_header = extract_ext_header ( data + _from_pos, length ); - if ( _retu->ext_header ){ + + if ( _retu->ext_header ) { _retu->length -= ( 4 /* Minimum ext header len */ + _retu->ext_header->length * size_32 ); _from_pos += ( 4 /* Minimum ext header len */ + _retu->ext_header->length * size_32 ); } else { /* Error */ @@ -473,14 +494,15 @@ RTPMessage* msg_parse ( uint16_t sequnum, const uint8_t* data, int length ) rtp_free_msg(NULL, _retu); return NULL; } + _retu->next = NULL; - + return _retu; } /** * @brief Callback for networking core. - * + * * @param object RTPSession object. * @param ip_port Where the message comes from. * @param data Message data. @@ -489,82 +511,82 @@ RTPMessage* msg_parse ( uint16_t sequnum, const uint8_t* data, int length ) * @retval -1 Error occurred. * @retval 0 Success. */ -int rtp_handle_packet ( void* object, IP_Port ip_port, uint8_t* data, uint32_t length ) +int rtp_handle_packet ( void *object, IP_Port ip_port, uint8_t *data, uint32_t length ) { - RTPSession* _session = object; - RTPMessage* _msg; - + RTPSession *_session = object; + RTPMessage *_msg; + if ( !_session || length < 13 ) /* 12 is the minimum length for rtp + desc. byte */ return -1; - + uint8_t _plain[MAX_UDP_PACKET_SIZE]; - + uint16_t _sequnum; bytes_to_U16(&_sequnum, data + 1); - + /* Clculate the right nonce */ uint8_t _calculated[crypto_box_NONCEBYTES]; memcpy(_calculated, _session->decrypt_nonce, crypto_box_NONCEBYTES); increase_nonce ( _calculated, _sequnum ); - + /* Decrypt message */ int _decrypted_length = decrypt_data_symmetric( - (uint8_t*)_session->decrypt_key, _calculated, data + 3, length - 3, _plain ); - - /* This packet is either not encrypted properly or late + (uint8_t *)_session->decrypt_key, _calculated, data + 3, length - 3, _plain ); + + /* This packet is either not encrypted properly or late */ - if ( -1 == _decrypted_length ){ - - /* If this is the case, then the packet is most likely late. + if ( -1 == _decrypted_length ) { + + /* If this is the case, then the packet is most likely late. * Try with old nonce cycle. */ if ( _session->rsequnum < _sequnum ) { _decrypted_length = decrypt_data_symmetric( - (uint8_t*)_session->decrypt_key, _session->nonce_cycle, data + 3, length - 3, _plain ); - + (uint8_t *)_session->decrypt_key, _session->nonce_cycle, data + 3, length - 3, _plain ); + if ( !_decrypted_length ) return -1; /* This packet is not encrypted properly */ - - /* Otherwise, if decryption is ok with new cycle, set new cycle - */ - } else { + + /* Otherwise, if decryption is ok with new cycle, set new cycle + */ + } else { increase_nonce ( _calculated, MAX_SEQU_NUM ); _decrypted_length = decrypt_data_symmetric( - (uint8_t*)_session->decrypt_key, _calculated, data + 3, length - 3, _plain ); - + (uint8_t *)_session->decrypt_key, _calculated, data + 3, length - 3, _plain ); + if ( !_decrypted_length ) return -1; /* This is just an error */ - + /* A new cycle setting. */ memcpy(_session->nonce_cycle, _session->decrypt_nonce, crypto_box_NONCEBYTES); memcpy(_session->decrypt_nonce, _calculated, crypto_box_NONCEBYTES); } } - + _msg = msg_parse ( _sequnum, _plain, _decrypted_length ); - + if ( !_msg ) return -1; - - /* Hopefully this goes well + + /* Hopefully this goes well * NOTE: Is this even used? */ memcpy(&_msg->from, &ip_port, sizeof(IP_Port)); - + /* Check if message came in late */ if ( check_late_message(_session, _msg) < 0 ) { /* Not late */ _session->rsequnum = _msg->header->sequnum; _session->timestamp = _msg->header->timestamp; } - + pthread_mutex_lock(&_session->mutex); - + if ( _session->last_msg ) { _session->last_msg->next = _msg; _session->last_msg = _msg; } else { _session->last_msg = _session->oldest_msg = _msg; } - + pthread_mutex_unlock(&_session->mutex); - + return 0; } @@ -573,50 +595,50 @@ int rtp_handle_packet ( void* object, IP_Port ip_port, uint8_t* data, uint32_t l /** * @brief Stores headers and payload data in one container ( data ) * and the length is set accordingly. Returned message is used for sending _only_. - * + * * @param session The control session. * @param data Payload data to send ( This is what you pass ). * @param length Size of the payload data. * @return RTPMessage* Created message. * @retval NULL Error occurred. */ -RTPMessage* rtp_new_message ( RTPSession* session, const uint8_t* data, uint32_t length ) +RTPMessage *rtp_new_message ( RTPSession *session, const uint8_t *data, uint32_t length ) { if ( !session ) return NULL; - - uint8_t* _from_pos; - RTPMessage* _retu = calloc(1, sizeof (RTPMessage)); + + uint8_t *_from_pos; + RTPMessage *_retu = calloc(1, sizeof (RTPMessage)); assert(_retu); - + /* Sets header values and copies the extension header in _retu */ _retu->header = build_header ( session ); /* It allocates memory and all */ _retu->ext_header = session->ext_header; - - + + uint32_t _total_length = length + _retu->header->length; - + if ( _retu->ext_header ) { _total_length += ( 4 /* Minimum ext header len */ + _retu->ext_header->length * size_32 ); - + _from_pos = add_header ( _retu->header, _retu->data ); _from_pos = add_ext_header ( _retu->ext_header, _from_pos + 1 ); } else { _from_pos = add_header ( _retu->header, _retu->data ); } - + /* * Parses the extension header into the message * Of course if any */ - + /* Appends _data on to _retu->_data */ memcpy ( _from_pos, data, length ); - + _retu->length = _total_length; - + _retu->next = NULL; - + return _retu; } @@ -626,18 +648,18 @@ RTPMessage* rtp_new_message ( RTPSession* session, const uint8_t* data, uint32_t -/******************************************************************************************************************** +/******************************************************************************************************************** ******************************************************************************************************************** ******************************************************************************************************************** ******************************************************************************************************************** ******************************************************************************************************************** - * - * - * + * + * + * * PUBLIC API FUNCTIONS IMPLEMENTATIONS - * - * - * + * + * + * ******************************************************************************************************************** ******************************************************************************************************************** ******************************************************************************************************************** @@ -654,66 +676,66 @@ RTPMessage* rtp_new_message ( RTPSession* session, const uint8_t* data, uint32_t /** * @brief Release all messages held by session. - * + * * @param session The session. * @return int * @retval -1 Error occurred. * @retval 0 Success. */ -int rtp_release_session_recv ( RTPSession* session ) +int rtp_release_session_recv ( RTPSession *session ) { - if ( !session ){ + if ( !session ) { return -1; } - - RTPMessage* _tmp,* _it; - + + RTPMessage *_tmp, * _it; + pthread_mutex_lock(&session->mutex); - - for ( _it = session->oldest_msg; _it; _it = _tmp ){ + + for ( _it = session->oldest_msg; _it; _it = _tmp ) { _tmp = _it->next; rtp_free_msg( session, _it); } - + session->last_msg = session->oldest_msg = NULL; - + pthread_mutex_unlock(&session->mutex); - + return 0; } /** * @brief Gets oldest message in the list. - * + * * @param session Where the list is. * @return RTPMessage* The message. You _must_ call rtp_msg_free() to free it. * @retval NULL No messages in the list, or no list. */ -RTPMessage* rtp_recv_msg ( RTPSession* session ) +RTPMessage *rtp_recv_msg ( RTPSession *session ) { if ( !session ) return NULL; - - RTPMessage* _retu = session->oldest_msg; - + + RTPMessage *_retu = session->oldest_msg; + pthread_mutex_lock(&session->mutex); - + if ( _retu ) session->oldest_msg = _retu->next; - + if ( !session->oldest_msg ) session->last_msg = NULL; - + pthread_mutex_unlock(&session->mutex); - + return _retu; } /** * @brief Sends data to _RTPSession::dest - * + * * @param session The session. * @param messenger Tox* object. * @param data The payload. @@ -722,38 +744,38 @@ RTPMessage* rtp_recv_msg ( RTPSession* session ) * @retval -1 On error. * @retval 0 On success. */ -int rtp_send_msg ( RTPSession* session, Messenger* messenger, const uint8_t* data, uint16_t length ) +int rtp_send_msg ( RTPSession *session, Messenger *messenger, const uint8_t *data, uint16_t length ) { - RTPMessage* msg = rtp_new_message (session, data, length); - - if ( !msg ) return -1; - + RTPMessage *msg = rtp_new_message (session, data, length); + + if ( !msg ) return -1; + uint8_t _send_data [ MAX_UDP_PACKET_SIZE ]; - + _send_data[0] = session->prefix; - + /* Generate the right nonce */ uint8_t _calculated[crypto_box_NONCEBYTES]; memcpy(_calculated, session->encrypt_nonce, crypto_box_NONCEBYTES); increase_nonce ( _calculated, msg->header->sequnum ); - + /* Need to skip 2 bytes that are for sequnum */ int encrypted_length = encrypt_data_symmetric( /* TODO: msg->length - 2 (fix this properly)*/ - (uint8_t*) session->encrypt_key, _calculated, msg->data + 2, msg->length, _send_data + 3 ); - + (uint8_t *) session->encrypt_key, _calculated, msg->data + 2, msg->length, _send_data + 3 ); + int full_length = encrypted_length + 3; - + _send_data[1] = msg->data[0]; _send_data[2] = msg->data[1]; - - + + /*if ( full_length != sendpacket ( messenger->net, *((IP_Port*) &session->dest), _send_data, full_length) ) {*/ if ( full_length != send_custom_user_packet(messenger, session->dest, _send_data, full_length) ) { printf("Rtp error: %s\n", strerror(errno)); return -1; } - - + + /* Set sequ number */ if ( session->sequnum >= MAX_SEQU_NUM ) { session->sequnum = 0; @@ -761,7 +783,7 @@ int rtp_send_msg ( RTPSession* session, Messenger* messenger, const uint8_t* dat } else { session->sequnum++; } - + rtp_free_msg ( session, msg ); return 0; } @@ -769,29 +791,31 @@ int rtp_send_msg ( RTPSession* session, Messenger* messenger, const uint8_t* dat /** * @brief Speaks for it self. - * + * * @param session The control session msg belongs to. You set it as NULL when freeing recved messages. * Otherwise set it to session the message was created from. * @param msg The message. * @return void */ -void rtp_free_msg ( RTPSession* session, RTPMessage* msg ) +void rtp_free_msg ( RTPSession *session, RTPMessage *msg ) { - if ( !session ){ + if ( !session ) { free ( msg->header->csrc ); - if ( msg->ext_header ){ + + if ( msg->ext_header ) { free ( msg->ext_header->table ); free ( msg->ext_header ); } } else { if ( session->csrc != msg->header->csrc ) free ( msg->header->csrc ); + if ( msg->ext_header && session->ext_header != msg->ext_header ) { free ( msg->ext_header->table ); free ( msg->ext_header ); } } - + free ( msg->header ); free ( msg ); } @@ -800,7 +824,7 @@ void rtp_free_msg ( RTPSession* session, RTPMessage* msg ) /** * @brief Must be called before calling any other rtp function. It's used * to initialize RTP control session. - * + * * @param payload_type Type of payload used to send. You can use values in toxmsi.h::MSICallType * @param messenger Tox* object. * @param friend_num Friend id. @@ -811,25 +835,24 @@ void rtp_free_msg ( RTPSession* session, RTPMessage* msg ) * @return RTPSession* Created control session. * @retval NULL Error occurred. */ -RTPSession* rtp_init_session ( int payload_type, - Messenger* messenger, - int friend_num, - const uint8_t* encrypt_key, - const uint8_t* decrypt_key, - const uint8_t* encrypt_nonce, - const uint8_t* decrypt_nonce ) -{ - RTPSession* _retu = calloc(1, sizeof(RTPSession)); +RTPSession *rtp_init_session ( int payload_type, + Messenger *messenger, + int friend_num, + const uint8_t *encrypt_key, + const uint8_t *decrypt_key, + const uint8_t *encrypt_nonce, + const uint8_t *decrypt_nonce ) +{ + RTPSession *_retu = calloc(1, sizeof(RTPSession)); assert(_retu); - + /*networking_registerhandler(messenger->net, payload_type, rtp_handle_packet, _retu);*/ - if ( -1 == custom_user_packet_registerhandler(messenger, friend_num, payload_type, rtp_handle_packet, _retu) ) - { + if ( -1 == custom_user_packet_registerhandler(messenger, friend_num, payload_type, rtp_handle_packet, _retu) ) { fprintf(stderr, "Error setting custom register handler for rtp session\n"); free(_retu); return NULL; } - + _retu->version = RTP_VERSION; /* It's always 2 */ _retu->padding = 0; /* If some additional data is needed about the packet */ _retu->extension = 0; /* If extension to header is needed */ @@ -837,41 +860,44 @@ RTPSession* rtp_init_session ( int payload_type, _retu->csrc = NULL; /* Container */ _retu->ssrc = random_int(); _retu->marker = 0; - _retu->payload_type = payload_table[payload_type]; - + _retu->payload_type = payload_table[payload_type]; + _retu->dest = friend_num; - + _retu->rsequnum = _retu->sequnum = 1; - + _retu->ext_header = NULL; /* When needed allocate */ _retu->framerate = -1; _retu->resolution = -1; - + _retu->encrypt_key = encrypt_key; _retu->decrypt_key = decrypt_key; - + /* Need to allocate new memory */ - _retu->encrypt_nonce = calloc ( crypto_box_NONCEBYTES, sizeof (uint8_t) ); assert(_retu->encrypt_nonce); - _retu->decrypt_nonce = calloc ( crypto_box_NONCEBYTES, sizeof (uint8_t) ); assert(_retu->decrypt_nonce); - _retu->nonce_cycle = calloc ( crypto_box_NONCEBYTES, sizeof (uint8_t) ); assert(_retu->nonce_cycle); - - memcpy(_retu->encrypt_nonce, encrypt_nonce, crypto_box_NONCEBYTES); + _retu->encrypt_nonce = calloc ( crypto_box_NONCEBYTES, sizeof (uint8_t) ); + assert(_retu->encrypt_nonce); + _retu->decrypt_nonce = calloc ( crypto_box_NONCEBYTES, sizeof (uint8_t) ); + assert(_retu->decrypt_nonce); + _retu->nonce_cycle = calloc ( crypto_box_NONCEBYTES, sizeof (uint8_t) ); + assert(_retu->nonce_cycle); + + memcpy(_retu->encrypt_nonce, encrypt_nonce, crypto_box_NONCEBYTES); memcpy(_retu->decrypt_nonce, decrypt_nonce, crypto_box_NONCEBYTES); memcpy(_retu->nonce_cycle , decrypt_nonce, crypto_box_NONCEBYTES); - + _retu->csrc = calloc(1, sizeof (uint32_t)); assert(_retu->csrc); - + _retu->csrc[0] = _retu->ssrc; /* Set my ssrc to the list receive */ - + /* Also set payload type as prefix */ _retu->prefix = payload_type; - + _retu->oldest_msg = _retu->last_msg = NULL; - + pthread_mutex_init(&_retu->mutex, NULL); /* - * + * */ return _retu; } @@ -879,30 +905,30 @@ RTPSession* rtp_init_session ( int payload_type, /** * @brief Terminate the session. - * + * * @param session The session. * @param messenger The messenger who owns the session * @return int * @retval -1 Error occurred. * @retval 0 Success. */ -int rtp_terminate_session ( RTPSession* session, Messenger* messenger ) +int rtp_terminate_session ( RTPSession *session, Messenger *messenger ) { if ( !session ) return -1; - + custom_user_packet_registerhandler(messenger, session->dest, session->prefix, NULL, NULL); - + free ( session->ext_header ); free ( session->csrc ); free ( session->decrypt_nonce ); free ( session->encrypt_nonce ); free ( session->nonce_cycle ); - + pthread_mutex_destroy(&session->mutex); - + /* And finally free session */ free ( session ); - + return 0; } \ No newline at end of file diff --git a/toxav/rtp.h b/toxav/rtp.h index acec8b0a..c2b68b01 100644 --- a/toxav/rtp.h +++ b/toxav/rtp.h @@ -1,5 +1,5 @@ /** toxrtp.h - * + * * Copyright (C) 2013 Tox project All Rights Reserved. * * This file is part of Tox. @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with Tox. If not, see . * - * + * * Report bugs/suggestions at #tox-dev @ freenode.net:6667 */ @@ -38,7 +38,7 @@ /** * @brief Standard rtp header - * + * */ typedef struct _RTPHeader { @@ -47,7 +47,7 @@ typedef struct _RTPHeader { uint16_t sequnum; /* Sequence Number */ uint32_t timestamp; /* Timestamp */ uint32_t ssrc; /* SSRC */ - uint32_t* csrc; /* CSRC's table */ + uint32_t *csrc; /* CSRC's table */ uint32_t length; /* Length of the header in payload string. */ } RTPHeader; @@ -55,29 +55,29 @@ typedef struct _RTPHeader { /** * @brief Standard rtp extension header. - * + * */ typedef struct _RTPExtHeader { uint16_t type; /* Extension profile */ uint16_t length; /* Number of extensions */ - uint32_t* table; /* Extension's table */ - + uint32_t *table; /* Extension's table */ + } RTPExtHeader; /** * @brief Standard rtp message. - * + * */ typedef struct _RTPMessage { - RTPHeader* header; - RTPExtHeader* ext_header; + RTPHeader *header; + RTPExtHeader *ext_header; uint8_t data[MAX_RTP_SIZE]; uint32_t length; IP_Port from; - struct _RTPMessage* next; + struct _RTPMessage *next; } RTPMessage; @@ -87,7 +87,7 @@ typedef struct _RTPMessage { * the entire session. There are functions for manipulating * the session so tend to use those instead of directly modifying * session parameters. - * + * */ typedef struct _RTPSession { uint8_t version; @@ -100,14 +100,14 @@ typedef struct _RTPSession { uint16_t rsequnum; /* Check when recving msg */ uint32_t timestamp; uint32_t ssrc; - uint32_t* csrc; + uint32_t *csrc; /* If some additional data must be sent via message * apply it here. Only by allocating this member you will be * automatically placing it within a message. */ - RTPExtHeader* ext_header; - + RTPExtHeader *ext_header; + /* External header identifiers */ int resolution; int framerate; @@ -117,15 +117,15 @@ typedef struct _RTPSession { * call structure don't allocate or free */ - const uint8_t* encrypt_key; - const uint8_t* decrypt_key; - uint8_t* encrypt_nonce; - uint8_t* decrypt_nonce; + const uint8_t *encrypt_key; + const uint8_t *decrypt_key; + uint8_t *encrypt_nonce; + uint8_t *decrypt_nonce; - uint8_t* nonce_cycle; + uint8_t *nonce_cycle; - RTPMessage* oldest_msg; - RTPMessage* last_msg; /* tail */ + RTPMessage *oldest_msg; + RTPMessage *last_msg; /* tail */ /* Msg prefix for core to know when recving */ uint8_t prefix; @@ -138,28 +138,28 @@ typedef struct _RTPSession { /** * @brief Release all messages held by session. - * + * * @param session The session. * @return int * @retval -1 Error occurred. * @retval 0 Success. */ -int rtp_release_session_recv ( RTPSession* session ); +int rtp_release_session_recv ( RTPSession *session ); /** * @brief Get's oldest message in the list. - * + * * @param session Where the list is. * @return RTPMessage* The message. You need to call rtp_msg_free() to free it. * @retval NULL No messages in the list, or no list. */ -RTPMessage* rtp_recv_msg ( RTPSession* session ); +RTPMessage *rtp_recv_msg ( RTPSession *session ); /** * @brief Sends msg to _RTPSession::dest - * + * * @param session The session. * @param msg The message * @param messenger Tox* object. @@ -167,23 +167,23 @@ RTPMessage* rtp_recv_msg ( RTPSession* session ); * @retval -1 On error. * @retval 0 On success. */ -int rtp_send_msg ( RTPSession* session, Messenger* messenger, const uint8_t* data, uint16_t length ); +int rtp_send_msg ( RTPSession *session, Messenger *messenger, const uint8_t *data, uint16_t length ); /** * @brief Speaks for it self. - * + * * @param session The control session msg belongs to. It can be NULL. * @param msg The message. * @return void */ -void rtp_free_msg ( RTPSession* session, RTPMessage* msg ); +void rtp_free_msg ( RTPSession *session, RTPMessage *msg ); /** * @brief Must be called before calling any other rtp function. It's used * to initialize RTP control session. - * + * * @param payload_type Type of payload used to send. You can use values in toxmsi.h::MSICallType * @param messenger Tox* object. * @param friend_num Friend id. @@ -194,25 +194,25 @@ void rtp_free_msg ( RTPSession* session, RTPMessage* msg ); * @return RTPSession* Created control session. * @retval NULL Error occurred. */ -RTPSession* rtp_init_session ( int payload_type, - Messenger* messenger, - int friend_num, - const uint8_t* encrypt_key, - const uint8_t* decrypt_key, - const uint8_t* encrypt_nonce, - const uint8_t* decrypt_nonce ); +RTPSession *rtp_init_session ( int payload_type, + Messenger *messenger, + int friend_num, + const uint8_t *encrypt_key, + const uint8_t *decrypt_key, + const uint8_t *encrypt_nonce, + const uint8_t *decrypt_nonce ); /** * @brief Terminate the session. - * + * * @param session The session. * @param messenger The messenger who owns the session * @return int * @retval -1 Error occurred. * @retval 0 Success. */ -int rtp_terminate_session ( RTPSession* session, Messenger* messenger ); +int rtp_terminate_session ( RTPSession *session, Messenger *messenger ); diff --git a/toxav/toxav.c b/toxav/toxav.c index b40a1c02..f704bc6b 100644 --- a/toxav/toxav.c +++ b/toxav/toxav.c @@ -1,5 +1,5 @@ /** toxav.c - * + * * Copyright (C) 2013 Tox project All Rights Reserved. * * This file is part of Tox. @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with Tox. If not, see . * - * + * * Report bugs/suggestions at #tox-dev @ freenode.net:6667 */ @@ -44,27 +44,26 @@ typedef enum { ts_closing, ts_running, ts_closed - + } ThreadState; -typedef struct _ToxAv -{ - Messenger* messenger; - - MSISession* msi_session; /** Main msi session */ - - RTPSession* rtp_sessions[2]; /* Audio is first and video is second */ - - struct jitter_buffer* j_buf; - CodecState* cs; - - void* agent_handler; +typedef struct _ToxAv { + Messenger *messenger; + + MSISession *msi_session; /** Main msi session */ + + RTPSession *rtp_sessions[2]; /* Audio is first and video is second */ + + struct jitter_buffer *j_buf; + CodecState *cs; + + void *agent_handler; } ToxAv; /** * @brief Start new A/V session. There can only be one session at the time. If you register more * it will result in undefined behaviour. - * + * * @param messenger The messenger handle. * @param useragent The agent handling A/V session (i.e. phone). * @param ua_name Useragent name. @@ -73,67 +72,69 @@ typedef struct _ToxAv * @return ToxAv* * @retval NULL On error. */ -ToxAv* toxav_new( Tox* messenger, void* useragent, const char* ua_name , uint16_t video_width, uint16_t video_height) +ToxAv *toxav_new( Tox *messenger, void *useragent, const char *ua_name , uint16_t video_width, uint16_t video_height) { - ToxAv* av = calloc ( sizeof(ToxAv), 1); + ToxAv *av = calloc ( sizeof(ToxAv), 1); + if (av == NULL) return NULL; av->messenger = (Messenger *)messenger; - av->msi_session = msi_init_session(av->messenger, (const unsigned char*) ua_name ); + av->msi_session = msi_init_session(av->messenger, (const unsigned char *) ua_name ); av->msi_session->agent_handler = av; - + av->rtp_sessions[0] = av->rtp_sessions [1] = NULL; /* NOTE: This should be user defined or? */ av->j_buf = create_queue(20); - - av->cs = codec_init_session(AUDIO_BITRATE, AUDIO_FRAME_DURATION, AUDIO_SAMPLE_RATE, AUDIO_CHANNELS, video_width, video_height, VIDEO_BITRATE); - + + av->cs = codec_init_session(AUDIO_BITRATE, AUDIO_FRAME_DURATION, AUDIO_SAMPLE_RATE, AUDIO_CHANNELS, video_width, + video_height, VIDEO_BITRATE); + av->agent_handler = useragent; - + return av; } /** * @brief Remove A/V session. - * + * * @param av Handler. * @return void */ -void toxav_kill ( ToxAv* av ) -{ +void toxav_kill ( ToxAv *av ) +{ msi_terminate_session(av->msi_session); - + if ( av->rtp_sessions[audio_index] ) { rtp_terminate_session(av->rtp_sessions[audio_index], av->msi_session->messenger_handle); } - + if ( av->rtp_sessions[video_index] ) { rtp_terminate_session(av->rtp_sessions[video_index], av->msi_session->messenger_handle); } - + codec_terminate_session(av->cs); - + free(av); } /** * @brief Register callback for call state. - * + * * @param callback The callback * @param id One of the ToxAvCallbackID values * @return void */ -void toxav_register_callstate_callback ( ToxAVCallback callback, ToxAvCallbackID id ) +void toxav_register_callstate_callback ( ToxAVCallback callback, ToxAvCallbackID id ) { msi_register_callback((MSICallback)callback, (MSICallbackID) id); } /** * @brief Call user. Use its friend_id. - * + * * @param av Handler. * @param user The user. * @param call_type Call type. @@ -142,68 +143,68 @@ void toxav_register_callstate_callback ( ToxAVCallback callback, ToxAvCallbackID * @retval 0 Success. * @retval ToxAvError On error. */ -int toxav_call (ToxAv* av, int user, ToxAvCallType call_type, int ringing_seconds ) +int toxav_call (ToxAv *av, int user, ToxAvCallType call_type, int ringing_seconds ) { if ( av->msi_session->call ) { return ErrorAlreadyInCall; } - + return msi_invite(av->msi_session, call_type, ringing_seconds * 1000, user); } /** * @brief Hangup active call. - * + * * @param av Handler. * @return int * @retval 0 Success. * @retval ToxAvError On error. */ -int toxav_hangup ( ToxAv* av ) +int toxav_hangup ( ToxAv *av ) { if ( !av->msi_session->call ) { return ErrorNoCall; } - + if ( av->msi_session->call->state != call_active ) { return ErrorInvalidState; } - + return msi_hangup(av->msi_session); } /** * @brief Answer incomming call. - * + * * @param av Handler. * @param call_type Answer with... * @return int * @retval 0 Success. * @retval ToxAvError On error. */ -int toxav_answer ( ToxAv* av, ToxAvCallType call_type ) +int toxav_answer ( ToxAv *av, ToxAvCallType call_type ) { if ( !av->msi_session->call ) { return ErrorNoCall; } - + if ( av->msi_session->call->state != call_starting ) { return ErrorInvalidState; } - + return msi_answer(av->msi_session, call_type); } /** * @brief Reject incomming call. - * + * * @param av Handler. * @param reason Optional reason. Set NULL if none. * @return int * @retval 0 Success. * @retval ToxAvError On error. */ -int toxav_reject ( ToxAv* av, const char* reason ) +int toxav_reject ( ToxAv *av, const char *reason ) { if ( !av->msi_session->call ) { return ErrorNoCall; @@ -213,126 +214,127 @@ int toxav_reject ( ToxAv* av, const char* reason ) return ErrorInvalidState; } - return msi_reject(av->msi_session, (const uint8_t*) reason); + return msi_reject(av->msi_session, (const uint8_t *) reason); } /** * @brief Cancel outgoing request. - * + * * @param av Handler. * @param reason Optional reason. * @return int * @retval 0 Success. * @retval ToxAvError On error. */ -int toxav_cancel ( ToxAv* av, const char* reason ) +int toxav_cancel ( ToxAv *av, const char *reason ) { if ( !av->msi_session->call ) { return ErrorNoCall; } - - return msi_cancel(av->msi_session, 0, (const uint8_t*)reason); + + return msi_cancel(av->msi_session, 0, (const uint8_t *)reason); } /** * @brief Terminate transmission. Note that transmission will be terminated without informing remote peer. - * + * * @param av Handler. * @return int * @retval 0 Success. * @retval ToxAvError On error. */ -int toxav_stop_call ( ToxAv* av ) +int toxav_stop_call ( ToxAv *av ) { if ( !av->msi_session->call ) { return ErrorNoCall; } - + return msi_stopcall(av->msi_session); } /** * @brief Must be call before any RTP transmission occurs. - * + * * @param av Handler. * @return int * @retval 0 Success. * @retval ToxAvError On error. */ -int toxav_prepare_transmission ( ToxAv* av ) +int toxav_prepare_transmission ( ToxAv *av ) { assert(av->msi_session); + if ( !av->msi_session || !av->msi_session->call ) { return ErrorNoCall; } - + av->rtp_sessions[audio_index] = rtp_init_session( - type_audio, - av->messenger, - av->msi_session->call->peers[0], - av->msi_session->call->key_peer, - av->msi_session->call->key_local, - av->msi_session->call->nonce_peer, - av->msi_session->call->nonce_local + type_audio, + av->messenger, + av->msi_session->call->peers[0], + av->msi_session->call->key_peer, + av->msi_session->call->key_local, + av->msi_session->call->nonce_peer, + av->msi_session->call->nonce_local ); - - + + if ( !av->rtp_sessions[audio_index] ) { fprintf(stderr, "Error while starting audio RTP session!\n"); return ErrorStartingAudioRtp; } - - av->rtp_sessions[video_index] = rtp_init_session ( - type_video, - av->messenger, - av->msi_session->call->peers[0], - av->msi_session->call->key_peer, - av->msi_session->call->key_local, - av->msi_session->call->nonce_peer, - av->msi_session->call->nonce_local + + av->rtp_sessions[video_index] = rtp_init_session ( + type_video, + av->messenger, + av->msi_session->call->peers[0], + av->msi_session->call->key_peer, + av->msi_session->call->key_local, + av->msi_session->call->nonce_peer, + av->msi_session->call->nonce_local ); - - + + if ( !av->rtp_sessions[video_index] ) { fprintf(stderr, "Error while starting video RTP session!\n"); return ErrorStartingVideoRtp; } - + return ErrorNone; } /** * @brief Call this at the end of the transmission. - * + * * @param av Handler. * @return int * @retval 0 Success. * @retval ToxAvError On error. */ -int toxav_kill_transmission ( ToxAv* av ) +int toxav_kill_transmission ( ToxAv *av ) { /* Both sessions should be active at any time */ if ( !av->rtp_sessions[0] || !av->rtp_sessions[0] ) return ErrorNoTransmission; - - + + if ( -1 == rtp_terminate_session(av->rtp_sessions[audio_index], av->messenger) ) { fprintf(stderr, "Error while terminating audio RTP session!\n"); return ErrorTerminatingAudioRtp; } - + if ( -1 == rtp_terminate_session(av->rtp_sessions[video_index], av->messenger) ) { fprintf(stderr, "Error while terminating video RTP session!\n"); return ErrorTerminatingVideoRtp; } - + return ErrorNone; } /** * @brief Send RTP payload. - * + * * @param av Handler. * @param type Type of payload. * @param payload The payload. @@ -341,7 +343,7 @@ int toxav_kill_transmission ( ToxAv* av ) * @retval 0 Success. * @retval -1 Failure. */ -inline__ int toxav_send_rtp_payload ( ToxAv* av, ToxAvCallType type, const uint8_t* payload, uint16_t length ) +inline__ int toxav_send_rtp_payload ( ToxAv *av, ToxAvCallType type, const uint8_t *payload, uint16_t length ) { if ( av->rtp_sessions[type - TypeAudio] ) return rtp_send_msg ( av->rtp_sessions[type - TypeAudio], av->msi_session->messenger_handle, payload, length ); @@ -350,7 +352,7 @@ inline__ int toxav_send_rtp_payload ( ToxAv* av, ToxAvCallType type, const uint8 /** * @brief Receive RTP payload. - * + * * @param av Handler. * @param type Type of the payload. * @param dest Storage. @@ -358,123 +360,131 @@ inline__ int toxav_send_rtp_payload ( ToxAv* av, ToxAvCallType type, const uint8 * @retval ToxAvError On Error. * @retval >=0 Size of received payload. */ -inline__ int toxav_recv_rtp_payload ( ToxAv* av, ToxAvCallType type, uint8_t* dest ) +inline__ int toxav_recv_rtp_payload ( ToxAv *av, ToxAvCallType type, uint8_t *dest ) { if ( !dest ) return ErrorInternal; - + if ( !av->rtp_sessions[type - TypeAudio] ) return ErrorNoRtpSession; - - RTPMessage* message; - + + RTPMessage *message; + if ( type == TypeAudio ) { - + do { message = rtp_recv_msg(av->rtp_sessions[audio_index]); - + if (message) { /* push the packet into the queue */ queue(av->j_buf, message); } - } while(message); - + } while (message); + int success = 0; message = dequeue(av->j_buf, &success); if ( success == 2) return ErrorAudioPacketLost; - } - else { + } else { message = rtp_recv_msg(av->rtp_sessions[video_index]); } - - if ( message ) { + + if ( message ) { memcpy(dest, message->data, message->length); - + int length = message->length; - + rtp_free_msg(NULL, message); - + return length; } - + return 0; } /** * @brief Receive decoded video packet. - * + * * @param av Handler. * @param output Storage. - * @return int + * @return int * @retval 0 Success. * @retval ToxAvError On Error. */ -inline__ int toxav_recv_video ( ToxAv* av, vpx_image_t **output) +inline__ int toxav_recv_video ( ToxAv *av, vpx_image_t **output) { if ( !output ) return ErrorInternal; + uint8_t packet [RTP_PAYLOAD_SIZE]; int recved_size = 0; + do { recved_size = toxav_recv_rtp_payload(av, TypeVideo, packet); + if (recved_size > 0) { printf("decode: %s\n", vpx_codec_err_to_string(vpx_codec_decode(&av->cs->v_decoder, packet, recved_size, NULL, 0))); } - }while (recved_size > 0); + } while (recved_size > 0); + vpx_codec_iter_t iter = NULL; vpx_image_t *img; img = vpx_codec_get_frame(&av->cs->v_decoder, &iter); + if (img == NULL) return ErrorInternal; - + *output = img; return 0; } /** * @brief Encode and send video packet. - * + * * @param av Handler. * @param input The packet. * @return int * @retval 0 Success. * @retval ToxAvError On error. */ -inline__ int toxav_send_video ( ToxAv* av, vpx_image_t *input) +inline__ int toxav_send_video ( ToxAv *av, vpx_image_t *input) { if (vpx_codec_encode(&av->cs->v_encoder, input, av->cs->frame_counter, 1, 0, MAX_ENCODE_TIME_US) != VPX_CODEC_OK) { printf("could not encode video frame\n"); return ErrorInternal; } + ++av->cs->frame_counter; - + vpx_codec_iter_t iter = NULL; const vpx_codec_cx_pkt_t *pkt; int sent = 0; - while( (pkt = vpx_codec_get_cx_data(&av->cs->v_encoder, &iter)) ) { + + while ( (pkt = vpx_codec_get_cx_data(&av->cs->v_encoder, &iter)) ) { if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) { if (toxav_send_rtp_payload(av, TypeVideo, pkt->data.frame.buf, pkt->data.frame.sz) != -1) ++sent; } } + if (sent > 0) return 0; - + return ErrorInternal; } /** * @brief Receive decoded audio frame. - * + * * @param av Handler. * @param frame_size ... - * @param dest Destination of the packet. Make sure it has enough space for + * @param dest Destination of the packet. Make sure it has enough space for * RTP_PAYLOAD_SIZE bytes. * @return int * @retval >=0 Size of received packet. * @retval ToxAvError On error. */ -inline__ int toxav_recv_audio ( ToxAv* av, int frame_size, int16_t* dest ) +inline__ int toxav_recv_audio ( ToxAv *av, int frame_size, int16_t *dest ) { if ( !dest ) return ErrorInternal; + uint8_t packet [RTP_PAYLOAD_SIZE]; int recved_size = toxav_recv_rtp_payload(av, TypeAudio, packet); @@ -482,7 +492,7 @@ inline__ int toxav_recv_audio ( ToxAv* av, int frame_size, int16_t* dest ) if ( recved_size == ErrorAudioPacketLost ) { printf("Lost packet\n"); return opus_decode(av->cs->audio_decoder, NULL, 0, dest, frame_size, 1); - } else if ( recved_size ){ + } else if ( recved_size ) { return opus_decode(av->cs->audio_decoder, packet, recved_size, dest, frame_size, 0); } else { return 0; /* Nothing received */ @@ -491,7 +501,7 @@ inline__ int toxav_recv_audio ( ToxAv* av, int frame_size, int16_t* dest ) /** * @brief Encode and send audio frame. - * + * * @param av Handler. * @param frame The frame. * @param frame_size It's size. @@ -499,10 +509,11 @@ inline__ int toxav_recv_audio ( ToxAv* av, int frame_size, int16_t* dest ) * @retval 0 Success. * @retval ToxAvError On error. */ -inline__ int toxav_send_audio ( ToxAv* av, const int16_t* frame, int frame_size) +inline__ int toxav_send_audio ( ToxAv *av, const int16_t *frame, int frame_size) { uint8_t temp_data[RTP_PAYLOAD_SIZE]; int32_t ret = opus_encode(av->cs->audio_encoder, frame, frame_size, temp_data, sizeof(temp_data)); + if (ret <= 0) return ErrorInternal; @@ -511,29 +522,30 @@ inline__ int toxav_send_audio ( ToxAv* av, const int16_t* frame, int frame_size) /** * @brief Get peer transmission type. It can either be audio or video. - * + * * @param av Handler. * @param peer The peer * @return int * @retval ToxAvCallType On success. * @retval ToxAvError On error. */ -int toxav_get_peer_transmission_type ( ToxAv* av, int peer ) +int toxav_get_peer_transmission_type ( ToxAv *av, int peer ) { assert(av->msi_session); + if ( peer < 0 || !av->msi_session->call || av->msi_session->call->peer_count <= peer ) return ErrorInternal; - + return av->msi_session->call->type_peer[peer]; } /** * @brief Get reference to an object that is handling av session. - * + * * @param av Handler. * @return void* */ -void* toxav_get_agent_handler ( ToxAv* av ) +void *toxav_get_agent_handler ( ToxAv *av ) { return av->agent_handler; } diff --git a/toxav/toxav.h b/toxav/toxav.h index 82334273..be7a2950 100644 --- a/toxav/toxav.h +++ b/toxav/toxav.h @@ -1,5 +1,5 @@ /** toxav.h - * + * * Copyright (C) 2013 Tox project All Rights Reserved. * * This file is part of Tox. @@ -17,7 +17,7 @@ * You should have received a copy of the GNU General Public License * along with Tox. If not, see . * - * + * * Report bugs/suggestions at #tox-dev @ freenode.net:6667 */ @@ -29,7 +29,7 @@ /* vpx_image_t */ #include -typedef void* ( *ToxAVCallback ) ( void* arg ); +typedef void *( *ToxAVCallback ) ( void *arg ); typedef struct _ToxAv ToxAv; #ifndef __TOX_DEFINED__ @@ -61,7 +61,7 @@ typedef struct Tox Tox; #define MAX_ENCODE_TIME_US ((1000 / 60) * 1000) -/** +/** * @brief Callbacks ids that handle the call states. */ typedef enum { @@ -71,16 +71,16 @@ typedef enum { OnCancel, OnReject, OnEnd, - + /* Responses */ OnRinging, OnStarting, OnEnding, - + /* Protocol */ OnError, OnRequestTimeout - + } ToxAvCallbackID; @@ -95,7 +95,7 @@ typedef enum { /** * @brief Error indicators. - * + * */ typedef enum { ErrorNone = 0, @@ -110,14 +110,14 @@ typedef enum { ErrorNoTransmission = -9, /* Returned in toxav_kill_transmission() */ ErrorTerminatingAudioRtp = -10, /* Returned in toxav_kill_transmission() */ ErrorTerminatingVideoRtp = -11, /* Returned in toxav_kill_transmission() */ - + } ToxAvError; /** * @brief Start new A/V session. There can only be one session at the time. If you register more * it will result in undefined behaviour. - * + * * @param messenger The messenger handle. * @param useragent The agent handling A/V session (i.e. phone). * @param ua_name Useragent name. @@ -126,19 +126,19 @@ typedef enum { * @return ToxAv* * @retval NULL On error. */ -ToxAv* toxav_new(Tox* messenger, void* useragent, const char* ua_name, uint16_t video_width, uint16_t video_height); +ToxAv *toxav_new(Tox *messenger, void *useragent, const char *ua_name, uint16_t video_width, uint16_t video_height); /** * @brief Remove A/V session. - * + * * @param av Handler. * @return void */ -void toxav_kill(ToxAv* av); +void toxav_kill(ToxAv *av); /** * @brief Register callback for call state. - * + * * @param callback The callback * @param id One of the ToxAvCallbackID values * @return void @@ -147,7 +147,7 @@ void toxav_register_callstate_callback (ToxAVCallback callback, ToxAvCallbackID /** * @brief Call user. Use its friend_id. - * + * * @param av Handler. * @param user The user. * @param call_type Call type. @@ -156,119 +156,119 @@ void toxav_register_callstate_callback (ToxAVCallback callback, ToxAvCallbackID * @retval 0 Success. * @retval ToxAvError On error. */ -int toxav_call(ToxAv* av, int user, ToxAvCallType call_type, int ringing_seconds); +int toxav_call(ToxAv *av, int user, ToxAvCallType call_type, int ringing_seconds); /** * @brief Hangup active call. - * + * * @param av Handler. * @return int * @retval 0 Success. * @retval ToxAvError On error. */ -int toxav_hangup(ToxAv* av); +int toxav_hangup(ToxAv *av); /** * @brief Answer incomming call. - * + * * @param av Handler. * @param call_type Answer with... * @return int * @retval 0 Success. * @retval ToxAvError On error. */ -int toxav_answer(ToxAv* av, ToxAvCallType call_type ); +int toxav_answer(ToxAv *av, ToxAvCallType call_type ); /** * @brief Reject incomming call. - * + * * @param av Handler. * @param reason Optional reason. Set NULL if none. * @return int * @retval 0 Success. * @retval ToxAvError On error. */ -int toxav_reject(ToxAv* av, const char* reason); +int toxav_reject(ToxAv *av, const char *reason); /** * @brief Cancel outgoing request. - * + * * @param av Handler. * @param reason Optional reason. * @return int * @retval 0 Success. * @retval ToxAvError On error. */ -int toxav_cancel(ToxAv* av, const char* reason); +int toxav_cancel(ToxAv *av, const char *reason); /** * @brief Terminate transmission. Note that transmission will be terminated without informing remote peer. - * + * * @param av Handler. * @return int * @retval 0 Success. * @retval ToxAvError On error. */ -int toxav_stop_call(ToxAv* av); +int toxav_stop_call(ToxAv *av); /** * @brief Must be call before any RTP transmission occurs. - * + * * @param av Handler. * @return int * @retval 0 Success. * @retval ToxAvError On error. */ -int toxav_prepare_transmission(ToxAv* av); +int toxav_prepare_transmission(ToxAv *av); /** * @brief Call this at the end of the transmission. - * + * * @param av Handler. * @return int * @retval 0 Success. * @retval ToxAvError On error. */ -int toxav_kill_transmission(ToxAv* av); +int toxav_kill_transmission(ToxAv *av); /** * @brief Receive decoded video packet. - * + * * @param av Handler. * @param output Storage. - * @return int + * @return int * @retval 0 Success. * @retval ToxAvError On Error. */ -int toxav_recv_video ( ToxAv* av, vpx_image_t **output); +int toxav_recv_video ( ToxAv *av, vpx_image_t **output); /** * @brief Receive decoded audio frame. - * + * * @param av Handler. * @param frame_size ... - * @param dest Destination of the packet. Make sure it has enough space for + * @param dest Destination of the packet. Make sure it has enough space for * RTP_PAYLOAD_SIZE bytes. * @return int * @retval >=0 Size of received packet. * @retval ToxAvError On error. */ -int toxav_recv_audio( ToxAv* av, int frame_size, int16_t* dest ); +int toxav_recv_audio( ToxAv *av, int frame_size, int16_t *dest ); /** * @brief Encode and send video packet. - * + * * @param av Handler. * @param input The packet. * @return int * @retval 0 Success. * @retval ToxAvError On error. */ -int toxav_send_video ( ToxAv* av, vpx_image_t *input); +int toxav_send_video ( ToxAv *av, vpx_image_t *input); /** * @brief Encode and send audio frame. - * + * * @param av Handler. * @param frame The frame. * @param frame_size It's size. @@ -276,25 +276,25 @@ int toxav_send_video ( ToxAv* av, vpx_image_t *input); * @retval 0 Success. * @retval ToxAvError On error. */ -int toxav_send_audio ( ToxAv* av, const int16_t* frame, int frame_size); +int toxav_send_audio ( ToxAv *av, const int16_t *frame, int frame_size); /** * @brief Get peer transmission type. It can either be audio or video. - * + * * @param av Handler. * @param peer The peer * @return int * @retval ToxAvCallType On success. * @retval ToxAvError On error. */ -int toxav_get_peer_transmission_type ( ToxAv* av, int peer ); +int toxav_get_peer_transmission_type ( ToxAv *av, int peer ); /** * @brief Get reference to an object that is handling av session. - * + * * @param av Handler. * @return void* */ -void* toxav_get_agent_handler ( ToxAv* av ); +void *toxav_get_agent_handler ( ToxAv *av ); #endif /* __TOXAV */ \ No newline at end of file