Esempio n. 1
0
/// Apply the mangalgorithm to the specified URI. The user part of the URI is
/// always mangled. The domain is mangled separately, and is only mangled if
/// mangelwurzel's change_domain flag is set, or if the function's
/// force_mangle_domain flag is set (we use this flag to make sure we always
/// mangle the domains for Routes and Record-Routes). We don't mangle
/// anything else (e.g. port number, SIP parameters).
void MangelwurzelTsx::mangle_uri(pjsip_uri* uri,
                                 pj_pool_t* pool,
                                 bool force_mangle_domain)
{
  if (PJSIP_URI_SCHEME_IS_SIP(uri))
  {
    pjsip_sip_uri* sip_uri = (pjsip_sip_uri*)uri;
    std::string user = PJUtils::pj_str_to_string(&sip_uri->user);
    mangle_string(user);
    sip_uri->user = pj_strdup3(pool, user.c_str());

    if ((force_mangle_domain) || (_config.change_domain))
    {
      std::string host = PJUtils::pj_str_to_string(&sip_uri->host);
      mangle_string(host);
      sip_uri->host = pj_strdup3(pool, host.c_str());
    }
  }
  else if (PJSIP_URI_SCHEME_IS_TEL(uri))
  {
    pjsip_tel_uri* tel_uri = (pjsip_tel_uri*)uri;
    std::string number = PJUtils::pj_str_to_string(&tel_uri->number);
    mangle_string(number);
    tel_uri->number = pj_strdup3(pool, number.c_str());
  }
}
Esempio n. 2
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;
}
Esempio n. 3
0
void SIPPresence::updateStatus(bool status, const std::string &note)
{
    //char* pj_note  = (char*) pj_pool_alloc(pool_, "50");

    pjrpid_element rpid = {
        PJRPID_ELEMENT_TYPE_PERSON,
        CONST_PJ_STR("0"),
        PJRPID_ACTIVITY_UNKNOWN,
        pj_str((char *) note.c_str())
    };

    /* fill activity if user not available. */
    if (note == "away")
        rpid.activity = PJRPID_ACTIVITY_AWAY;
    else if (note == "busy")
        rpid.activity = PJRPID_ACTIVITY_BUSY;
    /*
    else // TODO: is there any other possibilities
        DEBUG("Presence : no activity");
    */

    pj_bzero(&status_data_, sizeof(status_data_));
    status_data_.info_cnt = 1;
    status_data_.info[0].basic_open = status;

    // at most we will have 3 digits + NULL termination
    char buf[4];
    pj_utoa(rand() % 1000, buf);
    status_data_.info[0].id = pj_strdup3(pool_, buf);

    pj_memcpy(&status_data_.info[0].rpid, &rpid, sizeof(pjrpid_element));
    /* "contact" field is optionnal */
}
Esempio n. 4
0
pj_status_t init_authentication(const std::string& realm_name,
                                AvStore* avstore,
                                HSSConnection* hss_connection,
                                ChronosConnection* chronos_connection,
                                ACRFactory* rfacr_factory,
                                AnalyticsLogger* analytics_logger)
{
  pj_status_t status;

  aka_realm = (realm_name != "") ? pj_strdup3(stack_data.pool, realm_name.c_str()) : stack_data.local_host;
  av_store = avstore;
  hss = hss_connection;
  chronos = chronos_connection;
  acr_factory = rfacr_factory;
  analytics = analytics_logger;

  // Register the authentication module.  This needs to be in the stack
  // before the transaction layer.
  status = pjsip_endpt_register_module(stack_data.endpt, &mod_auth);

  // Initialize the authorization server.
  pjsip_auth_srv_init_param params;
  params.realm = &WILDCARD_REALM;
  params.lookup3 = user_lookup;
  params.options = 0;
  status = pjsip_auth_srv_init2(stack_data.pool, &auth_srv, &params);

  return status;
}
Esempio n. 5
0
/*!
 * \brief Get the path string associated with this contact and tdata
 *
 * \param endpoint The endpoint from which to pull associated path data
 * \param contact_uri The URI identifying the associated contact
 * \param path_str The place to store the retrieved path information
 *
 * \retval zero on success
 * \retval non-zero on failure or no available path information
 */
