more type punning warnings fixed
[sip-router] / modules / tm / t_cancel.c
1 /*
2  * $Id$
3  *
4  *
5  * Copyright (C) 2001-2003 FhG Fokus
6  *
7  * This file is part of ser, a free SIP server.
8  *
9  * ser is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version
13  *
14  * For a license to use the ser software under conditions
15  * other than those described here, or to purchase support for this
16  * software, please contact iptel.org by e-mail at the following addresses:
17  *    info@iptel.org
18  *
19  * ser is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License 
25  * along with this program; if not, write to the Free Software 
26  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27  *
28  * History:
29  * ----------
30  * 2003-04-14  checking if a reply sent before cancel is initiated
31  *             moved here (jiri)
32  * 2004-02-11  FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri)
33  * 2004-02-13  timer_link.payload removed (bogdan)
34  * 2006-10-10  cancel_uacs  & cancel_branch take more options now (andrei)
35  * 2007-03-15  TMCB_ONSEND hooks added (andrei)
36  * 2007-05-28: cancel_branch() constructs the CANCEL from the
37  *             outgoing INVITE instead of the incomming one.
38  *             (it can be disabled with reparse_invite=0) (Miklos)
39  * 2007-06-04  cancel_branch() can operate in lockless mode (with a lockless
40  *              should_cancel()) (andrei)
41  * 2008-03-07  cancel_branch() takes a new flag: F_CANCEL_B_FORCE_RETR (andrei)
42  * 2008-03-08  e2e_cancel handles non replied branches in 3 different ways,
43  *              selectable by the tm cancel_b_method parameter: fake reply,
44  *              retransmit request and send cancel on branch (andrei)
45  */
46
47 #include <stdio.h> /* for FILE* in fifo_uac_cancel */
48 #ifdef EXTRA_DEBUG
49 #include <assert.h>
50 #endif /* EXTRA_DEBUG */
51
52 #include "defs.h"
53 #include "config.h"
54
55 #include "t_funcs.h"
56 #include "../../dprint.h"
57 #include "../../ut.h"
58 #include "t_reply.h"
59 #include "t_cancel.h"
60 #include "t_msgbuilder.h"
61 #include "t_lookup.h" /* for t_lookup_callid in fifo_uac_cancel */
62 #include "t_hooks.h"
63
64
65 /* determine which branches should be canceled; can be called 
66    without REPLY_LOCK, since should_cancel_branch() is atomic now
67    -- andrei
68  WARNING: - has side effects, see should_cancel_branch()
69           - one _must_ call cancel_uacs(cancel_bm) if *cancel_bm!=0 or
70             you'll have some un-cancelable branches */
71 void which_cancel( struct cell *t, branch_bm_t *cancel_bm )
72 {
73         int i;
74         int branches_no;
75         
76         *cancel_bm=0;
77         branches_no=t->nr_of_outgoings;
78         membar_depends(); 
79         for( i=0 ; i<branches_no ; i++ ) {
80                 if (should_cancel_branch(t, i, 1)) 
81                         *cancel_bm |= 1<<i ;
82         }
83 }
84
85
86
87
88 /* cancel branches scheduled for deletion
89  * params: t          - transaction
90  *          cancel_bm - bitmap with the branches that are supposed to be 
91  *                       canceled 
92  *          flags     - how_to_cancel flags, see cancel_branch()
93  * returns: bitmap with the still active branches (on fr timer)
94  * WARNING: always fill cancel_bm using which_cancel(), supplying values
95  *          in any other way is a bug*/
96 int cancel_uacs( struct cell *t, branch_bm_t cancel_bm, int flags)
97 {
98         int i;
99         int ret;
100         int r;
101
102         ret=0;
103         /* cancel pending client transactions, if any */
104         for( i=0 ; i<t->nr_of_outgoings ; i++ ) 
105                 if (cancel_bm & (1<<i)){
106                         r=cancel_branch(
107                                 t,
108                                 i,
109                                 flags | ((t->uac[i].request.buffer==NULL)?
110                                         F_CANCEL_B_FAKE_REPLY:0) /* blind UAC? */
111                         );
112                         ret|=(r!=0)<<i;
113                 }
114         return ret;
115 }
116
117 int cancel_all_uacs(struct cell *trans, int how)
118 {
119         branch_bm_t cancel_bm;
120         int i,j;
121
122 #ifdef EXTRA_DEBUG
123         assert(trans);
124 #endif
125         DBG("Canceling T@%p [%u:%u]\n", trans, trans->hash_index, trans->label);
126         
127         cancel_bm=0;
128         which_cancel(trans, &cancel_bm);
129          /* tell tm to cancel the call */
130         i=cancel_uacs(trans, cancel_bm, how);
131         
132         if (how & F_CANCEL_UNREF)
133 #ifndef TM_DEL_UNREF
134         /* in case of 'too many' _buggy_ invocations, the ref count (a uint) might 
135          * actually wrap around, possibly leaving the T leaking. */
136 #warning "use of F_CANCEL_UNREF flag is unsafe without defining TM_DEL_UNREF"
137 #endif
138                 UNREF(trans);
139
140         /* count the still active branches */
141         if (! how) {
142                 j=0;
143                 while(i){
144                         j++;
145                         i&=i-1;
146                 }
147                 return j;
148         }
149         return 0;
150 }
151
152
153 /* should be called directly only if one of the condition bellow is true:
154  *  - should_cancel_branch or which_cancel returned true for this branch
155  *  - buffer value was 0 and then set to BUSY in an atomic op.:
156  *     if (atomic_cmpxchg_long(&buffer, 0, BUSY_BUFFER)==0).
157  *
158  * params:  t - transaction
159  *          branch - branch number to be canceled
160  *          flags - howto cancel: 
161  *                   F_CANCEL_B_KILL - will completely stop the 
162  *                     branch (stops the timers), use with care
163  *                   F_CANCEL_B_FAKE_REPLY - will send a fake 487
164  *                      to all branches that haven't received any response
165  *                      (>=100). It assumes the REPLY_LOCK is not held
166  *                      (if it is => deadlock)
167  *                  F_CANCEL_B_FORCE_C - will send a cancel (and create the 
168  *                       corresp. local cancel rb) even if no reply was 
169  *                       received; F_CANCEL_B_FAKE_REPLY will be ignored.
170  *                  F_CANCEL_B_FORCE_RETR - don't stop retransmission if no 
171  *                       reply was received on the branch; incompatible
172  *                       with F_CANCEL_B_FAKE_REPLY, F_CANCEL_B_FORCE_C and
173  *                       F_CANCEL_B_KILL (all of them take precedence) a
174  *                  default: stop only the retransmissions for the branch
175  *                      and leave it to timeout if it doesn't receive any
176  *                      response to the CANCEL
177  * returns: 0 - branch inactive after running cancel_branch() 
178  *          1 - branch still active  (fr_timer)
179  *         -1 - error
180  * WARNING:
181  *          - F_CANCEL_B_KILL should be used only if the transaction is killed
182  *            explicitly afterwards (since it might kill all the timers
183  *            the transaction won't be able to "kill" itself => if not
184  *            explicitly "put_on_wait" it might live forever)
185  *          - F_CANCEL_B_FAKE_REPLY must be used only if the REPLY_LOCK is not
186  *            held
187  *          - checking for buffer==0 under REPLY_LOCK is no enough, an 
188  *           atomic_cmpxhcg or atomic_get_and_set _must_ be used.
189  */
190 int cancel_branch( struct cell *t, int branch, int flags )
191 {
192         char *cancel;
193         unsigned int len;
194         struct retr_buf *crb, *irb;
195         int ret;
196         branch_bm_t tmp_bm;
197         void* pcbuf;
198
199         crb=&t->uac[branch].local_cancel;
200         irb=&t->uac[branch].request;
201         irb->flags|=F_RB_CANCELED;
202         ret=1;
203
204 #       ifdef EXTRA_DEBUG
205         if (crb->buffer!=BUSY_BUFFER) {
206                 LOG(L_CRIT, "ERROR: attempt to rewrite cancel buffer: %p\n",
207                                 crb->buffer);
208                 abort();
209         }
210 #       endif
211
212         if (flags & F_CANCEL_B_KILL){
213                 stop_rb_timers( irb );
214                 ret=0;
215                 if ((t->uac[branch].last_received < 100) &&
216                                 !(flags & F_CANCEL_B_FORCE_C)) {
217                         DBG("DEBUG: cancel_branch: no response ever received: "
218                             "giving up on cancel\n");
219                         /* remove BUSY_BUFFER -- mark cancel buffer as not used */
220                         pcbuf=&crb->buffer; /* workaround for type punning warnings */
221                         atomic_set_long(pcbuf, 0);
222                         if (flags & F_CANCEL_B_FAKE_REPLY){
223                                 LOCK_REPLIES(t);
224                                 if (relay_reply(t, FAKED_REPLY, branch, 487, &tmp_bm, 1) == 
225                                                                                 RPS_ERROR){
226                                         return -1;
227                                 }
228                         }
229                         /* do nothing, hope that the caller will clean up */
230                         return ret;
231                 }
232         }else{
233                 if (t->uac[branch].last_received < 100){
234                         if (!(flags & F_CANCEL_B_FORCE_C)) {
235                                 /* no response received => don't send a cancel on this branch,
236                                  *  just drop it */
237                                 if (!(flags & F_CANCEL_B_FORCE_RETR))
238                                         stop_rb_retr(irb); /* stop retransmissions */
239                                 /* remove BUSY_BUFFER -- mark cancel buffer as not used */
240                                 pcbuf=&crb->buffer; /* workaround for type punning warnings */
241                                 atomic_set_long(pcbuf, 0);
242                                 if (flags & F_CANCEL_B_FAKE_REPLY){
243                                         stop_rb_timers( irb ); /* stop even the fr timer */
244                                         LOCK_REPLIES(t);
245                                         if (relay_reply(t, FAKED_REPLY, branch, 487, &tmp_bm, 1)== 
246                                                                                         RPS_ERROR){
247                                                 return -1;
248                                         }
249                                         return 0; /* should be inactive after the 487 */
250                                 }
251                                 /* do nothing, just wait for the final timeout */
252                                 return 1;
253                         }
254                 }
255                 stop_rb_retr(irb); /* stop retransmissions */
256         }
257
258         if (cfg_get(tm, tm_cfg, reparse_invite)) {
259                 /* build the CANCEL from the INVITE which was sent out */
260                 cancel = build_local_reparse(t, branch, &len, CANCEL, CANCEL_LEN, &t->to);
261         } else {
262                 /* build the CANCEL from the reveived INVITE */
263                 cancel = build_local(t, branch, &len, CANCEL, CANCEL_LEN, &t->to);
264         }
265         if (!cancel) {
266                 LOG(L_ERR, "ERROR: attempt to build a CANCEL failed\n");
267                 /* remove BUSY_BUFFER -- mark cancel buffer as not used */
268                 pcbuf=&crb->buffer; /* workaround for type punning warnings */
269                 atomic_set_long(pcbuf, 0);
270                 return -1;
271         }
272         /* install cancel now */
273         crb->dst = irb->dst;
274         crb->branch = branch;
275         /* label it as cancel so that FR timer can better know how to
276            deal with it */
277         crb->activ_type = TYPE_LOCAL_CANCEL;
278         /* be extra carefully and check for bugs (the below if could be replaced
279          *  by an atomic_set((void*)&crb->buffer, cancel) */
280         if (unlikely(atomic_cmpxchg_long((void*)&crb->buffer, (long)BUSY_BUFFER,
281                                                         (long)cancel)!= (long)BUSY_BUFFER)){
282                 BUG("tm: cancel_branch: local_cancel buffer=%p != BUSY_BUFFER"
283                                 " (trying to continue)\n", crb->buffer);
284                 shm_free(cancel);
285                 return -1;
286         }
287         membar_write_atomic_op(); /* cancel retr. can be called from 
288                                                                  reply_received w/o the reply lock held => 
289                                                                  they check for buffer_len to 
290                                                                  see if a valid reply exists */
291         crb->buffer_len = len;
292
293         DBG("DEBUG: cancel_branch: sending cancel...\n");
294 #ifdef TMCB_ONSEND
295         if (SEND_BUFFER( crb )>=0){
296                 if (unlikely (has_tran_tmcbs(t, TMCB_REQUEST_SENT)))
297                         run_onsend_callbacks(TMCB_REQUEST_SENT, crb, 0, 0, TMCB_LOCAL_F);
298         }
299 #else
300         SEND_BUFFER( crb );
301 #endif
302         /*sets and starts the FINAL RESPONSE timer */
303         if (start_retr( crb )!=0)
304                 LOG(L_CRIT, "BUG: cancel_branch: failed to start retransmission"
305                                         " for %p\n", crb);
306         return ret;
307 }
308
309
310 const char* rpc_cancel_doc[2] = {
311         "Cancel a pending transaction",
312         0
313 };
314
315
316 /* fifo command to cancel a pending call (Uli)
317  * Syntax:
318  *
319  * ":uac_cancel:[response file]\n
320  * callid\n
321  * cseq\n
322  */
323 void rpc_cancel(rpc_t* rpc, void* c)
324 {
325         struct cell *trans;
326         static char cseq[128], callid[128];
327         branch_bm_t cancel_bm;
328         int i,j;
329
330         str cseq_s;   /* cseq */
331         str callid_s; /* callid */
332
333         cseq_s.s=cseq;
334         callid_s.s=callid;
335         cancel_bm=0;
336
337         if (rpc->scan(c, "SS", &callid_s, &cseq_s) < 2) {
338                 rpc->fault(c, 400, "Callid and CSeq expected as parameters");
339                 return;
340         }
341
342         if( t_lookup_callid(&trans, callid_s, cseq_s) < 0 ) {
343                 DBG("Lookup failed\n");
344                 rpc->fault(c, 400, "Transaction not found");
345                 return;
346         }
347         /*  find the branches that need cancel-ing */
348         LOCK_REPLIES(trans);
349                 which_cancel(trans, &cancel_bm);
350         UNLOCK_REPLIES(trans);
351          /* tell tm to cancel the call */
352         DBG("Now calling cancel_uacs\n");
353         i=cancel_uacs(trans, cancel_bm, 0); /* don't fake 487s, 
354                                                                                  just wait for timeout */
355         
356         /* t_lookup_callid REF`d the transaction for us, we must UNREF here! */
357         UNREF(trans);
358         j=0;
359         while(i){
360                 j++;
361                 i&=i-1;
362         }
363         rpc->add(c, "ds", j, "branches remaining (waiting for timeout)");
364 }
365
366
367
368 /* returns <0 on error */
369 int cancel_b_flags_get(unsigned int* f, int m)
370 {
371         int ret;
372         
373         ret=0;
374         switch(m){
375                 case 1:
376                         *f=F_CANCEL_B_FORCE_RETR;
377                         break;
378                 case 0:
379                         *f=F_CANCEL_B_FAKE_REPLY;
380                         break;
381                 case 2:
382                         *f=F_CANCEL_B_FORCE_C;
383                         break;
384                 default:
385                         *f=F_CANCEL_B_FAKE_REPLY;
386                         ret=-1;
387         }
388         return ret;
389 }
390
391
392
393 /* fixup function for the default cancel branch method/flags
394  * (called by the configuration framework) */
395 int cancel_b_flags_fixup(void* handle, str* name, void** val)
396 {
397         unsigned int m,f;
398         int ret;
399         
400         m=(unsigned int)(long)(*val);
401         ret=cancel_b_flags_get(&f, m);
402         if (ret<0)
403                 ERR("cancel_b_flags_fixup: invalid value for %.*s; %d\n",
404                                 name->len, name->s, m);
405         *val=(void*)(long)f;
406         return ret;
407 }
408
409
410
411