Esempio n. 1
0
/* returns : -1 - error
 *            0 - ok, but no contact added
 *            n - ok and n contacts added
 */
static int shmcontact2dset(struct sip_msg *req, struct sip_msg *sh_rpl,
											long max, pv_elem_t *reason)
{
	static struct sip_msg  dup_rpl;
	static str scontacts[MAX_CONTACTS_PER_REPLY];
	static qvalue_t  sqvalues[MAX_CONTACTS_PER_REPLY];
	struct hdr_field *hdr;
	struct hdr_field *contact_hdr;
	contact_t        *contacts;
	str backup_uri;
	int n,i;
	int added;
	int dup;
	int ret;

	dup = 0; /* sh_rpl not duplicated */
	ret = 0; /* success and no contact added */
	contact_hdr = NULL;
	hdr = NULL;

	if (sh_rpl==0 || sh_rpl==FAKED_REPLY)
		return 0;

	if ( sh_rpl->msg_flags&FL_SHM_CLONE ) {
		/* duplicate the reply into private memory to be able
		 * to parse it and after words to free the parsed mems */
		memcpy( &dup_rpl, sh_rpl, sizeof(struct sip_msg) );
		LM_DBG("duplicating shm reply\n");
		dup = 1;
		/* ok -> force the parsing of contact header */
		if ( parse_headers( &dup_rpl, HDR_EOH_F, 0)<0 ) {
			LM_ERR("dup_rpl parse failed\n");
			ret = -1;
			goto restore;
		}
		if (dup_rpl.contact==0) {
			LM_DBG("contact hdr not found in dup_rpl\n");
			goto restore;
		}
		contact_hdr = dup_rpl.contact;
	} else {
		/* parse directly the current copy */
		/* force the parsing of contact header */
		if ( parse_headers( sh_rpl, HDR_EOH_F, 0)<0 ) {
			LM_ERR("sh_rpl parse failed\n");
			ret = -1;
			goto restore;
		}
		if (sh_rpl->contact==0) {
			LM_DBG("contact hdr not found in sh_rpl\n");
			goto restore;
		}
		contact_hdr = sh_rpl->contact;
	}

	/* iterate through all contact headers and extract the URIs */
	for( n=0,hdr=contact_hdr ; hdr ; hdr=hdr->sibling ) {

		/* parse the body of contact header */
		if (hdr->parsed==0) {
			if ( parse_contact(hdr)<0 ) {
				LM_ERR("contact hdr parse failed\n");
				ret = -1;
				goto restore;
			}
		}

		/* we have the contact header and its body parsed -> sort the contacts
		 * based on the q value */
		contacts = ((contact_body_t*)hdr->parsed)->contacts;
		if (contacts==0) {
			LM_DBG("contact hdr has no contacts\n");
		} else {
			sort_contacts( contacts, scontacts, sqvalues, &n);
		}

		/* clean currently added contact */
		if (dup)
			free_contact( (contact_body_t**)(void*)(&hdr->parsed) );
	}

	if (n==0) {
		LM_DBG("no contacts left after filtering\n");
		goto restore;
	}

	/* to many branches ? */
	if (max!=-1 && n>max)
		n = max;

	LM_DBG("%d contacts remaining after filtering and sorting\n",n);

	added = 0;

	/* add the sorted contacts as branches in dset and log this! */
	for ( i=0 ; i<n ; i++ ) {
		LM_DBG("adding contact <%.*s>\n",
			scontacts[i].len, scontacts[i].s);
		if (i==0) {
			/* set RURI*/
			if ( set_ruri( req, &scontacts[i])==-1 ) {
				LM_ERR("failed to set new RURI\n");
				goto restore;
			}
			set_ruri_q(req, sqvalues[i]);
		} else {
			if (append_branch(0,&scontacts[i],0,0,sqvalues[i],0,0)<0) {
				LM_ERR("failed to add contact to dset\n");
				continue;
			}
		}
		added++;
		if (rd_acc_fct!=0 && reason) {
			/* log the redirect */
			backup_uri = req->new_uri;
			req->new_uri =  scontacts[i];
			//FIXME
			rd_acc_fct( req, (char*)reason, acc_db_table,
					NULL, NULL, NULL, NULL);
			req->new_uri = backup_uri;
		}
	}

	ret = (added==0)?-1:added;
restore:
	if (dup==1) {
		/* free current parsed contact header */
		if (hdr && hdr->parsed)
			free_contact( (contact_body_t**)(void*)(&hdr->parsed) );
		/* are any new headers found? */
		if (dup_rpl.last_header!=sh_rpl->last_header) {
			/* identify in the new headere list (from dup_rpl)
			 * the sh_rpl->last_header and start remove everything after */
			hdr = sh_rpl->last_header;
			free_hdr_field_lst(hdr->next);
			hdr->next=0;
		}
	}
	return ret;
}
Esempio n. 2
0
/* returns : -1 - error
 *            0 - ok, but no contact added
 *            n - ok and n contacts added
 */