static int path_get_string(pj_pool_t *pool, struct ast_sip_contact *contact, pj_str_t *path_str)
{
	if (!contact || ast_strlen_zero(contact->path)) {
		return -1;
	}

	*path_str = pj_strdup3(pool, contact->path);
	return 0;
}
Esempio n. 6
0
/// Apply the mangalgorithm to the From tag, To tag (if present) and call ID of
/// req.
void MangelwurzelTsx::mangle_dialog_identifiers(pjsip_msg* req, pj_pool_t* pool)
{
  pjsip_from_hdr* from_hdr = PJSIP_MSG_FROM_HDR(req);

  if (from_hdr != NULL)
  {
    std::string from_tag = PJUtils::pj_str_to_string(&from_hdr->tag);
    mangle_string(from_tag);
    TRC_DEBUG("From tag mangled to %s", from_tag.c_str());
    from_hdr->tag = pj_strdup3(pool, from_tag.c_str());
  }

  pjsip_to_hdr* to_hdr = PJSIP_MSG_TO_HDR(req);

  if (to_hdr != NULL)
  {
    std::string to_tag = PJUtils::pj_str_to_string(&to_hdr->tag);
    mangle_string(to_tag);
    TRC_DEBUG("To tag mangled to %s", to_tag.c_str());
    to_hdr->tag = pj_strdup3(pool, to_tag.c_str());
  }

  pjsip_cid_hdr* cid_hdr = (pjsip_cid_hdr*)pjsip_msg_find_hdr(req,
                                                              PJSIP_H_CALL_ID,
                                                              NULL);
  if (cid_hdr != NULL)
  {
    std::string call_id = PJUtils::pj_str_to_string(&cid_hdr->id);
    mangle_string(call_id);
    TRC_DEBUG("Call ID manged to %s", call_id.c_str());
    cid_hdr->id = pj_strdup3(pool, call_id.c_str());

    // Report a SAS marker for the new call ID so that the two dialogs can be
    // correlated in SAS.
    TRC_DEBUG("Logging SAS Call-ID marker, Call-ID %.*s",
              cid_hdr->id.slen,
              cid_hdr->id.ptr);
    SAS::Marker cid_marker(trail(), MARKER_ID_SIP_CALL_ID, 1u);
    cid_marker.add_var_param(cid_hdr->id.slen, cid_hdr->id.ptr);
    SAS::report_marker(cid_marker, SAS::Marker::Scope::Trace);
  }
}
Esempio n. 7
0
/* Create client publish session */
pj_status_t
SIPPresence::publish(SIPPresence *pres)
{
    pj_status_t status;
    const pj_str_t STR_PRESENCE = CONST_PJ_STR("presence");
    SIPAccount * acc = pres->getAccount();
    pjsip_endpoint *endpt = ((SIPVoIPLink*) acc->getVoIPLink())->getEndpoint();

    /* Create and init client publication session */

    /* Create client publication */
    status = pjsip_publishc_create(endpt, &my_publish_opt,
                                   pres, &publish_cb,
                                   &pres->publish_sess_);

    if (status != PJ_SUCCESS) {
        pres->publish_sess_ = NULL;
        ERROR("Failed to create a publish seesion.");
        return status;
    }

    /* Initialize client publication */
    pj_str_t from = pj_strdup3(pres->pool_, acc->getFromUri().c_str());
    status = pjsip_publishc_init(pres->publish_sess_, &STR_PRESENCE, &from, &from, &from, 0xFFFF);

    if (status != PJ_SUCCESS) {
        ERROR("Failed to init a publish session");
        pres->publish_sess_ = NULL;
        return status;
    }

    /* Add credential for authentication */
    if (acc->hasCredentials() and pjsip_publishc_set_credentials(pres->publish_sess_, acc->getCredentialCount(), acc->getCredInfo()) != PJ_SUCCESS) {
        ERROR("Could not initialize credentials for invite session authentication");
        return status;
    }

    /* Set route-set */
    // FIXME: is this really necessary?
    pjsip_regc *regc = acc->getRegistrationInfo();
    if (regc and acc->hasServiceRoute())
        pjsip_regc_set_route_set(regc, sip_utils::createRouteSet(acc->getServiceRoute(), pres->getPool()));

    /* Send initial PUBLISH request */
    status = send_publish(pres);

    if (status != PJ_SUCCESS)
        return status;

    return PJ_SUCCESS;
}
Esempio n. 8
0
/**
 * Create a SDP session description that describes the endpoint
 * capability.
 */
