int tsip_transac_remove(const tsip_transac_t* self) { int ret; tsip_transac_t* safe_copy; safe_copy = (tsip_transac_t*)tsk_object_ref(TSK_OBJECT(self)); ret = tsip_transac_layer_remove(TSIP_TRANSAC_GET_STACK(self)->layer_transac, safe_copy); tsk_object_unref(safe_copy); return ret; }
static int tsip_dialog_invite_ice_callback(const tnet_ice_event_t *e) { int ret = 0; tsip_dialog_invite_t *dialog; TSK_DEBUG_INFO("ICE callback: %s", e->phrase); dialog = tsk_object_ref(TSK_OBJECT(e->userdata)); // Do not lock: caller is thread safe switch(e->type){ case tnet_ice_event_type_gathering_completed: case tnet_ice_event_type_conncheck_succeed: case tnet_ice_event_type_conncheck_failed: case tnet_ice_event_type_cancelled: { if(dialog->ice.last_action_id != tsk_fsm_state_none){ if(tsip_dialog_invite_ice_got_local_candidates(dialog)){ ret = tsip_dialog_fsm_act(TSIP_DIALOG(dialog), dialog->ice.last_action_id, dialog->ice.last_message, dialog->ice.last_action); dialog->ice.last_action_id = tsk_fsm_state_none; } } if(dialog->ice.start_smgr){ ret = tsip_dialog_invite_msession_start(dialog); } break; } // fatal errors which discard ICE process case tnet_ice_event_type_gathering_host_candidates_failed: case tnet_ice_event_type_gathering_reflexive_candidates_failed: case tnet_ice_event_type_gathering_relay_candidates_failed: { if (dialog->ice.last_action_id != tsk_fsm_state_none) { ret = tsip_dialog_fsm_act(TSIP_DIALOG(dialog), dialog->ice.last_action_id, dialog->ice.last_message, dialog->ice.last_action); dialog->ice.last_action_id = tsk_fsm_state_none; } break; } // TURN session disconnected while we're in call case tnet_ice_event_type_turn_connection_broken: { ret = tsip_dialog_fsm_act_2(TSIP_DIALOG(dialog), _fsm_action_oBYE); break; } default: break; } TSK_OBJECT_SAFE_FREE(dialog); return ret; }
trtp_rtp_packet_t* trtp_rtp_packet_create_2(const trtp_rtp_header_t* header) { trtp_rtp_packet_t* packet; if(!header){ TSK_DEBUG_ERROR("Invalid parameter"); return tsk_null; } if((packet = tsk_object_new(trtp_rtp_packet_def_t))){ packet->header = tsk_object_ref(TSK_OBJECT(header)); } return packet; }
int tsip_transac_fsm_act(tsip_transac_t* self, tsk_fsm_action_id action_id, const tsip_message_t* message) { int ret; tsip_transac_t* safe_copy; if(!self || !self->fsm){ TSK_DEBUG_WARN("Invalid parameter."); return -1; } safe_copy = tsk_object_ref(TSK_OBJECT(self)); ret = tsk_fsm_act(self->fsm, action_id, safe_copy, message, self, message); tsk_object_unref(safe_copy); return ret; }
/**@ingroup tnet_nat_group * Internal function to send a STUN2 binding request over the network. * * @param [in,out] p_self The NAT context holding the user preferences. * @param [in,out] p_binding The STUN binding object used to create the message to send. * * @return Zero if succeed and non-zero error code otherwise. **/ int tnet_nat_stun_send_bind(const struct tnet_nat_ctx_s* pc_self, struct tnet_stun_binding_s *p_binding) { int ret = -1; tnet_stun_pkt_resp_t *p_pkt_resp = tsk_null; tnet_stun_pkt_req_t *p_pkt_req = tsk_null; if (!pc_self || !p_binding) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } if (!TNET_SOCKET_TYPE_IS_DGRAM(p_binding->socket_type)) { TSK_DEBUG_ERROR("Only DGRAM could be used for STUN transport"); return -2; } if ((ret = tnet_stun_binding_create_req(p_binding, &p_pkt_req))) { goto bail; } /* RFC 5389 - 10.2.1.1. First Request If the client has not completed a successful request/response transaction with the server (as identified by hostname, if the DNS procedures of Section 9 are used, else IP address if not), it SHOULD omit the USERNAME, MESSAGE-INTEGRITY, REALM, and NONCE attributes. In other words, the very first request is sent as if there were no authentication or message integrity applied. */ stun_phase0: { if ((ret = tnet_stun_utils_send_unreliably(p_binding->localFD, pc_self->RTO, pc_self->Rc, p_pkt_req, (struct sockaddr*)&p_binding->addr_server, &p_pkt_resp))) { goto bail; } if (p_pkt_resp) { if (TNET_STUN_PKT_RESP_IS_ERROR(p_pkt_resp)) { uint16_t u_code; if ((ret = tnet_stun_pkt_get_errorcode(p_pkt_resp, &u_code))) { goto bail; } if (u_code == kStunErrCodeUnauthorized || u_code == kStunErrCodeStaleNonce) { if (u_code == kStunErrCodeUnauthorized) { // Make sure this is not an authentication failure (#2 401) // Do not send another req to avoid endless messages if ((tnet_stun_pkt_attr_exists(p_pkt_req, tnet_stun_attr_type_message_integrity))) { // already has a MESSAGE-INTEGRITY? TSK_DEBUG_ERROR("STUN authentication failed"); goto bail; } } if ((ret = tnet_stun_pkt_auth_prepare_2(p_pkt_req, p_binding->p_username, p_binding->p_password, p_pkt_resp))) { goto bail; } // Try to send again now that authinfo is up2date goto stun_phase0; } else if (u_code == kStunErrCodeUnknownAttributes) { if((ret = tnet_stun_pkt_process_err420(p_pkt_req, p_pkt_resp))) { goto bail; } // Try to send again now that authinfo is up2date goto stun_phase0; } ret = -3; } else { const tnet_stun_attr_address_t* pc_addr; if ((ret = tnet_stun_pkt_attr_find_first(p_pkt_resp, tnet_stun_attr_type_xor_mapped_address, (const tnet_stun_attr_t**)&pc_addr)) == 0 && pc_addr) { TSK_OBJECT_SAFE_FREE(p_binding->p_xmaddr); p_binding->p_xmaddr = tsk_object_ref(TSK_OBJECT(pc_addr)); } if ((ret = tnet_stun_pkt_attr_find_first(p_pkt_resp, tnet_stun_attr_type_mapped_address, (const tnet_stun_attr_t**)&pc_addr)) == 0 && pc_addr) { TSK_OBJECT_SAFE_FREE(p_binding->p_maddr); p_binding->p_maddr = tsk_object_ref(TSK_OBJECT(pc_addr)); } } } } /* END OF stun_phase0 */ bail: TSK_OBJECT_SAFE_FREE(p_pkt_resp); TSK_OBJECT_SAFE_FREE(p_pkt_req); return ret; }
// RTP/RTCP callback (From the network to the consumer) static int tdav_session_audio_rtp_cb(const void* callback_data, const struct trtp_rtp_packet_s* packet) { tdav_session_audio_t* audio = (tdav_session_audio_t*)callback_data; tmedia_codec_t* codec = tsk_null; tdav_session_av_t* base = (tdav_session_av_t*)callback_data; int ret = -1; if (!audio || !packet || !packet->header) { TSK_DEBUG_ERROR("Invalid parameter"); goto bail; } if (audio->is_started && base->consumer && base->consumer->is_started) { tsk_size_t out_size = 0; // Find the codec to use to decode the RTP payload if (!audio->decoder.codec || audio->decoder.payload_type != packet->header->payload_type) { tsk_istr_t format; TSK_OBJECT_SAFE_FREE(audio->decoder.codec); tsk_itoa(packet->header->payload_type, &format); if (!(audio->decoder.codec = tmedia_codec_find_by_format(TMEDIA_SESSION(audio)->neg_codecs, format)) || !audio->decoder.codec->plugin || !audio->decoder.codec->plugin->decode){ TSK_DEBUG_ERROR("%s is not a valid payload for this session", format); ret = -2; goto bail; } audio->decoder.payload_type = packet->header->payload_type; } // ref() the codec to be able to use it short time after stop(SAFE_FREE(codec)) if (!(codec = tsk_object_ref(TSK_OBJECT(audio->decoder.codec)))) { TSK_DEBUG_ERROR("Failed to get decoder codec"); goto bail; } // Open codec if not already done if (!TMEDIA_CODEC(codec)->opened) { tsk_safeobj_lock(base); if ((ret = tmedia_codec_open(codec))) { tsk_safeobj_unlock(base); TSK_DEBUG_ERROR("Failed to open [%s] codec", codec->plugin->desc); TSK_OBJECT_SAFE_FREE(audio->decoder.codec); goto bail; } tsk_safeobj_unlock(base); } // Decode data out_size = codec->plugin->decode(codec, packet->payload.data, packet->payload.size, &audio->decoder.buffer, &audio->decoder.buffer_size, packet->header); if (out_size && audio->is_started) { // check "is_started" again ...to be sure stop() not called by another thread void* buffer = audio->decoder.buffer; tsk_size_t size = out_size; // resample if needed if ((base->consumer->audio.out.rate && base->consumer->audio.out.rate != codec->in.rate) || (base->consumer->audio.out.channels && base->consumer->audio.out.channels != TMEDIA_CODEC_AUDIO(codec)->in.channels)) { tsk_size_t resampler_result_size = 0; int bytesPerSample = (base->consumer->audio.bits_per_sample >> 3); if (!audio->decoder.resampler.instance) { TSK_DEBUG_INFO("Create audio resampler(%s) for consumer: rate=%d->%d, channels=%d->%d, bytesPerSample=%d", codec->plugin->desc, codec->in.rate, base->consumer->audio.out.rate, TMEDIA_CODEC_AUDIO(codec)->in.channels, base->consumer->audio.out.channels, bytesPerSample); audio->decoder.resampler.instance = _tdav_session_audio_resampler_create( bytesPerSample, codec->in.rate, base->consumer->audio.out.rate, base->consumer->audio.ptime, TMEDIA_CODEC_AUDIO(codec)->in.channels, base->consumer->audio.out.channels, TDAV_AUDIO_RESAMPLER_DEFAULT_QUALITY, &audio->decoder.resampler.buffer, &audio->decoder.resampler.buffer_size ); } if (!audio->decoder.resampler.instance) { TSK_DEBUG_ERROR("No resampler to handle data"); ret = -5; goto bail; } if (!(resampler_result_size = tmedia_resampler_process(audio->decoder.resampler.instance, buffer, size / bytesPerSample, audio->decoder.resampler.buffer, audio->decoder.resampler.buffer_size / bytesPerSample))){ TSK_DEBUG_ERROR("Failed to process audio resampler input buffer"); ret = -6; goto bail; } buffer = audio->decoder.resampler.buffer; size = audio->decoder.resampler.buffer_size; }