static int shmcontact2dset(struct sip_msg *req, struct sip_msg *sh_rpl,
													long max, str *reason)
{
	static struct sip_msg  dup_rpl;
	static contact_t *scontacts[MAX_CONTACTS_PER_REPLY];
	struct hdr_field *hdr;
	struct hdr_field *contact_hdr;
	contact_t        *contacts;
	int n,i;
	int added;
	int dup;
	int ret;

	/* dup can be:
	 *    0 - sh reply but nothing duplicated 
	 *    1 - sh reply but only contact body parsed
	 *    2 - sh reply and contact header and body parsed
	 *    3 - private reply
	 */
	dup = 0; /* sh_rpl not duplicated */
	ret = 0; /* success and no contact added */

	if (sh_rpl==0 || sh_rpl==FAKED_REPLY)
		return 0;

	if (sh_rpl->contact==0) {
		/* contact header is not parsed */
		if ( sh_rpl->msg_flags&FL_SHM_CLONE ) {
			/* duplicate the reply into private memory to be able 
			 * to parse it and after words to free the parsed mems */
			memcpy( &dup_rpl, sh_rpl, sizeof(struct sip_msg) );
			dup = 2;
			/* ok -> force the parsing of contact header */
			if ( parse_headers( &dup_rpl, HDR_CONTACT_T, 0)<0 ) {
				LOG(L_ERR,"ERROR:uac_redirect:shmcontact2dset: dup_rpl "
					"parse failed\n");
				ret = -1;
				goto restore;
			}
			if (dup_rpl.contact==0) {
				DBG("DEBUG:uac_redirect:shmcontact2dset: contact hdr not "
					"found in dup_rpl\n");
				goto restore;
			}
			contact_hdr = dup_rpl.contact;
		} else {
			dup = 3;
			/* force the parsing of contact header */
			if ( parse_headers( sh_rpl, HDR_CONTACT_T, 0)<0 ) {
				LOG(L_ERR,"ERROR:uac_redirect:shmcontact2dset: sh_rpl "
					"parse failed\n");
				ret = -1;
				goto restore;
			}
			if (sh_rpl->contact==0) {
				DBG("DEBUG:uac_redirect:shmcontact2dset: contact hdr not "
					"found in sh_rpl\n");
				goto restore;
			}
			contact_hdr = sh_rpl->contact;
		}
	} else {
		contact_hdr = sh_rpl->contact;
	}

	/* parse the body of contact header */
	if (contact_hdr->parsed==0) {
		if ( parse_contact(contact_hdr)<0 ) {
			LOG(L_ERR,"ERROR:uac_redirect:shmcontact2dset: contact hdr "
				"parse failed\n");
			ret = -1;
			goto restore;
		}
		if (dup==0)
			dup = 1;
	}


	/* we have the contact header and its body parsed -> sort the contacts
	 * based on the q value */
	contacts = ((contact_body_t*)contact_hdr->parsed)->contacts;
	if (contacts==0) {
		DBG("DEBUG:uac_redirect:shmcontact2dset: contact hdr "
			"has no contacts\n");
		goto restore;
	}
	n = sort_contacts( contacts, scontacts);

	/* to many branches ? */
	if (max!=-1 && n>max)
		n = max;

	added = 0;

	/* add the sortet contacts as branches in dset and log this! */
	for ( i=0 ; i<n ; i++ ) {
		DBG("DEBUG:uac_redirect:shmcontact2dset: adding contact <%.*s>\n",
			scontacts[i]->uri.len, scontacts[i]->uri.s);
		if (append_branch( 0, &scontacts[i]->uri, 0, Q_UNSPECIFIED, 0, 0)<0 ) {
			LOG(L_ERR,"ERROR:uac_redirect:shmcontact2dset: failed to add "
				"contact to dset\n");
		} else {
			added++;
			if (rd_acc_fct!=0 && reason) {
				/* log the redirect */
				req->new_uri =  scontacts[i]->uri;
				rd_acc_fct( req, (char*)reason, acc_db_table);
			}
		}
	}

	ret = (added==0)?-1:added;
restore:
	if (dup==1) {
		free_contact( (contact_body_t**)(&contact_hdr->parsed) );
	} else if (dup==2) {
		/* are any new headers found? */
		if (dup_rpl.last_header!=sh_rpl->last_header) {
			/* identify in the new headere list (from dup_rpl) 
			 * the sh_rpl->last_header and start remove everything after */
			hdr = sh_rpl->last_header;
			free_hdr_field_lst(hdr->next);
			hdr->next=0;
		}
	}
	return ret;

}
Esempio n. 3
0
/* returns : -1 - error
 *            0 - ok, but no contact added
 *            n - ok and n contacts added
 */