PJ_DEF(pj_status_t) pjmedia_endpt_create_sdp( pjmedia_endpt *endpt,
					      pj_pool_t *pool,
					      unsigned stream_cnt,
					      const pjmedia_sock_info sock_info[],
					      pjmedia_sdp_session **p_sdp )
{
    pj_time_val tv;
    unsigned i;
    const pj_sockaddr *addr0;
    pjmedia_sdp_session *sdp;
    pjmedia_sdp_media *m;
    pjmedia_sdp_attr *attr;

    /* Sanity check arguments */
    PJ_ASSERT_RETURN(endpt && pool && p_sdp && stream_cnt, PJ_EINVAL);

    /* Check that there are not too many codecs */
    PJ_ASSERT_RETURN(endpt->codec_mgr.codec_cnt <= PJMEDIA_MAX_SDP_FMT,
		     PJ_ETOOMANY);

    /* Create and initialize basic SDP session */
    sdp = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_session);

    addr0 = &sock_info[0].rtp_addr_name;

    pj_gettimeofday(&tv);
    sdp->origin.user = pj_str("-");
    sdp->origin.version = sdp->origin.id = tv.sec + 2208988800UL;
    sdp->origin.net_type = STR_IN;

    if (addr0->addr.sa_family == pj_AF_INET()) {
	sdp->origin.addr_type = STR_IP4;
	pj_strdup2(pool, &sdp->origin.addr, 
		   pj_inet_ntoa(addr0->ipv4.sin_addr));
    } else if (addr0->addr.sa_family == pj_AF_INET6()) {
	char tmp_addr[PJ_INET6_ADDRSTRLEN];

	sdp->origin.addr_type = STR_IP6;
	pj_strdup2(pool, &sdp->origin.addr, 
		   pj_sockaddr_print(addr0, tmp_addr, sizeof(tmp_addr), 0));

    } else {
	pj_assert(!"Invalid address family");
	return PJ_EAFNOTSUP;
    }

    sdp->name = STR_SDP_NAME;

    /* Since we only support one media stream at present, put the
     * SDP connection line in the session level.
     */
    sdp->conn = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_conn);
    sdp->conn->net_type = sdp->origin.net_type;
    sdp->conn->addr_type = sdp->origin.addr_type;
    sdp->conn->addr = sdp->origin.addr;


    /* SDP time and attributes. */
    sdp->time.start = sdp->time.stop = 0;
    sdp->attr_count = 0;

    /* Create media stream 0: */

    sdp->media_count = 1;
    m = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_media);
    sdp->media[0] = m;

    /* Standard media info: */
    pj_strdup(pool, &m->desc.media, &STR_AUDIO);
    m->desc.port = pj_sockaddr_get_port(addr0);
    m->desc.port_count = 1;
    pj_strdup (pool, &m->desc.transport, &STR_RTP_AVP);

    /* Init media line and attribute list. */
    m->desc.fmt_count = 0;
    m->attr_count = 0;

    /* Add "rtcp" attribute */
#if defined(PJMEDIA_HAS_RTCP_IN_SDP) && PJMEDIA_HAS_RTCP_IN_SDP!=0
    if (sock_info->rtcp_addr_name.addr.sa_family != 0) {
	attr = pjmedia_sdp_attr_create_rtcp(pool, &sock_info->rtcp_addr_name);
	if (attr)
	    pjmedia_sdp_attr_add(&m->attr_count, m->attr, attr);
    }
#endif

    /* Add format, rtpmap, and fmtp (when applicable) for each codec */
    for (i=0; i<endpt->codec_mgr.codec_cnt; ++i) {

	pjmedia_codec_info *codec_info;
	pjmedia_sdp_rtpmap rtpmap;
	char tmp_param[3];
	pjmedia_sdp_attr *attr;
	pjmedia_codec_param codec_param;
	pj_str_t *fmt;

	if (endpt->codec_mgr.codec_desc[i].prio == PJMEDIA_CODEC_PRIO_DISABLED)
	    break;

	codec_info = &endpt->codec_mgr.codec_desc[i].info;
	pjmedia_codec_mgr_get_default_param(&endpt->codec_mgr, codec_info,
					    &codec_param);
	fmt = &m->desc.fmt[m->desc.fmt_count++];

	fmt->ptr = (char*) pj_pool_alloc(pool, 8);
	fmt->slen = pj_utoa(codec_info->pt, fmt->ptr);

	rtpmap.pt = *fmt;
	rtpmap.enc_name = codec_info->encoding_name;

#if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG != 0)
	if (codec_info->pt == PJMEDIA_RTP_PT_G722)
	    rtpmap.clock_rate = 8000;
	else
	    rtpmap.clock_rate = codec_info->clock_rate;
#else
	rtpmap.clock_rate = codec_info->clock_rate;
#endif

	/* For audio codecs, rtpmap parameters denotes the number
	 * of channels, which can be omited if the value is 1.
	 */
	if (codec_info->type == PJMEDIA_TYPE_AUDIO &&
	    codec_info->channel_cnt > 1)
	{
	    /* Can only support one digit channel count */
	    pj_assert(codec_info->channel_cnt < 10);

	    tmp_param[0] = (char)('0' + codec_info->channel_cnt);

	    rtpmap.param.ptr = tmp_param;
	    rtpmap.param.slen = 1;

	} else {
	    rtpmap.param.slen = 0;
	}

	if (codec_info->pt >= 96 || pjmedia_add_rtpmap_for_static_pt) {
	    pjmedia_sdp_rtpmap_to_attr(pool, &rtpmap, &attr);
	    m->attr[m->attr_count++] = attr;
	}

	/* Add fmtp params */
	if (codec_param.setting.dec_fmtp.cnt > 0) {
	    enum { MAX_FMTP_STR_LEN = 160 };
	    char buf[MAX_FMTP_STR_LEN];
	    unsigned buf_len = 0, i;
	    pjmedia_codec_fmtp *dec_fmtp = &codec_param.setting.dec_fmtp;

	    /* Print codec PT */
	    buf_len += pj_ansi_snprintf(buf, 
					MAX_FMTP_STR_LEN - buf_len, 
					"%d", 
					codec_info->pt);

	    for (i = 0; i < dec_fmtp->cnt; ++i) {
		unsigned test_len = 2;

		/* Check if buf still available */
		test_len = dec_fmtp->param[i].val.slen + 
			   dec_fmtp->param[i].name.slen;
		if (test_len + buf_len >= MAX_FMTP_STR_LEN)
		    return PJ_ETOOBIG;

		/* Print delimiter */
		buf_len += pj_ansi_snprintf(&buf[buf_len], 
					    MAX_FMTP_STR_LEN - buf_len,
					    (i == 0?" ":";"));

		/* Print an fmtp param */
		if (dec_fmtp->param[i].name.slen)
		    buf_len += pj_ansi_snprintf(
					    &buf[buf_len],
					    MAX_FMTP_STR_LEN - buf_len,
					    "%.*s=%.*s",
					    (int)dec_fmtp->param[i].name.slen,
					    dec_fmtp->param[i].name.ptr,
					    (int)dec_fmtp->param[i].val.slen,
					    dec_fmtp->param[i].val.ptr);
		else
		    buf_len += pj_ansi_snprintf(&buf[buf_len], 
					    MAX_FMTP_STR_LEN - buf_len,
					    "%.*s", 
					    (int)dec_fmtp->param[i].val.slen,
					    dec_fmtp->param[i].val.ptr);
	    }

	    attr = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_attr);

	    attr->name = pj_str("fmtp");
	    attr->value = pj_strdup3(pool, buf);
	    m->attr[m->attr_count++] = attr;
	}
    }

    /* Add sendrecv attribute. */
    attr = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_attr);
    attr->name = STR_SENDRECV;
    m->attr[m->attr_count++] = attr;

