Пример #1
0
/*!
 * \internal
 * \brief Adds a path header to an outgoing 2XX response
 *
 * \param endpoint The endpoint to which the INVITE response is to be sent
 * \param contact The contact to which the INVITE response is to be sent
 * \param tdata The outbound INVITE response
 */
static void path_outgoing_response(struct ast_sip_endpoint *endpoint, struct ast_sip_contact *contact, pjsip_tx_data *tdata)
{
	struct pjsip_status_line status = tdata->msg->line.status;
	pj_str_t path_dup;
	pjsip_generic_string_hdr *path_hdr;
	pjsip_contact_hdr *contact_hdr;
	RAII_VAR(struct ast_sip_aor *, aor, NULL, ao2_cleanup);
	pjsip_cseq_hdr *cseq = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CSEQ, NULL);
	const pj_str_t REGISTER_METHOD = {"REGISTER", 8};

	if (!endpoint
		|| !pj_stristr(&REGISTER_METHOD, &cseq->method.name)
		|| !PJSIP_IS_STATUS_IN_CLASS(status.code, 200)) {
		return;
	}

	contact_hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTACT, NULL);
	if (!contact_hdr) {
		return;
	}

	aor = find_aor(endpoint, contact_hdr->uri);
	if (!aor || !aor->support_path || add_supported(tdata)
		|| path_get_string(tdata->pool, contact, &path_dup)) {
		return;
	}

	path_hdr = pjsip_generic_string_hdr_create(tdata->pool, &PATH_NAME, &path_dup);
	if (!path_hdr) {
		return;
	}

	pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)path_hdr);
}
/* Get platform info, returned format will be "Series60vX.X" */
unsigned pj_symbianos_get_platform_info(char *buf, unsigned buf_size)
{
    /* OS info */
    _LIT(KS60ProductIDFile, "Series60v*.sis");
    _LIT(KROMInstallDir, "z:\\system\\install\\");

    RFs fs;
    TFindFile ff(fs);
    CDir* result;
    pj_str_t plat_info = {NULL, 0};
    TInt err;

    fs.Connect(1);
    err = ff.FindWildByDir(KS60ProductIDFile, KROMInstallDir, result);
    if (err == KErrNone) {
	err = result->Sort(ESortByName|EDescending);
	if (err == KErrNone) {
	    TPtr8 tmp_ptr8((TUint8*)buf, buf_size);
	    const pj_str_t tmp_ext = {".sis", 4};
	    char *p;
	    
	    tmp_ptr8.Copy((*result)[0].iName);
	    pj_strset(&plat_info, buf, (pj_size_t)tmp_ptr8.Length());
	    p = pj_stristr(&plat_info, &tmp_ext);
	    if (p)
		plat_info.slen -= (p - plat_info.ptr);
	}
	delete result;
    }
    fs.Close();
    buf[plat_info.slen] = '\0';
    
    return plat_info.slen;
}
Пример #3
0
/* Toggle AMR octet-align setting in the fmtp.
 */