static int shmcontact2dset(struct sip_msg *req, struct sip_msg *sh_rpl,
								long max, struct acc_param *reason, unsigned int bflags)
{
	static struct sip_msg  dup_rpl;
	static contact_t *scontacts[MAX_CONTACTS_PER_REPLY];
	static qvalue_t  sqvalues[MAX_CONTACTS_PER_REPLY];
	struct hdr_field *hdr;
	struct hdr_field *contact_hdr;
	contact_t        *contacts;
	int n,i;
	int added;
	int dup;
	int ret;

	/* dup can be:
	 *    0 - sh reply but nothing duplicated 
	 *    1 - sh reply but only contact body parsed
	 *    2 - sh reply and contact header and body parsed
	 *    3 - private reply
	 */
	dup = 0; /* sh_rpl not duplicated */
	ret = 0; /* success and no contact added */
	contact_hdr = 0;

	if (sh_rpl==0 || sh_rpl==FAKED_REPLY)
		return 0;

	if (sh_rpl->contact==0) {
		/* contact header is not parsed */
		if ( sh_rpl->msg_flags&FL_SHM_CLONE ) {
			/* duplicate the reply into private memory to be able 
			 * to parse it and afterwards to free the parsed mems */
			memcpy( &dup_rpl, sh_rpl, sizeof(struct sip_msg) );
			dup = 2;
			/* ok -> force the parsing of contact header */
			if ( parse_headers( &dup_rpl, HDR_EOH_F, 0)<0 ) {
				LM_ERR("dup_rpl parse failed\n");
				ret = -1;
				goto restore;
			}
			if (dup_rpl.contact==0) {
				LM_DBG("contact hdr not found in dup_rpl\n");
				goto restore;
			}
			contact_hdr = dup_rpl.contact;
		} else {
			dup = 3;
			/* force the parsing of contact header */
			if ( parse_headers( sh_rpl, HDR_EOH_F, 0)<0 ) {
				LM_ERR("sh_rpl parse failed\n");
				ret = -1;
				goto restore;
			}
			if (sh_rpl->contact==0) {
				LM_DBG("contact hdr not found in sh_rpl\n");
				goto restore;
			}
			contact_hdr = sh_rpl->contact;
		}
	} else {
		contact_hdr = sh_rpl->contact;
	}

	/* parse the body of contact headers */
	hdr = contact_hdr;
	while(hdr) {
		if (hdr->type == HDR_CONTACT_T) {
			if (hdr->parsed==0) {
				if(parse_contact(hdr) < 0) {
					LM_ERR("failed to parse Contact body\n");
					ret = -1;
					goto restore;
				}
				if (dup==0)
					dup = 1;
				}
		}
		hdr = hdr->next;
	}

	/* we have the contact header and its body parsed -> sort the contacts
	 * based on the q value */
	contacts = ((contact_body_t*)contact_hdr->parsed)->contacts;
	if (contacts==0) {
		LM_DBG("contact hdr has no contacts\n");
		goto restore;
	}
	n = sort_contacts(contact_hdr, scontacts, sqvalues);
	if (n==0) {
		LM_DBG("no contacts left after filtering\n");
		goto restore;
	}

	i=0;

	/* more branches than requested in the parameter
	 * - add only the last ones from sorted array,
	 *   because the order is by increasing q */
	if (max!=-1 && n>max)
		i = n - max;

	added = 0;

	/* add the sortet contacts as branches in dset and log this! */
	for (  ; i<n ; i++ ) {
		LM_DBG("adding contact <%.*s>\n", scontacts[i]->uri.len,
				scontacts[i]->uri.s);
		if(sruid_next(&_redirect_sruid)==0) {
			if(append_branch( 0, &scontacts[i]->uri, 0, 0, sqvalues[i],
						bflags, 0, &_redirect_sruid.uid, 0,
						&_redirect_sruid.uid, &_redirect_sruid.uid)<0) {
				LM_ERR("failed to add contact to dset\n");
			} else {
				added++;
				if (rd_acc_fct!=0 && reason) {
					/* log the redirect */
					req->new_uri =  scontacts[i]->uri;
					//FIXME
					rd_acc_fct( req, (char*)reason, acc_db_table);
				}
			}
		} else {
			LM_ERR("failed to generate ruid for a new branch\n");
		}
	}

	ret = (added==0)?-1:added;
restore:
	if (dup==1) {
		free_contact( (contact_body_t**)(void*)(&contact_hdr->parsed) );
	} else if (dup==2) {
		/* are any new headers found? */
		if (dup_rpl.last_header!=sh_rpl->last_header) {
			/* identify in the new headere list (from dup_rpl) 
			 * the sh_rpl->last_header and start remove everything after */
			hdr = sh_rpl->last_header;
			free_hdr_field_lst(hdr->next);
			hdr->next=0;
		}
	}
	return ret;

}