#if defined(PJMEDIA_RTP_PT_TELEPHONE_EVENTS) && \
    PJMEDIA_RTP_PT_TELEPHONE_EVENTS != 0

    /*
     * Add support telephony event
     */
    m->desc.fmt[m->desc.fmt_count++] = 
	pj_str(PJMEDIA_RTP_PT_TELEPHONE_EVENTS_STR);

    /* Add rtpmap. */
    attr = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_attr);
    attr->name = pj_str("rtpmap");
    attr->value = pj_str(PJMEDIA_RTP_PT_TELEPHONE_EVENTS_STR 
			 " telephone-event/8000");
    m->attr[m->attr_count++] = attr;

    /* Add fmtp */
    attr = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_attr);
    attr->name = pj_str("fmtp");
    attr->value = pj_str(PJMEDIA_RTP_PT_TELEPHONE_EVENTS_STR " 0-15");
    m->attr[m->attr_count++] = attr;
#endif

    /* Done */
    *p_sdp = sdp;

    return PJ_SUCCESS;

}
Esempio n. 9
0
/* Create m=video SDP media line */
PJ_DEF(pj_status_t) pjmedia_endpt_create_video_sdp(pjmedia_endpt *endpt,
																									 pj_pool_t *pool,
																									 const pjmedia_sock_info *si,
																									 unsigned options,
																									 pjmedia_sdp_media **p_m)
{


	const pj_str_t STR_VIDEO = { "video", 5 };
	pjmedia_sdp_media *m;
	pjmedia_vid_codec_info codec_info[PJMEDIA_VID_CODEC_MGR_MAX_CODECS];
	unsigned codec_prio[PJMEDIA_VID_CODEC_MGR_MAX_CODECS];
	pjmedia_sdp_attr *attr;
	unsigned cnt, i;
	unsigned max_bitrate = 0;
	pj_status_t status;

	PJ_UNUSED_ARG(options);

	/* Make sure video codec manager is instantiated */
	if (!pjmedia_vid_codec_mgr_instance())
		pjmedia_vid_codec_mgr_create(endpt->pool, NULL);

	/* Create and init basic SDP media */
	m = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_media);
	status = init_sdp_media(m, pool, &STR_VIDEO, si);
	if (status != PJ_SUCCESS)
		return status;

	cnt = PJ_ARRAY_SIZE(codec_info);
	status = pjmedia_vid_codec_mgr_enum_codecs(NULL, &cnt, 
		codec_info, codec_prio);

	/* Check that there are not too many codecs */
	PJ_ASSERT_RETURN(0 <= PJMEDIA_MAX_SDP_FMT,
		PJ_ETOOMANY);

	/* Add format, rtpmap, and fmtp (when applicable) for each codec */
	for (i=0; i<cnt; ++i) {
		pjmedia_sdp_rtpmap rtpmap;
		pjmedia_vid_codec_param codec_param;
		pj_str_t *fmt;
		pjmedia_video_format_detail *vfd;

		pj_bzero(&rtpmap, sizeof(rtpmap));

		if (codec_prio[i] == PJMEDIA_CODEC_PRIO_DISABLED)
			break;

		if (i > PJMEDIA_MAX_SDP_FMT) {
			/* Too many codecs, perhaps it is better to tell application by
			* returning appropriate status code.
			*/
			PJ_PERROR(3,(THIS_FILE, PJ_ETOOMANY,
				"Skipping some video codecs"));
			break;
		}

		/* Must support RTP packetization and bidirectional */
		if ((codec_info[i].packings & PJMEDIA_VID_PACKING_PACKETS) == 0 ||
			codec_info[i].dir != PJMEDIA_DIR_ENCODING_DECODING)
		{
			continue;
		}

		pjmedia_vid_codec_mgr_get_default_param(NULL, &codec_info[i],
			&codec_param);

		fmt = &m->desc.fmt[m->desc.fmt_count++];
		fmt->ptr = (char*) pj_pool_alloc(pool, 8);
		fmt->slen = pj_utoa(codec_info[i].pt, fmt->ptr);
		rtpmap.pt = *fmt;

		/* Encoding name */
		rtpmap.enc_name = codec_info[i].encoding_name;

		/* Clock rate */
		rtpmap.clock_rate = codec_info[i].clock_rate;

		if (codec_info[i].pt >= 96 || pjmedia_add_rtpmap_for_static_pt) {
			pjmedia_sdp_rtpmap_to_attr(pool, &rtpmap, &attr);
			m->attr[m->attr_count++] = attr;
		}

		/* Add fmtp params */
		if (codec_param.dec_fmtp.cnt > 0) {
			enum { MAX_FMTP_STR_LEN = 160 };
			char buf[MAX_FMTP_STR_LEN];
			unsigned buf_len = 0, j;
			pjmedia_codec_fmtp *dec_fmtp = &codec_param.dec_fmtp;

			/* Print codec PT */
			buf_len += pj_ansi_snprintf(buf, 
				MAX_FMTP_STR_LEN - buf_len, 
				"%d", 
				codec_info[i].pt);

			for (j = 0; j < dec_fmtp->cnt; ++j) {
				unsigned test_len = 2;

				/* Check if buf still available */
				test_len = dec_fmtp->param[j].val.slen + 
					dec_fmtp->param[j].name.slen;
				if (test_len + buf_len >= MAX_FMTP_STR_LEN)
					return PJ_ETOOBIG;

				/* Print delimiter */
				buf_len += pj_ansi_snprintf(&buf[buf_len], 
					MAX_FMTP_STR_LEN - buf_len,
					(j == 0?" ":";"));

				/* Print an fmtp param */
				if (dec_fmtp->param[j].name.slen)
					buf_len += pj_ansi_snprintf(
					&buf[buf_len],
					MAX_FMTP_STR_LEN - buf_len,
					"%.*s=%.*s",
					(int)dec_fmtp->param[j].name.slen,
					dec_fmtp->param[j].name.ptr,
					(int)dec_fmtp->param[j].val.slen,
					dec_fmtp->param[j].val.ptr);
				else
					buf_len += pj_ansi_snprintf(&buf[buf_len], 
					MAX_FMTP_STR_LEN - buf_len,
					"%.*s", 
					(int)dec_fmtp->param[j].val.slen,
					dec_fmtp->param[j].val.ptr);
			}

			attr = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_attr);

			attr->name = pj_str("fmtp");
			attr->value = pj_strdup3(pool, buf);
			m->attr[m->attr_count++] = attr;
		}

		/* Find maximum bitrate in this media */
		vfd = pjmedia_format_get_video_format_detail(&codec_param.enc_fmt,
			PJ_TRUE);
		if (vfd && max_bitrate < vfd->max_bps)
			max_bitrate = vfd->max_bps;
	}

	/* Put bandwidth info in media level using bandwidth modifier "TIAS"
	* (RFC3890).
	*/
	if (max_bitrate) {
		const pj_str_t STR_BANDW_MODIFIER = { "TIAS", 4 };
		pjmedia_sdp_bandw *b;

		b = PJ_POOL_ALLOC_T(pool, pjmedia_sdp_bandw);
		b->modifier = STR_BANDW_MODIFIER;
		b->value = max_bitrate;
		m->bandw[m->bandw_count++] = b;
	}

	*p_m = m;
	return PJ_SUCCESS;
}
Esempio n. 10
0
/* Create m=audio SDP media line */
PJ_DEF(pj_status_t) pjmedia_endpt_create_audio_sdp(pjmedia_endpt *endpt,
																									 pj_pool_t *pool,
																									 const pjmedia_sock_info *si,
																									 unsigned options,
																									 pjmedia_sdp_media **p_m)
{
	const pj_str_t STR_AUDIO = { "audio", 5 };
	pjmedia_sdp_media *m;
	pjmedia_sdp_attr *attr;
	unsigned i;
	unsigned max_bitrate = 0;
	pj_status_t status;

	PJ_UNUSED_ARG(options);

	/* Check that there are not too many codecs */
	PJ_ASSERT_RETURN(endpt->codec_mgr.codec_cnt <= PJMEDIA_MAX_SDP_FMT,
		PJ_ETOOMANY);

	/* Create and init basic SDP media */
	m = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_media);
	status = init_sdp_media(m, pool, &STR_AUDIO, si);
	if (status != PJ_SUCCESS)
		return status;

	/* Add format, rtpmap, and fmtp (when applicable) for each codec */
	for (i=0; i<endpt->codec_mgr.codec_cnt; ++i) {

		pjmedia_codec_info *codec_info;
		pjmedia_sdp_rtpmap rtpmap;
		char tmp_param[3];
		pjmedia_codec_param codec_param;
		pj_str_t *fmt;

		if (endpt->codec_mgr.codec_desc[i].prio == PJMEDIA_CODEC_PRIO_DISABLED)
			break;

		codec_info = &endpt->codec_mgr.codec_desc[i].info;
		pjmedia_codec_mgr_get_default_param(&endpt->codec_mgr, codec_info,
			&codec_param);
		fmt = &m->desc.fmt[m->desc.fmt_count++];

		fmt->ptr = (char*) pj_pool_alloc(pool, 8);
		fmt->slen = pj_utoa(codec_info->pt, fmt->ptr);

		rtpmap.pt = *fmt;
		rtpmap.enc_name = codec_info->encoding_name;

#if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG != 0)
		if (codec_info->pt == PJMEDIA_RTP_PT_G722)
			rtpmap.clock_rate = 8000;
		else
			rtpmap.clock_rate = codec_info->clock_rate;
#else
		rtpmap.clock_rate = codec_info->clock_rate;
#endif

		/* For audio codecs, rtpmap parameters denotes the number
		* of channels, which can be omited if the value is 1.
		*/
		if (codec_info->type == PJMEDIA_TYPE_AUDIO &&
			codec_info->channel_cnt > 1)
		{
			/* Can only support one digit channel count */
			pj_assert(codec_info->channel_cnt < 10);

			tmp_param[0] = (char)('0' + codec_info->channel_cnt);

			rtpmap.param.ptr = tmp_param;
			rtpmap.param.slen = 1;

		} else {
			rtpmap.param.ptr = "";
			rtpmap.param.slen = 0;
		}

		if (codec_info->pt >= 96 || pjmedia_add_rtpmap_for_static_pt) {
			pjmedia_sdp_rtpmap_to_attr(pool, &rtpmap, &attr);
			m->attr[m->attr_count++] = attr;
		}

		/* Add fmtp params */
		if (codec_param.setting.dec_fmtp.cnt > 0) {
			enum { MAX_FMTP_STR_LEN = 160 };
			char buf[MAX_FMTP_STR_LEN];
			unsigned buf_len = 0, i;
			pjmedia_codec_fmtp *dec_fmtp = &codec_param.setting.dec_fmtp;

			/* Print codec PT */
			buf_len += pj_ansi_snprintf(buf, 
				MAX_FMTP_STR_LEN - buf_len, 
				"%d", 
				codec_info->pt);

			for (i = 0; i < dec_fmtp->cnt; ++i) {
				unsigned test_len = 2;

				/* Check if buf still available */
				test_len = dec_fmtp->param[i].val.slen + 
					dec_fmtp->param[i].name.slen;
				if (test_len + buf_len >= MAX_FMTP_STR_LEN)
					return PJ_ETOOBIG;

				/* Print delimiter */
				buf_len += pj_ansi_snprintf(&buf[buf_len], 
					MAX_FMTP_STR_LEN - buf_len,
					(i == 0?" ":";"));

				/* Print an fmtp param */
				if (dec_fmtp->param[i].name.slen)
					buf_len += pj_ansi_snprintf(
					&buf[buf_len],
					MAX_FMTP_STR_LEN - buf_len,
					"%.*s=%.*s",
					(int)dec_fmtp->param[i].name.slen,
					dec_fmtp->param[i].name.ptr,
					(int)dec_fmtp->param[i].val.slen,
					dec_fmtp->param[i].val.ptr);
				else
					buf_len += pj_ansi_snprintf(&buf[buf_len], 
					MAX_FMTP_STR_LEN - buf_len,
					"%.*s", 
					(int)dec_fmtp->param[i].val.slen,
					dec_fmtp->param[i].val.ptr);
			}

			attr = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_attr);

			attr->name = pj_str("fmtp");
			attr->value = pj_strdup3(pool, buf);
			m->attr[m->attr_count++] = attr;
		}

		/* Find maximum bitrate in this media */
		if (max_bitrate < codec_param.info.max_bps)
			max_bitrate = codec_param.info.max_bps;
	}

