t_funcs.c

Go to the documentation of this file.
00001 /*
00002  * $Id: t_funcs.c 5723 2009-03-19 09:27:41Z miconda $
00003  *
00004  * transaction maintenance functions
00005  *
00006  * Copyright (C) 2001-2003 FhG Fokus
00007  *
00008  * This file is part of Kamailio, a free SIP server.
00009  *
00010  * Kamailio is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version
00014  *
00015  * Kamailio is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License 
00021  * along with this program; if not, write to the Free Software 
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  *
00024  * History:
00025  * -------
00026  *  2003-03-31  200 for INVITE/UAS resent even for UDP (jiri)
00027  *               info only if compiling w/ -DEXTRA_DEBUG (andrei)
00028  *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
00029  *  2003-03-13  send_pr_buffer is called w/ file/function/line debugging
00030  *  2003-03-01  start_retr changed to retransmit only for UDP
00031  *  2003-02-13  modified send_pr_buffer to use msg_send & rb->dst (andrei)
00032  *  2003-04-14  use protocol from uri (jiri)
00033  *  2003-04-25  do it (^) really everywhere (jiri)
00034  *  2003-04-26  do it (^) really really really everywhere (jiri)
00035  *  2003-07-07  added get_proto calls when proxy!=0 (andrei)
00036  *  2004-02-13  t->is_invite and t->local replaced with flags (bogdan)
00037  *  2005-02-16  fr_*_timer acceps full AVP specifications; empty AVP
00038  *              desable variable timer feature (bogdan)
00039  *  2007-01-25  DNS failover at transaction level added (bogdan) 
00040  */
00041 
00042 /*! \file
00043  * \brief TM :: Transaction maintenance functions
00044  *
00045  * \ingroup tm
00046  * - Module: \ref tm
00047  */
00048 
00049 
00050 #include <limits.h>
00051 #include <string.h>
00052 #include <stdio.h>
00053 #include <errno.h>
00054 #include <stdlib.h>
00055 
00056 #include "../../dprint.h"
00057 #include "../../hash_func.h"
00058 #include "../../dset.h"
00059 #include "../../mem/mem.h"
00060 #include "t_funcs.h"
00061 #include "t_fwd.h"
00062 #include "t_msgbuilder.h"
00063 #include "t_lookup.h"
00064 #include "config.h"
00065 
00066 /* AVP specs */
00067 static int     fr_timer_avp_type;
00068 static int_str fr_timer_avp;
00069 int     fr_inv_timer_avp_type;
00070 int_str fr_inv_timer_avp;
00071 int     contacts_avp_type;
00072 int_str contacts_avp;
00073 
00074 extern str auto_inv_100_reason;
00075 
00076 
00077 /* ----------------------------------------------------- */
00078 int send_pr_buffer( struct retr_buf *rb, void *buf, int len
00079 #ifdef EXTRA_DEBUG
00080                   , char* file, const char *function, int line
00081 #endif
00082                )
00083 {
00084    if (buf && len && rb )
00085       return msg_send( rb->dst.send_sock, rb->dst.proto, &rb->dst.to,
00086                      rb->dst.proto_reserved1, buf, len);
00087    else {
00088 #ifdef EXTRA_DEBUG
00089       LM_CRIT("sending an empty buffer from %s: %s (%d)\n",file,
00090             function, line);
00091 #else
00092       LM_CRIT("attempt to send an empty buffer\n");
00093 #endif
00094       return -1;
00095    }
00096 }
00097 
00098 
00099 
00100 void tm_shutdown(void)
00101 {
00102 
00103    LM_DBG("tm_shutdown : start\n");
00104    unlink_timer_lists();
00105 
00106    /* destroy the hash table */
00107    LM_DBG("emptying hash table\n");
00108    free_hash_table( );
00109    LM_DBG("releasing timers\n");
00110    free_timer_table();
00111    LM_DBG("removing semaphores\n");
00112    lock_cleanup();
00113    LM_DBG("destroying callback lists\n");
00114    destroy_tmcb_lists();
00115    LM_DBG("tm_shutdown : done\n");
00116 }
00117 
00118 
00119 /*   returns 1 if everything was OK or -1 for error
00120 */
00121 int t_release_transaction( struct cell *trans )
00122 {
00123    set_kr(REQ_RLSD);
00124 
00125    reset_timer( & trans->uas.response.fr_timer );
00126    reset_timer( & trans->uas.response.retr_timer );
00127 
00128    cleanup_uac_timers( trans );
00129    
00130    put_on_wait( trans );
00131    return 1;
00132 }
00133 
00134 
00135 /* -----------------------HELPER FUNCTIONS----------------------- */
00136 
00137 
00138 /*
00139   */
00140 void put_on_wait(  struct cell  *Trans  )
00141 {
00142 
00143 #ifdef EXTRA_DEBUG
00144    LM_DBG("put on WAIT \n");
00145 #endif
00146 
00147 
00148    /*! 
00149             we put the transaction on wait timer; we do it only once
00150       in transaction's timelife because putting it multiple-times
00151       might result in a second instance of a wait timer to be
00152       set after the first one fired; on expiration of the second
00153       instance, the transaction would be re-deleted
00154 \verbatim
00155          PROCESS1    PROCESS2    TIMER PROCESS
00156       0. 200/INVITE rx;
00157          put_on_wait
00158       1.             200/INVITE rx;
00159       2.                         WAIT fires; transaction
00160                                  about to be deleted
00161       3.             avoid putting
00162                      on WAIT again
00163       4.                         WAIT timer executed,
00164                                  transaction deleted
00165 \endverbatim
00166    */
00167    set_1timer( &Trans->wait_tl, WT_TIMER_LIST, 0 );
00168 }
00169 
00170 
00171 
00172 static int kill_transaction( struct cell *trans )
00173 {
00174    char err_buffer[128];
00175    int sip_err;
00176    int reply_ret;
00177    int ret;
00178    str reason;
00179 
00180    /*  we reply statefully and enter WAIT state since error might
00181       have occurred in middle of forking and we do not
00182       want to put the forking burden on upstream client;
00183       however, it may fail too due to lack of memory */
00184 
00185    ret=err2reason_phrase( ser_error, &sip_err,
00186       err_buffer, sizeof(err_buffer), "TM" );
00187    if (ret>0) {
00188       reason.s = err_buffer;
00189       reason.len = ret;
00190       reply_ret=t_reply( trans, trans->uas.request, sip_err, &reason);
00191       /* t_release_transaction( T ); */
00192       return reply_ret;
00193    } else {
00194       LM_ERR("err2reason failed\n");
00195       return -1;
00196    }
00197 }
00198 
00199 
00200 
00201 int t_relay_to( struct sip_msg  *p_msg , struct proxy_l *proxy, int flags)
00202 {
00203    int ret;
00204    int new_tran;
00205    str *uri;
00206    int reply_ret;
00207    struct cell *t;
00208 
00209    ret=0;
00210 
00211    new_tran = t_newtran( p_msg );
00212 
00213    /* parsing error, memory alloc, whatever ... if via is bad
00214       and we are forced to reply there, return with 0 (->break),
00215       pass error status otherwise
00216    */
00217    if (new_tran<0) {
00218       ret = (ser_error==E_BAD_VIA && reply_to_via) ? 0 : new_tran;
00219       goto done;
00220    }
00221    /* if that was a retransmission, break from script */
00222    if (new_tran==0) {
00223       goto done;
00224    }
00225 
00226    /* new transaction */
00227 
00228    /* ACKs do not establish a transaction and are fwd-ed statelessly */
00229    if ( p_msg->REQ_METHOD==METHOD_ACK) {
00230       LM_DBG("forwarding ACK\n");
00231       /* send it out */
00232       if (proxy==0) {
00233          uri = GET_RURI(p_msg);
00234          proxy=uri2proxy(GET_NEXT_HOP(p_msg), PROTO_NONE);
00235          if (proxy==0) {
00236                ret=E_BAD_ADDRESS;
00237                goto done;
00238          }
00239          ret=forward_request( p_msg , proxy);
00240          if (ret>=0) ret=1;
00241          free_proxy( proxy );
00242          pkg_free( proxy );
00243       } else {
00244          ret=forward_request( p_msg , proxy);
00245          if (ret>=0) ret=1;
00246       }
00247       goto done;
00248    }
00249 
00250    /* if replication flag is set, mark the transaction as local
00251       so that replies will not be relayed */
00252    t=get_t();
00253    if (flags&TM_T_REPLY_repl_FLAG) t->flags|=T_IS_LOCAL_FLAG;
00254    if (flags&TM_T_REPLY_nodnsfo_FLAG) t->flags|=T_NO_DNS_FAILOVER_FLAG;
00255 
00256    /* INVITE processing might take long, particularly because of DNS
00257       look-ups -- let upstream know we're working on it */
00258    if ( p_msg->REQ_METHOD==METHOD_INVITE &&
00259    !(flags&(TM_T_REPLY_no100_FLAG|TM_T_REPLY_repl_FLAG)) )
00260       t_reply( t, p_msg , 100 , &auto_inv_100_reason);
00261 
00262    /* now go ahead and forward ... */
00263    ret=t_forward_nonack( t, p_msg, proxy);
00264    if (ret<=0) {
00265       LM_DBG("t_forward_nonack returned error \n");
00266       /* we don't want to pass upstream any reply regarding replicating
00267        * a request; replicated branch must stop at us*/
00268       if (!(flags&(TM_T_REPLY_repl_FLAG|TM_T_REPLY_noerr_FLAG))) {
00269          reply_ret = kill_transaction( t );
00270          if (reply_ret>0) {
00271             /* we have taken care of all -- do nothing in
00272             script */
00273             LM_DBG("generation of a stateful reply on error succeeded\n");
00274             ret=0;
00275          }  else {
00276             LM_DBG("generation of a stateful reply on error failed\n");
00277          }
00278       }
00279    } else {
00280       LM_DBG("new transaction fwd'ed\n");
00281    }
00282 
00283 done:
00284    return ret;
00285 }
00286 
00287 
00288 
00289 /*! \brief
00290  * Initialize AVP module parameters
00291  */
00292 int init_avp_params(char *fr_timer_param, char *fr_inv_timer_param,
00293           char *contacts_avp_param)
00294 {
00295    pv_spec_t avp_spec;
00296    unsigned short avp_flags;
00297    str s;
00298    if (fr_timer_param && *fr_timer_param) {
00299       s.s = fr_timer_param; s.len = strlen(s.s);
00300       if (pv_parse_spec(&s, &avp_spec)==0
00301               || avp_spec.type!=PVT_AVP) {
00302               LM_ERR("malformed or non AVP %s AVP definition\n", fr_timer_param);
00303          return -1;
00304       }
00305 
00306       if(pv_get_avp_name(0, &avp_spec.pvp, &fr_timer_avp, &avp_flags)!=0)
00307       {
00308          LM_ERR("[%s]- invalid AVP definition\n", fr_timer_param);
00309          return -1;
00310       }
00311       fr_timer_avp_type = avp_flags;
00312    } else {
00313       fr_timer_avp.n = 0;
00314       fr_timer_avp_type = 0;
00315    }
00316 
00317    if (fr_inv_timer_param && *fr_inv_timer_param) {
00318       s.s = fr_inv_timer_param; s.len = strlen(s.s);
00319       if (pv_parse_spec(&s, &avp_spec)==0
00320             || avp_spec.type!=PVT_AVP) {
00321          LM_ERR("malformed or non AVP %s AVP definition\n",
00322                fr_inv_timer_param);
00323          return -1;
00324       }
00325 
00326       if(pv_get_avp_name(0, &avp_spec.pvp, &fr_inv_timer_avp, &avp_flags)!=0)
00327       {
00328          LM_ERR("[%s]- invalid AVP definition\n", fr_inv_timer_param);
00329          return -1;
00330       }
00331       fr_inv_timer_avp_type = avp_flags;
00332    } else {
00333       fr_inv_timer_avp.n = 0;
00334       fr_inv_timer_avp_type = 0;
00335    }
00336 
00337    if (contacts_avp_param && *contacts_avp_param) {
00338        s.s = contacts_avp_param; s.len = strlen(s.s);
00339        if ((pv_parse_spec(&s, &avp_spec) == 0) 
00340       || (avp_spec.type != PVT_AVP)) {
00341       LM_ERR("malformed or non AVP definition <%s>\n",
00342              contacts_avp_param);
00343       return -1;
00344        }
00345    
00346        if(pv_get_avp_name(0, &(avp_spec.pvp), &contacts_avp, &avp_flags)
00347           != 0) {
00348       LM_ERR("invalid AVP definition <%s>\n", contacts_avp_param);
00349       return -1;
00350        }
00351        contacts_avp_type = avp_flags;
00352    } else {
00353        contacts_avp.n = 0;
00354        contacts_avp_type = 0;
00355    }
00356 
00357    return 0;
00358 }
00359 
00360 
00361 /*! \brief
00362  * Get the FR_{INV}_TIMER from corresponding AVP
00363  */
00364 static inline int avp2timer(utime_t *timer, int type, int_str name)
00365 {
00366    struct usr_avp *avp;
00367    int_str val_istr;
00368    int err;
00369 
00370    avp = search_first_avp( type, name, &val_istr, 0);
00371    if (!avp)
00372       return 1;
00373 
00374    if (avp->flags & AVP_VAL_STR) {
00375       *timer = str2s(val_istr.s.s, val_istr.s.len, &err);
00376       if (err) {
00377          LM_ERR("failed to convert string to integer\n");
00378          return -1;
00379       }
00380    } else {
00381       *timer = val_istr.n;
00382    }
00383 
00384    return 0;
00385 }
00386 
00387 
00388 int fr_avp2timer(utime_t* timer)
00389 {
00390    if (fr_timer_avp.n!=0)
00391       return avp2timer( timer, fr_timer_avp_type, fr_timer_avp);
00392    else
00393       return 1;
00394 }
00395 
00396 
00397 int fr_inv_avp2timer(utime_t* timer)
00398 {
00399    if (fr_inv_timer_avp.n!=0)
00400       return avp2timer( timer, fr_inv_timer_avp_type, fr_inv_timer_avp);
00401    else
00402       return 1;
00403 }
00404 
00405 

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