t_cancel.c

Go to the documentation of this file.
00001 /*
00002  * $Id: t_cancel.c 5376 2008-12-17 19:07:14Z osas $
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-04-14  checking if a reply sent before cancel is initiated
00025  *             moved here (jiri)
00026  * 2004-02-11  FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri)
00027  * 2004-02-13  timer_link.payload removed (bogdan)
00028  */
00029 
00030 /*! \file
00031  * \brief TM :: CANCEL processing
00032  *
00033  * \ingroup tm
00034  * - Module: \ref tm
00035  */
00036 
00037 #include "t_funcs.h"
00038 #include "../../dprint.h"
00039 #include "../../ut.h"
00040 #include "t_reply.h"
00041 #include "t_fwd.h"
00042 #include "t_cancel.h"
00043 #include "t_msgbuilder.h"
00044 #include "t_lookup.h" /* for t_lookup_callid in fifo_uac_cancel */
00045 
00046 
00047 /*! \brief
00048    Determine which branches should be canceled.
00049 
00050    Do it only from within REPLY_LOCK, otherwise collisions
00051    could occur (e.g., two 200 for two branches processed
00052    by two processes might concurrently try to generate
00053    a CANCEL for the third branch, resulting in race conditions
00054    during writing to cancel buffer
00055 */
00056 void which_cancel( struct cell *t, branch_bm_t *cancel_bm )
00057 {
00058    int i;
00059 
00060    for( i=t->first_branch ; i<t->nr_of_outgoings ; i++ ) {
00061       if (should_cancel_branch(t, i)) 
00062          *cancel_bm |= 1<<i ;
00063 
00064    }
00065 }
00066 
00067 
00068 /*! \brief cancel branches scheduled for deletion */
00069 void cancel_uacs( struct cell *t, branch_bm_t cancel_bm )
00070 {
00071    int i;
00072 
00073    /* cancel pending client transactions, if any */
00074    for( i=0 ; i<t->nr_of_outgoings ; i++ ) 
00075       if (cancel_bm & (1<<i))
00076          cancel_branch(t, i);
00077 }
00078 
00079 
00080 void cancel_branch( struct cell *t, int branch )
00081 {
00082    char *cancel;
00083    unsigned int len;
00084    struct retr_buf *crb, *irb;
00085 
00086    crb=&t->uac[branch].local_cancel;
00087    irb=&t->uac[branch].request;
00088 
00089 #  ifdef EXTRA_DEBUG
00090    if (crb->buffer.s!=0 && crb->buffer.s!=BUSY_BUFFER) {
00091       LM_CRIT("attempt to rewrite cancel buffer failed\n");
00092       abort();
00093    }
00094 #  endif
00095 
00096    cancel=build_cancel(t, branch, &len);
00097    if (!cancel) {
00098       LM_ERR("attempt to build a CANCEL failed\n");
00099       return;
00100    }
00101    /* install cancel now */
00102    crb->buffer.s=cancel;
00103    crb->buffer.len=len;
00104    crb->dst=irb->dst;
00105    crb->branch=branch;
00106    /* label it as cancel so that FR timer can better now how 
00107     * to deal with it */
00108    crb->activ_type=TYPE_LOCAL_CANCEL;
00109 
00110    if ( has_tran_tmcbs( t, TMCB_REQUEST_BUILT) ) {
00111       set_extra_tmcb_params( &crb->buffer, &crb->dst);
00112       run_trans_callbacks( TMCB_REQUEST_BUILT, t, t->uas.request,0,
00113          -t->uas.request->REQ_METHOD);
00114    }
00115 
00116    LM_DBG("sending cancel...\n");
00117    SEND_BUFFER( crb );
00118 
00119    /*sets and starts the FINAL RESPONSE timer */
00120    start_retr( crb );
00121 }
00122 
00123 
00124 char *build_cancel(struct cell *Trans,unsigned int branch,
00125    unsigned int *len )
00126 {
00127    return build_local( Trans, branch, len,
00128       CANCEL, CANCEL_LEN, &Trans->to );
00129 }
00130 
00131 
00132 /*! \brief
00133  * This function cancels a previously created local invite transaction.
00134  *
00135  * The cancel parameter should NOT have any via (CANCEL is hop-by-hop).
00136  *
00137  * \return 0 if error
00138  * \return >0 if OK (returns the LABEL of the cancel).
00139  */
00140 unsigned int t_uac_cancel( str *headers, str *body,
00141    unsigned int cancelled_hashIdx, unsigned int cancelled_label,
00142    transaction_cb cb, void* cbp)
00143 {
00144    struct cell *t_invite,*cancel_cell;
00145    struct retr_buf *cancel,*invite;
00146    unsigned int len,ret;
00147    char *buf;
00148 
00149    ret=0;
00150 
00151    if(t_lookup_ident(&t_invite,cancelled_hashIdx,cancelled_label)<0){
00152       LM_ERR("failed to t_lookup_ident hash_idx=%d,"
00153          "label=%d\n", cancelled_hashIdx,cancelled_label);
00154       return 0;
00155    }
00156    /* <sanity_checks> */
00157    if(! is_local(t_invite)){
00158       LM_ERR("tried to cancel a non-local transaction\n");
00159       goto error3;
00160    }
00161    if(t_invite->uac[0].last_received < 100){
00162       LM_WARN("trying to cancel a transaction not in "
00163          "Proceeding state !\n");
00164       goto error3;
00165    }
00166    if(t_invite->uac[0].last_received > 200){
00167       LM_WARN("trying to cancel a completed transaction !\n");
00168       goto error3;
00169    }
00170    /* </sanity_checks*/
00171 
00172 
00173    /* <build_cell> */
00174    if(!(cancel_cell = build_cell(0))){
00175       ret=0;
00176       LM_ERR("no more shm memory!\n");
00177       goto error3;
00178    }
00179    reset_avps();
00180    if(cb && insert_tmcb(&(cancel_cell->tmcb_hl),
00181    TMCB_RESPONSE_IN|TMCB_LOCAL_COMPLETED,cb,cbp,0)!=1){
00182       ret=0;
00183       LM_ERR("short of tmcb shmem !\n");
00184       goto error2;
00185    }
00186    /* </build_cell> */
00187 
00188    /* <insert_into_hashtable> */
00189    cancel_cell->flags |= T_IS_LOCAL_FLAG;
00190    cancel_cell->hash_index=t_invite->hash_index;
00191 
00192    LOCK_HASH(cancel_cell->hash_index);
00193    insert_into_hash_table_unsafe(cancel_cell,cancel_cell->hash_index);
00194    ret=cancel_cell->label;
00195    cancel_cell->label=t_invite->label;
00196    UNLOCK_HASH(cancel_cell->hash_index);
00197    /* </insert_into_hashtable> */
00198 
00199    /* <prepare_cancel> */
00200 
00201    cancel=&cancel_cell->uac[0].request;
00202    invite=&t_invite->uac[0].request;
00203 
00204    cancel->dst.to              = invite->dst.to;
00205    cancel->dst.send_sock       = invite->dst.send_sock;
00206    cancel->dst.proto           = invite->dst.proto;
00207    cancel->dst.proto_reserved1 = invite->dst.proto_reserved1;
00208 
00209    if(!(buf = build_uac_cancel(headers,body,t_invite,0,&len))){
00210       ret=0;
00211       LM_ERR("attempt to build a CANCEL failed\n");
00212       goto error1;
00213    }
00214    cancel->buffer.s=buf;
00215    cancel->buffer.len=len;
00216    cancel_cell->method.s = buf;
00217    cancel_cell->method.len = 6 /*c-a-n-c-e-l*/;
00218 
00219    /* </prepare_cancel> */
00220 
00221    /* <strart_sending> */
00222    cancel_cell->nr_of_outgoings++;
00223    if (SEND_BUFFER(cancel)==-1) {
00224       ret=0;
00225       LM_ERR("send failed\n");
00226       goto error1;
00227    }
00228    start_retr(cancel);
00229    /* </start_sending> */
00230 
00231    return ret;
00232 
00233 error1:
00234    LOCK_HASH(cancel_cell->hash_index);
00235    remove_from_hash_table_unsafe(cancel_cell);
00236    UNLOCK_HASH(cancel_cell->hash_index);
00237 error2:
00238    free_cell(cancel_cell);
00239 error3:
00240    return ret;
00241 }
00242 

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