#if defined(PJMEDIA_RTP_PT_TELEPHONE_EVENTS) && \
	PJMEDIA_RTP_PT_TELEPHONE_EVENTS != 0
	/*
	* Add support telephony event
	*/
	if (endpt->has_telephone_event) {
		m->desc.fmt[m->desc.fmt_count++] =
			pj_str(PJMEDIA_RTP_PT_TELEPHONE_EVENTS_STR);

		/* Add rtpmap. */
		attr = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_attr);
		attr->name = pj_str("rtpmap");
		attr->value = pj_str(PJMEDIA_RTP_PT_TELEPHONE_EVENTS_STR
			" telephone-event/8000");
		m->attr[m->attr_count++] = attr;

		/* Add fmtp */
		attr = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_attr);
		attr->name = pj_str("fmtp");
		attr->value = pj_str(PJMEDIA_RTP_PT_TELEPHONE_EVENTS_STR " 0-15");
		m->attr[m->attr_count++] = attr;
	}
#endif

	/* Put bandwidth info in media level using bandwidth modifier "TIAS"
	* (RFC3890).
	*/
	if (max_bitrate) {
		const pj_str_t STR_BANDW_MODIFIER = { "TIAS", 4 };
		pjmedia_sdp_bandw *b;

		b = PJ_POOL_ALLOC_T(pool, pjmedia_sdp_bandw);
		b->modifier = STR_BANDW_MODIFIER;
		b->value = max_bitrate;
		m->bandw[m->bandw_count++] = b;
	}

	*p_m = m;
	return PJ_SUCCESS;
}
Esempio n. 11
0
/*
 * Send PUBLISH request.
 */
