Пример #1
0
static int pv_get_sdp(sip_msg_t *msg, pv_param_t *param,
		pv_value_t *res)
{
	sdp_info_t *sdp = NULL;

	if(msg==NULL || param==NULL)
		return -1;

	if(parse_sdp(msg) < 0) {
		LM_INFO("Unable to parse sdp\n");
		return pv_get_null(msg, param, res);
	}
	sdp = (sdp_info_t*)msg->body;

	if (sdp==NULL) {
		LM_DBG("No SDP\n");
		return pv_get_null(msg, param, res);
	}

	switch(param->pvn.u.isname.name.n)
	{
		case 0:
			return pv_get_strval(msg, param, res, &sdp->raw_sdp);
		default:
			return pv_get_null(msg, param, res);
	}
}
Пример #2
0
int sdp_keep_codecs_by_name(sip_msg_t* msg, str* codecs, str *media)
{
	sdp_info_t *sdp = NULL;
	str idslist;

	if(parse_sdp(msg) < 0) {
		LM_ERR("Unable to parse sdp\n");
		return -1;
	}

	sdp = (sdp_info_t*)msg->body;

	if(sdp==NULL) {
		LM_DBG("No sdp body\n");
		return -1;
	}

	LM_DBG("attempting to keep codecs in sdp: [%.*s]\n",
			codecs->len, codecs->s);

	if(sdpops_build_ids_list(sdp, codecs, &idslist)<0)
		return -1;

	if(sdp_keep_codecs_by_id(msg, &idslist, media)<0)
		return -1;

	return 0;

}
Пример #3
0
int sdp_with_codecs_by_name(sip_msg_t* msg, str* codecs)
{
	str idslist;
	sdp_info_t *sdp = NULL;
	int ret;

	if(parse_sdp(msg) < 0) {
		LM_ERR("Unable to parse sdp\n");
		return -1;
	}

	sdp = (sdp_info_t*)msg->body;

	if(sdp==NULL) {
		LM_DBG("No sdp body\n");
		return -1;
	}

	if(sdpops_build_ids_list(sdp, codecs, &idslist)<0)
		return -1;

	ret = sdp_with_codecs_by_id(msg, &idslist);
	/* ret: -1 error; 0 not found */
	if(ret<=0)
		return (ret - 1);
	return ret;
}
Пример #4
0
int sdp_keep_codecs_by_id(sip_msg_t* msg, str* codecs)
{
	sdp_info_t *sdp = NULL;
	int sdp_session_num;
	int sdp_stream_num;
	sdp_session_cell_t* sdp_session;
	sdp_stream_cell_t* sdp_stream;
	str sdp_codecs;
	str tmp_codecs;
	str rm_codec;

	if(parse_sdp(msg) < 0) {
		LM_ERR("Unable to parse sdp\n");
		return -1;
	}

	LM_ERR("attempting to keep codecs in sdp: [%.*s]\n",
			codecs->len, codecs->s);

	sdp = (sdp_info_t*)msg->body;

	sdp_session_num = 0;
	for(;;)
	{
		sdp_session = get_sdp_session(msg, sdp_session_num);
		if(!sdp_session) break;
		sdp_stream_num = 0;
		for(;;)
		{
			sdp_stream = get_sdp_stream(msg, sdp_session_num, sdp_stream_num);
			if(!sdp_stream) break;

			LM_DBG("stream %d of %d - payloads [%.*s]\n",
				sdp_stream_num, sdp_session_num,
				sdp_stream->payloads.len, sdp_stream->payloads.s);
			sdp_codecs = sdp_stream->payloads;
			tmp_codecs = sdp_stream->payloads;
			while(str_find_token(&tmp_codecs, &rm_codec, ' ')==0
					&& rm_codec.len>0)
			{
				tmp_codecs.len -=(int)(&rm_codec.s[rm_codec.len]-tmp_codecs.s);
				tmp_codecs.s = rm_codec.s + rm_codec.len;

				if(sdp_codec_in_str(codecs, &rm_codec, ',')==0) {
					LM_DBG("codecs [%.*s] - remove [%.*s]\n",
						sdp_codecs.len, sdp_codecs.s,
						rm_codec.len, rm_codec.s);
					sdp_remove_str_codec_id(msg, &sdp_codecs, &rm_codec);
					sdp_remove_str_codec_id_attrs(msg, sdp_stream, &rm_codec);
				}
			}
			sdp_stream_num++;
		}
		sdp_session_num++;
	}

	return 0;
}
Пример #5
0
static int w_sdp_get(sip_msg_t* msg, char *avp)
{
	sdp_info_t *sdp = NULL;
	int_str avp_val;
	int_str avp_name;
	static unsigned short avp_type = 0;
	str s;
	pv_spec_t *avp_spec = NULL;
	int sdp_missing=1;

	s.s = avp; s.len = strlen(s.s);
	if (pv_locate_name(&s) != s.len)
	{
		LM_ERR("invalid parameter\n");
		return -1;
	}
	if (((avp_spec = pv_cache_get(&s)) == NULL)
			|| avp_spec->type!=PVT_AVP) {
		LM_ERR("malformed or non AVP %s AVP definition\n", avp);
		return -1;
	}

	if(pv_get_avp_name(0, &avp_spec->pvp, &avp_name, &avp_type)!=0)
	{
		LM_ERR("[%s]- invalid AVP definition\n", avp);
		return -1;
	}

	sdp_missing = parse_sdp(msg);
	if(sdp_missing < 0) {
		LM_ERR("Unable to parse sdp\n");
		return -1;
	}
	sdp = (sdp_info_t*)msg->body;

	if (sdp==NULL) {
		LM_DBG("No SDP\n");
		return -2;
	}

	avp_val.s.s = sdp->raw_sdp.s;
	avp_val.s.len = sdp->raw_sdp.len;
	LM_DBG("Found SDP %.*s\n", sdp->raw_sdp.len, sdp->raw_sdp.s);

	if (add_avp(AVP_VAL_STR | avp_type, avp_name, avp_val) != 0)
	{
		LM_ERR("Failed to add SDP avp");
		return -1;
	}

	return 1;
}
Пример #6
0
/**
 * @brief check 'media' matches the value of any 'm=value ...' lines, and that line is active
 * @return -1 - error; 0 - not found or inactive; 1 - at least one sendrecv, recvonly or sendonly stream
 */
static int sdp_with_active_media(sip_msg_t *msg, str *media)
{
	int sdp_session_num;
	int sdp_stream_num;
	int port_num;
	sdp_session_cell_t* sdp_session;
	sdp_stream_cell_t* sdp_stream;

	if(parse_sdp(msg) < 0) {
		LM_ERR("Unable to parse sdp\n");
		return -1;
	}

	LM_DBG("attempting to search for media type: [%.*s]\n",
			media->len, media->s);

	sdp_session_num = 0;
	for(;;)
	{
		sdp_session = get_sdp_session(msg, sdp_session_num);
		if(!sdp_session) break;
		sdp_stream_num = 0;
		for(;;)
		{
			sdp_stream = get_sdp_stream(msg, sdp_session_num, sdp_stream_num);
			if(!sdp_stream) break;

			LM_DBG("stream %d of %d - media [%.*s]\n",
					sdp_stream_num, sdp_session_num,
					sdp_stream->media.len, sdp_stream->media.s);
			if(media->len==sdp_stream->media.len
					&& strncasecmp(sdp_stream->media.s, media->s,
						media->len)==0) {
				port_num = atoi(sdp_stream->port.s);
				LM_DBG("Port number is %d\n", port_num);
				if (port_num != 0) {  /* Zero port number => inactive */
					LM_DBG("sendrecv_mode %.*s\n", sdp_stream->sendrecv_mode.len, sdp_stream->sendrecv_mode.s);
					if ((sdp_stream->sendrecv_mode.len == 0) || /* No send/recv mode given => sendrecv */
						(strncasecmp(sdp_stream->sendrecv_mode.s, "inactive", 8) != 0)) { /* Explicit mode is not inactive */
						/* Found an active stream for the correct media type */
						return 1;
					}
				}
			}
			sdp_stream_num++;
		}
		sdp_session_num++;
	}

	return 0;
}
Пример #7
0
/**
 * Every time a new dialog is created (from a new INVITE) the dialog
 * module will call this callback function. We need to track the
 * dialogs lifespan from this point forward until it is terminated
 * with a BYE, CANCEL, etc. In the process, we will see if either or
 * both ends of the conversation are trying to re-negotiate the media.
 *
 * This function will setup the other types of dialog callbacks
 * required to track the lifespan of the dialog.
 *
 *
 * @param did   - The dialog ID
 * @param type  - The trigger event type (CREATED)
 * @param msg   - The SIP message that triggered the callback (INVITE)
 * @param param - The pointer to nothing. As we did not attach
 *                anything to this callback in the dialog module.
 */
