Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
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;
}
Пример #5
0
/**@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;
}
Пример #6
0
// 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;
			}