... | ... |
@@ -34,6 +34,8 @@ |
34 | 34 |
* 2003-04-04 bug_fix: REQ_IN callback not called for local |
35 | 35 |
* UAC transactions (jiri) |
36 | 36 |
* 2003-09-12 timer_link->tg will be set only if EXTRA_DEBUG (andrei) |
37 |
+ * 2003-12-04 global callbacks replaceed with callbacks per transaction; |
|
38 |
+ * completion callback merged into them as LOCAL_COMPETED (bogdan) |
|
37 | 39 |
*/ |
38 | 40 |
|
39 | 41 |
#include "defs.h" |
... | ... |
@@ -106,6 +108,7 @@ void free_cell( struct cell* dead_cell ) |
106 | 108 |
int i; |
107 | 109 |
struct sip_msg *rpl; |
108 | 110 |
struct totag_elem *tt, *foo; |
111 |
+ struct tm_callback *cbs, *cbs_tmp; |
|
109 | 112 |
|
110 | 113 |
release_cell_lock( dead_cell ); |
111 | 114 |
shm_lock(); |
... | ... |
@@ -116,8 +119,12 @@ void free_cell( struct cell* dead_cell ) |
116 | 119 |
if ( dead_cell->uas.response.buffer ) |
117 | 120 |
shm_free_unsafe( dead_cell->uas.response.buffer ); |
118 | 121 |
|
119 |
- /* completion callback */ |
|
120 |
- if (dead_cell->cbp) shm_free_unsafe(dead_cell->cbp); |
|
122 |
+ /* callbacks */ |
|
123 |
+ for( cbs=dead_cell->tmcb_hl.first ; cbs ; ) { |
|
124 |
+ cbs_tmp = cbs; |
|
125 |
+ cbs = cbs->next; |
|
126 |
+ shm_free_unsafe( cbs_tmp ); |
|
127 |
+ } |
|
121 | 128 |
|
122 | 129 |
/* UA Clients */ |
123 | 130 |
for ( i =0 ; i<dead_cell->nr_of_outgoings; i++ ) |
... | ... |
@@ -183,15 +190,10 @@ struct cell* build_cell( struct sip_msg* p_msg ) |
183 | 190 |
new_cell->uas.response.retr_timer.payload = &(new_cell->uas.response); |
184 | 191 |
new_cell->uas.response.my_T=new_cell; |
185 | 192 |
|
186 |
- /* bogdan - debug */ |
|
187 |
- /*fprintf(stderr,"before clone VIA |%.*s|\n",via_len(p_msg->via1), |
|
188 |
- via_s(p_msg->via1,p_msg));*/ |
|
189 |
- |
|
190 | 193 |
/* enter callback, which may potentially want to parse some stuff, |
191 |
- before the request is shmem-ized |
|
192 |
- */ |
|
193 |
- if (p_msg) callback_event(TMCB_REQUEST_IN, new_cell, p_msg, |
|
194 |
- p_msg->REQ_METHOD ); |
|
194 |
+ * before the request is shmem-ized */ |
|
195 |
+ if ( p_msg && has_reqin_tmcbs() ) |
|
196 |
+ run_reqin_callbacks( new_cell, p_msg, p_msg->REQ_METHOD); |
|
195 | 197 |
|
196 | 198 |
if (p_msg) { |
197 | 199 |
new_cell->uas.request = sip_msg_cloner(p_msg); |
... | ... |
@@ -29,6 +29,8 @@ |
29 | 29 |
* 2003-03-16 removed _TOTAG (jiri) |
30 | 30 |
* 2003-03-06 we keep a list of 200/INV to-tags now (jiri) |
31 | 31 |
* 2003-03-01 kr set through a function now (jiri) |
32 |
+ * 2003-12-04 callbacks per transaction added; completion callback |
|
33 |
+ * merge into them as LOCAL_COMPETED (bogdan) |
|
32 | 34 |
*/ |
33 | 35 |
|
34 | 36 |
#include "defs.h" |
... | ... |
@@ -174,21 +176,15 @@ typedef struct cell |
174 | 176 |
with proxied transactions to inbound request */ |
175 | 177 |
str from, callid, cseq_n, to; |
176 | 178 |
/* a short-cut for remember whether this transaction needs |
177 |
- INVITE-special handling (e.g., CANCEL, ACK, FR...) |
|
178 |
- */ |
|
179 |
+ INVITE-special handling (e.g., CANCEL, ACK, FR...) */ |
|
179 | 180 |
short is_invite; |
180 | 181 |
/* method shortcut -- for local transactions, pointer to |
181 | 182 |
outbound buffer, for proxies transactions pointer to |
182 |
- original message; needed for reply matching |
|
183 |
- */ |
|
183 |
+ original message; needed for reply matching */ |
|
184 | 184 |
str method; |
185 | 185 |
|
186 |
- /* callback and parameter on completion of local transactions */ |
|
187 |
- transaction_cb *completion_cb; |
|
188 |
- /* the parameter stores a pointer to shmem -- it will be released |
|
189 |
- during freeing transaction too |
|
190 |
- */ |
|
191 |
- void *cbp; |
|
186 |
+ /* head of callback list */ |
|
187 |
+ struct tmcb_head_list tmcb_hl; |
|
192 | 188 |
|
193 | 189 |
/* how many processes are currently processing this transaction ; |
194 | 190 |
note that only processes working on a request/reply belonging |
... | ... |
@@ -110,6 +110,8 @@ void tm_shutdown() |
110 | 110 |
free_timer_table(); |
111 | 111 |
DBG("DEBUG: tm_shutdown : removing semaphores\n"); |
112 | 112 |
lock_cleanup(); |
113 |
+ DBG("DEBUG: tm_shutdown : destroing tmcb lists\n"); |
|
114 |
+ destroy_tmcb_lists(); |
|
113 | 115 |
free_tm_stats(); |
114 | 116 |
DBG("DEBUG: tm_shutdown : done\n"); |
115 | 117 |
} |
... | ... |
@@ -39,6 +39,8 @@ |
39 | 39 |
* 2003-03-30 we now watch downstream delivery and if it fails, send an |
40 | 40 |
* error message upstream (jiri) |
41 | 41 |
* 2003-04-14 use protocol from uri (jiri) |
42 |
+ * 2003-12-04 global TM callbacks switched to per transaction callbacks |
|
43 |
+ * (bogdan) |
|
42 | 44 |
*/ |
43 | 45 |
|
44 | 46 |
#include "defs.h" |
... | ... |
@@ -83,8 +85,8 @@ char *print_uac_request( struct cell *t, struct sip_msg *i_req, |
83 | 85 |
/* ... update uri ... */ |
84 | 86 |
i_req->new_uri=*uri; |
85 | 87 |
|
86 |
- /* ... give apps a chance to change things ... */ |
|
87 |
- callback_event( TMCB_REQUEST_FWDED, t, i_req, -i_req->REQ_METHOD); |
|
88 |
+ /* run the specific callbacks for this transaction */ |
|
89 |
+ run_trans_callbacks( TMCB_REQUEST_FWDED , t, i_req, 0, -i_req->REQ_METHOD); |
|
88 | 90 |
|
89 | 91 |
/* ... and build it now */ |
90 | 92 |
buf=build_req_buf_from_sip_req( i_req, len, send_sock, proto ); |
... | ... |
@@ -28,6 +28,9 @@ |
28 | 28 |
* History: |
29 | 29 |
* -------- |
30 | 30 |
* 2003-03-19 replaced all the mallocs/frees w/ pkg_malloc/pkg_free (andrei) |
31 |
+ * 2003-12-04 global callbacks moved into transaction callbacks; |
|
32 |
+ * multiple events per callback added; single list per |
|
33 |
+ * transaction for all its callbacks (bogdan) |
|
31 | 34 |
*/ |
32 | 35 |
|
33 | 36 |
#include "defs.h" |
... | ... |
@@ -38,46 +41,150 @@ |
38 | 41 |
#include "../../error.h" |
39 | 42 |
#include "../../mem/mem.h" |
40 | 43 |
#include "t_hooks.h" |
44 |
+#include "t_lookup.h" |
|
45 |
+#include "t_funcs.h" |
|
41 | 46 |
|
42 |
-/* strange things happen if callback_array is static on openbsd */ |
|
43 |
-struct tm_callback_s* callback_array[ TMCB_END ] = { 0, 0 } ; |
|
44 |
-static int callback_id=0; |
|
45 | 47 |
|
46 |
-/* register a callback function 'f' of type 'cbt'; will be called |
|
47 |
- back whenever the event 'cbt' occurs in transaction module |
|
48 |
-*/ |
|
49 |
-int register_tmcb( tmcb_type cbt, transaction_cb f, void *param ) |
|
48 |
+struct tmcb_head_list* req_in_tmcb_hl = 0; |
|
49 |
+ |
|
50 |
+ |
|
51 |
+ |
|
52 |
+int init_tmcb_lists() |
|
53 |
+{ |
|
54 |
+ req_in_tmcb_hl = (struct tmcb_head_list*)shm_malloc |
|
55 |
+ ( sizeof(struct tmcb_head_list) ); |
|
56 |
+ if (req_in_tmcb_hl==0) { |
|
57 |
+ LOG(L_CRIT,"ERROR:tm:init_tmcb_lists: nomore shared mem\n"); |
|
58 |
+ return -1; |
|
59 |
+ } |
|
60 |
+ req_in_tmcb_hl->first = 0; |
|
61 |
+ req_in_tmcb_hl->reg_types = 0; |
|
62 |
+ return 1; |
|
63 |
+} |
|
64 |
+ |
|
65 |
+ |
|
66 |
+void destroy_tmcb_lists() |
|
50 | 67 |
{ |
51 |
- struct tm_callback_s *cbs; |
|
68 |
+ struct tm_callback *cbp, *cbp_tmp; |
|
52 | 69 |
|
53 |
- if (cbt<0 || cbt>=TMCB_END ) { |
|
54 |
- LOG(L_ERR, "ERROR: register_tmcb: invalid callback type: %d\n", |
|
55 |
- cbt ); |
|
56 |
- return E_BUG; |
|
70 |
+ if (!req_in_tmcb_hl) |
|
71 |
+ return; |
|
72 |
+ |
|
73 |
+ for( cbp=req_in_tmcb_hl->first; cbp ; ) { |
|
74 |
+ cbp_tmp = cbp; |
|
75 |
+ cbp = cbp->next; |
|
76 |
+ if (cbp->param) shm_free( cbp->param ); |
|
77 |
+ shm_free( cbp_tmp ); |
|
57 | 78 |
} |
58 | 79 |
|
59 |
- if (!(cbs=pkg_malloc( sizeof( struct tm_callback_s)))) { |
|
60 |
- LOG(L_ERR, "ERROR: register_tmcb: out of mem\n"); |
|
80 |
+ shm_free(req_in_tmcb_hl); |
|
81 |
+} |
|
82 |
+ |
|
83 |
+ |
|
84 |
+inline int insert_tmcb(struct tmcb_head_list *cb_list, int types, |
|
85 |
+ transaction_cb f, void *param ) |
|
86 |
+{ |
|
87 |
+ struct tm_callback *cbp; |
|
88 |
+ |
|
89 |
+ /* build a new callback structure */ |
|
90 |
+ if (!(cbp=shm_malloc( sizeof( struct tm_callback)))) { |
|
91 |
+ LOG(L_ERR, "ERROR:tm:register_tmcb: out of shm. mem\n"); |
|
61 | 92 |
return E_OUT_OF_MEM; |
62 | 93 |
} |
63 | 94 |
|
64 |
- callback_id++; |
|
65 |
- cbs->id=callback_id; |
|
66 |
- cbs->callback=f; |
|
67 |
- cbs->next=callback_array[ cbt ]; |
|
68 |
- cbs->param=param; |
|
69 |
- callback_array[ cbt ]=cbs; |
|
95 |
+ /* link it into the proper place... */ |
|
96 |
+ cbp->next = cb_list->first; |
|
97 |
+ cb_list->first = cbp; |
|
98 |
+ cb_list->reg_types |= types; |
|
99 |
+ /* ... and fill it up */ |
|
100 |
+ cbp->callback = f; |
|
101 |
+ cbp->param = param; |
|
102 |
+ cbp->types = types; |
|
103 |
+ if (cbp->next) |
|
104 |
+ cbp->id = cbp->next->id+1; |
|
105 |
+ else |
|
106 |
+ cbp->id = 0; |
|
107 |
+ |
|
108 |
+ return 1; |
|
109 |
+} |
|
110 |
+ |
|
111 |
+ |
|
112 |
+ |
|
113 |
+/* register a callback function 'f' for 'types' mask of events; |
|
114 |
+ * will be called back whenever one of the events occurs in transaction module |
|
115 |
+ * (global or per transacation, depinding of event type) |
|
116 |
+*/ |
|
117 |
+int register_tmcb( struct sip_msg* p_msg, int types, transaction_cb f, |
|
118 |
+ void *param ) |
|
119 |
+{ |
|
120 |
+ struct cell* t; |
|
121 |
+ struct tmcb_head_list *cb_list; |
|
122 |
+ |
|
123 |
+ /* are the callback types valid?... */ |
|
124 |
+ if ( types<0 || types>=TMCB_MAX ) { |
|
125 |
+ LOG(L_CRIT, "BUG:tm:register_tmcb: invalid callback types: mask=%d\n", |
|
126 |
+ types); |
|
127 |
+ return E_BUG; |
|
128 |
+ } |
|
129 |
+ if (types&TMCB_REQUEST_IN) { |
|
130 |
+ if (types!=TMCB_REQUEST_IN) { |
|
131 |
+ LOG(L_CRIT, "BUG:tm:register_tmcb: callback type TMCB_REQUEST_IN " |
|
132 |
+ "can't be register along with types\n"); |
|
133 |
+ return E_BUG; |
|
134 |
+ } |
|
135 |
+ cb_list = req_in_tmcb_hl; |
|
136 |
+ } else { |
|
137 |
+ /* look for the transaction */ |
|
138 |
+ if ( t_check(p_msg,0)!=1 ){ |
|
139 |
+ LOG(L_CRIT,"BUG:tm:register_tmcb: no transaction found\n"); |
|
140 |
+ return E_BUG; |
|
141 |
+ } |
|
142 |
+ if ( (t=get_t())==0 ) { |
|
143 |
+ LOG(L_CRIT,"BUG:tm:register_tmcb: transaction found is NULL\n"); |
|
144 |
+ return E_BUG; |
|
145 |
+ } |
|
146 |
+ cb_list = &(t->tmcb_hl); |
|
147 |
+ } |
|
148 |
+ |
|
149 |
+ return insert_tmcb( cb_list, types, f, param ); |
|
150 |
+} |
|
70 | 151 |
|
71 |
- return callback_id; |
|
152 |
+ |
|
153 |
+void run_trans_callbacks( int type , struct cell *trans, |
|
154 |
+ struct sip_msg *req, struct sip_msg *rpl, int code ) |
|
155 |
+{ |
|
156 |
+ static struct tmcb_params params = {0,0,0,0}; |
|
157 |
+ struct tm_callback *cbp; |
|
158 |
+ |
|
159 |
+ params.req = req; |
|
160 |
+ params.rpl = rpl; |
|
161 |
+ params.code = code; |
|
162 |
+ |
|
163 |
+ for (cbp=trans->tmcb_hl.first; cbp; cbp=cbp->next) { |
|
164 |
+ if ( (cbp->types)&type ) { |
|
165 |
+ DBG("DBG: trans=%p, callback type %d, id %d entered\n", |
|
166 |
+ trans, type, cbp->id ); |
|
167 |
+ params.param = cbp->param; |
|
168 |
+ cbp->callback( trans, type, ¶ms ); |
|
169 |
+ } |
|
170 |
+ } |
|
72 | 171 |
} |
73 | 172 |
|
74 |
-void callback_event( tmcb_type cbt , struct cell *trans, |
|
75 |
- struct sip_msg *msg, int code ) |
|
173 |
+ |
|
174 |
+ |
|
175 |
+void run_reqin_callbacks( struct cell *trans, struct sip_msg *req, int code ) |
|
76 | 176 |
{ |
77 |
- struct tm_callback_s *cbs; |
|
177 |
+ static struct tmcb_params params = {0,0,0,0}; |
|
178 |
+ struct tm_callback *cbp; |
|
78 | 179 |
|
79 |
- for (cbs=callback_array[ cbt ]; cbs; cbs=cbs->next) { |
|
80 |
- DBG("DBG: callback type %d, id %d entered\n", cbt, cbs->id ); |
|
81 |
- cbs->callback( trans, msg, code, cbs->param ); |
|
180 |
+ params.req = req; |
|
181 |
+ params.code = code; |
|
182 |
+ |
|
183 |
+ for (cbp=req_in_tmcb_hl->first; cbp; cbp=cbp->next) { |
|
184 |
+ DBG("DBG: trans=%p, callback type %d, id %d entered\n", |
|
185 |
+ trans, cbp->types, cbp->id ); |
|
186 |
+ params.param = cbp->param; |
|
187 |
+ cbp->callback( trans, cbp->types, ¶ms ); |
|
82 | 188 |
} |
83 | 189 |
} |
190 |
+ |
... | ... |
@@ -26,8 +26,11 @@ |
26 | 26 |
* |
27 | 27 |
* History: |
28 | 28 |
* -------- |
29 |
- * 2003-03-16 backwards-compatibility callback names introduced (jiri) |
|
30 |
- * 2003-03-06 old callbacks renamed, new one introduced (jiri) |
|
29 |
+ * 2003-03-16 : backwards-compatibility callback names introduced (jiri) |
|
30 |
+ * 2003-03-06 : old callbacks renamed, new one introduced (jiri) |
|
31 |
+ * 2003-12-04 : global callbacks moved into transaction callbacks; |
|
32 |
+ * multiple events per callback added; single list per |
|
33 |
+ * transaction for all its callbacks (bogdan) |
|
31 | 34 |
*/ |
32 | 35 |
|
33 | 36 |
|
... | ... |
@@ -36,25 +39,20 @@ |
36 | 39 |
|
37 | 40 |
#include "defs.h" |
38 | 41 |
|
39 |
- |
|
40 | 42 |
struct sip_msg; |
41 | 43 |
struct cell; |
42 | 44 |
|
43 |
-/* backwards compatibility hooks */ |
|
44 |
-#define TMCB_REPLY TMCB_RESPONSE_OUT |
|
45 |
-#define TMCB_E2EACK TMCB_E2EACK_IN |
|
46 |
-#define TMCB_REPLY_IN TMCB_RESPONSE_IN |
|
47 |
-#define TMCB_REQUEST_OUT TMCB_REQUEST_FWDED |
|
48 |
-#define TMCB_ON_NEGATIVE TMCB_ON_FAILURE |
|
49 |
- |
|
50 |
-typedef enum { |
|
51 |
- /* input events */ |
|
52 |
- TMCB_RESPONSE_IN=1, TMCB_REQUEST_IN, TMCB_E2EACK_IN, |
|
53 |
- /* routing decisions in progress */ |
|
54 |
- TMCB_REQUEST_FWDED, TMCB_RESPONSE_FWDED, TMCB_ON_FAILURE, |
|
55 |
- /* completion events */ |
|
56 |
- TMCB_RESPONSE_OUT, TMCB_LOCAL_COMPLETED, |
|
57 |
- TMCB_END } tmcb_type; |
|
45 |
+ |
|
46 |
+#define TMCB_REQUEST_IN (1<<0) |
|
47 |
+#define TMCB_RESPONSE_IN (1<<1) |
|
48 |
+#define TMCB_E2EACK_IN (1<<2) |
|
49 |
+#define TMCB_REQUEST_FWDED (1<<3) |
|
50 |
+#define TMCB_RESPONSE_FWDED (1<<4) |
|
51 |
+#define TMCB_ON_FAILURE_RO (1<<5) |
|
52 |
+#define TMCB_ON_FAILURE (1<<6) |
|
53 |
+#define TMCB_RESPONSE_OUT (1<<7) |
|
54 |
+#define TMCB_LOCAL_COMPLETED (1<<8) |
|
55 |
+#define TMCB_MAX ((1<<9)-1) |
|
58 | 56 |
|
59 | 57 |
/* |
60 | 58 |
* Caution: most of the callbacks work with shmem-ized messages |
... | ... |
@@ -65,6 +63,13 @@ typedef enum { |
65 | 63 |
* is a non-dereferencable pointer indicating that no message |
66 | 64 |
* was received and a timer hit instead. |
67 | 65 |
* |
66 |
+ * All callbacks excepting the TMCB_REQUEST_IN are associates to a |
|
67 |
+ * transaction. It means they will be run only when the event will hint |
|
68 |
+ * the transaction the callbacks were register for. |
|
69 |
+ * TMCB_REQUEST_IN is a global callback - it means it will be run for |
|
70 |
+ * all transactions. |
|
71 |
+ * |
|
72 |
+ * |
|
68 | 73 |
* Callback description: |
69 | 74 |
* --------------------- |
70 | 75 |
* |
... | ... |
@@ -98,6 +103,11 @@ typedef enum { |
98 | 103 |
* drops state silently, doesn't use callbacks and expects the |
99 | 104 |
* transaction to complete statelessly. |
100 | 105 |
* |
106 |
+ * TMCB_ON_FAILURE_RO -- called on receipt of a reply or timer; |
|
107 |
+ * it means all branches completed with a failure; the callback |
|
108 |
+ * function MUST not change anything in the transaction (READONLY) |
|
109 |
+ * that's a chance for doing ACC or stuff like this |
|
110 |
+ * |
|
101 | 111 |
* TMCB_ON_FAILURE -- called on receipt of a reply or timer; |
102 | 112 |
* it means all branches completed with a failure; that's |
103 | 113 |
* a chance for example to add new transaction branches |
... | ... |
@@ -139,36 +149,73 @@ typedef enum { |
139 | 149 |
* TMCB_LOCAL COMPLETED -- final reply for localy initiated |
140 | 150 |
* transaction arrived. Message may be FAKED_REPLY. |
141 | 151 |
* |
142 |
- * TMCB_END - just a bumper |
|
143 |
- |
|
144 |
- see the 'acc' module for an example of callback usage |
|
145 | 152 |
|
146 | 153 |
note that callbacks MUST be installed before forking |
147 |
- (callback lists do not live in shmem and have no access |
|
154 |
+ (callback lists do not live in shmem and have no access |
|
148 | 155 |
protection), i.e., at best from mod_init functions. |
149 | 156 |
|
150 |
- also, note: the callback param is currently not used; |
|
151 |
- if whoever wishes to use a callback parameter, use |
|
152 |
- trans->cbp |
|
157 |
+ the callback's param MUST be in shared memory and will |
|
158 |
+ NOT be freed by TM; you must do it yourself from the |
|
159 |
+ callback function id necessary. |
|
153 | 160 |
*/ |
154 | 161 |
|
155 |
-typedef void (transaction_cb) ( struct cell* t, struct sip_msg* msg, |
|
156 |
- int code, void *param ); |
|
157 | 162 |
|
158 |
-struct tm_callback_s { |
|
159 |
- int id; |
|
160 |
- transaction_cb* callback; |
|
161 |
- struct tm_callback_s* next; |
|
163 |
+/* pack structure with all params passed toa callback function */ |
|
164 |
+struct tmcb_params { |
|
165 |
+ struct sip_msg* req; |
|
166 |
+ struct sip_msg* rpl; |
|
167 |
+ int code; |
|
162 | 168 |
void *param; |
163 | 169 |
}; |
164 | 170 |
|
171 |
+/* callback function prototype */ |
|
172 |
+typedef void (transaction_cb) (struct cell* t, int type, struct tmcb_params*); |
|
173 |
+/* register callback function prototype */ |
|
174 |
+typedef int (*register_tmcb_f)(struct sip_msg* p_msg, int cb_types, |
|
175 |
+ transaction_cb f, void *param); |
|
176 |
+ |
|
177 |
+ |
|
178 |
+struct tm_callback { |
|
179 |
+ int id; /* id of this callback - useless */ |
|
180 |
+ int types; /* types of events that trigger the callback*/ |
|
181 |
+ transaction_cb* callback; /* callback function */ |
|
182 |
+ void *param; /* param to be passed to callback function */ |
|
183 |
+ struct tm_callback* next; |
|
184 |
+}; |
|
185 |
+ |
|
186 |
+struct tmcb_head_list { |
|
187 |
+ struct tm_callback *first; |
|
188 |
+ int reg_types; |
|
189 |
+}; |
|
190 |
+ |
|
191 |
+ |
|
192 |
+extern struct tmcb_head_list* req_in_tmcb_hl; |
|
193 |
+ |
|
194 |
+ |
|
195 |
+#define has_tran_tmcbs(_T_, _types_) \ |
|
196 |
+ ( ((_T_)->tmcb_hl.reg_types)|(_types_) ) |
|
197 |
+#define has_reqin_tmcbs() \ |
|
198 |
+ ( req_in_tmcb_hl->first!=0 ) |
|
199 |
+ |
|
200 |
+ |
|
201 |
+int init_tmcb_lists(); |
|
202 |
+ |
|
203 |
+void destroy_tmcb_lists(); |
|
204 |
+ |
|
205 |
+ |
|
206 |
+/* register a callback for several types of events */ |
|
207 |
+int register_tmcb( struct sip_msg* p_msg, int types, transaction_cb f, |
|
208 |
+ void *param ); |
|
165 | 209 |
|
166 |
-extern struct tm_callback_s* callback_array[ TMCB_END ]; |
|
210 |
+/* inserts a callback into the a callback list */ |
|
211 |
+int insert_tmcb(struct tmcb_head_list *cb_list, int types, |
|
212 |
+ transaction_cb f, void *param ); |
|
167 | 213 |
|
168 |
-typedef int (*register_tmcb_f)(tmcb_type cbt, transaction_cb f, void *param); |
|
214 |
+/* run all transaction callbacks for an event type */ |
|
215 |
+void run_trans_callbacks( int type , struct cell *trans, |
|
216 |
+ struct sip_msg *req, struct sip_msg *rpl, int code ); |
|
169 | 217 |
|
170 |
-int register_tmcb( tmcb_type cbt, transaction_cb f, void *param ); |
|
171 |
-void callback_event( tmcb_type cbt, struct cell *trans, |
|
172 |
- struct sip_msg *msg, int code ); |
|
218 |
+/* run all REQUEST_IN callbacks */ |
|
219 |
+void run_reqin_callbacks( struct cell *trans, struct sip_msg *req, int code ); |
|
173 | 220 |
|
174 | 221 |
#endif |
... | ... |
@@ -72,6 +72,8 @@ |
72 | 72 |
* 2003-04-30 t_newtran clean up (jiri) |
73 | 73 |
* 2003-08-21 request lookups fixed to skip UAC transactions, |
74 | 74 |
* thanks Ed (jiri) |
75 |
+ * 2003-12-04 global TM callbacks switched to per transaction callbacks |
|
76 |
+ * (bogdan) |
|
75 | 77 |
*/ |
76 | 78 |
|
77 | 79 |
|
... | ... |
@@ -784,17 +786,19 @@ int t_reply_matching( struct sip_msg *p_msg , int *p_branch ) |
784 | 786 |
* retransmissions of multiple 200/INV or ACK/200s |
785 | 787 |
*/ |
786 | 788 |
if (p_cell->is_invite && p_msg->REPLY_STATUS>=200 |
787 |
- && p_msg->REPLY_STATUS<300 |
|
788 |
- && ( (!p_cell->local && |
|
789 |
- (callback_array[TMCB_RESPONSE_OUT]|| |
|
790 |
- callback_array[TMCB_E2EACK_IN])) |
|
791 |
- || (p_cell->local && callback_array[TMCB_LOCAL_COMPLETED]) )) { |
|
789 |
+ && p_msg->REPLY_STATUS<300 |
|
790 |
+ && ( (!p_cell->local && |
|
791 |
+ has_tran_tmcbs(p_cell,TMCB_RESPONSE_OUT|TMCB_E2EACK_IN) ) |
|
792 |
+ || (p_cell->local && has_tran_tmcbs(p_cell,TMCB_LOCAL_COMPLETED)) |
|
793 |
+ )) { |
|
792 | 794 |
if (parse_headers(p_msg, HDR_TO, 0)==-1) { |
793 | 795 |
LOG(L_ERR, "ERROR: t_reply_matching: to parsing failed\n"); |
794 | 796 |
} |
795 | 797 |
} |
796 |
- if (!p_cell->local) |
|
797 |
- callback_event(TMCB_RESPONSE_IN, T, p_msg, p_msg->REPLY_STATUS); |
|
798 |
+ if (!p_cell->local) { |
|
799 |
+ run_trans_callbacks( TMCB_RESPONSE_IN, T, T->uas.request, p_msg, |
|
800 |
+ p_msg->REPLY_STATUS); |
|
801 |
+ } |
|
798 | 802 |
return 1; |
799 | 803 |
} /* for cycle */ |
800 | 804 |
|
... | ... |
@@ -1051,21 +1055,20 @@ int t_newtran( struct sip_msg* p_msg ) |
1051 | 1055 |
|
1052 | 1056 |
if (lret==-2) { /* was it an e2e ACK ? if so, trigger a callback */ |
1053 | 1057 |
/* no callbacks? complete quickly */ |
1054 |
- if (!callback_array[TMCB_E2EACK_IN]) { |
|
1058 |
+ if ( !has_tran_tmcbs(t_ack,TMCB_E2EACK_IN) ) { |
|
1055 | 1059 |
UNLOCK_HASH(p_msg->hash_index); |
1056 | 1060 |
return 1; |
1057 | 1061 |
} |
1058 | 1062 |
REF_UNSAFE(t_ack); |
1059 | 1063 |
UNLOCK_HASH(p_msg->hash_index); |
1060 | 1064 |
/* we don't call from within REPLY_LOCK -- that introduces |
1061 |
- a race condition; however, it is so unlikely and the |
|
1062 |
- impact is so small (callback called multiple times of |
|
1063 |
- multiple ACK/200s received in parallel), that we do not |
|
1064 |
- better waste time in locks |
|
1065 |
- */ |
|
1065 |
+ * a race condition; however, it is so unlikely and the |
|
1066 |
+ * impact is so small (callback called multiple times of |
|
1067 |
+ * multiple ACK/200s received in parallel), that we do not |
|
1068 |
+ * better waste time in locks */ |
|
1066 | 1069 |
if (unmatched_totag(t_ack, p_msg)) { |
1067 |
- callback_event( TMCB_E2EACK_IN, t_ack, p_msg, |
|
1068 |
- p_msg->REQ_METHOD ); |
|
1070 |
+ run_trans_callbacks( TMCB_E2EACK_IN , t_ack, p_msg, 0, |
|
1071 |
+ -p_msg->REQ_METHOD ); |
|
1069 | 1072 |
} |
1070 | 1073 |
UNREF(t_ack); |
1071 | 1074 |
return 1; |
... | ... |
@@ -52,6 +52,8 @@ |
52 | 52 |
* 2003-11-05 flag context updated from failure/reply handlers back |
53 | 53 |
* to transaction context (jiri) |
54 | 54 |
* 2003-11-11: build_lump_rpl() removed, add_lump_rpl() has flags (bogdan) |
55 |
+ * 2003-12-04 global TM callbacks switched to per transaction callbacks |
|
56 |
+ * (bogdan) |
|
55 | 57 |
*/ |
56 | 58 |
|
57 | 59 |
|
... | ... |
@@ -102,6 +104,7 @@ static int goto_on_negative=0; |
102 | 104 |
static int goto_on_reply=0; |
103 | 105 |
|
104 | 106 |
|
107 |
+ |
|
105 | 108 |
/* we store the reply_route # in private memory which is |
106 | 109 |
then processed during t_relay; we cannot set this value |
107 | 110 |
before t_relay creates transaction context or after |
... | ... |
@@ -309,11 +312,13 @@ static int _reply_light( struct cell *trans, char* buf, unsigned int len, |
309 | 312 |
if (code>=200) { |
310 | 313 |
if (trans->local) { |
311 | 314 |
DBG("DEBUG: local transaction completed from _reply\n"); |
312 |
- callback_event( TMCB_LOCAL_COMPLETED, trans, FAKED_REPLY, code ); |
|
313 |
- if (trans->completion_cb) |
|
314 |
- trans->completion_cb( trans, FAKED_REPLY, code, trans->cbp); |
|
315 |
+ if ( has_tran_tmcbs(trans, TMCB_LOCAL_COMPLETED) ) |
|
316 |
+ run_trans_callbacks( TMCB_LOCAL_COMPLETED, trans, |
|
317 |
+ 0, FAKED_REPLY, code); |
|
315 | 318 |
} else { |
316 |
- callback_event( TMCB_RESPONSE_OUT, trans, FAKED_REPLY, code ); |
|
319 |
+ if ( has_tran_tmcbs(trans, TMCB_RESPONSE_OUT) ) |
|
320 |
+ run_trans_callbacks( TMCB_RESPONSE_OUT, trans, |
|
321 |
+ trans->uas.request, FAKED_REPLY, code); |
|
317 | 322 |
} |
318 | 323 |
|
319 | 324 |
cleanup_uac_timers( trans ); |
... | ... |
@@ -380,45 +385,15 @@ static int _reply( struct cell *trans, struct sip_msg* p_msg, |
380 | 385 |
} |
381 | 386 |
|
382 | 387 |
|
383 |
-/* create a temporary faked message environment in which a conserved |
|
384 |
- * t->uas.request in shmem is partially duplicated to pkgmem |
|
385 |
- * to allow pkg-based actions to use it; |
|
386 |
- * |
|
387 |
- * if restore parameter is set, the environment is restored to the |
|
388 |
- * original setting and return value is unsignificant (always 0); |
|
389 |
- * otherwise a faked environment if created; if that fails, |
|
390 |
- * false is returned |
|
391 |
- */ |
|
392 |
-static int faked_env(struct sip_msg *fake, |
|
393 |
- struct cell *_t, |
|
394 |
- struct sip_msg *shmem_msg, |
|
395 |
- int _restore ) |
|
388 |
+/*if msg is set -> it will fake the env. vars conforming with the msg; if NULL |
|
389 |
+ * the env. will be restore to original */ |
|
390 |
+static inline void faked_env( struct cell *t,struct sip_msg *msg) |
|
396 | 391 |
{ |
397 | 392 |
static enum route_mode backup_mode; |
398 | 393 |
static struct cell *backup_t; |
399 | 394 |
static unsigned int backup_msgid; |
400 | 395 |
|
401 |
- if (_restore) goto restore; |
|
402 |
- |
|
403 |
- /* |
|
404 |
- on_negative_reply faked msg now copied from shmem msg (as opposed |
|
405 |
- to zero-ing) -- more "read-only" actions (exec in particular) will |
|
406 |
- work from reply_route as they will see msg->from, etc.; caution, |
|
407 |
- rw actions may append some pkg stuff to msg, which will possibly be |
|
408 |
- never released (shmem is released in a single block) |
|
409 |
- */ |
|
410 |
- memcpy( fake, shmem_msg, sizeof(struct sip_msg)); |
|
411 |
- |
|
412 |
- /* if we set msg_id to something different from current's message |
|
413 |
- id, the first t_fork will properly clean new branch URIs |
|
414 |
- */ |
|
415 |
- fake->id=shmem_msg->id-1; |
|
416 |
- /* set items, which will be duped to pkg_mem, to zero, so that |
|
417 |
- * "restore" called on error does not free the original items */ |
|
418 |
- fake->add_rm=0; |
|
419 |
- fake->body_lumps=0; |
|
420 |
- fake->new_uri.s=0; fake->new_uri.len=0; |
|
421 |
- |
|
396 |
+ if (msg) { |
|
422 | 397 |
/* remember we are back in request processing, but process |
423 | 398 |
* a shmem-ed replica of the request; advertise it in rmode; |
424 | 399 |
* for example t_reply needs to know that |
... | ... |
@@ -435,90 +410,109 @@ static int faked_env(struct sip_msg *fake, |
435 | 410 |
backup_t=get_t(); |
436 | 411 |
backup_msgid=global_msg_id; |
437 | 412 |
/* fake transaction and message id */ |
438 |
- global_msg_id=fake->id; |
|
439 |
- set_t(_t); |
|
413 |
+ global_msg_id=msg->id; |
|
414 |
+ set_t(t); |
|
415 |
+ } else { |
|
416 |
+ /* restore original environment */ |
|
417 |
+ set_t(backup_t); |
|
418 |
+ global_msg_id=backup_msgid; |
|
419 |
+ rmode=backup_mode; |
|
420 |
+ } |
|
421 |
+} |
|
422 |
+ |
|
423 |
+ |
|
424 |
+ |
|
425 |
+/* return 1 if a failure_route processes */ |
|
426 |
+static inline int run_failure_handlers(struct cell *t, struct sip_msg *rpl, |
|
427 |
+ int code) |
|
428 |
+{ |
|
429 |
+ static struct sip_msg fake_req; |
|
430 |
+ struct sip_msg *shmem_msg = t->uas.request; |
|
431 |
+ |
|
432 |
+ /* failure_route for a local UAC? */ |
|
433 |
+ if (!shmem_msg) { |
|
434 |
+ LOG(L_WARN, "Warning: run_failure_handlers: no UAC support\n"); |
|
435 |
+ return 0; |
|
436 |
+ } |
|
437 |
+ |
|
438 |
+ /* don't start faking anything if we don't have to */ |
|
439 |
+ if ( !has_tran_tmcbs( t, TMCB_ON_FAILURE) && !t->on_negative ) { |
|
440 |
+ return 1; |
|
441 |
+ } |
|
440 | 442 |
|
441 |
- /* environment is set up now, try to fake the message */ |
|
443 |
+ /* on_negative_reply faked msg now copied from shmem msg (as opposed |
|
444 |
+ * to zero-ing) -- more "read-only" actions (exec in particular) will |
|
445 |
+ * work from reply_route as they will see msg->from, etc.; caution, |
|
446 |
+ * rw actions may append some pkg stuff to msg, which will possibly be |
|
447 |
+ * never released (shmem is released in a single block) */ |
|
448 |
+ memcpy( &fake_req, shmem_msg, sizeof(struct sip_msg)); |
|
449 |
+ |
|
450 |
+ /* if we set msg_id to something different from current's message |
|
451 |
+ * id, the first t_fork will properly clean new branch URIs */ |
|
452 |
+ fake_req.id=shmem_msg->id-1; |
|
442 | 453 |
|
443 | 454 |
/* new_uri can change -- make a private copy */ |
444 | 455 |
if (shmem_msg->new_uri.s!=0 && shmem_msg->new_uri.len!=0) { |
445 |
- fake->new_uri.s=pkg_malloc(shmem_msg->new_uri.len+1); |
|
446 |
- if (!fake->new_uri.s) { |
|
447 |
- LOG(L_ERR, "ERROR: faked_env: no uri/pkg mem\n"); |
|
448 |
- goto restore; |
|
456 |
+ fake_req.new_uri.s=pkg_malloc(shmem_msg->new_uri.len+1); |
|
457 |
+ if (!fake_req.new_uri.s) { |
|
458 |
+ LOG(L_ERR, "ERROR: run_failure_handlers: no uri/pkg mem\n"); |
|
459 |
+ return 0; |
|
449 | 460 |
} |
450 |
- fake->new_uri.len=shmem_msg->new_uri.len; |
|
451 |
- memcpy( fake->new_uri.s, shmem_msg->new_uri.s, |
|
452 |
- fake->new_uri.len); |
|
453 |
- fake->new_uri.s[fake->new_uri.len]=0; |
|
454 |
- } |
|
461 |
+ fake_req.new_uri.len=shmem_msg->new_uri.len; |
|
462 |
+ memcpy( fake_req.new_uri.s, shmem_msg->new_uri.s, |
|
463 |
+ fake_req.new_uri.len); |
|
464 |
+ fake_req.new_uri.s[fake_req.new_uri.len]=0; |
|
465 |
+ } |
|
455 | 466 |
|
456 | 467 |
/* create a duplicated lump list to which actions can add |
457 |
- * new pkg items |
|
458 |
- */ |
|
468 |
+ * new pkg items */ |
|
459 | 469 |
if (shmem_msg->add_rm) { |
460 |
- fake->add_rm=dup_lump_list(shmem_msg->add_rm); |
|
461 |
- if (!fake->add_rm) { /* non_emty->empty ... failure */ |
|
462 |
- LOG(L_ERR, "ERROR: on_negative_reply: lump dup failed\n"); |
|
463 |
- goto restore; |
|
470 |
+ fake_req.add_rm=dup_lump_list(shmem_msg->add_rm); |
|
471 |
+ if (!fake_req.add_rm) { /* non_emty->empty ... failure */ |
|
472 |
+ LOG(L_ERR, "ERROR: run_failure_handlers: lump dup failed\n"); |
|
473 |
+ if (fake_req.new_uri.s) pkg_free(fake_req.new_uri.s); |
|
474 |
+ return 0; |
|
464 | 475 |
} |
465 | 476 |
} |
466 | 477 |
|
478 |
+ /* same for the body lumps */ |
|
467 | 479 |
if (shmem_msg->body_lumps) { |
468 |
- fake->body_lumps=dup_lump_list(shmem_msg->body_lumps); |
|
469 |
- if (!fake->body_lumps) { /* non_empty->empty ... failure */ |
|
470 |
- LOG(L_ERR, "ERROR: on_negative_reply: lump dup failed\n"); |
|
471 |
- goto restore; |
|
480 |
+ fake_req.body_lumps=dup_lump_list(shmem_msg->body_lumps); |
|
481 |
+ if (!fake_req.body_lumps) { /* non_empty->empty ... failure */ |
|
482 |
+ LOG(L_ERR, "ERROR: on_negative_handlers: lump dup failed\n"); |
|
483 |
+ free_duped_lump_list(fake_req.add_rm); |
|
484 |
+ if (fake_req.new_uri.s) pkg_free(fake_req.new_uri.s); |
|
485 |
+ return 0; |
|
472 | 486 |
} |
473 | 487 |
} |
474 |
- |
|
475 |
- /* success */ |
|
476 |
- return 1; |
|
477 |
- |
|
478 |
-restore: |
|
479 |
- /* restore original environment and destroy faked message */ |
|
480 |
- free_duped_lump_list(fake->add_rm); |
|
481 |
- free_duped_lump_list(fake->body_lumps); |
|
482 |
- if (fake->new_uri.s) pkg_free(fake->new_uri.s); |
|
483 |
- set_t(backup_t); |
|
484 |
- global_msg_id=backup_msgid; |
|
485 |
- rmode=backup_mode; |
|
486 |
- /* if failure handler changed flag, update transaction context */ |
|
487 |
- shmem_msg->flags=fake->flags; |
|
488 |
- return 0; |
|
489 |
-} |
|
490 | 488 |
|
491 |
-/* return 1 if a failure_route processes */ |
|
492 |
-int failure_route(struct cell *t) |
|
493 |
-{ |
|
494 |
- struct sip_msg faked_msg; |
|
495 |
- struct sip_msg *orig_request; |
|
496 |
- |
|
497 |
- /* don't do anything if we don't have to */ |
|
498 |
- if (!t->on_negative) return 0; |
|
499 |
- orig_request=t->uas.request; |
|
500 |
- /* failure_route for a local UAC? */ |
|
501 |
- if (!orig_request) { |
|
502 |
- LOG(L_WARN, "Warning: failure_route: no UAC support\n"); |
|
503 |
- return 0; |
|
504 |
- } |
|
489 |
+ /* fake also the env. conforming to the fake msg */ |
|
490 |
+ faked_env( t, &fake_req); |
|
491 |
+ /* DONE with faking ;-) -> run the failure handlers */ |
|
505 | 492 |
|
506 |
- /* if fake message creation failes, return error too */ |
|
507 |
- if (!faked_env(&faked_msg, t, orig_request, 0 /* create fake */ )) { |
|
508 |
- LOG(L_ERR, "ERROR: on_negative_reply: faked_env failed\n"); |
|
509 |
- return 0; |
|
493 |
+ if ( has_tran_tmcbs( t, TMCB_ON_FAILURE) ) { |
|
494 |
+ run_trans_callbacks( TMCB_ON_FAILURE, t, &fake_req, rpl, code); |
|
510 | 495 |
} |
511 |
- |
|
496 |
+ if (t->on_negative) { |
|
512 | 497 |
/* avoid recursion -- if failure_route forwards, and does not |
513 | 498 |
* set next failure route, failure_route will not be rentered |
514 | 499 |
* on failure */ |
515 | 500 |
t_on_negative(0); |
516 | 501 |
/* run a reply_route action if some was marked */ |
517 |
- if (run_actions(failure_rlist[t->on_negative], &faked_msg)<0) |
|
518 |
- LOG(L_ERR, "ERROR: on_negative_reply: " |
|
519 |
- "Error in do_action\n"); |
|
520 |
- /* restore original environment */ |
|
521 |
- faked_env(&faked_msg, 0, orig_request, 1 ); |
|
502 |
+ if (run_actions(failure_rlist[t->on_negative], &fake_req)<0) |
|
503 |
+ LOG(L_ERR, "ERROR: run_failure_handlers: Error in do_action\n"); |
|
504 |
+ } |
|
505 |
+ |
|
506 |
+ /* restore original environment and free the fake msg */ |
|
507 |
+ faked_env( t, 0); |
|
508 |
+ free_duped_lump_list(fake_req.add_rm); |
|
509 |
+ free_duped_lump_list(fake_req.body_lumps); |
|
510 |
+ fake_req.add_rm = fake_req.body_lumps = 0; |
|
511 |
+ if (fake_req.new_uri.s) { |
|
512 |
+ pkg_free(fake_req.new_uri.s); |
|
513 |
+ fake_req.new_uri.s = 0; |
|
514 |
+ } |
|
515 |
+ |
|
522 | 516 |
return 1; |
523 | 517 |
} |
524 | 518 |
|
... | ... |
@@ -572,7 +566,6 @@ static enum rps t_should_relay_response( struct cell *Trans , int new_code, |
572 | 566 |
int branch , int *should_store, int *should_relay, |
573 | 567 |
branch_bm_t *cancel_bitmap, struct sip_msg *reply ) |
574 | 568 |
{ |
575 |
- |
|
576 | 569 |
int branch_cnt; |
577 | 570 |
int picked_branch; |
578 | 571 |
int picked_code; |
... | ... |
@@ -630,15 +623,16 @@ static enum rps t_should_relay_response( struct cell *Trans , int new_code, |
630 | 623 |
|
631 | 624 |
/* no more pending branches -- try if that changes after |
632 | 625 |
a callback; save banch count to be able to determine |
633 |
- later if new branches were initiated |
|
634 |
- */ |
|
626 |
+ later if new branches were initiated */ |
|
635 | 627 |
branch_cnt=Trans->nr_of_outgoings; |
636 |
- callback_event( TMCB_ON_FAILURE, Trans, |
|
637 |
- picked_branch==branch?reply:Trans->uac[picked_branch].reply, |
|
638 |
- picked_code); |
|
639 |
- /* here, we create a faked environment, from which we |
|
640 |
- * return to request processing, if marked to do so */ |
|
641 |
- failure_route(Trans); |
|
628 |
+ |
|
629 |
+ /* run ON_FAILURE handlers ( route and callbacks) */ |
|
630 |
+ if ( has_tran_tmcbs( Trans, TMCB_ON_FAILURE_RO|TMCB_ON_FAILURE) |
|
631 |
+ || Trans->on_negative ) { |
|
632 |
+ run_failure_handlers( Trans, |
|
633 |
+ picked_branch==branch?reply:Trans->uac[picked_branch].reply, |
|
634 |
+ picked_code); |
|
635 |
+ } |
|
642 | 636 |
|
643 | 637 |
/* look if the callback perhaps replied transaction; it also |
644 | 638 |
covers the case in which a transaction is replied localy |
... | ... |
@@ -849,7 +843,7 @@ enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch, |
849 | 843 |
|
850 | 844 |
|
851 | 845 |
/* remember, what was sent upstream to know whether we are |
852 |
- forwarding a first final reply or not */ |
|
846 |
+ * forwarding a first final reply or not */ |
|
853 | 847 |
|
854 | 848 |
/* *** store and relay message as needed *** */ |
855 | 849 |
reply_status = t_should_relay_response(t, msg_status, branch, |
... | ... |
@@ -866,19 +860,19 @@ enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch, |
866 | 860 |
|
867 | 861 |
uas_rb = & t->uas.response; |
868 | 862 |
if (relay >= 0 ) { |
869 |
- |
|
870 | 863 |
/* initialize sockets for outbound reply */ |
871 | 864 |
uas_rb->activ_type=msg_status; |
872 | 865 |
/* only messages known to be relayed immediately will be |
873 |
- be called on; we do not evoke this callback on messages |
|
874 |
- stored in shmem -- they are fixed and one cannot change them |
|
875 |
- anyway |
|
876 |
- */ |
|
877 |
- if (msg_status<300 && branch==relay) { |
|
878 |
- callback_event( TMCB_RESPONSE_FWDED, t, p_msg, msg_status ); |
|
866 |
+ * be called on; we do not evoke this callback on messages |
|
867 |
+ * stored in shmem -- they are fixed and one cannot change them |
|
868 |
+ * anyway */ |
|
869 |
+ if (msg_status<300 && branch==relay |
|
870 |
+ && has_tran_tmcbs(t,TMCB_RESPONSE_FWDED) ) { |
|
871 |
+ run_trans_callbacks( TMCB_RESPONSE_FWDED, t, t->uas.request, |
|
872 |
+ p_msg, msg_status ); |
|
879 | 873 |
} |
880 | 874 |
/* try bulding the outbound reply from either the current |
881 |
- or a stored message */ |
|
875 |
+ * or a stored message */ |
|
882 | 876 |
relayed_msg = branch==relay ? p_msg : t->uac[relay].reply; |
883 | 877 |
if (relayed_msg==FAKED_REPLY) { |
884 | 878 |
tm_stats->replied_localy++; |
... | ... |
@@ -942,9 +936,8 @@ enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch, |
942 | 936 |
t->relaied_reply_branch = relay; |
943 | 937 |
|
944 | 938 |
if (t->is_invite && relayed_msg!=FAKED_REPLY |
945 |
- && relayed_code>=200 && relayed_code < 300 |
|
946 |
- && (callback_array[TMCB_RESPONSE_OUT] || |
|
947 |
- callback_array[TMCB_E2EACK_IN])) { |
|
939 |
+ && relayed_code>=200 && relayed_code < 300 |
|
940 |
+ && has_tran_tmcbs( t, TMCB_RESPONSE_OUT|TMCB_E2EACK_IN) ) { |
|
948 | 941 |
totag_retr=update_totag_set(t, relayed_msg); |
949 | 942 |
} |
950 | 943 |
}; /* if relay ... */ |
... | ... |
@@ -956,8 +949,10 @@ enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch, |
956 | 949 |
SEND_PR_BUFFER( uas_rb, buf, res_len ); |
957 | 950 |
DBG("DEBUG: reply relayed. buf=%p: %.9s..., shmem=%p: %.9s\n", |
958 | 951 |
buf, buf, uas_rb->buffer, uas_rb->buffer ); |
959 |
- if (!totag_retr) |
|
960 |
- callback_event( TMCB_RESPONSE_OUT, t, relayed_msg, relayed_code ); |
|
952 |
+ if (!totag_retr && has_tran_tmcbs(t, TMCB_RESPONSE_OUT) ) { |
|
953 |
+ run_trans_callbacks( TMCB_RESPONSE_OUT, t, t->uas.request, |
|
954 |
+ relayed_msg, relayed_code); |
|
955 |
+ } |
|
961 | 956 |
pkg_free( buf ); |
962 | 957 |
} |
963 | 958 |
|
... | ... |
@@ -1026,22 +1021,19 @@ enum rps local_reply( struct cell *t, struct sip_msg *p_msg, int branch, |
1026 | 1021 |
} |
1027 | 1022 |
t->uas.status = winning_code; |
1028 | 1023 |
update_reply_stats( winning_code ); |
1029 |
- if (t->is_invite && winning_msg!=FAKED_REPLY |
|
1030 |
- && winning_code>=200 && winning_code <300 |
|
1031 |
- && (callback_array[TMCB_RESPONSE_OUT] || |
|
1032 |
- callback_array[TMCB_E2EACK_IN])) { |
|
1024 |
+ if (t->is_invite && winning_msg!=FAKED_REPLY |
|
1025 |
+ && winning_code>=200 && winning_code <300 |
|
1026 |
+ && has_tran_tmcbs(t,TMCB_RESPONSE_OUT|TMCB_E2EACK_IN) ) { |
|
1033 | 1027 |
totag_retr=update_totag_set(t, winning_msg); |
1034 | 1028 |
} |
1035 |
- |
|
1036 | 1029 |
} |
1037 | 1030 |
UNLOCK_REPLIES(t); |
1038 | 1031 |
if (local_winner>=0 && winning_code>=200 ) { |
1039 | 1032 |
DBG("DEBUG: local transaction completed\n"); |
1040 | 1033 |
if (!totag_retr) { |
1041 |
- callback_event( TMCB_LOCAL_COMPLETED, t, winning_msg, |
|
1042 |
- winning_code ); |
|
1043 |
- if (t->completion_cb) t->completion_cb( t, winning_msg, |
|
1044 |
- winning_code, t->cbp); |
|
1034 |
+ if ( has_tran_tmcbs(t,TMCB_LOCAL_COMPLETED) ) |
|
1035 |
+ run_trans_callbacks( TMCB_LOCAL_COMPLETED, t, 0, |
|
1036 |
+ winning_msg, winning_code ); |
|
1045 | 1037 |
} |
1046 | 1038 |
} |
1047 | 1039 |
return reply_status; |
... | ... |
@@ -452,12 +452,12 @@ static int mod_init(void) |
452 | 452 |
return -1; |
453 | 453 |
} |
454 | 454 |
|
455 |
+ /* building the hash table*/ |
|
455 | 456 |
if (!init_hash_table()) { |
456 | 457 |
LOG(L_ERR, "ERROR: mod_init: initializing hash_table failed\n"); |
457 | 458 |
return -1; |
458 | 459 |
} |
459 | 460 |
|
460 |
- |
|
461 | 461 |
/* init static hidden values */ |
462 | 462 |
init_t(); |
463 | 463 |
|
... | ... |
@@ -480,20 +480,24 @@ static int mod_init(void) |
480 | 480 |
return -1; |
481 | 481 |
} |
482 | 482 |
|
483 |
- /* building the hash table*/ |
|
484 |
- |
|
485 | 483 |
if (uac_init()==-1) { |
486 | 484 |
LOG(L_ERR, "ERROR: mod_init: uac_init failed\n"); |
487 | 485 |
return -1; |
488 | 486 |
} |
487 |
+ |
|
488 |
+ if (init_tmcb_lists()!=1) { |
|
489 |
+ LOG(L_CRIT, "ERROR:tm:mod_init: failed to init tmcb lists\n"); |
|
490 |
+ return -1; |
|
491 |
+ } |
|
492 |
+ |
|
493 |
+ tm_init_tags(); |
|
494 |
+ |
|
489 | 495 |
/* register post-script clean-up function */ |
490 | 496 |
register_script_cb( w_t_unref, POST_SCRIPT_CB, |
491 | 497 |
0 /* empty param */ ); |
492 | 498 |
register_script_cb( script_init, PRE_SCRIPT_CB , |
493 | 499 |
0 /* empty param */ ); |
494 | 500 |
|
495 |
- tm_init_tags(); |
|
496 |
- |
|
497 | 501 |
return 0; |
498 | 502 |
} |
499 | 503 |
|
... | ... |
@@ -45,7 +45,6 @@ int load_tm( struct tm_binds *tmb) |
45 | 45 |
LOG(L_ERR, LOAD_ERROR "'register_tmcb' not found\n"); |
46 | 46 |
return -1; |
47 | 47 |
} |
48 |
- |
|
49 | 48 |
if (!( tmb->t_relay_to_tcp=find_export(T_RELAY_TO_TCP, 2, 0)) ) { |
50 | 49 |
LOG(L_ERR, LOAD_ERROR "'t_relay_to_tcp' not found\n"); |
51 | 50 |
return -1; |
... | ... |
@@ -56,6 +56,7 @@ |
56 | 56 |
#define T_RELAY "t_relay" |
57 | 57 |
#define T_REPLY "t_reply" |
58 | 58 |
#define T_REPLY_WB "t_reply_with_body" |
59 |
+#define T_REPLY_UNSAFE "t_reply_unsafe" |
|
59 | 60 |
#define T_ADDBLIND "t_add_blind" |
60 | 61 |
#define T_REPLY_UNSAFE "t_reply_unsafe" |
61 | 62 |
#define T_FORWARD_NONACK "t_forward_nonack" |
... | ... |
@@ -68,35 +69,33 @@ |
68 | 69 |
#define T_IS_LOCAL "t_is_local" |
69 | 70 |
#define T_REQUEST_WITHIN "request_within" |
70 | 71 |
#define T_REQUEST_OUTSIDE "request_outside" |
71 |
-#define T_GETT "t_gett" |
|
72 |
+#define T_GETT "t_gett" |
|
72 | 73 |
|
73 | 74 |
|
74 | 75 |
|
75 | 76 |
struct tm_binds { |
76 |
- register_tmcb_f register_tmcb; |
|
77 |
- cmd_function t_relay_to_udp; |
|
78 |
- cmd_function t_relay_to_tcp; |
|
79 |
- cmd_function t_relay; |
|
80 |
- treply_f t_reply; |
|
81 |
- treply_wb_f t_reply_with_body; |
|
82 |
- tislocal_f t_is_local; |
|
83 |
- tget_ti_f t_get_trans_ident; |
|
84 |
- tlookup_ident_f t_lookup_ident; |
|
85 |
- taddblind_f t_addblind; |
|
86 |
- treply_f t_reply_unsafe; |
|
87 |
- tfwd_f t_forward_nonack; |
|
88 |
- reqwith_t t_request_within; |
|
89 |
- reqout_t t_request_outside; |
|
90 |
- req_t t_request; |
|
91 |
- |
|
77 |
+ register_tmcb_f register_tmcb; |
|
78 |
+ cmd_function t_relay_to_udp; |
|
79 |
+ cmd_function t_relay_to_tcp; |
|
80 |
+ cmd_function t_relay; |
|
81 |
+ treply_f t_reply; |
|
82 |
+ treply_wb_f t_reply_with_body; |
|
83 |
+ tislocal_f t_is_local; |
|
84 |
+ tget_ti_f t_get_trans_ident; |
|
85 |
+ tlookup_ident_f t_lookup_ident; |
|
86 |
+ taddblind_f t_addblind; |
|
87 |
+ treply_f t_reply_unsafe; |
|
88 |
+ tfwd_f t_forward_nonack; |
|
89 |
+ reqwith_t t_request_within; |
|
90 |
+ reqout_t t_request_outside; |
|
91 |
+ req_t t_request; |
|
92 | 92 |
new_dlg_uac_f new_dlg_uac; |
93 | 93 |
dlg_response_uac_f dlg_response_uac; |
94 | 94 |
new_dlg_uas_f new_dlg_uas; |
95 | 95 |
dlg_request_uas_f dlg_request_uas; |
96 | 96 |
free_dlg_f free_dlg; |
97 | 97 |
print_dlg_f print_dlg; |
98 |
- |
|
99 |
- tgett_f t_gett; |
|
98 |
+ tgett_f t_gett; |
|
100 | 99 |
}; |
101 | 100 |
|
102 | 101 |
|
... | ... |
@@ -45,6 +45,8 @@ |
45 | 45 |
* 2003-07-08 appropriate log messages in check_params(...), |
46 | 46 |
* call calculate_hooks if next_hop==NULL in t_uac (dcm) |
47 | 47 |
* 2003-10-24 updated to the new socket_info lists (andrei) |
48 |
+ * 2003-12-03 completion filed removed from transaction and uac callbacks |
|
49 |
+ * merged in transaction callbacks as LOCAL_COMPLETED (bogdan) |
|
48 | 50 |
*/ |
49 | 51 |
|
50 | 52 |
#include <string.h> |
... | ... |
@@ -148,7 +150,8 @@ static inline int check_params(str* method, str* to, str* from, dlg_t** dialog) |
148 | 150 |
/* |
149 | 151 |
* Send a request using data from the dialog structure |
150 | 152 |
*/ |
151 |
-int t_uac(str* method, str* headers, str* body, dlg_t* dialog, transaction_cb cb, void* cbp) |
|
153 |
+int t_uac(str* method, str* headers, str* body, dlg_t* dialog, |
|
154 |
+ transaction_cb cb, void* cbp) |
|
152 | 155 |
{ |
153 | 156 |
struct socket_info* send_sock; |
154 | 157 |
union sockaddr_union to_su; |
... | ... |
@@ -180,13 +183,15 @@ int t_uac(str* method, str* headers, str* body, dlg_t* dialog, transaction_cb cb |
180 | 183 |
goto error2; |
181 | 184 |
} |
182 | 185 |
|
183 |
- new_cell->completion_cb = cb; |
|
184 |
- new_cell->cbp = cbp; |
|
185 |
- |
|
186 |
- /* cbp is installed -- tell error handling bellow not to free it */ |
|
187 |
- cbp = 0; |
|
186 |
+ /* add the callback the the transaction for LOCAL_COMPLETED event */ |
|
187 |
+ if (insert_tmcb( &(new_cell->tmcb_hl), TMCB_LOCAL_COMPLETED, cb, cbp)!=1) { |
|
188 |
+ ret=E_OUT_OF_MEM; |
|
189 |
+ LOG(L_ERR, "t_uac: short of tmcb shmem\n"); |
|
190 |
+ goto error2; |
|
191 |
+ } |
|
188 | 192 |
|
189 |
- new_cell->is_invite = method->len == INVITE_LEN && memcmp(method->s, INVITE, INVITE_LEN) == 0; |
|
193 |
+ new_cell->is_invite = |
|
194 |
+ method->len==INVITE_LEN && memcmp(method->s, INVITE, INVITE_LEN)==0; |
|
190 | 195 |
new_cell->local= 1; |
191 | 196 |
set_kr(REQ_FWDED); |
192 | 197 |
|
... | ... |
@@ -196,12 +201,13 @@ int t_uac(str* method, str* headers, str* body, dlg_t* dialog, transaction_cb cb |
196 | 201 |
request->dst.proto = send_sock->proto; |
197 | 202 |
request->dst.proto_reserved1 = 0; |
198 | 203 |
|
199 |
- /* need to put in table to calculate label which is needed for printing */ |
|
204 |
+ /* need to put in table to calculate label which is needed for printing */ |
|
200 | 205 |
LOCK_HASH(new_cell->hash_index); |
201 | 206 |
insert_into_hash_table_unsafe(new_cell); |
202 | 207 |
UNLOCK_HASH(new_cell->hash_index); |
203 | 208 |
|
204 |
- buf = build_uac_req(method, headers, body, dialog, 0, new_cell, &buf_len, send_sock); |
|
209 |
+ buf = build_uac_req(method, headers, body, dialog, 0, new_cell, |
|
210 |
+ &buf_len, send_sock); |
|
205 | 211 |
if (!buf) { |
206 | 212 |
LOG(L_ERR, "t_uac: Error while building message\n"); |
207 | 213 |
ret=E_OUT_OF_MEM; |
... | ... |
@@ -217,23 +223,19 @@ int t_uac(str* method, str* headers, str* body, dlg_t* dialog, transaction_cb cb |
217 | 223 |
|
218 | 224 |
if (SEND_BUFFER(request) == -1) { |
219 | 225 |
LOG(L_ERR, "t_uac: Attempt to send to '%.*s' failed\n", |
220 |
- dialog->hooks.next_hop->len, |
|
221 |
- dialog->hooks.next_hop->s |
|
222 |
- ); |
|
226 |
+ dialog->hooks.next_hop->len, |
|
227 |
+ dialog->hooks.next_hop->s); |
|
223 | 228 |
} |
224 | 229 |
|
225 | 230 |
start_retr(request); |
226 | 231 |
return 1; |
227 | 232 |
|
228 |
- error1: |
|
233 |
+error1: |
|
229 | 234 |
LOCK_HASH(new_cell->hash_index); |
230 | 235 |
remove_from_hash_table_unsafe(new_cell); |
231 | 236 |
UNLOCK_HASH(new_cell->hash_index); |
232 | 237 |
free_cell(new_cell); |
233 |
- |
|
234 |
- error2: |
|
235 |
- /* if we did not install cbp, release it now */ |
|
236 |
- if (cbp) shm_free(cbp); |
|
238 |
+error2: |
|
237 | 239 |
return ret; |
238 | 240 |
} |
239 | 241 |
|
... | ... |
@@ -1,5 +1,32 @@ |
1 | 1 |
/* |
2 | 2 |
* $Id$ |
3 |
+ * |
|
4 |
+ * Copyright (C) 2001-2003 Fhg Fokus |
|
5 |
+ * |
|
6 |
+ * This file is part of ser, a free SIP server. |
|
7 |
+ * |
|
8 |
+ * ser is free software; you can redistribute it and/or modify |
|
9 |
+ * it under the terms of the GNU General Public License as published by |
|
10 |
+ * the Free Software Foundation; either version 2 of the License, or |
|
11 |
+ * (at your option) any later version |
|
12 |
+ * |
|
13 |
+ * For a license to use the ser software under conditions |
|
14 |
+ * other than those described here, or to purchase support for this |
|
15 |
+ * software, please contact iptel.org by e-mail at the following addresses: |
|
16 |
+ * info@iptel.org |
|
17 |
+ * |
|
18 |
+ * ser is distributed in the hope that it will be useful, |
|
19 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
20 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
21 |
+ * GNU General Public License for more details. |
|
22 |
+ * |
|
23 |
+ * You should have received a copy of the GNU General Public License |
|
24 |
+ * along with this program; if not, write to the Free Software |
|
25 |
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
26 |
+ * |
|
27 |
+ * History: |
|
28 |
+ * -------- |
|
29 |
+ * 2003-12-03 : fifo_callback() updated for changes in tm callbacks (bogdan) |
|
3 | 30 |
*/ |
4 | 31 |
|
5 | 32 |
#include <string.h> |
... | ... |
@@ -31,8 +58,8 @@ struct cb_data { |
31 | 58 |
|
32 | 59 |
|
33 | 60 |
struct str_list { |
34 |
- str s; |
|
35 |
- struct str_list *next; |
|
61 |
+ str s; |
|
62 |
+ struct str_list *next; |
|
36 | 63 |
}; |
37 | 64 |
|
38 | 65 |
|
... | ... |
@@ -502,8 +529,7 @@ static inline int print_uris(FILE* out, struct sip_msg* reply) |
502 | 529 |
} |
503 | 530 |
|
504 | 531 |
|
505 |
-static void fifo_callback(struct cell *t, struct sip_msg *reply, |
|
506 |
- int code, void *param) |
|
532 |
+static void fifo_callback( struct cell *t, int type, struct tmcb_params *ps ) |
|
507 | 533 |
{ |
508 | 534 |
|
509 | 535 |
char *filename; |
... | ... |
@@ -512,35 +538,39 @@ static void fifo_callback(struct cell *t, struct sip_msg *reply, |
512 | 538 |
|
513 | 539 |
DBG("!!!!! ref_counter: %d\n", t->ref_count); |
514 | 540 |
|
515 |
- DBG("DEBUG: fifo UAC completed with status %d\n", code); |
|
516 |
- if (!t->cbp) { |
|
517 |
- LOG(L_INFO, "INFO: fifo UAC completed with status %d\n", code); |
|
541 |
+ DBG("DEBUG: fifo UAC completed with status %d\n", ps->code); |
|
542 |
+ if (!ps->param) { |
|
543 |
+ LOG(L_INFO, "INFO: fifo UAC completed with status %d\n", ps->code); |
|
518 | 544 |
return; |
519 | 545 |
} |
520 | 546 |
|
521 |
- filename=(char *)(t->cbp); |
|
522 |
- if (reply==FAKED_REPLY) { |
|
523 |
- get_reply_status(&text,reply,code); |
|
547 |
+ filename=(char *)(ps->param); |
|
548 |
+ if (ps->rpl==FAKED_REPLY) { |
|
549 |
+ get_reply_status( &text, ps->rpl, ps->code); |
|
524 | 550 |
if (text.s==0) { |
525 | 551 |
LOG(L_ERR, "ERROR: fifo_callback: get_reply_status failed\n"); |
526 |
- fifo_reply(filename, "500 fifo_callback: get_reply_status failed\n"); |
|
527 |
- return; |
|
552 |
+ fifo_reply( filename, |
|
553 |
+ "500 fifo_callback: get_reply_status failed\n"); |
|
554 |
+ goto done; |
|
528 | 555 |
} |
529 | 556 |
fifo_reply(filename, "%.*s\n", text.len, text.s ); |
530 | 557 |
pkg_free(text.s); |
531 | 558 |
} else { |
532 |
- text.s=reply->first_line.u.reply.reason.s; |
|
533 |
- text.len=reply->first_line.u.reply.reason.len; |
|
559 |
+ text.s = ps->rpl->first_line.u.reply.reason.s; |
|
560 |
+ text.len = ps->rpl->first_line.u.reply.reason.len; |
|
534 | 561 |
|
535 | 562 |
f = fopen(filename, "wt"); |
536 |
- if (!f) return; |
|
537 |
- fprintf(f, "%d %.*s\n", reply->first_line.u.reply.statuscode, text.len, text.s); |
|
538 |
- print_uris(f, reply); |
|
539 |
- fprintf(f, "%s\n", reply->headers->name.s); |
|
563 |
+ if (!f) goto done; |
|
564 |
+ fprintf(f, "%d %.*s\n", ps->rpl->first_line.u.reply.statuscode, |
|
565 |
+ text.len, text.s); |
|
566 |
+ print_uris(f, ps->rpl); |
|
567 |
+ fprintf(f, "%s\n", ps->rpl->headers->name.s); |
|
540 | 568 |
fclose(f); |
541 | 569 |
} |
542 | 570 |
DBG("DEBUG: fifo_callback sucesssfuly completed\n"); |
543 |
-} |
|
571 |
+done: |
|
572 |
+ shm_free(ps->param); |
|
573 |
+} |
|
544 | 574 |
|
545 | 575 |
|
546 | 576 |
int fifo_uac(FILE *stream, char *response_file) |
... | ... |
@@ -624,7 +654,7 @@ int fifo_uac(FILE *stream, char *response_file) |
624 | 654 |
|
625 | 655 |
if (ret <= 0) { |
626 | 656 |
err_ret = err2reason_phrase(ret, &sip_error, err_buf, |
627 |
- sizeof(err_buf), "FIFO/UAC") ; |
|
657 |
+ sizeof(err_buf), "FIFO/UAC") ; |
|
628 | 658 |
if (err_ret > 0 ) |
629 | 659 |
{ |
630 | 660 |
fifo_uac_error(response_file, sip_error, err_buf); |