void qos_dialog_created_CB(struct dlg_cell *did, int type, struct dlg_cb_params * params)
{
	qos_ctx_t *qos_ctx = NULL;
	struct sip_msg* msg = params->req;
	unsigned int dir = params->direction, role, other_role;

	if (dir == DLG_DIR_UPSTREAM) {
		role = QOS_CALLEE;
		other_role = QOS_CALLER;
	} else if (dir == DLG_DIR_DOWNSTREAM) {
		role = QOS_CALLER;
		other_role = QOS_CALLEE;
	} else {
		LM_ERR("Unknown dir %d\n", dir);
		return;
	}

	if (msg == NULL || msg == FAKED_REPLY) {
		LM_ERR("Improper msg\n");
		return;
	}

	/* look only at INVITE */
	if (msg->first_line.type != SIP_REQUEST ||
		msg->first_line.u.request.method_value != METHOD_INVITE) {
		LM_WARN("Dialog create callback called with a non-INVITE req.\n");
		return;
	}

	qos_ctx = build_new_qos_ctx();
	if (qos_ctx==NULL) {
		/* Error message printed in build_new_qos_ctx() */
		return;
	}

	LM_DBG("setup_dialog_callbacks( %p , %p )\n", did, qos_ctx);
	setup_dialog_callbacks(did, qos_ctx);

	run_create_cbs(qos_ctx, msg);

	if (0 == parse_sdp(msg)) {
		lock_get(&qos_ctx->lock);
		add_sdp(qos_ctx, dir, msg, role, other_role);
		lock_release(&qos_ctx->lock);
	}


	return;
}
Пример #8
0
/**
 * @brief check 'media' matches the value of any 'm=media port value ...' lines
 * @return -1 - error; 0 - not found; 1 - found
 */
static int sdp_with_transport(sip_msg_t *msg, str *transport, int like)
{
	int sdp_session_num;
	int sdp_stream_num;
	sdp_session_cell_t* sdp_session;
	sdp_stream_cell_t* sdp_stream;

	if(parse_sdp(msg) < 0) {
		LM_ERR("Unable to parse sdp\n");
		return -1;
	}

	LM_DBG("attempting to search for transport type: [%.*s]\n",
			transport->len, transport->s);

	sdp_session_num = 0;
	for(;;)
	{
		sdp_session = get_sdp_session(msg, sdp_session_num);
		if(!sdp_session) break;
		sdp_stream_num = 0;
		for(;;)
		{
			sdp_stream = get_sdp_stream(msg, sdp_session_num, sdp_stream_num);
			if(!sdp_stream) break;

			LM_DBG("stream %d of %d - transport [%.*s]\n",
					sdp_stream_num, sdp_session_num,
					sdp_stream->transport.len, sdp_stream->transport.s);
			if (like == 0) {
				if(transport->len==sdp_stream->transport.len
						&& strncasecmp(sdp_stream->transport.s, transport->s,
							transport->len)==0)
				return 1;
			} else {
				if (ser_memmem(sdp_stream->transport.s, transport->s,
						sdp_stream->transport.len, transport->len)!=NULL)
				return 1;
			}
			sdp_stream_num++;
		}
		sdp_session_num++;
	}

	return 0;
}
Пример #9
0
/** 
 * @brief check 'media' matches the value of any 'm=value ...' lines
 * @return -1 - error; 0 - not found; 1 - found
 */
static int sdp_with_media(sip_msg_t *msg, str *media)
{
	sdp_info_t *sdp = NULL;
	int sdp_session_num;
	int sdp_stream_num;
	sdp_session_cell_t* sdp_session;
	sdp_stream_cell_t* sdp_stream;

	if(parse_sdp(msg) < 0) {
		LM_ERR("Unable to parse sdp\n");
		return -1;
	}

	LM_DBG("attempting to search for media type: [%.*s]\n",
			media->len, media->s);

	sdp = (sdp_info_t*)msg->body;

	sdp_session_num = 0;
	for(;;)
	{
		sdp_session = get_sdp_session(msg, sdp_session_num);
		if(!sdp_session) break;
		sdp_stream_num = 0;
		for(;;)
		{
			sdp_stream = get_sdp_stream(msg, sdp_session_num, sdp_stream_num);
			if(!sdp_stream) break;

			LM_DBG("stream %d of %d - media [%.*s]\n",
				sdp_stream_num, sdp_session_num,
				sdp_stream->media.len, sdp_stream->media.s);
			if(media->len==sdp_stream->media.len
					&& strncasecmp(sdp_stream->media.s, media->s,
							media->len)==0)
				return 1;
			sdp_stream_num++;
		}
		sdp_session_num++;
	}

	return 0;
}
Пример #10
0
//open the sdp info
static int rtsp_rtp_recv_start(RTSP_HANDLE *rtsp_handle)
{
	char sdp_info[2048] = {0};
	if(rtsp_handle == NULL || strlen(rtsp_handle->sdp_info) == 0)
	{
		PRINTF("rtsp_rtp_recv_start:the sdp info ERROR\n");
		return -1;
	}
	SDP_Info* info=parse_sdp(rtsp_handle->sdp_info,strlen(rtsp_handle->sdp_info));
	if( !info )
	{
		PRINTF("rtsp_rtp_recv_start:sdp_info NULL\n");
		return -1;
	}
	PRINTF("rtsp_rtp_recv_start:info->video=%d,audio=%d,config=0x%x,IP=%s,info->type=%d\n",
		info->video_port,info->audio_port,info->config,info->IP,info->type);
	
	/****** video ********/
	rtsp_handle->video_handle = rtp_video_open_url(info);
	if(rtsp_handle->video_handle == NULL)
		{
		PRINTF("rtsp_rtp_recv_start:rtsp_handle->video_handle  NULL\n");
		return -1;
	}else{
		rtsp_handle->video_handle->fCCEvent = (Msg_func)rtsp_handle->fCCEvent;
		if(rtsp_handle->fGetVideoEs)
			rtsp_handle->video_handle->fGetVideoEs = (VideoEsCallBack)rtsp_handle->fGetVideoEs;
	}
	/******* audio *********/
	rtsp_handle->audio_handle= rtp_audio_open_url(info);
	if(rtsp_handle->audio_handle == NULL)
		{
		PRINTF("rtsp_rtp_recv_start:rtsp_handle->audio_handle  NULL\n");
		return -1;
	}else {
		rtsp_handle->audio_handle->fCCEvent = (Msg_func)rtsp_handle->fCCEvent;
		if(rtsp_handle->fGetAudioEs)
			rtsp_handle->audio_handle->fGetVideoEs = (VideoEsCallBack)rtsp_handle->fGetAudioEs;
		}
	free(info);
	info=NULL;
	return 0;
}
Пример #11
0
static int do_for_all_streams(struct sip_msg* msg, str* str1,str * str2,
				regex_t* re, int op,int desc)
{
	struct sdp_session_cell * cur_session;
	int rez;

	if (msg==NULL || msg==FAKED_REPLY)
		return -1;

	if(parse_sdp(msg))
	{
		LM_DBG("Message has no SDP\n");
		return -1;
	}

	if (get_codec_lumps(msg)<0) {
		LM_ERR("failed to prepare changes for codecs\n");
		return -1;
	}

	cur_session = msg->sdp->sessions;
	rez = 0;

	while(cur_session)
	{
		struct sdp_stream_cell * cur_cell = cur_session->streams;

		while(cur_cell)
		{
			rez |= stream_process(msg,cur_cell,str1,str2,re,op,desc);
			cur_cell = cur_cell->next;
		}

		cur_session = cur_session->next;

	}

	if( rez <0 )
		rez = 0;
	return rez;
}
Пример #12
0
int sdp_keep_codecs_by_name(sip_msg_t* msg, str* codecs)
{
	str idslist;

	if(parse_sdp(msg) < 0) {
		LM_ERR("Unable to parse sdp\n");
		return -1;
	}

	LM_ERR("attempting to keep codecs in sdp: [%.*s]\n",
			codecs->len, codecs->s);

	if(sdpops_build_ids_list(codecs, &idslist)<0)
		return -1;

	if(sdp_keep_codecs_by_id(msg, &idslist)<0)
		return -1;

	return 0;

}
Пример #13
0
static int w_sdp_print(sip_msg_t* msg, char* level, char *bar)
{
	sdp_info_t *sdp = NULL;
	int llevel = L_DBG;

	if(parse_sdp(msg) < 0) {
		LM_ERR("Unable to parse sdp\n");
		return -1;
	}

	if(fixup_get_ivalue(msg, (gparam_p)level, &llevel)!=0)
	{
		LM_ERR("unable to get the debug level value\n");
		return -1;
	}

	sdp = (sdp_info_t*)msg->body;

	print_sdp(sdp, llevel);
	return 1;
}
Пример #14
0
bool parse_sap(int length, uint32_t* data){//Parse SAP, false for an unaccepted annoucement, true for everything else (including parsing errors)
	DBG("Length sap:%d\n",length);
	struct saphdr* header = (struct saphdr*)data;
	if(header->version != 1){
		fprintf(stderr,"Version 0x%x unsuported!\n",header->version);
		return true;
	}

	if(header->type == 1) return true;

	data = (uint32_t*)(((unsigned long)data) + 8 + 4*(header->encrypted) + 4*(header->auth_len)); 
	length -= (8 +4*(header->encrypted) + 4*(header->auth_len));
	DBG("Length sap without flags:%d\n",length);
	if(((char*)(data))[1] != '='){//got MIME-Type/payloadType 
		length -= (strlen((char*)data) + 1);
		data = (uint32_t*)((unsigned long)data + strlen((char*)data) + 1);
		DBG("Length sap without mime:%d\n",length);
	}
	
	return parse_sdp(length,data);
}	
Пример #15
0
/**
 *
 * @param did - The dialog structure. The pointer is used as an ID.
 * @param type - The reason for the callback. DLGCB_REQ_WITHIN
 * @param msg - The SIP message that causes the callback.
 * @param param - The qos information
 */
static void qos_dialog_request_CB(struct dlg_cell* did, int type, struct dlg_cb_params * params)
{
	struct sip_msg* msg = params->req;
	unsigned int dir = params->direction, role, other_role;
	qos_ctx_t* qos_ctx = (qos_ctx_t*)*(params->param);

	if (dir == DLG_DIR_UPSTREAM) {
		role = QOS_CALLEE;
		other_role = QOS_CALLER;
	} else if (dir == DLG_DIR_DOWNSTREAM) {
		role = QOS_CALLER;
		other_role = QOS_CALLEE;
	} else {
		LM_ERR("Unknown dir %d\n", dir);
		return;
	}

	if (msg->first_line.type == SIP_REQUEST) {
		if (    (msg->first_line.u.request.method_value == METHOD_INVITE) ||
			(msg->first_line.u.request.method_value == METHOD_UPDATE) ||
			(msg->first_line.u.request.method_value == METHOD_ACK) ||
			(msg->first_line.u.request.method_value == METHOD_PRACK)) {
			if (0 == parse_sdp(msg)) {
				lock_get(&qos_ctx->lock);
				add_sdp(qos_ctx, dir, msg, role, other_role);
				lock_release(&qos_ctx->lock);
			}
		} else {
			LM_DBG("Ignoring non-carrying SDP req\n");
			return;
		}
	} else {
		LM_ERR("not a SIP_REQUEST\n");
		return;
	}

	return;
}
Пример #16
0
/**
 * This callback is called on any response message in the lifespan of
 * the dialog. The callback is called just before the message is
 * copied to pkg memory so it is still mutable.
 *
 * @param did - The dialog structure. The pointer is used as an ID.
 * @param type - The reason for the callback. DLGCB_CONFIRMED
 * @param msg - The SIP message that causes the callback.
 * @param param - The qos information
 */
static void qos_dialog_response_CB(struct dlg_cell* did, int type, struct dlg_cb_params * params)
{
	struct sip_msg* msg = params->rpl;
	unsigned int dir = params->direction, role, other_role;
	qos_ctx_t* qos_ctx = (qos_ctx_t*)*(params->param);

	if (dir == DLG_DIR_UPSTREAM) {
		role = QOS_CALLEE;
		other_role = QOS_CALLER;
	} else if (dir == DLG_DIR_DOWNSTREAM) {
		role = QOS_CALLER;
		other_role = QOS_CALLEE;
	} else {
		LM_ERR("Unknown dir %d\n", dir);
		return;
	}

	if (msg->first_line.type == SIP_REPLY) {
		if (msg->first_line.u.reply.statuscode > 100 &&
			msg->first_line.u.reply.statuscode < 300) {
			if (0 == parse_sdp(msg)) {
				lock_get(&qos_ctx->lock);
				add_sdp(qos_ctx, dir, msg, role, other_role);
				lock_release(&qos_ctx->lock);
			}
		} else if (msg->first_line.u.reply.statuscode > 399 &&
			msg->first_line.u.reply.statuscode < 700) {
			lock_get(&qos_ctx->lock);
			remove_sdp(qos_ctx, dir, msg, role, other_role);
			lock_release(&qos_ctx->lock);
		}
	} else {
		LM_ERR("not a SIP_REPLY\n");
		return;
	}

	return;
}
Пример #17
0
/* XXX this considers any held stream to mean the call is on hold. correct? */
    int
sca_call_is_held( sip_msg_t *msg )
{
    sdp_session_cell_t	*session;
    sdp_stream_cell_t	*stream;
    int			n_sess;
    int			n_str;
    int			is_held = 0;
    int			rc;

    rc = parse_sdp( msg );
    if ( rc < 0 ) {
	LM_ERR( "sca_call_is_held: parse_sdp body failed" );
	return( 0 );
    } else if ( rc > 0 ) {
	LM_DBG( "sca_call_is_held: parse_sdp returned %d, no SDP body", rc );
	return( 0 );
    }

    /* Cf. modules_k/textops's exported is_audio_on_hold */
    for ( n_sess = 0, session = get_sdp_session( msg, n_sess );
	    session != NULL;
	    n_sess++, session = get_sdp_session( msg, n_sess )) {

	for ( n_str = 0, stream = get_sdp_stream( msg, n_sess, n_str );
		stream != NULL;
		n_str++, stream = get_sdp_stream( msg, n_sess, n_str )) {
	    if ( stream->is_on_hold ) {
		is_held = 1;
		goto done;
	    }
	}
    }

done:
    return( is_held );
}
Пример #18
0
int sdp_with_codecs_by_id(sip_msg_t* msg, str* codecs)
{
	sdp_info_t *sdp = NULL;
	int sdp_session_num;
	int sdp_stream_num;
	sdp_session_cell_t* sdp_session;
	sdp_stream_cell_t* sdp_stream;
	str sdp_codecs;
	str tmp_codecs;
	str fnd_codec;
	int foundone = 0;
	int notfound = 0;

	if(parse_sdp(msg) < 0) {
		LM_ERR("Unable to parse sdp\n");
		return -1;
	}

	sdp = (sdp_info_t*)msg->body;

	if(sdp==NULL) {
		LM_DBG("No sdp body\n");
		return -1;
	}

	LM_DBG("attempting to search codecs in sdp: [%.*s]\n",
			codecs->len, codecs->s);

	sdp_session_num = 0;
	for(;;)
	{
		sdp_session = get_sdp_session(msg, sdp_session_num);
		if(!sdp_session) break;
		sdp_stream_num = 0;
		for(;;)
		{
			sdp_stream = get_sdp_stream(msg, sdp_session_num, sdp_stream_num);
			if(!sdp_stream) break;

			LM_DBG("stream %d of %d - payloads [%.*s]\n",
					sdp_stream_num, sdp_session_num,
					sdp_stream->payloads.len, sdp_stream->payloads.s);
			sdp_codecs = sdp_stream->payloads;
			tmp_codecs = *codecs;
			while(str_find_token(&tmp_codecs, &fnd_codec, ',')==0
					&& fnd_codec.len>0)
			{
				tmp_codecs.len -=(int)(&fnd_codec.s[fnd_codec.len]-tmp_codecs.s);
				tmp_codecs.s = fnd_codec.s + fnd_codec.len;

				if(sdp_codec_in_str(&sdp_codecs, &fnd_codec, ' ')==0) {
					LM_DBG("codecs [%.*s] - not found [%.*s]\n",
							sdp_codecs.len, sdp_codecs.s,
							fnd_codec.len, fnd_codec.s);
					notfound = 1;
				} else {
					LM_DBG("codecs [%.*s] - found [%.*s]\n",
							sdp_codecs.len, sdp_codecs.s,
							fnd_codec.len, fnd_codec.s);
					foundone = 1;
				}
			}
			sdp_stream_num++;
		}
		sdp_session_num++;
	}

	return (foundone + ((foundone)?notfound:0));
}
Пример #19
0
/** Helper function for adding media component AVPs for each SDP stream*/
int add_media_components(AAAMessage* aar, struct sip_msg *req,
        struct sip_msg *rpl, enum dialog_direction direction, AAASession* auth) {
    int sdp_session_num;
    int sdp_stream_num;
    sdp_session_cell_t* req_sdp_session, *rpl_sdp_session;
    sdp_stream_cell_t* req_sdp_stream, *rpl_sdp_stream;
    int add_flow = 1;

    if (!req || !rpl) {
        return CSCF_RETURN_FALSE;
    }

    if (parse_sdp(req) < 0) {
        LM_ERR("Unable to parse req SDP\n");
        return CSCF_RETURN_FALSE;
    }

    if (parse_sdp(rpl) < 0) {
        LM_ERR("Unable to parse res SDP\n");
        return CSCF_RETURN_FALSE;
    }

    sdp_session_num = 0;

    //Loop through req sessions and streams and get corresponding rpl sessions and streams and populate avps
    for (;;) {
        //we only cater for one session at the moment: TDOD: extend
        if (sdp_session_num > 0) {
            break;
        }

        req_sdp_session = get_sdp_session(req, sdp_session_num);
        rpl_sdp_session = get_sdp_session(rpl, sdp_session_num);
        if (!req_sdp_session || !rpl_sdp_session) {
            if (!req_sdp_session)
                LM_ERR("Missing SDP session information from req\n");

            if (!rpl_sdp_session)
                LM_ERR("Missing SDP session information from rpl\n");
            break;
        }

        sdp_stream_num = 0;
        for (;;) {
            req_sdp_stream = get_sdp_stream(req, sdp_session_num,
                    sdp_stream_num);
            rpl_sdp_stream = get_sdp_stream(rpl, sdp_session_num,
                    sdp_stream_num);
            if (!req_sdp_stream || !rpl_sdp_stream) {
                //LM_ERR("Missing SDP stream information\n");
                break;
            }
            //is this a stream to add to AAR.
            if (req_sdp_stream->is_rtp) {

		//check if the src or dst port is 0 and if so then don't add to rx
		int intportA = atoi(req_sdp_stream->port.s);
		int intportB = atoi(rpl_sdp_stream->port.s);
		if(intportA != 0 && intportB != 0){
			if(!authorize_video_flow) {
			    if (strncmp(req_sdp_stream->media.s, "video", 5) == 0) {
				add_flow = 0;
			    }
			}
		    
			if(add_flow) {
			//add this to auth session data
			    add_flow_description((rx_authsessiondata_t*) auth->u.auth.generic_data, sdp_stream_num + 1,
				    &req_sdp_stream->media, &req_sdp_session->ip_addr,
				    &req_sdp_stream->port, &rpl_sdp_session->ip_addr,
				    &rpl_sdp_stream->port, &rpl_sdp_stream->transport,
				    &req_sdp_stream->raw_stream,
				    &rpl_sdp_stream->raw_stream, direction, 0 /*This is a new mcd, we are not setting it as active*/);

			    rx_add_media_component_description_avp(aar, sdp_stream_num + 1,
				    &req_sdp_stream->media, &req_sdp_session->ip_addr,
				    &req_sdp_stream->port, &rpl_sdp_session->ip_addr,
				    &rpl_sdp_stream->port, &rpl_sdp_stream->transport,
				    &req_sdp_stream->raw_stream,
				    &rpl_sdp_stream->raw_stream, direction);	
			}
			add_flow = 1;
		}
            }
            sdp_stream_num++;
        }
        sdp_session_num++;
    }

    free_sdp((sdp_info_t**) (void*) &req->body);
    free_sdp((sdp_info_t**) (void*) &rpl->body);

    return 0;
}
Пример #20
0
static void rtsp_parse_thread(void *rtsp_handle2)
{
	SDP_Info* sdp_info=NULL;
	
		RTSP_HANDLE *rtsp_handle = (RTSP_HANDLE *)rtsp_handle2;
		
//		char url[1024] = {0};
		
		char buff[512] = {0};
		rtsp_client_t *handle = rtsp_handle->client;
		int ret = 0;
		int x = 0;
		if(handle == NULL)
		{
			PRINTF("rtsp_parse_thread:ERROR,the rtsp handle is NULL\n");
			goto MSG_EXIT;
		}

		ret = 	reach_rtsp_connect(handle, rtsp_handle->rtsp_url,"User-Agent: LibVLC/2.0.1 (LIVE555 Streaming Media v2011.12.23)" );
		if(ret != 0)
		{
			PRINTF("rtsp_parse_thread:ERROR!!!!!!!!! reach_rtsp_connect\n");
			goto MSG_EXIT;
		}
	
		PRINTF("rtsp_parse_thread:*** rtsp_request_describe ***\n");
		rtsp_schedule_field( handle, "Accept: application/sdp");	
		ret = rtsp_request_describe(handle,NULL);		
		if(ret != 200)
		{
			PRINTF("rtsp_parse_thread:rtsp_request_describe ERROR!\n");
			goto MSG_EXIT;
		}
		
		PRINTF("\nrtsp_parse_thread:*** rtsp_recv_sdp_info ***\n");
		ret =rtsp_recv_sdp_info(handle,rtsp_handle->sdp_info,sizeof(rtsp_handle->sdp_info));	
		if(ret != 0)
		{
			PRINTF("rtsp_parse_thread:rtsp_request_describe ERROR! \n");
			goto MSG_EXIT;
		}
		PRINTF("rtsp_parse_thread:sdp_info=#%s#",rtsp_handle->sdp_info);

		/** sdp info **/
		sdp_info = parse_sdp(rtsp_handle->sdp_info,strlen(rtsp_handle->sdp_info));
		if(sdp_info==NULL){
			PRINTF("rtsp_parse_thread:parse_sdp ERROR\n");
			goto MSG_EXIT; ;
		}
		if( sdp_info->video_port == 0 )
			sdp_info->video_port = 8436;
	
		if(sdp_info->audio_port == 0 )
			sdp_info->audio_port = sdp_info->video_port+2;
		
		PRINTF("rtsp_parse_thread:*** rtsp_request_setup ***\n");
		sprintf(buff,"Transport: RTP/AVP;unicast;client_port=%d-%d",
			sdp_info->video_port,sdp_info->video_port+1);
		rtsp_schedule_field( handle, buff);	
		memset(buff,0,sizeof(buff));
		sprintf(buff,"rtsp://%s:554/trackID=1",sdp_info->IP);
		ret = rtsp_request_setup(handle,buff); //"rtsp://192.168.4.161:554/trackID=1");
		if(ret != 200)
		{
			PRINTF("rtsp_parse_thread:rtsp_request_setup ERROR! \n");
			goto MSG_EXIT;
		}		
		
		PRINTF("rtsp_parse_thread:*** rtsp_request_setup ***\n");
		memset(buff,0,sizeof(buff));
		sprintf(buff,"Transport: RTP/AVP;unicast;client_port=%d-%d",
			sdp_info->audio_port,sdp_info->audio_port+1);
		rtsp_schedule_field( handle,buff);// "Transport: RTP/AVP;unicast;client_port=8502-8503");	
		memset(buff,0,sizeof(buff));
		sprintf(buff,"rtsp://%s:554/trackID=2",sdp_info->IP);
		ret = rtsp_request_setup(handle, buff);//"rtsp://192.168.4.161:554/trackID=2");	
		if(ret != 200)
		{
			PRINTF("rtsp_parse_thread: rtsp_request_setup ERROR!\n");
			goto MSG_EXIT;
		}

		PRINTF("rtsp_parse_thread:*** rtsp_request_play ***\n");
		rtsp_schedule_field( handle, "Range: npt=0.000-");	
		ret = rtsp_request_play(handle, NULL);			
		if(ret != 200)
		{
			PRINTF("rtsp_parse_thread:rtsp_request_play ERROR! \n");
			goto MSG_EXIT;
		}	
				
		//add rtp handle
		ret = rtsp_rtp_recv_start(rtsp_handle);
		if( ret < 0){
			PRINTF("rtsp_parse_thread:rtsp_rtp_recv_start ERROR! \n");
			goto MSG_EXIT;
			}
		

    while(1)
    {
    	
    	//if need stop
    	if(rtsp_handle ->status == 1 
			|| rtsp_handle->video_handle == NULL 
			|| rtsp_handle->audio_handle == NULL)
    	{
    		rtsp_rtp_recv_stop(rtsp_handle);
			Sleep(1000);
    		rtsp_request_tearoff(handle, "");
    		Sleep(1000);
    		break;
    	}
    	Sleep(3000);
    	if(x++ != DEFAULT_HEARTBIT_TIME/3)
    		continue;
  		x =0;
#if 0
		ret = 	rtsp_request_getparameter(handle, NULL);
		PRINTF("rtsp_request_play ret =%d\n",ret);	
		if(ret != 200)
		{
			PRINTF("ERROR! rtsp_request_play\n");
			rtsp_rtp_recv_stop( rtsp_handle);
			break;
		}
#endif
    }       	

EXIT:
	if(handle)
		rtsp_close(handle );          	
	if(rtsp_handle)
	{
		rtsp_handle->fCCEvent=NULL;
		rtsp_handle->fGetAudioEs=NULL;
		rtsp_handle->fGetVideoEs=NULL;
		free(rtsp_handle);
		rtsp_handle = NULL;
		}
	return;
MSG_EXIT:
	if(rtsp_handle != NULL  && rtsp_handle->fCCEvent)
		rtsp_handle->fCCEvent(RTSP_STREAM,MSG_RECV_FAIL);
	
	if(handle)
		rtsp_close(handle );          	
	if(rtsp_handle)
	{
		rtsp_handle->fCCEvent=NULL;
		rtsp_handle->fGetAudioEs=NULL;
		rtsp_handle->fGetVideoEs=NULL;
		free(rtsp_handle);
		rtsp_handle = NULL;
		}
	return;
}
Пример #21
0
static int w_sdp_content(sip_msg_t* msg, char* foo, char *bar)
{
	if(parse_sdp(msg)==0 && msg->body!=NULL)
		return 1;
	return -1;
}
Пример #22
0
/**
 * Send a CCR to the OCS based on the SIP message (INVITE ONLY)
 * @param msg - SIP message
 * @param direction - orig|term
 * @param reservation_units - units to try to reserve
 * @param reservation_units - config route to call when receiving a CCA
 * @param tindex - transaction index
 * @param tindex - transaction label
 *
 * @returns #CSCF_RETURN_BREAK if OK, #CSCF_RETURN_ERROR on error
 */
