tm: remove old timer based transaction delete functionality, not active since 2007
[kamailio] / src / modules / tm / t_cancel.c
1 /*
2  * Copyright (C) 2001-2003 FhG Fokus
3  *
4  * This file is part of Kamailio, a free SIP server.
5  *
6  * Kamailio is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version
10  *
11  * Kamailio is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #include <stdio.h> /* for FILE* in fifo_uac_cancel */
23 #ifdef EXTRA_DEBUG
24 #include <assert.h>
25 #endif /* EXTRA_DEBUG */
26
27 #include "defs.h"
28 #include "config.h"
29
30 #include "t_funcs.h"
31 #include "../../core/dprint.h"
32 #include "../../core/ut.h"
33 #include "t_reply.h"
34 #include "t_cancel.h"
35 #include "t_msgbuilder.h"
36 #include "t_lookup.h" /* for t_lookup_callid in fifo_uac_cancel */
37 #include "t_hooks.h"
38
39
40 typedef struct cancel_reason_map {
41         int code;
42         str text;
43 } cancel_reason_map_t;
44
45 static cancel_reason_map_t _cancel_reason_map[] = {
46         { 200, str_init("Call completed elsewhere") },
47         { 0, {0, 0} }
48 };
49
50 /**
51  *
52  */
53 void cancel_reason_text(struct cancel_info* cancel_data)
54 {
55         int i;
56
57         if(cancel_data->reason.cause<=0
58                         || cancel_data->reason.u.text.s!=NULL) return;
59
60         for(i=0; _cancel_reason_map[i].text.s!=0; i++) {
61                 if(_cancel_reason_map[i].code==cancel_data->reason.cause) {
62                         cancel_data->reason.u.text = _cancel_reason_map[i].text;
63                         return;
64                 }
65         }
66
67         return;
68 }
69
70 /** Prepare to cancel a transaction.
71  * Determine which branches should be canceled and prepare them (internally
72  * mark them as "cancel in progress", see prepare_cancel_branch()).
73  * Can be called without REPLY_LOCK, since prepare_cancel_branch() is atomic
74  *  now *  -- andrei
75  * WARNING: - has side effects, see prepare_cancel_branch()
76  *          - one _must_ call cancel_uacs(cancel_bm) if *cancel_bm!=0 or
77  *             you'll have some un-cancelable branches (because they remain
78  *             "marked" internally)
79  * @param t - transaction whose branches will be canceled
80  * @param cancel_bm - pointer to a branch bitmap that will be filled with
81 *    the branches that must be canceled (must be passed to cancel_uacs() if
82 *    !=0).
83 *  @param skip - branch bitmap of branches that should not be canceled
84 */
85 void prepare_to_cancel(struct cell *t, branch_bm_t *cancel_bm,
86                                                 branch_bm_t skip_branches)
87 {
88         int i;
89         int branches_no;
90         branch_bm_t mask;
91
92         *cancel_bm=0;
93         branches_no=t->nr_of_outgoings;
94         mask=~skip_branches;
95         membar_depends();
96         for( i=0 ; i<branches_no ; i++ ) {
97                 *cancel_bm |= ((mask & (1<<i)) &&  prepare_cancel_branch(t, i, 1))<<i;
98         }
99 }
100
101
102
103
104 /* cancel branches scheduled for deletion
105  * params: t          - transaction
106  *          cancel_data - structure filled with the cancel bitmap (bitmap with
107  *                       the branches that are supposed to be canceled) and
108  *                       the cancel reason.
109  *          flags     - how_to_cancel flags, see cancel_branch()
110  * returns: bitmap with the still active branches (on fr timer)
111  * WARNING: always fill cancel_data->cancel_bitmap using prepare_to_cancel(),
112  *          supplying values in any other way is a bug*/
113 int cancel_uacs( struct cell *t, struct cancel_info* cancel_data, int flags)
114 {
115         int i;
116         int ret;
117         int r;
118
119         ret=0;
120
121         cancel_reason_text(cancel_data);
122
123         /* cancel pending client transactions, if any */
124         for( i=0 ; i<t->nr_of_outgoings ; i++ )
125                 if (cancel_data->cancel_bitmap & (1<<i)){
126                         r=cancel_branch(
127                                 t,
128                                 i,
129 #ifdef CANCEL_REASON_SUPPORT
130                                 &cancel_data->reason,
131 #endif /* CANCEL_REASON_SUPPORT */
132                                 flags | ((t->uac[i].request.buffer==NULL)?
133                                         F_CANCEL_B_FAKE_REPLY:0) /* blind UAC? */
134                         );
135                         ret|=(r!=0)<<i;
136                 }
137         return ret;
138 }
139
140 int cancel_all_uacs(struct cell *trans, int how)
141 {
142         struct cancel_info cancel_data;
143         int i,j;
144
145 #ifdef EXTRA_DEBUG
146         assert(trans);
147 #endif
148         LM_DBG("Canceling T@%p [%u:%u]\n", trans, trans->hash_index, trans->label);
149
150         init_cancel_info(&cancel_data);
151         prepare_to_cancel(trans, &cancel_data.cancel_bitmap, 0);
152          /* tell tm to cancel the call */
153         i=cancel_uacs(trans, &cancel_data, how);
154
155         if (how & F_CANCEL_UNREF)
156                 UNREF(trans);
157
158         /* count the still active branches */
159         if (! how) {
160                 j=0;
161                 while(i){
162                         j++;
163                         i&=i-1;
164                 }
165                 return j;
166         }
167         return 0;
168 }
169
170
171 /* should be called directly only if one of the condition below is true:
172  *  - prepare_cancel_branch or prepare_to_cancel returned true for this branch
173  *  - buffer value was 0 and then set to BUSY in an atomic op.:
174  *     if (atomic_cmpxchg_long(&buffer, 0, BUSY_BUFFER)==0).
175  *
176  * params:  t - transaction
177  *          branch - branch number to be canceled
178  *          reason - cancel reason structure
179  *          flags - howto cancel:
180  *                   F_CANCEL_B_KILL - will completely stop the
181  *                     branch (stops the timers), use with care
182  *                   F_CANCEL_B_FAKE_REPLY - will send a fake 487
183  *                      to all branches that haven't received any response
184  *                      (>=100). It assumes the REPLY_LOCK is not held
185  *                      (if it is => deadlock)
186  *                  F_CANCEL_B_FORCE_C - will send a cancel (and create the
187  *                       corresp. local cancel rb) even if no reply was
188  *                       received; F_CANCEL_B_FAKE_REPLY will be ignored.
189  *                  F_CANCEL_B_FORCE_RETR - don't stop retransmission if no
190  *                       reply was received on the branch; incompatible
191  *                       with F_CANCEL_B_FAKE_REPLY, F_CANCEL_B_FORCE_C and
192  *                       F_CANCEL_B_KILL (all of them take precedence) a
193  *                  default: stop only the retransmissions for the branch
194  *                      and leave it to timeout if it doesn't receive any
195  *                      response to the CANCEL
196  * returns: 0 - branch inactive after running cancel_branch()
197  *          1 - branch still active  (fr_timer)
198  *         -1 - error
199  * WARNING:
200  *          - F_CANCEL_B_KILL should be used only if the transaction is killed
201  *            explicitly afterwards (since it might kill all the timers
202  *            the transaction won't be able to "kill" itself => if not
203  *            explicitly "put_on_wait" it might live forever)
204  *          - F_CANCEL_B_FAKE_REPLY must be used only if the REPLY_LOCK is not
205  *            held
206  *          - checking for buffer==0 under REPLY_LOCK is no enough, an
207  *           atomic_cmpxhcg or atomic_get_and_set _must_ be used.
208  */
209 int cancel_branch( struct cell *t, int branch,
210         #ifdef CANCEL_REASON_SUPPORT
211                                         struct cancel_reason* reason,
212         #endif /* CANCEL_REASON_SUPPORT */
213                                         int flags )
214 {
215         char *cancel;
216         unsigned int len;
217         struct retr_buf *crb, *irb;
218         int ret;
219         struct cancel_info tmp_cd;
220         void* pcbuf;
221
222         crb=&t->uac[branch].local_cancel;
223         irb=&t->uac[branch].request;
224         irb->flags|=F_RB_CANCELED;
225         ret=1;
226         init_cancel_info(&tmp_cd);
227
228 #       ifdef EXTRA_DEBUG
229         if (crb->buffer!=BUSY_BUFFER) {
230                 LM_CRIT("attempt to rewrite cancel buffer: %p\n", crb->buffer);
231                 abort();
232         }
233 #       endif
234
235         if (flags & F_CANCEL_B_KILL){
236                 stop_rb_timers( irb );
237                 ret=0;
238                 if ((t->uac[branch].last_received < 100) &&
239                                 !(flags & F_CANCEL_B_FORCE_C)) {
240                         LM_DBG("no response ever received: giving up on cancel\n");
241                         /* remove BUSY_BUFFER -- mark cancel buffer as not used */
242                         pcbuf=&crb->buffer; /* workaround for type punning warnings */
243                         atomic_set_long(pcbuf, 0);
244                         /* try to relay auto-generated 487 canceling response only when
245                          * another one is not under relaying on the branch and there is
246                          * no forced response per transaction from script */
247                         if((flags & F_CANCEL_B_FAKE_REPLY)
248                                         && !(irb->flags&F_RB_RELAYREPLY)
249                                         && !(t->flags&T_ADMIN_REPLY)) {
250                                 LOCK_REPLIES(t);
251                                 if (relay_reply(t, FAKED_REPLY, branch, 487, &tmp_cd, 1) ==
252                                                                                 RPS_ERROR){
253                                         return -1;
254                                 }
255                         }
256                         /* do nothing, hope that the caller will clean up */
257                         return ret;
258                 }
259         }else{
260                 if (t->uac[branch].last_received < 100){
261                         if (!(flags & F_CANCEL_B_FORCE_C)) {
262                                 /* no response received => don't send a cancel on this branch,
263                                  *  just drop it */
264                                 if (!(flags & F_CANCEL_B_FORCE_RETR))
265                                         stop_rb_retr(irb); /* stop retransmissions */
266                                 /* remove BUSY_BUFFER -- mark cancel buffer as not used */
267                                 pcbuf=&crb->buffer; /* workaround for type punning warnings */
268                                 atomic_set_long(pcbuf, 0);
269                                 if (flags & F_CANCEL_B_FAKE_REPLY){
270                                         stop_rb_timers( irb ); /* stop even the fr timer */
271                                         LOCK_REPLIES(t);
272                                         if (relay_reply(t, FAKED_REPLY, branch, 487, &tmp_cd, 1)==
273                                                                                         RPS_ERROR){
274                                                 return -1;
275                                         }
276                                         return 0; /* should be inactive after the 487 */
277                                 }
278                                 /* do nothing, just wait for the final timeout */
279                                 return 1;
280                         }
281                 }
282                 stop_rb_retr(irb); /* stop retransmissions */
283         }
284
285         if (cfg_get(tm, tm_cfg, reparse_invite) ||
286                         (t->uas.request && t->uas.request->msg_flags&(FL_USE_UAC_FROM|FL_USE_UAC_TO))) {
287                 /* build the CANCEL from the INVITE which was sent out */
288                 cancel = build_local_reparse(t, branch, &len, CANCEL, CANCEL_LEN,
289                                                                          (t->uas.request && t->uas.request->msg_flags&FL_USE_UAC_TO)?0:&t->to
290         #ifdef CANCEL_REASON_SUPPORT
291                                                                          , reason
292         #endif /* CANCEL_REASON_SUPPORT */
293                                                                          );
294         } else {
295                 /* build the CANCEL from the received INVITE */
296                 cancel = build_local(t, branch, &len, CANCEL, CANCEL_LEN, &t->to
297         #ifdef CANCEL_REASON_SUPPORT
298                                                                 , reason
299         #endif /* CANCEL_REASON_SUPPORT */
300                                                                 );
301         }
302         if (!cancel) {
303                 LM_ERR("attempt to build a CANCEL failed\n");
304                 /* remove BUSY_BUFFER -- mark cancel buffer as not used */
305                 pcbuf=&crb->buffer; /* workaround for type punning warnings */
306                 atomic_set_long(pcbuf, 0);
307                 return -1;
308         }
309         /* install cancel now */
310         crb->dst = irb->dst;
311         crb->branch = branch;
312         /* label it as cancel so that FR timer can better know how to
313            deal with it */
314         crb->rbtype = TYPE_LOCAL_CANCEL;
315         /* be extra carefully and check for bugs (the below if could be replaced
316          *  by an atomic_set((void*)&crb->buffer, cancel) */
317         if (unlikely(atomic_cmpxchg_long((void*)&crb->buffer, (long)BUSY_BUFFER,
318                                                         (long)cancel)!= (long)BUSY_BUFFER)){
319                 LM_BUG("local_cancel buffer=%p != BUSY_BUFFER"
320                                 " (trying to continue)\n", crb->buffer);
321                 shm_free(cancel);
322                 return -1;
323         }
324         membar_write_atomic_op(); /* cancel retr. can be called from
325                                                                  reply_received w/o the reply lock held =>
326                                                                  they check for buffer_len to
327                                                                  see if a valid reply exists */
328         crb->buffer_len = len;
329
330         LM_DBG("sending cancel...\n");
331         if (SEND_BUFFER( crb )>=0){
332                 if (unlikely (has_tran_tmcbs(t, TMCB_REQUEST_OUT)))
333                         run_trans_callbacks_with_buf(TMCB_REQUEST_OUT, crb, t->uas.request, 0, TMCB_LOCAL_F);
334                 if (unlikely (has_tran_tmcbs(t, TMCB_REQUEST_SENT)))
335                         run_trans_callbacks_with_buf(TMCB_REQUEST_SENT, crb, t->uas.request, 0, TMCB_LOCAL_F);
336         }
337         /*sets and starts the FINAL RESPONSE timer */
338         if (start_retr( crb )!=0)
339                 LM_CRIT("failed to start retransmission for %p\n", crb);
340         return ret;
341 }
342
343
344 /* fifo command to cancel a pending call (Uli)
345  * Syntax:
346  *
347  * ":uac_cancel:[response file]\n
348  * callid\n
349  * cseq\n
350  */
351 void rpc_cancel(rpc_t* rpc, void* c)
352 {
353         struct cell *trans;
354         static char cseq[128], callid[128];
355         struct cancel_info cancel_data;
356         int i,j;
357
358         str cseq_s;   /* cseq */
359         str callid_s; /* callid */
360
361         cseq_s.s=cseq;
362         callid_s.s=callid;
363         init_cancel_info(&cancel_data);
364
365         if (rpc->scan(c, "SS", &callid_s, &cseq_s) < 2) {
366                 rpc->fault(c, 400, "Callid and CSeq expected as parameters");
367                 return;
368         }
369
370         if( t_lookup_callid(&trans, callid_s, cseq_s) < 0 ) {
371                 LM_DBG("Lookup failed\n");
372                 rpc->fault(c, 400, "Transaction not found");
373                 return;
374         }
375         /*  find the branches that need cancel-ing */
376         prepare_to_cancel(trans, &cancel_data.cancel_bitmap, 0);
377          /* tell tm to cancel the call */
378         DBG("Now calling cancel_uacs\n");
379         i=cancel_uacs(trans, &cancel_data, 0); /* don't fake 487s,
380                                                                                  just wait for timeout */
381
382         /* t_lookup_callid REF`d the transaction for us, we must UNREF here! */
383         UNREF(trans);
384         j=0;
385         while(i){
386                 j++;
387                 i&=i-1;
388         }
389         rpc->add(c, "ds", j, "branches remaining (waiting for timeout)");
390 }
391
392
393
394 /* returns <0 on error */
395 int cancel_b_flags_get(unsigned int* f, int m)
396 {
397         int ret;
398
399         ret=0;
400         switch(m){
401                 case 1:
402                         *f=F_CANCEL_B_FORCE_RETR;
403                         break;
404                 case 0:
405                         *f=F_CANCEL_B_FAKE_REPLY;
406                         break;
407                 case 2:
408                         *f=F_CANCEL_B_FORCE_C;
409                         break;
410                 default:
411                         *f=F_CANCEL_B_FAKE_REPLY;
412                         ret=-1;
413         }
414         return ret;
415 }
416
417
418
419 /* fixup function for the default cancel branch method/flags
420  * (called by the configuration framework) */
421 int cancel_b_flags_fixup(void* handle, str* gname, str* name, void** val)
422 {
423         unsigned int m,f;
424         int ret;
425
426         m=(unsigned int)(long)(*val);
427         ret=cancel_b_flags_get(&f, m);
428         if (ret<0)
429                 LM_ERR("invalid value for %.*s; %d\n", name->len, name->s, m);
430         *val=(void*)(long)f;
431         return ret;
432 }
433
434
435 /**
436  * This function cancels a previously created local invite
437  * transaction. The cancel parameter should NOT have any via (CANCEL is
438  * hop by hop). returns 0 if error return >0 if OK (returns the LABEL of
439  * the cancel).*/
440 unsigned int t_uac_cancel( str *headers, str *body,
441                 unsigned int cancelled_hashIdx, unsigned int cancelled_label,
442                 transaction_cb cb, void* cbp)
443 {
444         struct cell *t_invite,*cancel_cell;
445         struct retr_buf *cancel,*invite;
446         unsigned int len,ret;
447         char *buf;
448
449         ret=0;
450         if(t_lookup_ident(&t_invite,cancelled_hashIdx,cancelled_label)<0){
451                 LM_ERR("failed to t_lookup_ident hash_idx=%d,"
452                                 "label=%d\n", cancelled_hashIdx,cancelled_label);
453                 return 0;
454         }
455         /* <sanity_checks> */
456         if(! is_local(t_invite))
457         {
458                 LM_ERR("tried to cancel a non-local transaction\n");
459                 goto error3;
460         }
461         if(t_invite->uac[0].last_received < 100)
462         {
463                 LM_WARN("trying to cancel a transaction not in "
464                                         "Proceeding state !\n");
465                 goto error3;
466         }
467         if(t_invite->uac[0].last_received > 200)
468         {
469                 LM_WARN("trying to cancel a completed transaction !\n");
470                 goto error3;
471         }
472         /* </sanity_checks*/
473         /* <build_cell> */
474         if(!(cancel_cell = build_cell(0))){
475                 ret=0;
476                 LM_ERR("no more shm memory!\n");
477                 goto error3;
478         }
479         reset_avps();
480         if(cb && insert_tmcb(&(cancel_cell->tmcb_hl),
481                         TMCB_RESPONSE_IN|TMCB_LOCAL_COMPLETED,cb,cbp,0)!=1){
482                 ret=0;
483                 LM_ERR("short of tmcb shmem !\n");
484                 goto error2;
485         }
486         /* </build_cell> */
487
488         /* <insert_into_hashtable> */
489         cancel_cell->flags |= T_IS_LOCAL_FLAG;
490         cancel_cell->hash_index=t_invite->hash_index;
491
492         LOCK_HASH(cancel_cell->hash_index);
493         insert_into_hash_table_unsafe(cancel_cell,cancel_cell->hash_index);
494         ret=cancel_cell->label;
495         cancel_cell->label=t_invite->label;
496         UNLOCK_HASH(cancel_cell->hash_index);
497         /* </insert_into_hashtable> */
498
499         /* <prepare_cancel> */
500
501         cancel=&cancel_cell->uac[0].request;
502         invite=&t_invite->uac[0].request;
503
504         cancel->dst.to              = invite->dst.to;
505         cancel->dst.send_sock       = invite->dst.send_sock;
506         cancel->dst.proto           = invite->dst.proto;
507         //cancel->dst.proto_reserved1 = invite->dst.proto_reserved1;
508
509         if(!(buf = build_uac_cancel(headers,body,t_invite,0,&len,
510                                         &(cancel->dst)))){
511                 ret=0;
512                 LM_ERR("attempt to build a CANCEL failed\n");
513                 goto error1;
514         }
515         cancel->buffer=buf;
516         cancel->buffer_len=len;
517         cancel_cell->method.s = buf;
518         cancel_cell->method.len = 6 /*c-a-n-c-e-l*/;
519         /* </prepare_cancel> */
520
521         /* <strart_sending> */
522         cancel_cell->nr_of_outgoings++;
523         if (SEND_BUFFER(cancel)==-1) {
524                 ret=0;
525                 LM_ERR("send failed\n");
526                 goto error1;
527         }
528         start_retr(cancel);
529         /* </start_sending> */
530
531         return ret;
532
533 error1:
534         LOCK_HASH(cancel_cell->hash_index);
535         remove_from_hash_table_unsafe(cancel_cell);
536         UNLOCK_HASH(cancel_cell->hash_index);
537 error2:
538         free_cell(cancel_cell);
539 error3:
540         return ret;
541 }