Example #1
0
/*
 * Extract the data from b=  lines and add it to the structure
 * @param bw - the pointer to the bandwidth structure to fill
 * @param sdp - the sdp body where to look for b= lines 
 * @param start - the pointer to the starting point to look at
 
 * returns 1 on success 0 if no b= line was found
 */
int extract_bandwidth(bandwidth *bw,str sdp,char *start)
{
	char *b;
	char *m; /*next mline*/
	
	bw->bAS=0; bw->bRS=0; bw->bRR=0;	
	
	b=find_next_sdp_line(start,(sdp.s+sdp.len),'b',NULL);
	while (b!=NULL) {
				
		m=find_next_sdp_line(b,(sdp.s+sdp.len),'m',NULL);
		if (m!=NULL && b>m)
		{
		/*this bandwidth belongs to some other media!*/
			return 0;
		}
		b+=2; /*skip b and =*/
		while (*b==' ')	
		{
			b++;		
		}
		if (*b=='A' && *(b+1)=='S')
		{
			sscanf(b,"AS:%i%*s",&bw->bAS);
					
		} else if( *b=='R') {
			if (*(b+1)=='S') 
			{
				sscanf(b,"RS:%i%*s",&bw->bRS);
				
			} else if (*(b+1)=='R')	{
				sscanf(b,"RR:%i%*s",&bw->bRR);
				
			}
		} 
		/*find next b line*/
		b=find_next_sdp_line(b,(sdp.s+sdp.len),'b',NULL);
			
	}
		
		return 1;
}
Example #2
0
/**
 * add the sdp component from a request or a reply, respectively an offer or an answer
 * @param msg - the SIP message
 * @param sdp_type - 0 for SDP offer and 1 for SDP answer
 * @param sip_uri - the SIP uri of the one that sent the SDP body
 * @param sdp_media_comps - the  built structure
 * @returns 1 if ok, 0 if an error occured
 */