int Ro_Send_CCR(struct sip_msg *msg, struct dlg_cell *dlg, int dir, int reservation_units, str* incoming_trunk_id, str* outgoing_trunk_id,
        str* pani, cfg_action_t* action, unsigned int tindex, unsigned int tlabel) {
    str session_id = {0, 0},
    called_asserted_identity = {0, 0},
    subscription_id = {0, 0},
    asserted_identity = {0, 0};
    int subscription_id_type = AVP_EPC_Subscription_Id_Type_End_User_SIP_URI;
    AAASession* cc_acc_session = NULL;
    Ro_CCR_t * ro_ccr_data = 0;
    AAAMessage * ccr = 0;
    struct ro_session *new_session = 0;
    struct session_setup_data *ssd;
    int ret = 0;
    struct hdr_field *h = 0;
    char *p;

    int cc_event_number = 0; //According to IOT tests this should start at 0
    int cc_event_type = RO_CC_START;
    int free_called_asserted_identity = 0;

    sdp_session_cell_t* msg_sdp_session;
    sdp_stream_cell_t* msg_sdp_stream;

    int active_service_identifier;
    int active_rating_group;

    int sdp_stream_num = 0;

    LM_DBG("Sending initial CCR request (%c) for reservation_units [%d] incoming_trunk_id [%.*s] outgoing_trunk_id [%.*s]\n",
	dir==RO_ORIG_DIRECTION?'O':'T',
			reservation_units,
            incoming_trunk_id->len, incoming_trunk_id->s,
            outgoing_trunk_id->len, outgoing_trunk_id->s);

    ssd = shm_malloc(sizeof (struct session_setup_data)); // lookup structure used to load session info from cdp callback on CCA
    if (!ssd) {
        LM_ERR("no more shm mem\n");
        goto error;
    }

    //getting asserted identity
    if ((asserted_identity = cscf_get_asserted_identity(msg, 0)).len == 0) {
        LM_DBG("No P-Asserted-Identity hdr found. Using From hdr for asserted_identity");
        asserted_identity = dlg->from_uri;
        if (asserted_identity.len > 0 && asserted_identity.s) {
            p=(char*)memchr(asserted_identity.s, ';',asserted_identity.len);
            if (p) 
                asserted_identity.len = (p-asserted_identity.s);
        }
    }

    //getting called asserted identity
    if ((called_asserted_identity = cscf_get_public_identity_from_called_party_id(msg, &h)).len == 0) {
        LM_DBG("No P-Called-Identity hdr found. Using request URI for called_asserted_identity");
        called_asserted_identity = cscf_get_public_identity_from_requri(msg);
        free_called_asserted_identity = 1;
    }

    if (dir == RO_ORIG_DIRECTION) {
        subscription_id.s = asserted_identity.s;
        subscription_id.len = asserted_identity.len;

    } else if (dir == RO_TERM_DIRECTION) {
        subscription_id.s = called_asserted_identity.s;
        subscription_id.len = called_asserted_identity.len;
    } else {
        LM_CRIT("don't know what to do in unknown mode - should we even get here\n");
        goto error;
    }

    //getting subscription id type
    if (strncasecmp(subscription_id.s, "tel:", 4) == 0) {
        subscription_id_type = Subscription_Type_MSISDN;
    } else {
        subscription_id_type = Subscription_Type_IMPU; //default is END_USER_SIP_URI
    }

    str mac = {0, 0};
    if (get_mac_avp_value(msg, &mac) != 0)
        LM_DBG(RO_MAC_AVP_NAME" was not set. Using default.");

    //by default we use voice service id and rate group
    //then we check SDP - if we find video then we use video service id and rate group
    LM_DBG("Setting default SID to %d and RG to %d for voice",
            voice_service_identifier, voice_rating_group);
    active_service_identifier = voice_service_identifier;
    active_rating_group = voice_rating_group;

    //check SDP - if there is video then set default to video, if not set it to audio
    if (parse_sdp(msg) < 0) {
        LM_ERR("Unable to parse req SDP\n");
        goto error;
    }

    msg_sdp_session = get_sdp_session(msg, 0);
    if (!msg_sdp_session) {
        LM_ERR("Missing SDP session information from rpl\n");
    } else {
        for (;;) {
            msg_sdp_stream = get_sdp_stream(msg, 0, sdp_stream_num);
            if (!msg_sdp_stream) {
                //LM_ERR("Missing SDP stream information\n");
                break;
            }

            int intportA = atoi(msg_sdp_stream->port.s);
            if (intportA != 0 && strncasecmp(msg_sdp_stream->media.s, "video", 5) == 0) {
                LM_DBG("This SDP has a video component and src ports not equal to 0 - so we set default SID to %d and RG to %d for video",
                        video_service_identifier, video_rating_group);
                active_service_identifier = video_service_identifier;
                active_rating_group = video_rating_group;
                break;
            }

            sdp_stream_num++;
        }
    }

    free_sdp((sdp_info_t**) (void*) &msg->body);

    //create a session object without auth and diameter session id - we will add this later.
    new_session = build_new_ro_session(dir, 0, 0, &session_id, &dlg->callid,
            &asserted_identity, &called_asserted_identity, &mac, dlg->h_entry, dlg->h_id,
            reservation_units, 0, active_rating_group, active_service_identifier, incoming_trunk_id, outgoing_trunk_id, pani);

    if (!new_session) {
        LM_ERR("Couldn't create new Ro Session - this is BAD!\n");
        goto error;
    }

    ssd->action = action;
    ssd->tindex = tindex;
    ssd->tlabel = tlabel;
    ssd->ro_session = new_session;

    if (!sip_create_ro_ccr_data(msg, dir, &ro_ccr_data, &cc_acc_session, asserted_identity, called_asserted_identity, subscription_id, subscription_id_type, incoming_trunk_id, outgoing_trunk_id, pani))
        goto error;

    if (!ro_ccr_data)
        goto error;

    if (!cc_acc_session)
        goto error;

    if (!(ccr = Ro_new_ccr(cc_acc_session, ro_ccr_data)))
        goto error;

    if (!Ro_add_vendor_specific_appid(ccr, IMS_vendor_id_3GPP, IMS_Ro, 0)) {
        LM_ERR("Problem adding Vendor specific ID\n");
        goto error;
    }

    if (!Ro_add_cc_request(ccr, cc_event_type, cc_event_number)) {
        LM_ERR("Problem adding CC-Request data\n");
        goto error;
    }

    if (!Ro_add_event_timestamp(ccr, time(NULL))) {
        LM_ERR("Problem adding Event-Timestamp data\n");
        goto error;
    }

    if (!Ro_add_user_equipment_info(ccr, AVP_EPC_User_Equipment_Info_Type_MAC, mac)) {
        LM_ERR("Problem adding User-Equipment data\n");
        goto error;
    }

    if (!Ro_add_subscription_id(ccr, subscription_id_type, &subscription_id)) {
        LM_ERR("Problem adding Subscription ID data\n");
        goto error;
    }
    if (!Ro_add_multiple_service_credit_Control(ccr, reservation_units, -1, active_rating_group, active_service_identifier)) {
        LM_ERR("Problem adding Multiple Service Credit Control data\n");
        goto error;
    }

    /* before we send, update our session object with CC App session ID and data */
    new_session->auth_appid = cc_acc_session->application_id;
    new_session->auth_session_type = cc_acc_session->type;
    new_session->ro_session_id.s = (char*) shm_malloc(cc_acc_session->id.len);
    if (!new_session->ro_session_id.s) {
        LM_ERR("no more shm mem\n");
        goto error;
    }

    new_session->ro_session_id.len = cc_acc_session->id.len;
    memcpy(new_session->ro_session_id.s, cc_acc_session->id.s, cc_acc_session->id.len);

    LM_DBG("new CC Ro Session ID: [%.*s] stored in shared memory address [%p]\n", cc_acc_session->id.len, cc_acc_session->id.s, new_session);

    LM_DBG("Sending CCR Diameter message.\n");
//    new_session->ccr_sent = 1;      //assume we will send successfully
    cdpb.AAASessionsUnlock(cc_acc_session->hash);

    if (ro_forced_peer.len > 0) {
        LM_DBG("Sending message with Peer\n");
        ret = cdpb.AAASendMessageToPeer(ccr, &ro_forced_peer, resume_on_initial_ccr, (void *) ssd);
    } else {
        LM_DBG("Sending message without Peer and realm is [%.*s]\n", ccr->dest_realm->data.len, ccr->dest_realm->data.s);
        ret = cdpb.AAASendMessage(ccr, resume_on_initial_ccr, (void *) ssd);
    }

    if (ret != 1) {
        LM_ERR("Failed to send Diameter CCR\n");
//        new_session->ccr_sent = 0;
        goto error;
    }

    Ro_free_CCR(ro_ccr_data);

    LM_DBG("Registering for callbacks on Dialog [%p] and charging session [%p]\n", dlg, new_session);

    //TODO: if the following fail, we should clean up the Ro session.......
    if (dlgb.register_dlgcb(dlg, DLGCB_TERMINATED | DLGCB_FAILED | DLGCB_EXPIRED | DLGCB_CONFIRMED, dlg_callback_received, (void*) new_session, NULL) != 0) {
        LM_CRIT("cannot register callback for dialog confirmation\n");
        goto error;
    }

    counter_inc(ims_charging_cnts_h.initial_ccrs);
    counter_inc(ims_charging_cnts_h.active_ro_sessions);

    if (free_called_asserted_identity) shm_free(called_asserted_identity.s); // shm_malloc in cscf_get_public_identity_from_requri	
    return RO_RETURN_BREAK;

error:
    LM_DBG("Trying to reserve credit on initial INVITE failed.\n");

    if (free_called_asserted_identity) shm_free(called_asserted_identity.s); // shm_malloc in cscf_get_public_identity_from_requri	
    Ro_free_CCR(ro_ccr_data);
    if (cc_acc_session) {
        cdpb.AAASessionsUnlock(cc_acc_session->hash);
        cdpb.AAADropSession(cc_acc_session);
    }

    if (ssd)
        shm_free(ssd);

	    return RO_RETURN_ERROR;
}
Пример #23
0
/**
 * sngtc_callee_answer - handles the SDP offer of the callee
 *
 * At this point, we have both offers of the endpoints, and can decide whether
 * transcoding is needed or not.
 */
