e0d8327ee84a845aa59012a7a4811e50155ae9da
[sip-router] / modules / tm / t_cancel.c
1 /*
2  * $Id$
3  *
4  */
5
6
7 #include "t_funcs.h"
8 #include "../../dprint.h"
9 #include "../../ut.h"
10 #include "t_reply.h"
11 #include "t_cancel.h"
12 #include "t_msgbuilder.h"
13
14
15 /* determine which branches should be cancelled; do it
16    only from within REPLY_LOCK, otherwise collisions
17    could occur (e.g., two 200 for two branches processed
18    by two processes might concurrently try to generate
19    a CANCEL for the third branch, resulting in race conditions
20    during writing to cancel buffer
21 */
22
23
24 void which_cancel( struct cell *t, branch_bm_t *cancel_bm )
25 {
26         int i;
27
28         for( i=0 ; i<t->nr_of_outgoings ; i++ ) {
29                 if (should_cancel_branch(t, i)) 
30                         *cancel_bm |= 1<<i ;
31
32         }
33 }
34
35
36 /* cancel branches scheduled for deletion */
37 void cancel_uacs( struct cell *t, branch_bm_t cancel_bm )
38 {
39         int i;
40
41         /* cancel pending client transactions, if any */
42         for( i=0 ; i<t->nr_of_outgoings ; i++ ) 
43                 if (cancel_bm & (1<<i))
44                 cancel_branch(t, i);
45 }
46
47 void cancel_branch( struct cell *t, int branch )
48 {
49         char *cancel;
50         int len;
51         struct retr_buf *crb, *irb;
52
53         crb=&t->uac[branch].local_cancel;
54         irb=&t->uac[branch].request;
55
56 #       ifdef EXTRA_DEBUG
57         if (crb->buffer!=0 && crb->buffer!=BUSY_BUFFER) {
58                 LOG(L_CRIT, "ERROR: attempt to rewrite cancel buffer\n");
59                 abort();
60         }
61 #       endif
62
63         cancel=build_cancel(t, branch, &len);
64         if (!cancel) {
65                 LOG(L_ERR, "ERROR: attempt to build a CANCEL failed\n");
66                 return;
67         }
68         /* install cancel now */
69         crb->buffer=cancel;
70         crb->buffer_len=len;
71         crb->to=irb->to;
72         crb->send_sock=irb->send_sock;
73         crb->branch=branch;
74 #ifdef _OBSOLETED
75         crb->fr_timer.tg=TG_FR;
76         crb->retr_timer.tg=TG_RT;
77         crb->my_T=t;
78 #endif
79         crb->retr_timer.payload=crb->fr_timer.payload=crb;
80         /* label it as cancel so that FR timer can better now how to
81            deal with it */
82         crb->activ_type=TYPE_LOCAL_CANCEL;
83
84     DBG("DEBUG: cancel_branch: sending cancel...\n");
85         SEND_BUFFER( crb );
86
87     /*sets and starts the FINAL RESPONSE timer */
88         start_retr( crb );
89 }
90
91 char *build_cancel(struct cell *Trans,unsigned int branch,
92         unsigned int *len )
93 {
94         return build_local( Trans, branch, len,
95                 CANCEL, CANCEL_LEN, &Trans->to );
96 }
97