pj_status_t
SIPPresence::send_publish(SIPPresence * pres)
{
    pjsip_tx_data *tdata;
    pj_status_t status;

    DEBUG("Send PUBLISH (%s).", pres->getAccount()->getAccountID().c_str());

    SIPAccount * acc = pres->getAccount();
    std::string contactWithAngles =  acc->getFromUri();
    contactWithAngles.erase(contactWithAngles.find('>'));
    int semicolon = contactWithAngles.find_first_of(":");
    std::string contactWithoutAngles = contactWithAngles.substr(semicolon + 1);
//    pj_str_t contact = pj_str(strdup(contactWithoutAngles.c_str()));
//    pj_memcpy(&status_data.info[0].contact, &contt, sizeof(pj_str_t));;

    /* Create PUBLISH request */
    char *bpos;
    pj_str_t entity;

    status = pjsip_publishc_publish(pres->publish_sess_, PJ_TRUE, &tdata);
    pj_str_t from = pj_strdup3(pres->pool_, acc->getFromUri().c_str());

    if (status != PJ_SUCCESS) {
        ERROR("Error creating PUBLISH request", status);
        goto on_error;
    }

    if ((bpos = pj_strchr(&from, '<')) != NULL) {
        char *epos = pj_strchr(&from, '>');

        if (epos - bpos < 2) {
            pj_assert(!"Unexpected invalid URI");
            status = PJSIP_EINVALIDURI;
            goto on_error;
        }

        entity.ptr = bpos + 1;
        entity.slen = epos - bpos - 1;
    } else {
        entity = from;
    }

    /* Create and add PIDF message body */
    status = pjsip_pres_create_pidf(tdata->pool, pres->getStatus(),
                                    &entity, &tdata->msg->body);

    pres_msg_data msg_data;

    if (status != PJ_SUCCESS) {
        ERROR("Error creating PIDF for PUBLISH request");
        pjsip_tx_data_dec_ref(tdata);
        goto on_error;
    }

    pj_bzero(&msg_data, sizeof(msg_data));
    pj_list_init(&msg_data.hdr_list);
    pjsip_media_type_init(&msg_data.multipart_ctype, NULL, NULL);
    pj_list_init(&msg_data.multipart_parts);

    pres->fillDoc(tdata, &msg_data);

    /* Send the PUBLISH request */
    status = pjsip_publishc_send(pres->publish_sess_, tdata);

    if (status == PJ_EPENDING) {
        WARN("Previous request is in progress, ");
    } else if (status != PJ_SUCCESS) {
        ERROR("Error sending PUBLISH request");
        goto on_error;
    }

    return PJ_SUCCESS;

on_error:

    if (pres->publish_sess_) {
        pjsip_publishc_destroy(pres->publish_sess_);
        pres->publish_sess_ = NULL;
    }

    return status;
}