int append_sip_sdp_comp(struct sip_msg * msg, 
			int sdp_type, str sip_uri, str user_sip_uri,
			sdp_media_component_list_t * sdp_media_comps){
	

	sdp_media_component_t * sdp_media_elem = NULL;
	str sdp_body = {0,0};
	str mline_s = {0,0}, next_mline_s= {0,0};
	char * end, *media_info_end;
	str copy_sdp_body = {0,0};

	LOG(L_DBG, "checking if the message has sdp body\n");
	/*if the SIP message contains SDP body*/
	if(extract_sdp_body(msg, &copy_sdp_body)==-1) {
		return 1;
	}
	
	str_dup(sdp_body, copy_sdp_body, pkg);
	
	end = sdp_body.s + sdp_body.len;

	mline_s.s = find_sdp_line(sdp_body.s,end,'m');
	for(;mline_s.s;mline_s.s = next_mline_s.s){
		
		mline_s.len = get_line_length(mline_s.s, end);
		next_mline_s.s = find_next_sdp_line(mline_s.s,end,'m',NULL);

		mem_new(sdp_media_elem, sizeof(sdp_media_component_t), pkg);

		str_dup_ptr_ptr(sdp_media_elem->sdp_media_name, &mline_s, pkg);

		media_info_end = end;

		mem_new(sdp_media_elem->sdp_type, sizeof(int32_t), pkg);
		*(sdp_media_elem->sdp_type) = sdp_type;

		if(!get_media_description_list(mline_s.s+mline_s.len, end, 
					&(sdp_media_elem->sdp_media_descriptions)))
			goto error;
		/*if(str_equal(user_sip_uri, sip_uri))
				add_an_charging_id(sip_uri, sdp_media_elem);*/
		WL_APPEND(sdp_media_comps, sdp_media_elem);
	}
	str_free(sdp_body,pkg);
	return 1;
out_of_memory:
	LOG(L_ERR, "append_sip_sdp_comp: out of pkg memory\n");
error:
	WL_FREE(sdp_media_elem, sdp_media_component_list_t, pkg);
	return 0;
}
Example #3
0
int get_all_media_lines(char * start, char * end, char line_name, 
				str_list_t * sdp_media_descriptions){

	
	str sdp_par = {0,0};
	str_list_slot_t * str_slot = NULL;

       while((sdp_par.s = find_next_sdp_line(start, end,line_name,NULL))){
                sdp_par.len = get_line_length(sdp_par.s, end);
                mem_new(str_slot, sizeof(str_list_slot_t), pkg);
                str_dup(str_slot->data,sdp_par,pkg);
                WL_APPEND(sdp_media_descriptions,str_slot);
                str_slot=0;
		start = sdp_par.s + sdp_par.len;
        }

	return 1;

out_of_memory:
	LOG(L_ERR, "ERR:"M_NAME":get_media_description_list: out of pkg memory\n");
	if(str_slot) WL_FREE(str_slot, str_list_t,pkg);
	return 0;
}
Example #4
0
int extract_mclines(str sdpA,str sdpB,char **mlineA,char **clineA,char **mlineB,char **clineB,int number)
{
 	
 	char *nclineA,*nclineB; /*next*/
 	char *sclineA=NULL,*sclineB=NULL; /*session*/
 	char *nmlineA,*nmlineB; /*next*/
 	int i;
 	
 	 		
 	
 	
 	*clineA=find_sdp_line(sdpA.s,(sdpA.s+sdpA.len),'c');
 	*clineB=find_sdp_line(sdpB.s,(sdpB.s+sdpB.len),'c');
 	*mlineA=find_sdp_line(sdpA.s,(sdpA.s+sdpA.len),'m');
 	*mlineB=find_sdp_line(sdpB.s,(sdpB.s+sdpB.len),'m');
	
	
 	
	if (*clineA==NULL || *clineB==NULL || *mlineA==NULL || *mlineB==NULL)
 	{
 		/*missing at least one cline and mline in each SDPbody*/
 		LOG(L_ERR, ANSI_RED"ERR:"M_NAME" Malformed SDP body\n");
 		return 0;
 	} 	
 	
 	nclineA=find_next_sdp_line(*clineA,(sdpA.s+sdpA.len),'c',NULL);
 	nclineB=find_next_sdp_line(*clineB,(sdpB.s+sdpB.len),'c',NULL);
 	nmlineA=find_next_sdp_line(*mlineA,(sdpA.s+sdpA.len),'m',NULL);
 	nmlineB=find_next_sdp_line(*mlineB,(sdpB.s+sdpB.len),'m',NULL);
 	
 	
 	
 	if (*clineA < *mlineA) 
 	{
 		sclineA=*clineA;
 	}
 	if (*clineB < *mlineB)
 	{
 		sclineB=*clineB;
 	}
 	
 	
 	
 	if (number > 1)
 	 {
 		for (i=1;i<number;i++)
 		{
 			*mlineA=nmlineA;
 			*mlineB=nmlineB;
 			nmlineA=find_next_sdp_line(*mlineA,(sdpA.s+sdpA.len),'m',NULL);
 			nmlineB=find_next_sdp_line(*mlineB,(sdpB.s+sdpB.len),'m',NULL);
 			
 			if(nclineA >*mlineA && (nclineA < nmlineA || nmlineA== NULL))
 			{
 				// if there is a c line between two m lines or after the last m line
 				// then this c line belongs to the first one 
 			 		*clineA=nclineA;
 			 		nclineA=find_next_sdp_line(*clineA,(sdpA.s+sdpA.len),'c',NULL);
 			} else {
 				// if not then the session description one is the one 
 				*clineA=sclineA;
 			}
 			
 			if(nclineB >*mlineB && (nclineB < nmlineB || nmlineB== NULL))
 			{
 				// if there is a c line between two m lines or after the last m line
 				// then this c line belongs to the first one 
 			 		*clineB=nclineB;
 			 		nclineB=find_next_sdp_line(*clineB,(sdpB.s+sdpB.len),'c',NULL);
 			} else {
 				// if not then the session description one is the one 
 				*clineB=sclineB;
 			}
 		
 		
 		
 		if (*mlineA == NULL || *mlineB == NULL || *clineA == NULL || *clineB == NULL)
 		{
 			LOG(L_ERR,"ERR:"M_NAME":%s: Failed getting m= and c= lines in SDP\n","extract_mclines");
 			return 0;
 		}
 					
 		}
 		// after this we should have mlineA , mlineB , clineA, clineB
 		// with the right values	
 		
 	 }
 	 
 	
 	 return 1;
}
Example #5
0
AAA_AVP* Gq_create_codec_data(str sdp,int number,int direction)
{
		char data[Gq_MAX_Char4];
		char *p,*q,*r;
		int i=1,l;
		
		switch(direction) {
			
			case 0: sprintf(data,"uplink\noffer\n");	
					break;
			case 1: sprintf(data,"uplink\nanswer\n");
					break;
			case 2: sprintf(data,"downlink\noffer\n");
					break;
			case 3: sprintf(data,"downlink\nanswer\n");
					break;
			default: 
					break;
						
		}
		l=strlen(data);
		
		p=find_sdp_line(sdp.s,(sdp.s+sdp.len),'m');
		
		while (p!= NULL && i<number)
		{
			p=find_next_sdp_line(p,(sdp.s+sdp.len),'m',NULL);
			i++;
		} 
		if (p==NULL)
		{
			return NULL;
		}
		q=find_next_sdp_line(p,(sdp.s+sdp.len),'m',(sdp.s+sdp.len));
		
		
		r=index(p,'\n');
		memcpy(data+l,p,r-p+1);
		l+=r-p+1;
		/*the m= line is always copied*/
		
		
		
		
		p=r+1; /* p is always the start of the line*/
		r=index(r+1,'\n'); /*r always the \n char of that line*/
		
		while(p+2<q && (l+r-p+1)<Gq_MAX_Char4)
			{
				/*what about spaces? think it closely*/
				if ((strstr(p,"a=sendonly")!=NULL && strstr(p,"a=sendonly")<r) || 
						(strstr(p,"a=recvonly")!=NULL && strstr(p,"a=recvonly")<r) ||
						(strstr(p,"a=sendrecv")!=NULL && strstr(p,"a=sendrecv")<r) ||
						strncmp(p,"b=RS",4)==0 || strncmp(p,"b=RR",4)==0 || strncmp(p,"b=AS",4)==0)
				{
							p=r+1; 		/*skip this line*/
							r=index(r+1,'\n');
				
						
				} else {
						memcpy(data+l,p,r-p+1);
						l+=r-p+1;
						p=r+1;
						r=index(r+1,'\n');
				}
			}
		data[l-2]='\0';
			
			
		l=strlen(data);
		return (cdpb.AAACreateAVP(AVP_IMS_Codec_Data,
 											AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
 											IMS_vendor_id_3GPP,data,l,
 											AVP_DUPLICATE_DATA));
 											
}
Example #6
0
 inline int Gq_add_media_component_description(AAAMessage *msg,str sdpinvite,str sdp200,char *mline,int number,int tag)
 {
 	str data;
 	AAA_AVP_LIST list;
 	AAA_AVP *media_component_number,*media_type;
 	AAA_AVP *codec_data1,*codec_data2;
 	AAA_AVP *media_sub_component[Gq_Media_Sub_Components];
 	AAA_AVP *Max_DL,*Max_UL;
 	AAA_AVP *RR,*RS;
 	AAA_AVP *flow_status;
 	
 	bandwidth bwUL,bwDL;
 	
 	
 	char *ptr;
 	char port[Gq_MAX_Char];
 	int type,i,n,a;
 	char x[4];
	
 	
 	/*needed to use AAA_AVP-LIST!!*/
 	list.head=0;	 	
 	list.tail=0;
 	
 	
 	
 	/*media-component-number*/
 	 	
 	set_4bytes(x,number);	
 	media_component_number=cdpb.AAACreateAVP(AVP_IMS_Media_Component_Number,
 											AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
 											IMS_vendor_id_3GPP,x,4,
 											AVP_DUPLICATE_DATA);

 	if (media_component_number!=NULL) 
 	{
 		AAAAddAVPToAVPList(&list,media_component_number);
 	} else {
 		LOG(L_INFO, ANSI_RED"INF:"M_NAME"Unable to create media_component_number AVP");
 		return 0;
 	}
 	
 	/*media-sub-component*/
 	
	n=Gq_create_add_media_subcomponents(&list,sdpinvite,sdp200,number,media_sub_component,tag);
 	if(n==-1)
 	{
 		LOG(L_INFO, ANSI_RED"INF:"M_NAME"Unable to create media_sub_components list AVP");
 		cdpb.AAAFreeAVP(&media_component_number);
 		list.head=0;
 		list.tail=0;	
 		return 0;
 	}
 	if (n==0) {
 		/*we don't create a Media Description for this media line*/
 		/*because answerer rejected the offer!*/
 		cdpb.AAAFreeAVP(&media_component_number);
 		list.head=0;
 		list.tail=0;
 		return 1;
 	}
 	
 	
 	
 	/*if n=-1 then its error*/
 	/*if n=0 is because answerer rejected this media offer*/
 	/*or offerer wanted it to be disabled*/
 	 	
 	/*media-type*/
 	 ptr=mline;
 	 ptr+=2; /*skip m=*/
 	 	 
 	 
 	 
 	 if (strncmp(ptr,"audio",5)==0)
 	 {
 	 	type=AVP_IMS_Media_Type_Audio;
 	 } else if(strncmp(ptr,"video",5)==0)
 	 {
 	 	type=AVP_IMS_Media_Type_Video;
 	 }else if(strncmp(ptr,"data",4)==0)
 	 {
 	 	type=AVP_IMS_Media_Type_Data;
 	 }else if(strncmp(ptr,"application",11)==0)
 	 {
 	 	type=AVP_IMS_Media_Type_Application;
 	 }else if(strncmp(ptr,"control",7)==0)
 	 {
 	 	type=AVP_IMS_Media_Type_Control;
 	 }else if(strncmp(ptr,"text",4)==0)
 	 {
 	 	type=AVP_IMS_Media_Type_Text;
 	 }else if(strncmp(ptr,"message",7)==0)
 	 {
 	 	type=AVP_IMS_Media_Type_Message;
 	 } else 
 	 {
 	 	type=AVP_IMS_Media_Type_Other;
 	 }
 	 
 	  	 
 	 set_4bytes(x,type);
 	 media_type=cdpb.AAACreateAVP(AVP_IMS_Media_Type,
 	 								AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
 	 								IMS_vendor_id_3GPP,x,4,
 	 								AVP_DUPLICATE_DATA);
 	 AAAAddAVPToAVPList(&list,media_type);								

 		 								
 	
 	/*Max-Requested-Bandwidth-UL*/
 	/*Max-Requested-Bandwidth-DL*/
 	/*SDP bodies have been check by gq_create_add_media_subcomponents*/
 	
 	i=1;
 	ptr=find_sdp_line(sdp200.s,(sdp200.s+sdp200.len),'m');
 	
 	while(i!=number) 
 	{
 		ptr=find_next_sdp_line(ptr,(sdp200.s+sdp200.len),'m',NULL);
 		i++;	
 	}
 	
 	
 	
 	if(tag==1)
 	{
 		/*in the invite its defined how much bandwidth
 		 * you want in the downlink!*/
 		extract_bandwidth(&bwDL,sdpinvite,mline);
 		extract_bandwidth(&bwUL,sdp200,ptr);
 	} else {
 		extract_bandwidth(&bwDL,sdp200,ptr);
 		extract_bandwidth(&bwUL,sdpinvite,mline);	
 		 		
 	}
 	/*
 	 * IN a SDP b=AS:x line  the x is the amount of bandwidth
 	 * the sender of the SDP body is willing to RECEIVE 
 	 * therefor the next code is right 
 	 * 
 	 * */
	if (bwDL.bAS!=0)
	 {
	 	
 			set_4bytes(x,bwDL.bAS);
 			Max_UL=cdpb.AAACreateAVP(AVP_IMS_Max_Requested_Bandwidth_UL,
											AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
											IMS_vendor_id_3GPP,x,4,
											AVP_DUPLICATE_DATA);
			AAAAddAVPToAVPList(&list,Max_UL);
		
	 }
	if (bwUL.bAS!=0)
	{
 			set_4bytes(x,bwUL.bAS);
 			Max_DL=cdpb.AAACreateAVP(AVP_IMS_Max_Requested_Bandwidth_DL,
											AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
											IMS_vendor_id_3GPP,x,4,
											AVP_DUPLICATE_DATA);
			AAAAddAVPToAVPList(&list,Max_DL);
			
	}
	
	
	
 	/*Flow-Status*/
 	/*lets follow the specs*/
 		if (tag==0)
 		{
 			extract_token(mline,port,Gq_MAX_Char,2);
 		} else {
 			extract_token(ptr,port,Gq_MAX_Char,2);
 		}
 		if(strncmp(port,"0",1)==0)
 		{
 			set_4bytes(x,AVP_IMS_Flow_Status_Removed);
  		} else {
  			
  			if (tag==1)
  			{
  				a=check_atributes(sdp200,ptr);
  			} else {
  				a=check_atributes(sdpinvite,mline);
  			}
  			
  			if (a==1)
  			{
  				set_4bytes(x,AVP_IMS_Flow_Status_Enabled_Uplink);
  			} else if(a==2)
  			{
  				set_4bytes(x,AVP_IMS_Flow_Status_Enabled_Downlink);
  			} else {
  				set_4bytes(x,AVP_IMS_Flow_Status_Enabled);
  			} 
  			
  			
 		}
 	
 	
 		
 		flow_status=cdpb.AAACreateAVP(AVP_IMS_Flow_Status,
 											AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
 											IMS_vendor_id_3GPP,x,4,
 											AVP_DUPLICATE_DATA);
		AAAAddAVPToAVPList(&list,flow_status);
 	
 	
 	/*RR and RS*/
 	
 	
 	x[0]=0; x[1]=0; x[2]=0; x[3]=0;
 	
		
			if(bwUL.bRR!=0) {
				set_4bytes(x,bwUL.bRR);
			} /*else if (bwDL.bRS!=0) {
				set_4bytes(x,bwDL.bRS);
			}*/
		
	RR=0;
	if (x[0]!=0 || x[1]!=0 || x[2]!=0 || x[3]!=0) {
			RR=cdpb.AAACreateAVP(AVP_IMS_RR_Bandwidth,
											AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
											IMS_vendor_id_3GPP,x,4,
											AVP_DUPLICATE_DATA);
			AAAAddAVPToAVPList(&list,RR);
			 	 		
	}	
	

 	x[0]=0; x[1]=0; x[2]=0; x[3]=0;
 	
			if(bwUL.bRS!=0) 
			{
				set_4bytes(x,bwUL.bRS);
			} /*else if(bwDL.bRR!=0){
				set_4bytes(x,bwDL.bRR);
			}*/
	
			
 	RS=0;
	if (x[0]!=0 || x[1]!=0 || x[2]!=0 || x[3]!=0)
	 {
		RS=cdpb.AAACreateAVP(AVP_IMS_RS_Bandwidth,
								AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
								IMS_vendor_id_3GPP,x,4,
								AVP_DUPLICATE_DATA);
		AAAAddAVPToAVPList(&list,RS);
		
	}		
 	
 	
 	
 	
 	
 	
 	/*codec-data*/
 	 	
 	
 	if (tag==0)
 	{
 		/*0 means uplink offer*/
 		codec_data1=Gq_create_codec_data(sdpinvite,number,0);
 		AAAAddAVPToAVPList(&list,codec_data1);
 		/*3 means downlink answer*/
 		codec_data2=Gq_create_codec_data(sdp200,number,3);
 		AAAAddAVPToAVPList(&list,codec_data2);
 	} else { 
 		/*2 means downlink offer*/
 		codec_data1=Gq_create_codec_data(sdpinvite,number,2);
 		AAAAddAVPToAVPList(&list,codec_data1);
 		/*1 means uplink answer*/
 		codec_data2=Gq_create_codec_data(sdp200,number,1);
 		AAAAddAVPToAVPList(&list,codec_data2);
 	
 	}
 	/*now group them in one big AVP and free them*/
 	
 	data=cdpb.AAAGroupAVPS(list);
  	 		
  	Gq_add_avp(msg,data.s,data.len,AVP_IMS_Media_Component_Description,
 				AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC,
 				IMS_vendor_id_3GPP,
 				AVP_DUPLICATE_DATA,
 				__FUNCTION__);
 	
 			
 	cdpb.AAAFreeAVP(&media_component_number);
 	for(i=0;i<n;i++)
 	{
 		cdpb.AAAFreeAVP(&media_sub_component[i]);
 	}
 	
 	if (bwUL.bAS!=0)
	 {	
	 	cdpb.AAAFreeAVP(&Max_UL);	 	
	 }
	if (bwDL.bAS!=0)
	{
		cdpb.AAAFreeAVP(&Max_DL);		
	}
	
	
	cdpb.AAAFreeAVP(&flow_status);
	if (RS!=0)
 	{
 		cdpb.AAAFreeAVP(&RS);
 	}
 	if (RR!=0)
 	{
 		cdpb.AAAFreeAVP(&RR);
 	}
 	
 	cdpb.AAAFreeAVP(&media_type);
 	cdpb.AAAFreeAVP(&codec_data1);
 	cdpb.AAAFreeAVP(&codec_data2);
 	
 	list.tail=0;
 	list.head=0;
 	return 1;
 }
Example #7
0
/* Check for sendonly or recvonly modifiers in a= lines
 * @param sdpbody - SDP body
 * @param mline - pointer to beginning of m= line
 * returns  0 if no modifier was found,
 *  -1 on error (malformed SDP body)
 * 1 if sendonly , 2 if recvonly
 * */
int check_atributes(str sdpbody,char *mline) 
{
	char *p,*q;
	int s=0;
	
	p=find_sdp_line(sdpbody.s,sdpbody.s+sdpbody.len,'a');
	q=find_sdp_line(sdpbody.s,sdpbody.s+sdpbody.len,'m');
	
	
	if (p==NULL) 
	{
		return 0;
	}
	
	/*see if there is a sessionwide  a= line*/
	if (p<q)
	{
		p+=2; /*skip a=*/
		while(*p==' ')
		{
			p++;
		}
		if(strncmp(p,"sendonly",8)==0)
		{
			s=1;
		} else if(strncmp(p,"recvonly",8)==0)
		{
			s=2;
		}
		
		
	}
	/*see if there is a mediawide a= line*/
	
	p=find_sdp_line(mline,(sdpbody.s+sdpbody.len),'a');
	if (p==NULL)
	{
		return s;
	}
	mline++;
	q=find_next_sdp_line(mline,(sdpbody.s+sdpbody.len),'m',NULL);
	
	if (q!=NULL && p>q) 
	{		
			return s; /*the a= line found belongs to some other m= line*/	
	}
	
	p+=2; /*skip a=*/
	while(*p==' ')
	{
		p++;
	}
	if(strncmp(p,"sendonly",8)==0)
	{
		return 1;
	} else if(strncmp(p,"recvonly",8)==0)
	{
		return 2;
	} else {
		return s;
	}
			
}
Example #8
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;
}
Example #9
0
static int
force_rtp_proxy2_f(struct sip_msg* msg, char* str1, char* str2)
{
	str body, body1, oldport, oldip, newport, newip;
	str callid, from_tag, to_tag, tmp;
	int create, port, len, asymmetric, flookup, argc, proxied, real;
	int oidx, pf=0, pf1, force, node_idx;
	char opts[16];
	char *cp, *cp1;
	char  *cpend, *next;
	char **ap, *argv[10];
	struct lump* anchor;
	struct rtpp_node *node;
	struct iovec v[14] = {
		{NULL, 0},	/* command */
		{NULL, 0},	/* options */
		{" ", 1},	/* separator */
		{NULL, 0},	/* callid */
		{" ", 1},	/* separator */
		{NULL, 7},	/* newip */
		{" ", 1},	/* separator */
		{NULL, 1},	/* oldport */
		{" ", 1},	/* separator */
		{NULL, 0},	/* from_tag */
		{";", 1},	/* separator */
		{NULL, 0},	/* medianum */
		{" ", 1},	/* separator */
		{NULL, 0}	/* to_tag */
	};
	char *v1p, *v2p, *c1p, *c2p, *m1p, *m2p, *bodylimit;
	char medianum_buf[20];
	int medianum, media_multi;
	str medianum_str, tmpstr1;
	int c1p_altered;

	v[1].iov_base=opts;
	asymmetric = flookup = force = real = 0;
	oidx = 1;
	node_idx = -1;
	for (cp = str1; *cp != '\0'; cp++) {
		switch (*cp) {
		case ' ':
		case '\t':
			break;

		case 'a':
		case 'A':
			opts[oidx++] = 'A';
			asymmetric = 1;
			real = 1;
			break;

		case 'i':
		case 'I':
			opts[oidx++] = 'I';
			break;

		case 'e':
		case 'E':
			opts[oidx++] = 'E';
			break;

		case 'l':
		case 'L':
			flookup = 1;
			break;

		case 'f':
		case 'F':
			force = 1;
			break;

		case 'r':
		case 'R':
			real = 1;
			break;

		case 'n':
		case 'N':
			cp++;
			for (len = 0; isdigit(cp[len]); len++)
				continue;
			if (len == 0) {
				LOG(L_ERR, "ERROR: force_rtp_proxy2: non-negative integer"
				    "should follow N option\n");
				return -1;
			}
			node_idx = strtoul(cp, NULL, 10);
			cp += len - 1;
			break;

		default:
			LOG(L_ERR, "ERROR: force_rtp_proxy2: unknown option `%c'\n", *cp);
			return -1;
		}
	}

	if (msg->first_line.type == SIP_REQUEST &&
	    msg->first_line.u.request.method_value == METHOD_INVITE) {
		create = 1;
	} else if (msg->first_line.type == SIP_REPLY) {
		create = 0;
	} else {
		return -1;
	}
	/* extract_body will also parse all the headers in the message as
	 * a side effect => don't move get_callid/get_to_tag in front of it
	 * -- andrei */
	if (extract_body(msg, &body) == -1) {
		LOG(L_ERR, "ERROR: force_rtp_proxy2: can't extract body "
		    "from the message\n");
		return -1;
	}
	if (get_callid(msg, &callid) == -1 || callid.len == 0) {
		LOG(L_ERR, "ERROR: force_rtp_proxy2: can't get Call-Id field\n");
		return -1;
	}
	if (get_to_tag(msg, &to_tag) == -1) {
		LOG(L_ERR, "ERROR: force_rtp_proxy2: can't get To tag\n");
		return -1;
	}
	if (get_from_tag(msg, &from_tag) == -1 || from_tag.len == 0) {
		LOG(L_ERR, "ERROR: force_rtp_proxy2: can't get From tag\n");
		return -1;
	}
	if (flookup != 0) {
		if (create == 0 || to_tag.len == 0)
			return -1;
		create = 0;
		tmp = from_tag;
		from_tag = to_tag;
		to_tag = tmp;
	}
	proxied = 0;
	for (cp = body.s; (len = body.s + body.len - cp) >= ANORTPPROXY_LEN;) {
		cp1 = ser_memmem(cp, ANORTPPROXY, len, ANORTPPROXY_LEN);
		if (cp1 == NULL)
			break;
		if (cp1[-1] == '\n' || cp1[-1] == '\r') {
			proxied = 1;
			break;
		}
		cp = cp1 + ANORTPPROXY_LEN;
	}
	if (proxied != 0 && force == 0)
		return -1;
	/*
	 * Parsing of SDP body.
	 * It can contain a few session descriptions (each starts with
	 * v-line), and each session may contain a few media descriptions
	 * (each starts with m-line).
	 * We have to change ports in m-lines, and also change IP addresses in
	 * c-lines which can be placed either in session header (fallback for
	 * all medias) or media description.
	 * Ports should be allocated for any media. IPs all should be changed
	 * to the same value (RTP proxy IP), so we can change all c-lines
	 * unconditionally.
	 */
	bodylimit = body.s + body.len;
	v1p = find_sdp_line(body.s, bodylimit, 'v');
	if (v1p == NULL) {
		LOG(L_ERR, "ERROR: force_rtp_proxy2: no sessions in SDP\n");
		return -1;
	}
	v2p = find_next_sdp_line(v1p, bodylimit, 'v', bodylimit);
	media_multi = (v2p != bodylimit);
	v2p = v1p;
	medianum = 0;
	for(;;) {
		/* Per-session iteration. */
		v1p = v2p;
		if (v1p == NULL || v1p >= bodylimit)
			break; /* No sessions left */
		v2p = find_next_sdp_line(v1p, bodylimit, 'v', bodylimit);
		/* v2p is text limit for session parsing. */
		m1p = find_sdp_line(v1p, v2p, 'm');
		/* Have this session media description? */
		if (m1p == NULL) {
			LOG(L_ERR, "ERROR: force_rtp_proxy2: no m= in session\n");
			return -1;
		}
		/*
		 * Find c1p only between session begin and first media.
		 * c1p will give common c= for all medias.
		 */
		c1p = find_sdp_line(v1p, m1p, 'c');
		c1p_altered = 0;
		/* Have session. Iterate media descriptions in session */
		m2p = m1p;
		for (;;) {
			m1p = m2p;
			if (m1p == NULL || m1p >= v2p)
				break;
			m2p = find_next_sdp_line(m1p, v2p, 'm', v2p);
			/* c2p will point to per-media "c=" */
			c2p = find_sdp_line(m1p, m2p, 'c');
			/* Extract address and port */
			tmpstr1.s = c2p ? c2p : c1p;
			if (tmpstr1.s == NULL) {
				/* No "c=" */
				LOG(L_ERR, "ERROR: force_rtp_proxy2: can't"
				    " find media IP in the message\n");
				return -1;
			}
			tmpstr1.len = v2p - tmpstr1.s; /* limit is session limit text */
			if (extract_mediaip(&tmpstr1, &oldip, &pf) == -1) {
				LOG(L_ERR, "ERROR: force_rtp_proxy2: can't"
				    " extract media IP from the message\n");
				return -1;
			}
			tmpstr1.s = m1p;
			tmpstr1.len = m2p - m1p;
			if (extract_mediaport(&tmpstr1, &oldport) == -1) {
				LOG(L_ERR, "ERROR: force_rtp_proxy2: can't"
				    " extract media port from the message\n");
				return -1;
			}
			++medianum;
			if (asymmetric != 0 || real != 0) {
				newip = oldip;
			} else {
				newip.s = ip_addr2a(&msg->rcv.src_ip);
				newip.len = strlen(newip.s);
			}
			/* XXX must compare address families in all addresses */
			if (pf == AF_INET6) {
				opts[oidx] = '6';
				oidx++;
			}
			snprintf(medianum_buf, sizeof medianum_buf, "%d", medianum);
			medianum_str.s = medianum_buf;
			medianum_str.len = strlen(medianum_buf);
			opts[0] = (create == 0) ? 'L' : 'U';
			v[1].iov_len = oidx;
			STR2IOVEC(callid, v[3]);
			STR2IOVEC(newip, v[5]);
			STR2IOVEC(oldport, v[7]);
			STR2IOVEC(from_tag, v[9]);
			if (1 || media_multi) /* XXX netch: can't choose now*/
			{
				STR2IOVEC(medianum_str, v[11]);
			} else {
				v[10].iov_len = v[11].iov_len = 0;
			}
			STR2IOVEC(to_tag, v[13]);
			do {
				node = select_rtpp_node(callid, 1, node_idx);
				if (!node) {
					LOG(L_ERR, "ERROR: force_rtp_proxy2: no available proxies\n");
					return -1;
				}
				cp = send_rtpp_command(node, v, (to_tag.len > 0) ? 14 : 12);
			} while (cp == NULL);
			/* Parse proxy reply to <argc,argv> */
			argc = 0;
			memset(argv, 0, sizeof(argv));
			cpend=cp+strlen(cp);
			next=eat_token_end(cp, cpend);
			for (ap = argv; cp<cpend; cp=next+1, next=eat_token_end(cp, cpend)){
				*next=0;
				if (*cp != '\0') {
					*ap=cp;
					argc++;
					if ((char*)++ap >= ((char*)argv+sizeof(argv)))
						break;
				}
			}
			if (argc < 1) {
				LOG(L_ERR, "force_rtp_proxy2: no reply from rtp proxy\n");
				return -1;
			}
			port = atoi(argv[0]);
			if (port <= 0 || port > 65535) {
				LOG(L_ERR, "force_rtp_proxy2: incorrect port in reply from rtp proxy\n");
				return -1;
			}

			pf1 = (argc >= 3 && argv[2][0] == '6') ? AF_INET6 : AF_INET;

			if (isnulladdr(&oldip, pf)) {
				if (pf1 == AF_INET6) {
					newip.s = "::";
					newip.len = 2;
				} else {
					newip.s = "0.0.0.0";
					newip.len = 7;
				}
			} else {
				newip.s = (argc < 2) ? str2 : argv[1];
				newip.len = strlen(newip.s);
			}
			newport.s = int2str(port, &newport.len); /* beware static buffer */
			/* Alter port. */
			body1.s = m1p;
			body1.len = bodylimit - body1.s;
			if (alter_mediaport(msg, &body1, &oldport, &newport, 0) == -1)
				return -1;
			/*
			 * Alter IP. Don't alter IP common for the session
			 * more than once.
			 */
			if (c2p != NULL || !c1p_altered) {
				body1.s = c2p ? c2p : c1p;
				body1.len = bodylimit - body1.s;
				if (alter_mediaip(msg, &body1, &oldip, pf, &newip, pf1, 0) == -1)
					return -1;
				if (!c2p)
					c1p_altered = 1;
			}
		} /* Iterate medias in session */
	} /* Iterate sessions */

	if (proxied == 0) {
		cp = pkg_malloc(ANORTPPROXY_LEN * sizeof(char));
		if (cp == NULL) {
			LOG(L_ERR, "ERROR: force_rtp_proxy2: out of memory\n");
			return -1;
		}
		anchor = anchor_lump(msg, body.s + body.len - msg->buf, 0, 0);
		if (anchor == NULL) {
			LOG(L_ERR, "ERROR: force_rtp_proxy2: anchor_lump failed\n");
			pkg_free(cp);
			return -1;
		}
		memcpy(cp, ANORTPPROXY, ANORTPPROXY_LEN);
		if (insert_new_lump_after(anchor, cp, ANORTPPROXY_LEN, 0) == NULL) {
			LOG(L_ERR, "ERROR: force_rtp_proxy2: insert_new_lump_after failed\n");
			pkg_free(cp);
			return -1;
		}
	}

	return 1;
}