static pj_status_t amr_toggle_octet_align(pj_pool_t *pool,
					  pjmedia_sdp_media *media,
					  unsigned fmt_idx)
{
    pjmedia_sdp_attr *attr;
    pjmedia_sdp_fmtp fmtp;
    const pj_str_t STR_OCTET_ALIGN = {"octet-align=", 12};
    
    enum { MAX_FMTP_STR_LEN = 160 };

    attr = pjmedia_sdp_media_find_attr2(media, "fmtp", 
					&media->desc.fmt[fmt_idx]);
    /* Check if the AMR media format has FMTP attribute */
    if (attr) {
	char *p;
	pj_status_t status;

	status = pjmedia_sdp_attr_get_fmtp(attr, &fmtp);
	if (status != PJ_SUCCESS)
	    return status;

	/* Check if the fmtp has octet-align field. */
	p = pj_stristr(&fmtp.fmt_param, &STR_OCTET_ALIGN);
	if (p) {
	    /* It has, just toggle the value */
	    unsigned octet_align;
	    pj_str_t s;

	    pj_strset(&s, p + STR_OCTET_ALIGN.slen, fmtp.fmt_param.slen -
		      (p - fmtp.fmt_param.ptr) - STR_OCTET_ALIGN.slen);
	    octet_align = pj_strtoul(&s);
	    *(p + STR_OCTET_ALIGN.slen) = (char)(octet_align? '0' : '1');
	} else {
	    /* It doesn't, append octet-align field */
	    char buf[MAX_FMTP_STR_LEN];

	    pj_ansi_snprintf(buf, MAX_FMTP_STR_LEN, "%.*s;octet-align=1",
			     (int)fmtp.fmt_param.slen, fmtp.fmt_param.ptr);
	    attr->value = pj_strdup3(pool, buf);
	}
    } else {
	/* Add new attribute for the AMR media format with octet-align 
	 * field set.
	 */
	char buf[MAX_FMTP_STR_LEN];

	attr = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_attr);
	attr->name = pj_str("fmtp");
	pj_ansi_snprintf(buf, MAX_FMTP_STR_LEN, "%.*s octet-align=1",
			 (int)media->desc.fmt[fmt_idx].slen,
		         media->desc.fmt[fmt_idx].ptr);
	attr->value = pj_strdup3(pool, buf);
	media->attr[media->attr_count++] = attr;
    }

    return PJ_SUCCESS;
}
Пример #4
0
/* Matching G722.1 bitrates between offer and answer.
 */
static pj_bool_t match_g7221( const pjmedia_sdp_media *offer,
			      unsigned o_fmt_idx,
			      const pjmedia_sdp_media *answer,
			      unsigned a_fmt_idx)
{
    const pjmedia_sdp_attr *a_ans;
    const pjmedia_sdp_attr *a_off;
    pjmedia_sdp_fmtp fmtp;
    unsigned a_bitrate = 0, o_bitrate = 0;
    const pj_str_t bitrate = {"bitrate=", 8};
    const char *p;

    a_ans = pjmedia_sdp_media_find_attr2(answer, "fmtp", 
					 &answer->desc.fmt[a_fmt_idx]);
    if (!a_ans)
	return PJ_FALSE;

    if (pjmedia_sdp_attr_get_fmtp(a_ans, &fmtp) != PJ_SUCCESS)
	return PJ_FALSE;

    p = pj_stristr(&fmtp.fmt_param, &bitrate);
    if (p == NULL)
	return PJ_FALSE;

    a_bitrate = atoi(p + bitrate.slen);

    a_off = pjmedia_sdp_media_find_attr2(offer, "fmtp", 
					 &offer->desc.fmt[o_fmt_idx]);
    if (!a_off)
	return PJ_FALSE;

    if (pjmedia_sdp_attr_get_fmtp(a_off, &fmtp) != PJ_SUCCESS)
	return PJ_FALSE;

    p = pj_stristr(&fmtp.fmt_param, &bitrate);
    if (p == NULL)
	return PJ_FALSE;

    o_bitrate = atoi(p + bitrate.slen);

    return (a_bitrate == o_bitrate);
}
static pjmedia_sdp_attr* opus_sdp_get_opus_rtpmap_attr(pjmedia_sdp_session* sdp_session){

    unsigned media_idx;
    unsigned attr_idx;
    for(media_idx = 0; media_idx < sdp_session->media_count; media_idx++){
        pjmedia_sdp_media *media = sdp_session->media[media_idx];

        if(pj_stricmp(&media->desc.media, &STR_AUDIO)==0){
            for(attr_idx=0; attr_idx < media->attr_count; attr_idx++){
                if(pj_stricmp(&media->attr[attr_idx]->name, &STR_RTPMAP)==0){
                    char* found_opus = pj_stristr(&media->attr[attr_idx]->value, &STR_OPUS);
                    if(found_opus != NULL){
                        return media->attr[attr_idx];
                    }
                }
            }
        }
    }
    return NULL;
}
/* Notification on incoming messages */
static pj_bool_t opus_sdp_on_rx_msg(pjsip_rx_data *rdata)
{

    if(rdata && rdata->msg_info.msg){
        pjsip_msg_body* body = rdata->msg_info.msg->body;
        if(opus_sdp_body_is_sdp(body)){
            pj_str_t body_str = {body->data, body->len};
            char* found_opus = pj_stristr(&body_str, &STR_OPUS_RFC_FMT);
            if(found_opus != NULL){
                pj_str_t new_value;
                new_value.ptr = (char*) pj_pool_alloc(rdata->tp_info.pool, STR_OPUS_RFC_FMT.slen+1);
                new_value.slen = pj_ansi_snprintf(new_value.ptr, STR_OPUS_RFC_FMT.slen+1, "opus/%d/1", pjopus_internal_clockrate);
                while(new_value.slen < STR_OPUS_RFC_FMT.slen+1){
                    new_value.ptr[new_value.slen ++] = ' ';
                }
                pj_memcpy(found_opus, new_value.ptr, new_value.slen - 1);
            }
        }
    }

    /* Always return false, otherwise messages will not get processed! */
    return PJ_FALSE;
}
/* Notification on outgoing messages */
static pj_status_t opus_sdp_on_tx_msg(pjsip_tx_data *tdata)
{
    if(tdata && tdata->msg){
        pjsip_msg_body* body = tdata->msg->body;
        if (opus_sdp_body_is_sdp(body))
        {
            pjsip_msg_body* new_body = pjsip_msg_body_clone(tdata->pool, body);
            pjmedia_sdp_attr* opus_attr = opus_sdp_get_opus_rtpmap_attr((pjmedia_sdp_session*) new_body->data);
            if(opus_attr != NULL){
                pj_str_t new_value;
                char* found_opus = pj_stristr(&opus_attr->value, &STR_OPUS);
                new_value.ptr = (char*) pj_pool_alloc(tdata->pool, 20);
                new_value.slen = pj_ansi_snprintf(new_value.ptr, 20, "%.*s%.*s",
                                                                                                                found_opus - opus_attr->value.ptr, opus_attr->value.ptr,
                                                                                                                STR_OPUS_RFC_FMT.slen, STR_OPUS_RFC_FMT.ptr);
                opus_attr->value = new_value;
                tdata->msg->body = new_body;
            }
        }
    }

    /* Always return success, otherwise message will not get sent! */
    return PJ_SUCCESS;
}
PJ_END_DECL


/* Get Symbian phone model info, returning length of model info */
unsigned pj_symbianos_get_model_info(char *buf, unsigned buf_size)
{
    pj_str_t model_name;

    /* Get machine UID */
    TInt hal_val;
    HAL::Get(HAL::EMachineUid, hal_val);
    pj_ansi_snprintf(buf, buf_size, "0x%08X", hal_val);
    pj_strset2(&model_name, buf);

    /* Get model name */
    const pj_str_t st_copyright = {"(C)", 3};
    const pj_str_t st_nokia = {"Nokia", 5};
    char tmp_buf[64];
    pj_str_t tmp_str;

    _LIT(KModelFilename,"Z:\\resource\\versions\\model.txt");
    RFile file;
    RFs fs;
    TInt err;
    
    fs.Connect(1);
    err = file.Open(fs, KModelFilename, EFileRead);
    if (err == KErrNone) {
	TFileText text;
	text.Set(file);
	TBuf16<64> ModelName16;
	err = text.Read(ModelName16);
	if (err == KErrNone) {
	    TPtr8 ptr8((TUint8*)tmp_buf, sizeof(tmp_buf));
	    ptr8.Copy(ModelName16);
	    pj_strset(&tmp_str, tmp_buf, ptr8.Length());
	    pj_strtrim(&tmp_str);
	}
	file.Close();
    }
    fs.Close();
    if (err != KErrNone)
	goto on_return;
    
    /* The retrieved model name is usually in long format, e.g: 
     * "© Nokia N95 (01.01)", "(C) Nokia E52". As we need only
     * the short version, let's clean it up.
     */
    
    /* Remove preceding non-ASCII chars, e.g: "©" */
    char *p = tmp_str.ptr;
    while (!pj_isascii(*p)) { p++; }
    pj_strset(&tmp_str, p, tmp_str.slen - (p - tmp_str.ptr));
    
    /* Remove "(C)" */
    p = pj_stristr(&tmp_str, &st_copyright);
    if (p) {
	p += st_copyright.slen;
	pj_strset(&tmp_str, p, tmp_str.slen - (p - tmp_str.ptr));
    }

    /* Remove "Nokia" */
    p = pj_stristr(&tmp_str, &st_nokia);
    if (p) {
	p += st_nokia.slen;
	pj_strset(&tmp_str, p, tmp_str.slen - (p - tmp_str.ptr));
    }
    
    /* Remove language version, e.g: "(01.01)" */
    p = pj_strchr(&tmp_str, '(');
    if (p) {
	tmp_str.slen = p - tmp_str.ptr;
    }
    
    pj_strtrim(&tmp_str);
    
    if (tmp_str.slen == 0)
	goto on_return;
    
    if ((unsigned)tmp_str.slen > buf_size - model_name.slen - 3)
	tmp_str.slen = buf_size - model_name.slen - 3;
    
    pj_strcat2(&model_name, "(");
    pj_strcat(&model_name, &tmp_str);
    pj_strcat2(&model_name, ")");
    
    /* Zero terminate */
    buf[model_name.slen] = '\0';
    
on_return:
    return model_name.slen;
}
Пример #9
0
static void pcap2wav(const pj_str_t *codec,
		     const pj_str_t *wav_filename,
		     pjmedia_aud_dev_index dev_id,
		     const pj_str_t *srtp_crypto,
		     const pj_str_t *srtp_key)
{
    const pj_str_t WAV = {".wav", 4};
    struct pkt
    {
	pj_uint8_t	 buffer[320];
	pjmedia_rtp_hdr	*rtp;
	pj_uint8_t	*payload;
	unsigned	 payload_len;
    } pkt0;
    pjmedia_codec_mgr *cmgr;
    const pjmedia_codec_info *ci;
    pjmedia_codec_param param;
    unsigned samples_per_frame;
    pj_status_t status;

    /* Initialize all codecs */
    T( pjmedia_codec_register_audio_codecs(app.mept, NULL) );

    /* Create SRTP transport is needed */
#if PJMEDIA_HAS_SRTP
    if (srtp_crypto->slen) {
	pjmedia_srtp_crypto crypto;

	pj_bzero(&crypto, sizeof(crypto));
	crypto.key = *srtp_key;
	crypto.name = *srtp_crypto;
	T( pjmedia_transport_srtp_create(app.mept, NULL, NULL, &app.srtp) );
	T( pjmedia_transport_srtp_start(app.srtp, &crypto, &crypto) );
    }
#else
    PJ_UNUSED_ARG(srtp_crypto);
    PJ_UNUSED_ARG(srtp_key);
#endif

    /* Read first packet */
    read_rtp(pkt0.buffer, sizeof(pkt0.buffer), &pkt0.rtp, 
	     &pkt0.payload, &pkt0.payload_len, PJ_FALSE);

    cmgr = pjmedia_endpt_get_codec_mgr(app.mept);

    /* Get codec info and param for the specified payload type */
    app.pt = pkt0.rtp->pt;
    if (app.pt >=0 && app.pt < 96) {
	T( pjmedia_codec_mgr_get_codec_info(cmgr, pkt0.rtp->pt, &ci) );
    } else {
	unsigned cnt = 2;
	const pjmedia_codec_info *info[2];
	T( pjmedia_codec_mgr_find_codecs_by_id(cmgr, codec, &cnt, 
					       info, NULL) );
	if (cnt != 1)
	    err_exit("Codec ID must be specified and unique!", 0);

	ci = info[0];
    }
    T( pjmedia_codec_mgr_get_default_param(cmgr, ci, &param) );

    /* Alloc and init codec */
    T( pjmedia_codec_mgr_alloc_codec(cmgr, ci, &app.codec) );
    T( pjmedia_codec_init(app.codec, app.pool) );
    T( pjmedia_codec_open(app.codec, &param) );

    /* Init audio device or WAV file */
    samples_per_frame = ci->clock_rate * param.info.frm_ptime / 1000;
    if (pj_strcmp2(wav_filename, "-") == 0) {
	pjmedia_aud_param aud_param;

	/* Open audio device */
	T( pjmedia_aud_dev_default_param(dev_id, &aud_param) );
	aud_param.dir = PJMEDIA_DIR_PLAYBACK;
	aud_param.channel_count = ci->channel_cnt;
	aud_param.clock_rate = ci->clock_rate;
	aud_param.samples_per_frame = samples_per_frame;
	T( pjmedia_aud_stream_create(&aud_param, NULL, &play_cb, 
				     NULL, &app.aud_strm) );
	T( pjmedia_aud_stream_start(app.aud_strm) );
    } else if (pj_stristr(wav_filename, &WAV)) {
	/* Open WAV file */
	T( pjmedia_wav_writer_port_create(app.pool, wav_filename->ptr,
					  ci->clock_rate, ci->channel_cnt,
					  samples_per_frame,
					  param.info.pcm_bits_per_sample, 0, 0,
					  &app.wav) );
    } else {
	err_exit("invalid output file", PJ_EINVAL);
    }

    /* Loop reading PCAP and writing WAV file */
    for (;;) {
	struct pkt pkt1;
	pj_timestamp ts;
	pjmedia_frame frames[16], pcm_frame;
	short pcm[320];
	unsigned i, frame_cnt;
	long samples_cnt, ts_gap;

	pj_assert(sizeof(pcm) >= samples_per_frame);

	/* Parse first packet */
	ts.u64 = 0;
	frame_cnt = PJ_ARRAY_SIZE(frames);
	T( pjmedia_codec_parse(app.codec, pkt0.payload, pkt0.payload_len, 
				&ts, &frame_cnt, frames) );

	/* Decode and write to WAV file */
	samples_cnt = 0;
	for (i=0; i<frame_cnt; ++i) {
	    pjmedia_frame pcm_frame;

	    pcm_frame.buf = pcm;
	    pcm_frame.size = samples_per_frame * 2;

	    T( pjmedia_codec_decode(app.codec, &frames[i], 
				    (unsigned)pcm_frame.size, &pcm_frame) );
	    if (app.wav) {
		T( pjmedia_port_put_frame(app.wav, &pcm_frame) );
	    }
	    if (app.aud_strm) {
		T( wait_play(&pcm_frame) );
	    }
	    samples_cnt += samples_per_frame;
	}

	/* Read next packet */
	read_rtp(pkt1.buffer, sizeof(pkt1.buffer), &pkt1.rtp,
		 &pkt1.payload, &pkt1.payload_len, PJ_TRUE);

	/* Fill in the gap (if any) between pkt0 and pkt1 */
	ts_gap = pj_ntohl(pkt1.rtp->ts) - pj_ntohl(pkt0.rtp->ts) -
		 samples_cnt;
	while (ts_gap >= (long)samples_per_frame) {

	    pcm_frame.buf = pcm;
	    pcm_frame.size = samples_per_frame * 2;

	    if (app.codec->op->recover) {
		T( pjmedia_codec_recover(app.codec, (unsigned)pcm_frame.size, 
					 &pcm_frame) );
	    } else {
		pj_bzero(pcm_frame.buf, pcm_frame.size);
	    }

	    if (app.wav) {
		T( pjmedia_port_put_frame(app.wav, &pcm_frame) );
	    }
	    if (app.aud_strm) {
		T( wait_play(&pcm_frame) );
	    }
	    ts_gap -= samples_per_frame;
	}
	
	/* Next */
	pkt0 = pkt1;
	pkt0.rtp = (pjmedia_rtp_hdr*)pkt0.buffer;
	pkt0.payload = pkt0.buffer + (pkt1.payload - pkt1.buffer);
    }
}