static int sngtc_callee_answer(struct sip_msg *msg)
{
	struct dlg_cell *dlg;
	struct sngtc_info *info;
	str caller_sdp, dst;
	sdp_info_t sdp;
	str *sdp_ptr;
	int rc;

	LM_DBG("sngtc_callee_answer\n");

	dlg = dlg_binds.get_dlg();
	if (!dlg) {
		LM_ERR("failed to fetch current dialog\n");
		return SNGTC_ERR;
	}

	/* get the pointer to the SDP body of the caller */
	if (dlg_binds.fetch_dlg_value(dlg, &dlg_key_sngtc_info, &dst, 0) != 0) {
		LM_ERR("failed to fetch caller sdp\n");
		return SNGTC_ERR;
	}

	info = *(struct sngtc_info **)(dst.s);
	sdp_ptr = &info->caller_sdp;

	LM_DBG("ptrs: %p %p\n", sdp_ptr, info->caller_sdp.s);

	caller_sdp.len = sdp_ptr->len;
	caller_sdp.s   = sdp_ptr->s;

	lock_get(&info->lock);

	LM_DBG("FETCHED CALLER SDP: '%.*s' [%d]\n", caller_sdp.len, caller_sdp.s,
	       caller_sdp.len);

	memset(&sdp, 0, sizeof(sdp));
	if (parse_sdp_session(&caller_sdp, 0, NULL, &sdp) != 0) {
		LM_ERR("failed to parse caller sdp body\n");
		rc = SNGTC_SDP_ERR;
		goto out_free;
	}

	if (parse_sdp(msg) != 0) {
		LM_ERR("failed to parse callee sdp body\n");
		rc = SNGTC_SDP_ERR;
		goto out_free;
	}

	dst.s = sdp_buffer.s;
	dst.len = 0;

	/* perform all 200 OK SDP changes and pre-compute the ACK SDP body */
	rc = process_session(msg, info, &caller_sdp, &dst, sdp.sessions,
	                     msg->sdp->sessions);
	if (rc != 0) {
		LM_ERR("failed to rewrite SDP bodies of the endpoints\n");
		goto out_free;
	}

	if (!is_processed(info)) {
		dst.s = sdp_buffer.s;
		LM_DBG("caller ACK SDP: '%.*s'\n", dst.len, dst.s);

		info->modified_caller_sdp.s = shm_malloc(dst.len);
		if (!info->modified_caller_sdp.s) {
			LM_ERR("no more shm memory\n");
			rc = SNGTC_ERR;
			goto out_free;
		}

		memcpy(info->modified_caller_sdp.s, dst.s, dst.len);
		info->modified_caller_sdp.len = dst.len;
	}

	info->flags |= PROCESSED_FLAG;
	lock_release(&info->lock);

	if (sdp.sessions)
		__free_sdp(&sdp);

	return 1;

out_free:
	free_transcoding_sessions(info->sessions);
	lock_release(&info->lock);

	if (sdp.sessions)
		__free_sdp(&sdp);

	return rc;
}
Пример #24
0
static int w_sdp_get_line_startswith(sip_msg_t *msg, char *avp, char *s_line)
{
	sdp_info_t *sdp = NULL;
	str body = {NULL, 0};
	str line = {NULL, 0};
	char* p = NULL;
	str s;
	str sline;
	int_str avp_val;
	int_str avp_name;
	pv_spec_t *avp_spec = NULL;
	static unsigned short avp_type = 0;
	int sdp_missing=1;

	if (s_line == NULL || strlen(s_line) <= 0)
	{
		LM_ERR("Search string is null or empty\n");
		return -1;
	}
	sline.s = s_line;
	sline.len = strlen(s_line);

	sdp_missing = parse_sdp(msg);

	if(sdp_missing < 0) {
		LM_ERR("Unable to parse sdp\n");
		return -1;
	}

	sdp = (sdp_info_t *)msg->body;

	if (sdp_missing || sdp == NULL)
	{
		LM_DBG("No SDP\n");
		return -2;
	}

	body.s = sdp->raw_sdp.s;
	body.len = sdp->raw_sdp.len;

	if (body.s==NULL) {
		LM_ERR("failed to get the message body\n");
		return -1;
	}

	body.len = msg->len - (body.s - msg->buf);
	if (body.len==0) {
		LM_DBG("message body has zero length\n");
		return -1;
	}

	if (avp == NULL || strlen(avp) <= 0)
	{
		LM_ERR("avp variable is null or empty\n");
		return -1;
	}

	s.s = avp;
	s.len = strlen(s.s);

	if (pv_locate_name(&s) != s.len)
	{
		LM_ERR("invalid parameter\n");
		return -1;
	}

	if (((avp_spec = pv_cache_get(&s)) == NULL)
			|| avp_spec->type!=PVT_AVP) {
		LM_ERR("malformed or non AVP %s AVP definition\n", avp);
		return -1;
	}

	if(pv_get_avp_name(0, &avp_spec->pvp, &avp_name, &avp_type)!=0)
	{
		LM_ERR("[%s]- invalid AVP definition\n", avp);
		return -1;
	}

	p = find_sdp_line(body.s, body.s+body.len, sline.s[0]);
	while (p != NULL)
	{
		if (sdp_locate_line(msg, p, &line) != 0)
		{
			LM_ERR("sdp_locate_line fail\n");
			return -1;
		}

		if (strncmp(line.s, sline.s, sline.len) == 0)
		{
			avp_val.s.s = line.s;
			avp_val.s.len = line.len;

			/* skip ending \r\n if exists */
			if (avp_val.s.s[line.len-2] == '\r' && avp_val.s.s[line.len-1] == '\n')
			{
				/* add_avp() clones to shm and adds 0-terminating char */
				avp_val.s.len -= 2;
			}

			if (add_avp(AVP_VAL_STR | avp_type, avp_name, avp_val) != 0)
			{
				LM_ERR("Failed to add SDP line avp");
				return -1;
			}

			return 1;
		}

		p = find_sdp_line(line.s + line.len, body.s + body.len, sline.s[0]);
	}

	return -1;
}
Пример #25
0
/**
 * @brief remove all SDP lines that begin with prefix
 * @return -1 - error; 0 - no lines found ; 1..N - N lines deleted
 */
