/* 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; }
/* 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; }
/* 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; }