📄 cpl_proxy.h
字号:
/* * $Id: cpl_proxy.h,v 1.22.2.2 2005/06/21 17:52:13 andrei Exp $ * * Copyright (C) 2001-2003 FhG Fokus * * This file is part of ser, a free SIP server. * * ser is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version * * For a license to use the ser software under conditions * other than those described here, or to purchase support for this * software, please contact iptel.org by e-mail at the following addresses: * info@iptel.org * * ser is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * History: * ------- * 2003-07-29: file created (bogdan) * 2004-06-14: flag CPL_IS_STATEFUL is set now immediately after the * transaction is created (bogdan) */#include "../tm/h_table.h"#include "../../parser/contact/parse_contact.h"#define duplicate_str( _orig_ , _new_ ) \ do {\ (_new_) = (str*)shm_malloc(sizeof(str)+(_orig_)->len);\ if (!(_new_)) goto mem_error;\ (_new_)->len = (_orig_)->len;\ (_new_)->s = (char*)((_new_))+sizeof(str);\ memcpy((_new_)->s,(_orig_)->s,(_orig_)->len);\ } while(0)#define search_and_duplicate_hdr( _intr_ , _field_ , _name_ , _sfoo_ ) \ do {\ if (!(_intr_)->_field_) {\ if (!(_intr_)->msg->_field_) { \ if (parse_headers((_intr_)->msg,_name_,0)==-1) {\ LOG(L_ERR,"ERROR:run_proxy: bad %u hdr\n",_name_);\ goto runtime_error;\ } else if ( !(_intr_)->msg->_field_) {\ (_intr_)->_field_ = STR_NOT_FOUND;\ } else {\ (_sfoo_) = &((_intr_)->msg->_field_->body);\ duplicate_str( (_sfoo_) , (_intr_)->_field_ );\ }\ } else {\ (_sfoo_) = &((_intr_)->msg->_field_->body);\ duplicate_str( (_sfoo_) , (_intr_)->_field_ );\ }\ } else {\ (_sfoo_) = (_intr_)->_field_;\ duplicate_str( (_sfoo_) , (_intr_)->_field_ );\ }\ }while(0)static inline int parse_q(str *q, unsigned int *prio){ if (q->s[0]=='0') *prio=0; else if (q->s[0]=='1') *prio=10; else goto error; if (q->s[1]!='.') goto error; if (q->s[2]<'0' || q->s[2]>'9') goto error; *prio += q->s[2] - '0'; if (*prio>10) goto error; return 0;error: LOG(L_ERR,"ERROR:cpl-c:parse_q:bad q param <%.*s>\n",q->len,q->s); return -1;}static inline int add_contacts_to_loc_set(struct sip_msg* msg, struct location **loc_set){ struct sip_uri uri; struct contact *contacts; unsigned int prio; /* we need to have the contact header */ if (msg->contact==0) { /* find and parse the Contact header */ if ((parse_headers(msg, HDR_CONTACT, 0)==-1) || (msg->contact==0) ) { LOG(L_ERR,"ERROR:cpl-c:add_contacts_to_loc_set: error parsing or " "no Contact hdr found!\n"); goto error; } } /* extract from contact header the all the addresses */ if (parse_contact( msg->contact )!=0) { LOG(L_ERR,"ERROR:cpl-c:add_contacts_to_loc_set: unable to parse " "Contact hdr!\n"); goto error; } /* in contact hdr, in parsed attr, we should have a list of contacts */ if ( msg->contact->parsed ) { contacts = ((struct contact_body*)msg->contact->parsed)->contacts; for( ; contacts ; contacts=contacts->next) { /* check if the contact is a valid sip uri */ if (parse_uri( contacts->uri.s, contacts->uri.len , &uri)!=0) { continue; } /* convert the q param to int value (if any) */ if (contacts->q) { if (parse_q( &(contacts->q->body), &prio )!=0) continue; } else { prio = 10; /* set default to minimum */ } /* add the uri to location set */ if (add_location( loc_set, &contacts->uri,prio, CPL_LOC_DUPL)!=0) { LOG(L_ERR,"ERROR:cpl-c:add_contacts_to_loc_set: unable to add " "<%.*s>\n",contacts->uri.len,contacts->uri.s); } } } return 0;error: return -1;}static void reply_callback( struct cell* t, int type, struct tmcb_params* ps){ struct cpl_interpreter *intr = (struct cpl_interpreter*)(*(ps->param)); struct location *loc = 0; int rez; if (intr==0) { LOG(L_WARN,"WARNING:cpl-c:reply_callback: param=0 for callback %d," " transaction=%p \n",type,t); return; } if (type&TMCB_RESPONSE_OUT) { /* the purpose of the final reply is to trash down the interpreter * structure! it's the safest place to do that, since this callback * it's called only once per transaction for final codes (>=200) ;-) */ if (ps->code>=200) { DBG("DEBUG:cpl-c:final_reply: code=%d -------------->\n" " --------------------------> final reply received\n", ps->code); /* CPL interpretation done, call established -> destroy */ free_cpl_interpreter( intr ); /* set to zero the param callback*/ *(ps->param) = 0; } return; } else if (!type&TMCB_ON_FAILURE) { LOG(L_ERR,"BUG:cpl-c:reply_callback: unknown type %d\n",type); goto exit; } DBG("DEBUG:cpl-c:negativ_reply: ------------------------------>\n" " ---------------------------------> negativ reply received\n"); intr->flags |= CPL_PROXY_DONE; intr->msg = ps->req; /* if it's a redirect-> do I have to added to the location set ? */ if (intr->proxy.recurse && (ps->code)/100==3) { DBG("DEBUG:cpl-c:negativ_reply: recurse level %d processing..\n", intr->proxy.recurse); intr->proxy.recurse--; /* get the locations from the Contact */ add_contacts_to_loc_set( ps->rpl, &(intr->loc_set)); switch (intr->proxy.ordering) { case SEQUENTIAL_VAL: /* update the last_to_proxy to last location from set */ if (intr->proxy.last_to_proxy==0) { /* the pointer went through entire old set -> set it to the * updated set, from the beginning */ if (intr->loc_set==0) /* the updated set is also empty -> proxy ended */ break; intr->proxy.last_to_proxy = intr->loc_set; } while(intr->proxy.last_to_proxy->next) intr->proxy.last_to_proxy=intr->proxy.last_to_proxy->next; break; case PARALLEL_VAL: /* push the whole new location set to be proxy */ intr->proxy.last_to_proxy = intr->loc_set; break; case FIRSTONLY_VAL: intr->proxy.last_to_proxy = 0; break; } } /* the current proxying failed -> do I have another location to try ? * This applies only for SERIAL forking or if RECURSE is set */ if (intr->proxy.last_to_proxy) { /* continue proxying */ DBG("DEBUG:cpl-c:failed_reply: resuming proxying....\n"); switch (intr->proxy.ordering) { case PARALLEL_VAL: /* I get here only if I got a 3xx and RECURSE in on -> * forward to all location from location set */ intr->proxy.last_to_proxy = 0; cpl_proxy_to_loc_set(intr->msg,&(intr->loc_set),intr->flags ); break; case SEQUENTIAL_VAL: /* place a new branch to the next location from loc. set*/ loc = remove_first_location( &(intr->loc_set) ); /*print_location_set(intr->loc_set);*/ /* update (if necessary) the last_to_proxy location */ if (intr->proxy.last_to_proxy==loc) intr->proxy.last_to_proxy = 0; cpl_proxy_to_loc_set(intr->msg,&loc,intr->flags ); break; default: LOG(L_CRIT,"BUG:cpl_c:failed_reply: unexpected ordering found " "when continuing proxying (%d)\n",intr->proxy.ordering); goto exit; } /* nothing more to be done */ return; } else { /* done with proxying.... -> process the final response */ DBG("DEBUG:cpl-c:failed_reply:final_reply: got a final %d\n",ps->code); intr->ip = 0; if (ps->code==486 || ps->code==600) { /* busy response */ intr->ip = intr->proxy.busy; } else if (ps->code==408) { /* request timeout -> no response */ intr->ip = intr->proxy.noanswer; } else if (((ps->code)/100)==3) { /* redirection */ /* add to the location list all the addresses from Contact */ add_contacts_to_loc_set( ps->rpl, &(intr->loc_set)); print_location_set( intr->loc_set ); intr->ip = intr->proxy.redirect; } else { /* generic failure */ intr->ip = intr->proxy.failure; } if (intr->ip==0) intr->ip = (intr->proxy.default_)? intr->proxy.default_:DEFAULT_ACTION; if (intr->ip!=DEFAULT_ACTION) intr->ip = get_first_child( intr->ip );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -