t_fwd.c

Go to the documentation of this file.
00001 /*
00002  * $Id: t_fwd.c 5801 2009-04-23 09:48:08Z miconda $
00003  *
00004  * Copyright (C) 2001-2003 FhG Fokus
00005  *
00006  * This file is part of Kamailio, a free SIP server.
00007  *
00008  * Kamailio is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * Kamailio is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License 
00019  * along with this program; if not, write to the Free Software 
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  * History:
00023  * -------
00024  *  2003-02-13  proto support added (andrei)
00025  *  2003-02-24  s/T_NULL/T_NULL_CELL/ to avoid redefinition conflict w/
00026  *              nameser_compat.h (andrei)
00027  *  2003-03-01  kr set through a function now (jiri)
00028  *  2003-03-06  callbacks renamed; "blind UAC" introduced, which makes
00029  *              transaction behave as if it was forwarded even if it was
00030  *              not -- good for local UAS, like VM (jiri)
00031  *  2003-03-19  replaced all the mallocs/frees w/ pkg_malloc/pkg_free (andrei)
00032  *  2003-03-30  we now watch downstream delivery and if it fails, send an
00033  *              error message upstream (jiri)
00034  *  2003-04-14  use protocol from uri (jiri)
00035  *  2003-12-04  global TM callbacks switched to per transaction callbacks
00036  *              (bogdan)
00037  *  2004-02-13: t->is_invite and t->local replaced with flags (bogdan)
00038  *  2007-01-25  DNS failover at transaction level added (bogdan)
00039  */
00040 
00041 /*! \file
00042  * \brief TM :: Message forwarding
00043  *
00044  * \ingroup tm
00045  * - Module: \ref tm
00046  */
00047 
00048 #include "../../dprint.h"
00049 #include "../../config.h"
00050 #include "../../ut.h"
00051 #include "../../dset.h"
00052 #include "../../timer.h"
00053 #include "../../hash_func.h"
00054 #include "../../globals.h"
00055 #include "../../action.h"
00056 #include "../../data_lump.h"
00057 #include "../../blacklists.h"
00058 #include "../../usr_avp.h"
00059 #include "../../mem/mem.h"
00060 #include "../../parser/parser_f.h"
00061 #include "t_funcs.h"
00062 #include "t_hooks.h"
00063 #include "t_msgbuilder.h"
00064 #include "ut.h"
00065 #include "t_cancel.h"
00066 #include "t_lookup.h"
00067 #include "t_fwd.h"
00068 #include "fix_lumps.h"
00069 #include "config.h"
00070 
00071 /* route to execute for the branches */
00072 static int goto_on_branch;
00073 int _tm_branch_index = 0;
00074 
00075 void t_on_branch( unsigned int go_to )
00076 {
00077    struct cell *t = get_t();
00078 
00079    /* in MODE_REPLY and MODE_ONFAILURE T will be set to current transaction;
00080     * in MODE_REQUEST T will be set only if the transaction was already 
00081     * created; if not -> use the static variable */
00082    if (route_type==BRANCH_ROUTE || !t || t==T_UNDEFINED )
00083       goto_on_branch=go_to;
00084    else
00085       t->on_branch = go_to;
00086 }
00087 
00088 
00089 unsigned int get_on_branch(void)
00090 {
00091    return goto_on_branch;
00092 }
00093 
00094 
00095 static inline int pre_print_uac_request( struct cell *t, int branch, 
00096       struct sip_msg *request)
00097 {
00098    int backup_route_type;
00099    struct usr_avp **backup_list;
00100    char *p;
00101 
00102    /* ... we calculate branch ... */
00103    if (!t_calc_branch(t, branch, request->add_to_branch_s,
00104          &request->add_to_branch_len ))
00105    {
00106       LM_ERR("branch computation failed\n");
00107       goto error;
00108    }
00109 
00110    /* from now on, flag all new lumps with LUMPFLAG_BRANCH flag in order to
00111     * be able to remove them later --bogdan */
00112    set_init_lump_flags(LUMPFLAG_BRANCH);
00113 
00114    /* copy path vector into branch */
00115    if (request->path_vec.len) {
00116       t->uac[branch].path_vec.s =
00117          shm_resize(t->uac[branch].path_vec.s, request->path_vec.len+1);
00118       if (t->uac[branch].path_vec.s==NULL) {
00119          LM_ERR("shm_resize failed\n");
00120          goto error;
00121       }
00122       t->uac[branch].path_vec.len = request->path_vec.len;
00123       memcpy( t->uac[branch].path_vec.s, request->path_vec.s,
00124          request->path_vec.len+1);
00125    }
00126 
00127    /********** run route & callback ************/
00128 
00129    /* run branch route, if any; run it before RURI's DNS lookup 
00130     * to allow to be changed --bogdan */
00131    if (t->on_branch) {
00132       /* need to pkg_malloc the dst_uri */
00133       if ( request->dst_uri.len ) {
00134          if ( (p=pkg_malloc(request->dst_uri.len))==0 ) {
00135             LM_ERR("no more pkg mem\n");
00136             ser_error=E_OUT_OF_MEM;
00137             goto error;
00138          }
00139          memcpy( p, request->dst_uri.s, request->dst_uri.len);
00140          request->dst_uri.s = p;
00141       }
00142       /* need to pkg_malloc the new_uri */
00143       if ( (p=pkg_malloc(request->new_uri.len))==0 ) {
00144          LM_ERR("no more pkg mem\n");
00145          ser_error=E_OUT_OF_MEM;
00146          goto error;
00147       }
00148       memcpy( p, request->new_uri.s, request->new_uri.len);
00149       request->new_uri.s = p;
00150       request->parsed_uri_ok = 0;
00151       /* make available the avp list from transaction */
00152       backup_list = set_avp_list( &t->user_avps );
00153       /* run branch route */
00154       swap_route_type( backup_route_type, BRANCH_ROUTE);
00155 
00156       _tm_branch_index = branch+1;
00157       if (run_top_route(branch_rlist[t->on_branch], request)&ACT_FL_DROP) {
00158          LM_DBG("dropping branch <%.*s>\n", request->new_uri.len,
00159                request->new_uri.s);
00160          _tm_branch_index = 0;
00161          goto error;
00162       }
00163       check_hdrs_changes(request);
00164       t->uas.request->msg_flags |= request->msg_flags;
00165       _tm_branch_index = 0;
00166 
00167       set_route_type( backup_route_type );
00168       /* restore original avp list */
00169       set_avp_list( backup_list );
00170    }
00171 
00172    /* run the specific callbacks for this transaction */
00173    run_trans_callbacks( TMCB_REQUEST_FWDED, t, request, 0,
00174          -request->REQ_METHOD);
00175 
00176    return 0;
00177 error:
00178    return -1;
00179 }
00180 
00181 /*! \brief be aware and use it *all* the time between pre_* and post_* functions! */
00182 static inline char *print_uac_request(struct sip_msg *i_req, unsigned int *len,
00183       struct socket_info *send_sock, enum sip_protos proto )
00184 {
00185    char *buf;
00186 
00187    /* build the shm buffer now */
00188    buf=build_req_buf_from_sip_req( i_req, len, send_sock, proto,
00189          MSG_TRANS_SHM_FLAG);
00190    if (!buf) {
00191       LM_ERR("no more shm_mem\n"); 
00192       ser_error=E_OUT_OF_MEM;
00193       return NULL;
00194    }
00195 
00196    return buf;
00197 }
00198 
00199 
00200 static inline void post_print_uac_request(struct sip_msg *request,
00201       str *org_uri, str *org_dst)
00202 {
00203    reset_init_lump_flags();
00204    /* delete inserted branch lumps */
00205    del_flaged_lumps( &request->add_rm, LUMPFLAG_BRANCH);
00206    del_flaged_lumps( &request->body_lumps, LUMPFLAG_BRANCH);
00207    /* free any potential new uri */
00208    if (request->new_uri.s!=org_uri->s) {
00209       pkg_free(request->new_uri.s);
00210       /* and just to be sure */
00211       request->new_uri.s = 0;
00212       request->new_uri.len = 0;
00213       request->parsed_uri_ok = 0;
00214    }
00215    /* free any potential dst uri */
00216    if (request->dst_uri.s!=org_dst->s) {
00217       pkg_free(request->dst_uri.s);
00218       /* and just to be sure */
00219       request->dst_uri.s = 0;
00220       request->dst_uri.len = 0;
00221    }
00222 }
00223 
00224 
00225 static inline struct proxy_l* shm_clone_proxy(struct proxy_l *sp,
00226                                        unsigned int move_dn)
00227 {
00228    struct proxy_l *dp;
00229 
00230    dp = (struct proxy_l*)shm_malloc(sizeof(struct proxy_l));
00231    if (dp==NULL) {
00232       LM_ERR("no more shm memory\n");
00233       return 0;
00234    }
00235    memset( dp , 0 , sizeof(struct proxy_l));
00236 
00237    dp->port = sp->port;
00238    dp->proto = sp->proto;
00239    dp->addr_idx = sp->addr_idx;
00240    dp->flags = PROXY_SHM_FLAG;
00241 
00242    /* clone the hostent */
00243    if (hostent_shm_cpy( &dp->host, &sp->host)!=0)
00244       goto error0;
00245 
00246    /* clone the dns resolver */
00247    if (sp->dn) {
00248       if (move_dn) {
00249          dp->dn = sp->dn;
00250          sp->dn = 0;
00251       } else {
00252          dp->dn = dns_res_copy(sp->dn);
00253          if (dp->dn==NULL)
00254             goto error1;
00255       }
00256    }
00257 
00258    return dp;
00259 error1:
00260    free_shm_hostent(&dp->host);
00261 error0:
00262    shm_free(dp);
00263    return 0;
00264 }
00265 
00266 
00267 
00268 /*! \brief
00269    introduce a new uac, which is blind 
00270 
00271    This UA only creates the
00272    data structures and starts FR timer, but that's it; it does
00273    not print messages and send anything anywhere; that is good
00274    for FIFO apps -- the transaction must look operationally
00275    and FR must be ticking, whereas the request is "forwarded"
00276    using a non-SIP way and will be replied the same way
00277 */
00278 int add_blind_uac(void)  /*struct cell *t*/
00279 {
00280    unsigned short branch;
00281    struct cell *t;
00282 
00283    t=get_t();
00284    if (t==T_UNDEFINED || !t ) {
00285       LM_ERR("no transaction context\n");
00286       return -1;
00287    }
00288 
00289    branch=t->nr_of_outgoings; 
00290    if (branch==MAX_BRANCHES) {
00291       LM_ERR("maximum number of branches exceeded\n");
00292       return -1;
00293    }
00294 
00295    t->flags |= T_BLIND_UAC;
00296    t->nr_of_outgoings++;
00297    /* start FR timer -- protocol set by default to PROTO_NONE,
00298       which means retransmission timer will not be started */
00299    start_retr(&t->uac[branch].request);
00300    /* we are on a timer -- don't need to put on wait on script
00301       clean-up */
00302    set_kr(REQ_FWDED);
00303 
00304    return 1; /* success */
00305 }
00306 
00307 
00308 static inline int update_uac_dst( struct sip_msg *request, struct ua_client *uac )
00309 {
00310    struct socket_info* send_sock;
00311    char *shbuf;
00312    unsigned int len;
00313 
00314    send_sock = get_send_socket( request, &uac->request.dst.to ,
00315          uac->request.dst.proto );
00316    if (send_sock==0) {
00317       LM_ERR("failed to fwd to af %d, proto %d "
00318          " (no corresponding listening socket)\n",
00319          uac->request.dst.to.s.sa_family, uac->request.dst.proto );
00320       ser_error=E_NO_SOCKET;
00321       return -1;
00322    }
00323 
00324    if (send_sock!=uac->request.dst.send_sock) {
00325       /* rebuild */
00326       shbuf = print_uac_request( request, &len, send_sock,
00327          uac->request.dst.proto);
00328       if (!shbuf) {
00329          ser_error=E_OUT_OF_MEM;
00330          return -1;
00331       }
00332 
00333       if (uac->request.buffer.s)
00334          shm_free(uac->request.buffer.s);
00335 
00336       /* things went well, move ahead and install new buffer! */
00337       uac->request.dst.send_sock = send_sock;
00338       uac->request.dst.proto_reserved1 = 0;
00339       uac->request.buffer.s = shbuf;
00340       uac->request.buffer.len = len;
00341    }
00342 
00343    return 0;
00344 }
00345 
00346 
00347 static inline unsigned int count_local_rr(struct sip_msg *req)
00348 {
00349    unsigned int cnt = 0;
00350    struct lump *r;
00351 
00352    /* we look for the RR anchors only 
00353     * in the main list (no after or before) */
00354    for( r=req->add_rm ; r ; r=r->next )
00355       if ( r->type==HDR_RECORDROUTE_T && r->op==LUMP_NOP) {
00356          if (r->after && r->after->op==LUMP_ADD_OPT) {
00357             if (r->after->flags&LUMPFLAG_COND_TRUE) {
00358                cnt++;
00359             }
00360          } else {
00361             cnt++;
00362          }
00363       }
00364 
00365    return cnt;
00366 }
00367 
00368 
00369 /*!
00370  * \brief Introduce a new UAC to transaction.
00371  *
00372  * Introduce a new UAC to a transaction. It doesn't send a message yet --
00373  * a reply to it might interfere with the processes of adding multiple branches.
00374  * \return the branch id (positive) or negative result on error
00375  */
00376 static int add_uac( struct cell *t, struct sip_msg *request, str *uri, 
00377                      str* next_hop, str* path, struct proxy_l *proxy)
00378 {
00379    unsigned short branch;
00380    int do_free_proxy;
00381    int ret;
00382 
00383    branch=t->nr_of_outgoings;
00384    if (branch==MAX_BRANCHES) {
00385       LM_ERR("maximum number of branches exceeded\n");
00386       ret=E_CFG;
00387       goto error;
00388    }
00389 
00390    /* check existing buffer -- rewriting should never occur */
00391    if (t->uac[branch].request.buffer.s) {
00392       LM_CRIT("buffer rewrite attempt\n");
00393       ret=ser_error=E_BUG;
00394       goto error;
00395    }
00396 
00397    /* set proper RURI to request to reflect the branch */
00398    request->new_uri=*uri;
00399    request->parsed_uri_ok=0;
00400    request->dst_uri=*next_hop;
00401    request->path_vec=*path;
00402 
00403    if ( pre_print_uac_request( t, branch, request)!= 0 ) {
00404       ret = -1;
00405       goto error01;
00406    }
00407 
00408    /* check DNS resolution */
00409    if (proxy){
00410       do_free_proxy = 0;
00411    }else {
00412       proxy=uri2proxy( request->dst_uri.len ?
00413          &request->dst_uri:&request->new_uri, PROTO_NONE );
00414       if (proxy==0)  {
00415          ret=E_BAD_ADDRESS;
00416          goto error01;
00417       }
00418       do_free_proxy = 1;
00419    }
00420 
00421    if ( !(t->flags&T_NO_DNS_FAILOVER_FLAG) ) {
00422       t->uac[branch].proxy = shm_clone_proxy( proxy , do_free_proxy );
00423       if (t->uac[branch].proxy==NULL) {
00424          ret = E_OUT_OF_MEM;
00425          goto error02;
00426       }
00427    }
00428 
00429    /* use the first address */
00430    hostent2su( &t->uac[branch].request.dst.to,
00431       &proxy->host, proxy->addr_idx, proxy->port ? proxy->port:SIP_PORT);
00432    t->uac[branch].request.dst.proto = proxy->proto;
00433 
00434    if ( update_uac_dst( request, &t->uac[branch] )!=0) {
00435       ret = E_OUT_OF_MEM;
00436       goto error02;
00437    }
00438 
00439    /* things went well, move ahead */
00440    t->uac[branch].uri.s=t->uac[branch].request.buffer.s+
00441       request->first_line.u.request.method.len+1;
00442    t->uac[branch].uri.len=request->new_uri.len;
00443    t->uac[branch].br_flags = getb0flags();
00444    t->uac[branch].added_rr = count_local_rr( request );
00445    t->nr_of_outgoings++;
00446 
00447    /* done! */
00448    ret=branch;
00449 
00450 error02:
00451    if(do_free_proxy) {
00452       free_proxy( proxy );
00453       pkg_free( proxy );
00454    }
00455 error01:
00456    post_print_uac_request( request, uri, next_hop);
00457 error:
00458    return ret;
00459 }
00460 
00461 
00462 int e2e_cancel_branch( struct sip_msg *cancel_msg, struct cell *t_cancel, 
00463    struct cell *t_invite, int branch )
00464 {
00465    int ret;
00466    char *shbuf;
00467    unsigned int len;
00468    str bk_dst_uri;
00469    str bk_path_vec;
00470 
00471    if (t_cancel->uac[branch].request.buffer.s) {
00472       LM_CRIT("buffer rewrite attempt\n");
00473       ret=ser_error=E_BUG;
00474       goto error;
00475    }
00476 
00477    cancel_msg->new_uri = t_invite->uac[branch].uri;
00478    cancel_msg->parsed_uri_ok=0;
00479    bk_dst_uri = cancel_msg->dst_uri;
00480    bk_path_vec = cancel_msg->path_vec;
00481 
00482    /* force same path as for request */
00483    cancel_msg->path_vec = t_invite->uac[branch].path_vec;
00484 
00485    if ( pre_print_uac_request( t_cancel, branch, cancel_msg)!= 0 ) {
00486       ret = -1;
00487       goto error01;
00488    }
00489 
00490    /* force same uri as in INVITE */
00491    if (cancel_msg->new_uri.s!=t_invite->uac[branch].uri.s) {
00492       pkg_free(cancel_msg->new_uri.s);
00493       cancel_msg->new_uri = t_invite->uac[branch].uri;
00494       /* and just to be sure */
00495       cancel_msg->parsed_uri_ok = 0;
00496    }
00497 
00498    /* print */
00499    shbuf=print_uac_request( cancel_msg, &len,
00500       t_invite->uac[branch].request.dst.send_sock,
00501       t_invite->uac[branch].request.dst.proto);
00502    if (!shbuf) {
00503       LM_ERR("printing e2e cancel failed\n");
00504       ret=ser_error=E_OUT_OF_MEM;
00505       goto error01;
00506    }
00507 
00508    /* install buffer */
00509    t_cancel->uac[branch].request.dst=t_invite->uac[branch].request.dst;
00510    t_cancel->uac[branch].request.buffer.s=shbuf;
00511    t_cancel->uac[branch].request.buffer.len=len;
00512    t_cancel->uac[branch].uri.s=t_cancel->uac[branch].request.buffer.s+
00513       cancel_msg->first_line.u.request.method.len+1;
00514    t_cancel->uac[branch].uri.len=t_invite->uac[branch].uri.len;
00515    t_cancel->uac[branch].br_flags = cancel_msg->flags;
00516 
00517    /* success */
00518    ret=1;
00519 
00520 error01:
00521    post_print_uac_request( cancel_msg, &t_invite->uac[branch].uri,
00522       &bk_dst_uri);
00523    cancel_msg->dst_uri = bk_dst_uri;
00524    cancel_msg->path_vec = bk_path_vec;
00525 error:
00526    return ret;
00527 }
00528 
00529 
00530 
00531 void cancel_invite(struct sip_msg *cancel_msg,
00532                         struct cell *t_cancel, struct cell *t_invite )
00533 {
00534    branch_bm_t cancel_bitmap;
00535    branch_bm_t dummy_bm;
00536    str reason;
00537    unsigned int i;
00538    int lowest_error;
00539 
00540    lowest_error=0;
00541    cancel_bitmap=0;
00542 
00543    /* send back 200 OK as per RFC3261 */
00544    reason.s = CANCELING;
00545    reason.len = sizeof(CANCELING)-1;
00546    t_reply( t_cancel, cancel_msg, 200, &reason );
00547 
00548    /* generate local cancels for all branches */
00549    which_cancel(t_invite, &cancel_bitmap );
00550    cancel_uacs(t_invite, cancel_bitmap );
00551 
00552    /* internally cancel branches with no received reply */
00553    for (i=t_invite->first_branch; i<t_invite->nr_of_outgoings; i++) {
00554       if (t_invite->uac[i].last_received==0){
00555          /* reset the "request" timers */
00556          reset_timer(&t_invite->uac[i].request.retr_timer);
00557          reset_timer(&t_invite->uac[i].request.fr_timer);
00558          LOCK_REPLIES( t_invite );
00559          if (RPS_ERROR==relay_reply(t_invite,FAKED_REPLY,i,487,&dummy_bm))
00560             lowest_error = -1; /* force sending 500 error */
00561       }
00562    }
00563 }
00564 
00565 
00566 
00567 /* function returns:
00568  *       1 - forward successful
00569  *      -1 - error during forward
00570  */
00571 int t_forward_nonack( struct cell *t, struct sip_msg* p_msg , 
00572    struct proxy_l * proxy)
00573 {
00574    str backup_uri;
00575    str backup_dst;
00576    int branch_ret, lowest_ret;
00577    str current_uri;
00578    branch_bm_t  added_branches;
00579    int i, q;
00580    struct cell *t_invite;
00581    int success_branch;
00582    int try_new;
00583    str dst_uri;
00584    struct socket_info *bk_sock;
00585    unsigned int br_flags;
00586    unsigned int bk_br_flags;
00587    int idx;
00588    str path;
00589    str bk_path;
00590 
00591    /* make -Wall happy */
00592    current_uri.s=0;
00593 
00594    if (p_msg->REQ_METHOD==METHOD_CANCEL) {
00595       t_invite=t_lookupOriginalT(  p_msg );
00596       if (t_invite!=T_NULL_CELL) {
00597          t_invite->flags |= T_WAS_CANCELLED_FLAG;
00598          cancel_invite( p_msg, t, t_invite );
00599          return 1;
00600       }
00601    }
00602 
00603    /* do not forward requests which were already cancelled*/
00604    if (was_cancelled(t) || no_new_branches(t)) {
00605       LM_ERR("discarding fwd for a cancelled/6xx transaction\n");
00606       ser_error = E_NO_DESTINATION;
00607       return -1;
00608    }
00609 
00610    /* backup current uri, sock and flags... add_uac changes it */
00611    backup_uri = p_msg->new_uri;
00612    backup_dst = p_msg->dst_uri;
00613    bk_sock = p_msg->force_send_socket;
00614    bk_br_flags = getb0flags();
00615    bk_path = p_msg->path_vec;
00616 
00617    /* if no more specific error code is known, use this */
00618    lowest_ret=E_BUG;
00619    /* branches added */
00620    added_branches=0;
00621    /* branch to begin with */
00622    t->first_branch=t->nr_of_outgoings;
00623 
00624    /* on first-time forwarding, use current uri, later only what
00625       is in additional branches (which may be continuously refilled)
00626    */
00627    if (t->first_branch==0) {
00628       try_new=1;
00629       current_uri = *GET_RURI(p_msg);
00630       branch_ret = add_uac( t, p_msg, &current_uri, &backup_dst, 
00631             &p_msg->path_vec, proxy);
00632       if (branch_ret>=0)
00633          added_branches |= 1<<branch_ret;
00634       else
00635          lowest_ret=branch_ret;
00636    } else try_new=0;
00637 
00638    for( idx=0; (current_uri.s=get_branch( idx, &current_uri.len, &q,
00639    &dst_uri, &path, &br_flags, &p_msg->force_send_socket))!=0 ; idx++ ) {
00640       try_new++;
00641       setb0flags(br_flags);
00642       branch_ret = add_uac( t, p_msg, &current_uri, &dst_uri, &path, proxy);
00643       /* pick some of the errors in case things go wrong;
00644          note that picking lowest error is just as good as
00645          any other algorithm which picks any other negative
00646          branch result */
00647       if (branch_ret>=0) 
00648          added_branches |= 1<<branch_ret;
00649       else
00650          lowest_ret=branch_ret;
00651    }
00652    /* consume processed branches */
00653    clear_branches();
00654 
00655    /* restore original stuff */
00656    p_msg->new_uri=backup_uri;
00657    p_msg->parsed_uri_ok = 0;/* just to be sure; add_uac may parse other uris*/
00658    p_msg->dst_uri = backup_dst;
00659    p_msg->force_send_socket = bk_sock;
00660    p_msg->path_vec = bk_path;
00661    setb0flags(bk_br_flags);
00662    /* update on_branch, if modified */
00663    t->on_branch = get_on_branch();
00664    /* update flags, if changed in branch route */
00665    t->uas.request->flags = p_msg->flags;
00666 
00667    /* things went wrong ... no new branch has been fwd-ed at all */
00668    if (added_branches==0) {
00669       if (try_new==0) {
00670          ser_error = E_NO_DESTINATION;
00671          LM_ERR("no branch for forwarding\n");
00672          return -1;
00673       }
00674       LM_ERR("failure to add branches\n");
00675       ser_error = lowest_ret;
00676       return lowest_ret;
00677    }
00678 
00679    /* send them out now */
00680    success_branch=0;
00681    for (i=t->first_branch; i<t->nr_of_outgoings; i++) {
00682       if (added_branches & (1<<i)) {
00683          do {
00684             if (check_blacklists( t->uac[i].request.dst.proto,
00685             &t->uac[i].request.dst.to,
00686             t->uac[i].request.buffer.s,
00687             t->uac[i].request.buffer.len)) {
00688                LM_DBG("blocked by blacklists\n");
00689                ser_error=E_IP_BLOCKED;
00690             } else {
00691                if (SEND_BUFFER( &t->uac[i].request)==0) {
00692                   ser_error = 0;
00693                   break;
00694                }
00695                LM_ERR("sending request failed\n");
00696                ser_error=E_SEND;
00697             }
00698             /* get next dns entry */
00699             if ( t->uac[i].proxy==0 ||
00700             get_next_su( t->uac[i].proxy, &t->uac[i].request.dst.to,
00701             (ser_error==E_IP_BLOCKED)?0:1)!=0 )
00702                break;
00703             t->uac[i].request.dst.proto = t->uac[i].proxy->proto;
00704             /* update branch */
00705             if ( update_uac_dst( p_msg, &t->uac[i] )!=0)
00706                break;
00707          }while(1);
00708 
00709          if (ser_error)
00710             continue;
00711 
00712          success_branch++;
00713 
00714          /* successfully sent out -> run callbacks */
00715          if ( has_tran_tmcbs( t, TMCB_REQUEST_BUILT) ) {
00716             set_extra_tmcb_params( &t->uac[i].request.buffer,
00717                &t->uac[i].request.dst);
00718             run_trans_callbacks( TMCB_REQUEST_BUILT, t, p_msg,0,
00719                -p_msg->REQ_METHOD);
00720          }
00721 
00722          if(p_msg->REQ_METHOD==METHOD_INVITE
00723                && t->uac[i].last_received>=100)
00724             LM_DBG("Last received %d\n",t->uac[i].last_received);
00725          else
00726             start_retr( &t->uac[i].request );
00727          set_kr(REQ_FWDED);
00728       }
00729    }
00730 
00731    return (success_branch>0)?1:-1;
00732 }
00733 
00734 /*!
00735  * \brief Relay a replicated message.
00736  *
00737  * Relay a replicated message. We just take the message as is,
00738  * including Route-s, Record-route-s, and Vias, forward it downstream
00739  * and prevent replies received from relaying by setting the
00740  * replication/local_trans bit.
00741  * \note this is a quite horrible hack - nevertheless, it should be
00742  * good enough for the primary customer of this function, REGISTER
00743  * replication. If we want later to make it thoroughly, we need to
00744  * introduce delete lumps for all the header fields above.
00745  * \param p_msg replicated message
00746  * \param dst destination
00747  * \param flags message flags
00748  * \return -1 on errors, otherwise the return value from t_relay_to
00749  */
00750 int t_replicate(struct sip_msg *p_msg, str *dst, int flags)
00751 {
00752    if ( set_dst_uri( p_msg, dst)!=0 ) {
00753       LM_ERR("failed to set dst uri\n");
00754       return -1;
00755    }
00756 
00757    if ( branch_uri2dset( GET_RURI(p_msg) )!=0 ) {
00758       LM_ERR("failed to convert uri to dst\n");
00759       return -1;
00760    }
00761 
00762    return t_relay_to( p_msg, 0, flags|TM_T_REPLY_repl_FLAG);
00763 }

Generated on Thu May 24 20:00:32 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6