int sdp_remove_line_by_prefix(sip_msg_t* msg, str* prefix)
{
	str body = {NULL, 0};

	if(parse_sdp(msg) < 0) {
		LM_ERR("Unable to parse SDP\n");
		return -1;
	}

	if(msg->body == NULL) {
		LM_DBG("No SDP body\n");
		return -1;
	}

	body.s = ((sdp_info_t*)msg->body)->raw_sdp.s;
	body.len = ((sdp_info_t*)msg->body)->raw_sdp.len;

	if (body.s==NULL) {
		LM_ERR("failed to get the message body\n");
		return -1;
	}
	body.len = msg->len - (body.s - msg->buf);
	if (body.len==0) {
		LM_DBG("message body has zero length\n");
		return -1;
	}

	char *ptr = NULL;
	str line = {NULL, 0};
	str remove = {NULL, 0};
	int found = 0;
	struct lump *anchor = NULL;

	ptr = find_sdp_line(body.s, body.s + body.len, prefix->s[0]);
	while (ptr)
	{
		if (sdp_locate_line(msg, ptr, &line) != 0)
		{
			LM_ERR("sdp_locate_line() failed\n");
			return -1;
		}

		if (body.s + body.len < line.s + prefix->len) // check if strncmp would run too far
		{
			//LM_DBG("done searching, prefix string >%.*s< (%d) does not fit into remaining buffer space (%ld) \n", prefix->len, prefix->s, prefix->len, body.s + body.len - line.s);
			break;
		}

		if (strncmp(line.s, prefix->s, prefix->len ) == 0)
		{
			//LM_DBG("current remove >%.*s< (%d)\n", remove.len, remove.s, remove.len);
			if (!found) {
				//LM_DBG("first match >%.*s< (%d)\n", line.len,line.s,line.len);
				remove.s = line.s;
				remove.len = line.len;
			} else {
				//LM_DBG("cont. match >%.*s< (%d)\n", line.len,line.s,line.len);
				if (remove.s + remove.len == line.s) {
					//LM_DBG("this match is right after previous match\n");
					remove.len += line.len;
				} else {
					//LM_DBG("there is gap between this and previous match, remove now\n");
					anchor = del_lump(msg, remove.s - msg->buf, remove.len, HDR_OTHER_T);
					if (anchor==NULL)
					{
						LM_ERR("failed to remove lump\n");
						return -1;
					}
					remove.s = line.s;
					remove.len = line.len;
				}
			}
			found++;
			//LM_DBG("updated remove >%.*s< (%d)\n", remove.len, remove.s, remove.len);

		}
		ptr = find_next_sdp_line(ptr, body.s + body.len, prefix->s[0], NULL);
	}

	if (found) {
		//LM_DBG("remove >%.*s< (%d)\n", remove.len, remove.s, remove.len);
		anchor = del_lump(msg, remove.s - msg->buf, remove.len, HDR_OTHER_T);
		if (anchor==NULL)
		{
			LM_ERR("failed to remove lump\n");
			return -1;
		}
		return found;
	}

	LM_DBG("no match\n");
	return 0;
}
Пример #26
0
/** Helper function for adding media component AVPs for each SDP stream*/
int add_media_components(AAAMessage* aar, struct sip_msg *req,
        struct sip_msg *rpl, enum dialog_direction direction, str *ip,
        uint16_t *ip_version) {
    int sdp_session_num;
    int sdp_stream_num;
    sdp_session_cell_t* req_sdp_session, *rpl_sdp_session;
    sdp_stream_cell_t* req_sdp_stream, *rpl_sdp_stream;

    if (!req || !rpl) {
        return RX_RETURN_FALSE;
    }

    if (parse_sdp(req) < 0) {
        LM_ERR("Unable to parse req SDP\n");
        return RX_RETURN_FALSE;
    }

    if (parse_sdp(rpl) < 0) {
        LM_ERR("Unable to parse res SDP\n");
        return RX_RETURN_FALSE;
    }

    sdp_session_num = 0;

    //Loop through req sessions and streams and get corresponding rpl sessions and streams and populate avps
    for (;;) {
        //we only cater for one session at the moment: TDOD: extend
        if (sdp_session_num > 0) {
            break;
        }

        req_sdp_session = get_sdp_session(req, sdp_session_num);
        rpl_sdp_session = get_sdp_session(rpl, sdp_session_num);
        if (!req_sdp_session || !rpl_sdp_session) {
            if (!req_sdp_session)
                LM_ERR("Missing SDP session information from req\n");

            if (!rpl_sdp_session)
                LM_ERR("Missing SDP session information from rpl\n");
            break;
        }

        if (direction == DLG_MOBILE_ORIGINATING) {
            *ip_version = req_sdp_session->pf;
            *ip = req_sdp_session->ip_addr;
        } else if (direction == DLG_MOBILE_TERMINATING) {
            *ip_version = rpl_sdp_session->pf;
            *ip = rpl_sdp_session->ip_addr;
        }

        sdp_stream_num = 0;
        for (;;) {
            req_sdp_stream = get_sdp_stream(req, sdp_session_num,
                    sdp_stream_num);
            rpl_sdp_stream = get_sdp_stream(rpl, sdp_session_num,
                    sdp_stream_num);
            if (!req_sdp_stream || !rpl_sdp_stream) {
                //LM_ERR("Missing SDP stream information\n");
                break;
            }
            //is this a stream to add to AAR.
            if (req_sdp_stream->is_rtp) {

                rx_add_media_component_description_avp(aar, sdp_stream_num + 1,
                        &req_sdp_stream->media, &req_sdp_session->ip_addr,
                        &req_sdp_stream->port, &rpl_sdp_session->ip_addr,
                        &rpl_sdp_stream->port, &rpl_sdp_stream->transport,
                        &req_sdp_stream->raw_stream,
                        &rpl_sdp_stream->raw_stream, direction);
            }
            sdp_stream_num++;
        }
        sdp_session_num++;
    }

    free_sdp((sdp_info_t**) (void*) &req->body);
    free_sdp((sdp_info_t**) (void*) &rpl->body);

    return 0;
}
Пример #27
0
/**
 * @brief assigns common media transport (if any) of 'm' lines to pv argument
 * @return -1 - error; 0 - not found; 1 - found
 */
static int w_sdp_transport(sip_msg_t* msg, char *avp)
{
	int_str avp_val;
	int_str avp_name;
	static unsigned short avp_type = 0;
	str s;
	pv_spec_t *avp_spec = NULL;
	int sdp_session_num;
	int sdp_stream_num;
	sdp_session_cell_t* sdp_session;
	sdp_stream_cell_t* sdp_stream;
	str *transport;

	s.s = avp; s.len = strlen(s.s);
	if (pv_locate_name(&s) != s.len) {
		LM_ERR("invalid avp parameter %s\n", avp);
		return -1;
	}
	if (((avp_spec = pv_cache_get(&s)) == NULL)
			|| avp_spec->type!=PVT_AVP) {
		LM_ERR("malformed or non AVP %s\n", avp);
		return -1;
	}
	if (pv_get_avp_name(0, &avp_spec->pvp, &avp_name, &avp_type) != 0) {
		LM_ERR("invalid AVP definition %s\n", avp);
		return -1;
	}

	if(parse_sdp(msg) < 0) {
		LM_ERR("unable to parse sdp\n");
		return -1;
	}

	sdp_session_num = 0;
	transport = (str *)NULL;

	for (;;) {
		sdp_session = get_sdp_session(msg, sdp_session_num);
		if (!sdp_session) break;
		sdp_stream_num = 0;
		for (;;) {
			sdp_stream = get_sdp_stream(msg, sdp_session_num,
					sdp_stream_num);
			if (!sdp_stream) break;
			LM_DBG("stream %d of %d - transport [%.*s]\n",
			sdp_stream_num, sdp_session_num,
			sdp_stream->transport.len, sdp_stream->transport.s);
			if (transport) {
				if (transport->len != sdp_stream->transport.len
						|| strncasecmp(sdp_stream->transport.s, transport->s,
								transport->len) != 0) {
					LM_DBG("no common transport\n");
					return -2;
				}
			} else {
				transport = &sdp_stream->transport;
			}
			sdp_stream_num++;
		}
		sdp_session_num++;
	}
	if (transport) {
		avp_val.s.s = transport->s;
		avp_val.s.len = transport->len;
		LM_DBG("found common transport '%.*s'\n",
				transport->len, transport->s);
		if (add_avp(AVP_VAL_STR | avp_type, avp_name, avp_val) != 0) {
			LM_ERR("failed to add transport avp");
			return -1;
		}
	}

	return 1;
}
Пример #28
0
int sca_logic_notify(b2bl_cb_params_t *params, unsigned int b2b_event)
{
	int on_hold = 0;
	int sdp_session_num = 0, sdp_stream_num;
	sdp_session_cell_t* sdp_session;
	sdp_stream_cell_t* sdp_stream;
	struct sip_msg *msg = params->msg;
	b2bl_cb_ctx_t *cb_params = params->param;
	str *shared_line;
	unsigned int hash_index, appearance;
	b2b_sca_record_t *record;
	b2b_sca_call_t *call = NULL;
	str publish_hdr;
	unsigned int call_info_appearance;
	unsigned int call_info_appearance_state = 0;
	struct hdr_field *call_info;
	struct call_info_body *callinfo_b;
	struct to_body *call_info_b;
	struct to_param *param;

	if (b2b_sca_shutdown_completed) return B2B_FOLLOW_SCENARIO_CB_RET;
	if (params == NULL) {
		LM_ERR("callback event [%d] without cb params\n", b2b_event);
		return B2B_DROP_MSG_CB_RET;
	}

	shared_line = &cb_params->shared_line;
	hash_index = cb_params->hash_index;
	appearance = cb_params->appearance;

	LM_DBG("*** GOT NOTIFICATION TYPE [%d] WITH cb_params [%p]->[%.*s] appearance [%d] on hash index [%d]"
			" for b2bl entity [%d]\n",
			b2b_event, cb_params, shared_line->len, shared_line->s,
			appearance, hash_index, params->entity);


	if (msg && msg->call_info) {
		if (0 == parse_call_info_header(msg)) {
			call_info = msg->call_info;
			if (call_info) {
				LM_DBG("BODY=[%p]->[%.*s] sibling=[%p]\n", call_info,
					call_info->body.len, call_info->body.s, call_info->sibling);
				callinfo_b = call_info->parsed;
				while (callinfo_b) {
					call_info_b = &(callinfo_b->call_info_body);
					LM_DBG(". body=[%.*s] param_lst=[%p] last_param=[%p]\n",
						call_info_b->body.len, call_info_b->body.s,
						call_info_b->param_lst, call_info_b->last_param);
					param = call_info_b->param_lst;
					while (param) {
						LM_DBG(".. [%p]->[%d] [%.*s]=[%.*s]->[%p]\n",
							param, param->type, param->name.len, param->name.s,
							param->value.len, param->value.s, param->next);
						if (param->name.len==APPEARANCE_INDEX_LEN &&
							strncmp(APPEARANCE_INDEX_STR,
							param->name.s, APPEARANCE_INDEX_LEN)==0) {
							if (strno2int(&param->value,&call_info_appearance)<0) {
								LM_ERR("bad appearance-index [%.*s]\n",
									param->value.len, param->value.s);
								return -1;
							}
							if (appearance != call_info_appearance) {
								LM_ERR("got appearance[%d] while expecting[%d]\n",
									call_info_appearance, appearance);
								goto next_callinfo_b;
							} else {
								LM_DBG("*** GOT APP-INDEX [%d]\n",
									call_info_appearance);
							}
						} else if (param->name.len==APPEARANCE_STATE_LEN &&
							strncmp(APPEARANCE_STATE_STR,
							param->name.s, APPEARANCE_STATE_LEN)==0) {
							LM_DBG("*** GOT APP-STATE [%.*s]\n",
								param->value.len, param->value.s);
							if (param->value.len == strlen(APP_STATE_HELD_PRIVATE) &&
								strncmp(param->value.s,
									app_state[HELD_PRIVATE_STATE].s,
									param->value.len)==0) {
								call_info_appearance_state = HELD_PRIVATE_STATE;
							}
						}
						param=param->next;
					}
					goto handle_appearance;
next_callinfo_b:
					callinfo_b = callinfo_b->next;
				}
				call_info = call_info->sibling;
			}
		} else {
			LM_ERR("Unable to parse Call-Info header\n");
			return B2B_DROP_MSG_CB_RET;
		}
	}

handle_appearance:
	lock_get(&b2b_sca_htable[hash_index].lock);
	record = b2b_sca_search_record_safe(hash_index, shared_line);
	if (record == NULL) {
		lock_release(&b2b_sca_htable[hash_index].lock);
		LM_ERR("record not found for shared line [%.*s] on hash index [%d]\n",
			shared_line->len, shared_line->s, hash_index);
		return B2B_DROP_MSG_CB_RET;
	}

	b2b_sca_print_record(record);

	switch(b2b_event){
	case B2B_DESTROY_CB:
		/* Destroy the sca index record */
		shm_free(params->param);
		b2b_sca_delete_call_record(hash_index, record, appearance);
		break;
	case B2B_RE_INVITE_CB:
	case B2B_CONFIRMED_CB:
		call = b2b_sca_search_call_safe(record, appearance);
		if (call == NULL) {
			LM_ERR("call record not found for shared line [%.*s] with index [%d]\n",
						shared_line->len, shared_line->s, appearance);
			lock_release(&b2b_sca_htable[hash_index].lock);
			return B2B_DROP_MSG_CB_RET;
		}
		if (0 == parse_sdp(msg)) {
			sdp_session = get_sdp_session(msg, sdp_session_num);
			if(!sdp_session) break;
			sdp_stream_num = 0;
			for(;;) {
				sdp_stream = get_sdp_stream(msg, sdp_session_num, sdp_stream_num);
				if(!sdp_stream) break;
				if(sdp_stream->media.len==AUDIO_STR_LEN &&
					strncmp(sdp_stream->media.s,AUDIO_STR,AUDIO_STR_LEN)==0 &&
					sdp_stream->is_on_hold) {
					on_hold = 1;
					break;
				}
				sdp_stream_num++;
			}
			sdp_session_num++;
		}

		if (on_hold) {
			if (call_info_appearance_state)
				call->call_state = HELD_PRIVATE_STATE;
			else
				call->call_state = HELD_STATE;
		} else {
			call->call_state = ACTIVE_STATE;
		}
		break;
	default:
		LM_ERR("Unexpected event\n");
	}

	/* Prepare PUBLISH Call-Info header.  */
	if (build_publish_call_info_header(record, &publish_hdr) != 0) {
		lock_release(&b2b_sca_htable[hash_index].lock);
		LM_ERR("Unable to build PUBLISH Call-Info header\n");
		return B2B_FOLLOW_SCENARIO_CB_RET;
	}

	/* Save the record to db. */
	if (push_sca_info_to_db(record, appearance, 1) != 0)
		LM_ERR("DB out of synch\n");

	/* Notify the watchers. */
	sca_publish(record, &publish_hdr);

	b2b_sca_delete_record_if_empty(record, hash_index);

	lock_release(&b2b_sca_htable[hash_index].lock);

	if (publish_hdr.s != publish_call_info_hdr_buf)
		pkg_free(publish_hdr.s);

	return B2B_FOLLOW_SCENARIO_CB_RET;
}
Пример #29
0
/**
 * @brief remove streams matching the m='media'
 * @return -1 - error; 0 - not found; >=1 - found
 */
static int sdp_remove_media(sip_msg_t *msg, str *media)
{
	sdp_info_t *sdp = NULL;
	int sdp_session_num;
	int sdp_stream_num;
	sdp_session_cell_t* sdp_session;
	sdp_stream_cell_t* sdp_stream;
	sdp_stream_cell_t* nxt_stream;
	int ret = 0;
	char *dstart = NULL;
	int dlen = 0;
	struct lump *anchor;

	if(parse_sdp(msg) < 0) {
		LM_ERR("Unable to parse sdp\n");
		return -1;
	}

	LM_DBG("attempting to search for media type: [%.*s]\n",
			media->len, media->s);

	sdp = (sdp_info_t*)msg->body;

	sdp_session_num = 0;
	for(;;)
	{
		sdp_session = get_sdp_session(msg, sdp_session_num);
		if(!sdp_session) break;
		sdp_stream_num = 0;
		for(;;)
		{
			sdp_stream = get_sdp_stream(msg, sdp_session_num, sdp_stream_num);
			if(!sdp_stream) break;

			LM_DBG("stream %d of %d - media [%.*s]\n",
					sdp_stream_num, sdp_session_num,
					sdp_stream->media.len, sdp_stream->media.s);
			if(media->len==sdp_stream->media.len
					&& strncasecmp(sdp_stream->media.s, media->s,
						media->len)==0)
			{
				/* found - remove */
				LM_DBG("removing media stream: %.*s", media->len, media->s);
				nxt_stream = get_sdp_stream(msg, sdp_session_num,
						sdp_stream_num+1);
				/* skip back 'm=' */
				dstart = sdp_stream->media.s - 2;
				if(!nxt_stream) {
					/* delete to end of sdp */
					dlen = (int)(sdp->text.s + sdp->text.len - dstart);
				} else {
					/* delete to start of next stream */
					dlen = (int)(nxt_stream->media.s - 2 - dstart);
				}
				anchor = del_lump(msg, dstart - msg->buf, dlen, 0);
				if (anchor == NULL) {
					LM_ERR("failed to remove media type [%.*s]\n",
							media->len, media->s);
					return -1;
				}

				ret++;
			}
			sdp_stream_num++;
		}
		sdp_session_num++;
	}

	return ret;
}