... | ... |
@@ -35,10 +35,13 @@ New features |
35 | 35 |
- improved tm/FIFO (external applications, such as |
36 | 36 |
click-to-dial can now better initiate transactions) |
37 | 37 |
[tm module] |
38 |
+- nathelper utility for Cisco/ATA NAT traversal |
|
38 | 39 |
- powerpc fast locking support |
39 | 40 |
- netbsd support |
40 | 41 |
- 64 bits arch. support (e.g. netbsd/sparc64). |
41 | 42 |
- tcp2udp and udp2tcp stateless forwarding (see forward_udp & forward_tcp) |
43 |
+- rich access control lists [module permissions] |
|
44 |
+ |
|
42 | 45 |
|
43 | 46 |
Changes to use of ser scripts |
44 | 47 |
============================= |
... | ... |
@@ -47,6 +50,8 @@ Changes to use of ser scripts |
47 | 50 |
core |
48 | 51 |
---- |
49 | 52 |
XXX TCP |
53 |
+- reply_route has been renamed to failure_route -- the old name caused |
|
54 |
+ too much confusion |
|
50 | 55 |
|
51 | 56 |
acc module: |
52 | 57 |
----------- |
... | ... |
@@ -94,4 +99,26 @@ tm module: |
94 | 99 |
---------- |
95 | 100 |
- t_reply_unsafe, used in former versions within reply_routes, |
96 | 101 |
is deprecated; now t_reply is used from any places in script |
97 |
-- XXX t_uac/FIFO |
|
102 |
+- t_on_negative is renamed to t_on_failure -- the old name just |
|
103 |
+ caused too much confusion |
|
104 |
+- FIFO t_uac used by some applications (like serweb) has been |
|
105 |
+ replaced with t_uac_dlg (which allows easier use by dialog- |
|
106 |
+ oriented applications, like click-to-dial) |
|
107 |
+- if you wish to do forward to another destination from |
|
108 |
+ failure_route (reply_route formerly), you need to call t_relay |
|
109 |
+ or t_relay_to explicitely now |
|
110 |
+ |
|
111 |
+List of new modules: |
|
112 |
+-------------------- |
|
113 |
+- dbtext -- flat-file database |
|
114 |
+- domain -- automated domain management |
|
115 |
+- enum -- ENUM support |
|
116 |
+- nathelper -- utility for NAT traversal for Cisco ATAs |
|
117 |
+- pa -- presence agent |
|
118 |
+- permissions -- ACLs |
|
119 |
+- vm -- voicemail interface |
|
120 |
+ |
|
121 |
+List of deprecated modules: |
|
122 |
+--------------------------- |
|
123 |
+- im (t_uac_dlg is used for sending messages) |
|
124 |
+- radius_acc (radius accounting now part of acc module) |
... | ... |
@@ -32,6 +32,7 @@ |
32 | 32 |
* 2003-01-23 mhomed added (jiri) |
33 | 33 |
* 2003-03-19 replaced all the mallocs/frees w/ pkg_malloc/pkg_free (andrei) |
34 | 34 |
* 2003-04-01 added dst_port, proto (tcp, udp, tls), af(inet, inet6) (andrei) |
35 |
+ * 2003-04-05 s/reply_route/failure_route, onreply_route introduced (jiri) |
|
35 | 36 |
*/ |
36 | 37 |
|
37 | 38 |
|
... | ... |
@@ -78,7 +79,8 @@ SEND_TCP send_tcp |
78 | 79 |
LOG log |
79 | 80 |
ERROR error |
80 | 81 |
ROUTE route |
81 |
-REPL_ROUTE reply_route |
|
82 |
+FAILURE_ROUTE failure_route |
|
83 |
+ONREPLY_ROUTE onreply_route |
|
82 | 84 |
EXEC exec |
83 | 85 |
SETFLAG setflag |
84 | 86 |
RESETFLAG resetflag |
... | ... |
@@ -106,7 +108,11 @@ MAX_LEN "max_len" |
106 | 108 |
|
107 | 109 |
/* condition keywords */ |
108 | 110 |
METHOD method |
109 |
-URI uri |
|
111 |
+/* hack -- the second element in first line is referrable |
|
112 |
+ as either uri or status; it only would makes sense to |
|
113 |
+ call it "uri" from route{} and status from onreply_route{} |
|
114 |
+*/ |
|
115 |
+URI "uri"|"status" |
|
110 | 116 |
SRCIP src_ip |
111 | 117 |
SRCPORT src_port |
112 | 118 |
DSTIP dst_ip |
... | ... |
@@ -206,7 +212,8 @@ EAT_ABLE [\ \t\b\r] |
206 | 212 |
<INITIAL>{ISFLAGSET} { count(); yylval.strval=yytext; return ISFLAGSET; } |
207 | 213 |
<INITIAL>{LEN_GT} { count(); yylval.strval=yytext; return LEN_GT; } |
208 | 214 |
<INITIAL>{ROUTE} { count(); yylval.strval=yytext; return ROUTE; } |
209 |
-<INITIAL>{REPL_ROUTE} { count(); yylval.strval=yytext; return REPL_ROUTE; } |
|
215 |
+<INITIAL>{ONREPLY_ROUTE} { count(); yylval.strval=yytext; return ONREPLY_ROUTE; } |
|
216 |
+<INITIAL>{FAILURE_ROUTE} { count(); yylval.strval=yytext; return FAILURE_ROUTE; } |
|
210 | 217 |
<INITIAL>{EXEC} { count(); yylval.strval=yytext; return EXEC; } |
211 | 218 |
<INITIAL>{SET_HOST} { count(); yylval.strval=yytext; return SET_HOST; } |
212 | 219 |
<INITIAL>{SET_HOSTPORT} { count(); yylval.strval=yytext; return SET_HOSTPORT; } |
... | ... |
@@ -35,6 +35,7 @@ |
35 | 35 |
* 2003-03-19 Added support for route type in find_export (janakj) |
36 | 36 |
* 2003-03-20 Regex support in modparam (janakj) |
37 | 37 |
* 2003-04-01 added dst_port, proto , af (andrei) |
38 |
+ * 2003-04-05 s/reply_route/failure_route, onreply_route introduced (jiri) |
|
38 | 39 |
*/ |
39 | 40 |
|
40 | 41 |
|
... | ... |
@@ -106,7 +107,8 @@ int rt; /* Type of route block for find_export */ |
106 | 107 |
%token LOG_TOK |
107 | 108 |
%token ERROR |
108 | 109 |
%token ROUTE |
109 |
-%token REPL_ROUTE |
|
110 |
+%token FAILURE_ROUTE |
|
111 |
+%token ONREPLY_ROUTE |
|
110 | 112 |
%token EXEC |
111 | 113 |
%token SET_HOST |
112 | 114 |
%token SET_HOSTPORT |
... | ... |
@@ -221,7 +223,8 @@ statements: statements statement {} |
221 | 223 |
statement: assign_stm |
222 | 224 |
| module_stm |
223 | 225 |
| {rt=REQUEST_ROUTE;} route_stm |
224 |
- | {rt=REPLY_ROUTE;} reply_route_stm |
|
226 |
+ | {rt=FAILURE_ROUTE;} failure_route_stm |
|
227 |
+ | {rt=ONREPLY_ROUTE;} onreply_route_stm |
|
225 | 228 |
|
226 | 229 |
| CR /* null statement*/ |
227 | 230 |
; |
... | ... |
@@ -463,15 +466,26 @@ route_stm: ROUTE LBRACE actions RBRACE { push($3, &rlist[DEFAULT_RT]); } |
463 | 466 |
| ROUTE error { yyerror("invalid route statement"); } |
464 | 467 |
; |
465 | 468 |
|
466 |
-reply_route_stm: REPL_ROUTE LBRACK NUMBER RBRACK LBRACE actions RBRACE { |
|
467 |
- if (($3<REPLY_RT_NO)&&($3>=1)){ |
|
468 |
- push($6, &reply_rlist[$3]); |
|
469 |
+failure_route_stm: FAILURE_ROUTE LBRACK NUMBER RBRACK LBRACE actions RBRACE { |
|
470 |
+ if (($3<FAILURE_RT_NO)&&($3>=1)){ |
|
471 |
+ push($6, &failure_rlist[$3]); |
|
469 | 472 |
} else { |
470 | 473 |
yyerror("invalid reply routing" |
471 | 474 |
"table number"); |
472 | 475 |
YYABORT; } |
473 | 476 |
} |
474 |
- | REPL_ROUTE error { yyerror("invalid reply_route statement"); } |
|
477 |
+ | FAILURE_ROUTE error { yyerror("invalid failure_route statement"); } |
|
478 |
+ ; |
|
479 |
+ |
|
480 |
+onreply_route_stm: ONREPLY_ROUTE LBRACK NUMBER RBRACK LBRACE actions RBRACE { |
|
481 |
+ if (($3<ONREPLY_RT_NO)&&($3>=1)){ |
|
482 |
+ push($6, &onreply_rlist[$3]); |
|
483 |
+ } else { |
|
484 |
+ yyerror("invalid reply routing" |
|
485 |
+ "table number"); |
|
486 |
+ YYABORT; } |
|
487 |
+ } |
|
488 |
+ | ONREPLY_ROUTE error { yyerror("invalid failure_route statement"); } |
|
475 | 489 |
; |
476 | 490 |
/* |
477 | 491 |
rules: rules rule { push($2, &$1); $$=$1; } |
... | ... |
@@ -50,7 +50,8 @@ |
50 | 50 |
#define CHILD_NO 8 |
51 | 51 |
|
52 | 52 |
#define RT_NO 10 /* routing tables number */ |
53 |
-#define REPLY_RT_NO 10 /* reply routing tables number */ |
|
53 |
+#define FAILURE_RT_NO RT_NO /* on_failure routing tables number */ |
|
54 |
+#define ONREPLY_RT_NO RT_NO /* on_reply routing tables number */ |
|
54 | 55 |
#define DEFAULT_RT 0 /* default routing table */ |
55 | 56 |
|
56 | 57 |
#define MAX_REC_LEV 100 /* maximum number of recursive calls */ |
... | ... |
@@ -39,20 +39,20 @@ route{ |
39 | 39 |
seturi("sip:nobody@iptel.org"); |
40 | 40 |
append_branch("sip:parallel@iptel.org:9"); |
41 | 41 |
# if we do not get a positive reply, continue at reply_route[1] |
42 |
- t_on_negative("1"); |
|
42 |
+ t_on_failure("1"); |
|
43 | 43 |
# forward the request to all destinations in destination set now |
44 | 44 |
t_relay(); |
45 | 45 |
} |
46 | 46 |
|
47 |
-reply_route[1] { |
|
47 |
+failure_route[1] { |
|
48 | 48 |
# forwarding failed -- try again at another destination |
49 | 49 |
append_branch("sip:nonsense@iptel.org"); |
50 | 50 |
log(1,"first redirection\n"); |
51 | 51 |
# if this alternative destination fails too, proceed to reply_route[2] |
52 |
- t_on_negative("2"); |
|
52 |
+ t_on_failure("2"); |
|
53 | 53 |
} |
54 | 54 |
|
55 |
-reply_route[2] { |
|
55 |
+failure_route[2] { |
|
56 | 56 |
# try out the last resort destination |
57 | 57 |
append_branch("sip:foo@iptel.org"); |
58 | 58 |
log(1, "second redirection\n"); |
... | ... |
@@ -225,6 +225,8 @@ typedef struct cell |
225 | 225 |
|
226 | 226 |
/* the route to take if no final positive reply arrived */ |
227 | 227 |
unsigned int on_negative; |
228 |
+ /* the onreply_route to be processed if registered to do so */ |
|
229 |
+ unsigned int on_reply; |
|
228 | 230 |
/* set to one if you want to disallow silent transaction |
229 | 231 |
dropping when C timer hits |
230 | 232 |
*/ |
... | ... |
@@ -386,6 +386,7 @@ int t_forward_nonack( struct cell *t, struct sip_msg* p_msg , |
386 | 386 |
int i; |
387 | 387 |
struct cell *t_invite; |
388 | 388 |
int success_branch; |
389 |
+ int try_new; |
|
389 | 390 |
|
390 | 391 |
/* make -Wall happy */ |
391 | 392 |
current_uri.s=0; |
... | ... |
@@ -414,15 +415,17 @@ int t_forward_nonack( struct cell *t, struct sip_msg* p_msg , |
414 | 415 |
is in additional branches (which may be continuously refilled |
415 | 416 |
*/ |
416 | 417 |
if (first_branch==0) { |
418 |
+ try_new=1; |
|
417 | 419 |
branch_ret=add_uac( t, p_msg, &GET_RURI(p_msg), &GET_NEXT_HOP(p_msg), proxy, proto ); |
418 | 420 |
if (branch_ret>=0) |
419 | 421 |
added_branches |= 1<<branch_ret; |
420 | 422 |
else |
421 | 423 |
lowest_ret=branch_ret; |
422 |
- } |
|
424 |
+ } else try_new=0; |
|
423 | 425 |
|
424 | 426 |
init_branch_iterator(); |
425 | 427 |
while((current_uri.s=next_branch( ¤t_uri.len))) { |
428 |
+ try_new++; |
|
426 | 429 |
branch_ret=add_uac( t, p_msg, ¤t_uri, |
427 | 430 |
(p_msg->dst_uri.len) ? (&p_msg->dst_uri) : ¤t_uri, |
428 | 431 |
proxy, proto); |
... | ... |
@@ -444,10 +447,19 @@ int t_forward_nonack( struct cell *t, struct sip_msg* p_msg , |
444 | 447 |
/* don't forget to clear all branches processed so far */ |
445 | 448 |
|
446 | 449 |
/* things went wrong ... no new branch has been fwd-ed at all */ |
447 |
- if (added_branches==0) |
|
450 |
+ if (added_branches==0) { |
|
451 |
+ if (try_new==0) { |
|
452 |
+ LOG(L_ERR, "ERROR: t_forward_nonack: no branched for fwding\n"); |
|
453 |
+ return -1; |
|
454 |
+ } |
|
455 |
+ LOG(L_ERR, "ERROR: t_forward_nonack: failure to add branches\n"); |
|
448 | 456 |
return lowest_ret; |
457 |
+ } |
|
449 | 458 |
|
450 |
- /* if someone set on_negative, store in in T-context */ |
|
459 |
+ /* store script processing value of failure route to transactional |
|
460 |
+ context; if currently 0, this forwarding attempt will no longer |
|
461 |
+ result in failure_route on error |
|
462 |
+ */ |
|
451 | 463 |
t->on_negative=get_on_negative(); |
452 | 464 |
|
453 | 465 |
/* send them out now */ |
... | ... |
@@ -67,6 +67,8 @@ |
67 | 67 |
* 2003-03-30 set_kr for requests only (jiri) |
68 | 68 |
* 2003-04-04 bug_fix: RESPONSE_IN callback not called for local |
69 | 69 |
* UAC transactions (jiri) |
70 |
+ * 2003-04-07 new transactions inherit on_negative and on_relpy from script |
|
71 |
+ * variables on instatntiation (jiri) |
|
70 | 72 |
*/ |
71 | 73 |
|
72 | 74 |
|
... | ... |
@@ -1023,6 +1025,8 @@ int t_newtran( struct sip_msg* p_msg ) |
1023 | 1025 |
|
1024 | 1026 |
new_cell->method=new_cell->uas.request->first_line.u.request.method; |
1025 | 1027 |
new_cell->is_invite=p_msg->REQ_METHOD==METHOD_INVITE; |
1028 |
+ new_cell->on_negative=get_on_negative(); |
|
1029 |
+ new_cell->on_reply=get_on_reply(); |
|
1026 | 1030 |
|
1027 | 1031 |
} |
1028 | 1032 |
|
... | ... |
@@ -41,6 +41,7 @@ |
41 | 41 |
* 2003-03-16 removed _TOTAG (jiri) |
42 | 42 |
* 2003-03-31 200 for INVITE/UAS resent even for UDP (jiri) |
43 | 43 |
* 2003-03-31 removed msg->repl_add_rm (andrei) |
44 |
+ * 2003-04-05 s/reply_route/failure_route, onreply_route introduced (jiri) |
|
44 | 45 |
*/ |
45 | 46 |
|
46 | 47 |
|
... | ... |
@@ -82,6 +83,8 @@ static char *tm_tag_suffix; |
82 | 83 |
|
83 | 84 |
/* where to go if there is no positive reply */ |
84 | 85 |
static int goto_on_negative=0; |
86 |
+/* where to go on receipt of reply */ |
|
87 |
+static int goto_on_reply=0; |
|
85 | 88 |
|
86 | 89 |
|
87 | 90 |
/* we store the reply_route # in private memory which is |
... | ... |
@@ -94,10 +97,14 @@ static int goto_on_negative=0; |
94 | 97 |
*/ |
95 | 98 |
|
96 | 99 |
|
97 |
-int t_on_negative( unsigned int go_to ) |
|
100 |
+void t_on_negative( unsigned int go_to ) |
|
98 | 101 |
{ |
99 | 102 |
goto_on_negative=go_to; |
100 |
- return 1; |
|
103 |
+} |
|
104 |
+ |
|
105 |
+void t_on_reply( unsigned int go_to ) |
|
106 |
+{ |
|
107 |
+ goto_on_reply=go_to; |
|
101 | 108 |
} |
102 | 109 |
|
103 | 110 |
|
... | ... |
@@ -105,6 +112,10 @@ unsigned int get_on_negative() |
105 | 112 |
{ |
106 | 113 |
return goto_on_negative; |
107 | 114 |
} |
115 |
+unsigned int get_on_reply() |
|
116 |
+{ |
|
117 |
+ return goto_on_reply; |
|
118 |
+} |
|
108 | 119 |
|
109 | 120 |
void tm_init_tags() |
110 | 121 |
{ |
... | ... |
@@ -141,6 +152,16 @@ int unmatched_totag(struct cell *t, struct sip_msg *ack) |
141 | 152 |
return 1; |
142 | 153 |
} |
143 | 154 |
|
155 |
+static inline void update_local_tags(struct cell *trans, |
|
156 |
+ struct bookmark *bm, char *dst_buffer, |
|
157 |
+ char *src_buffer /* to which bm refers */) |
|
158 |
+{ |
|
159 |
+ if (bm->to_tag_val.s) { |
|
160 |
+ trans->uas.local_totag.s=bm->to_tag_val.s-src_buffer+dst_buffer; |
|
161 |
+ trans->uas.local_totag.len=bm->to_tag_val.len; |
|
162 |
+ } |
|
163 |
+} |
|
164 |
+ |
|
144 | 165 |
|
145 | 166 |
/* append a newly received tag from a 200/INVITE to |
146 | 167 |
* transaction's set; (only safe if called from within |
... | ... |
@@ -213,6 +234,141 @@ static char *build_ack(struct sip_msg* rpl,struct cell *trans,int branch, |
213 | 234 |
ACK, ACK_LEN, &to ); |
214 | 235 |
} |
215 | 236 |
|
237 |
+static int _reply_light( struct cell *trans, char* buf, unsigned int len, |
|
238 |
+ unsigned int code, char * text, |
|
239 |
+ char *to_tag, unsigned int to_tag_len, int lock, |
|
240 |
+ struct bookmark *bm ) |
|
241 |
+{ |
|
242 |
+ struct retr_buf *rb; |
|
243 |
+ unsigned int buf_len; |
|
244 |
+ branch_bm_t cancel_bitmap; |
|
245 |
+ |
|
246 |
+ if (!buf) |
|
247 |
+ { |
|
248 |
+ DBG("DEBUG: t_reply: response building failed\n"); |
|
249 |
+ /* determine if there are some branches to be cancelled */ |
|
250 |
+ if (trans->is_invite) { |
|
251 |
+ if (lock) LOCK_REPLIES( trans ); |
|
252 |
+ which_cancel(trans, &cancel_bitmap ); |
|
253 |
+ if (lock) UNLOCK_REPLIES( trans ); |
|
254 |
+ } |
|
255 |
+ /* and clean-up, including cancellations, if needed */ |
|
256 |
+ goto error; |
|
257 |
+ } |
|
258 |
+ |
|
259 |
+ cancel_bitmap=0; |
|
260 |
+ if (lock) LOCK_REPLIES( trans ); |
|
261 |
+ if (trans->is_invite) which_cancel(trans, &cancel_bitmap ); |
|
262 |
+ if (trans->uas.status>=200) { |
|
263 |
+ LOG( L_ERR, "ERROR: t_reply: can't generate %d reply" |
|
264 |
+ " when a final %d was sent out\n", code, trans->uas.status); |
|
265 |
+ goto error2; |
|
266 |
+ } |
|
267 |
+ |
|
268 |
+ |
|
269 |
+ rb = & trans->uas.response; |
|
270 |
+ rb->activ_type=code; |
|
271 |
+ |
|
272 |
+ trans->uas.status = code; |
|
273 |
+ buf_len = rb->buffer ? len : len + REPLY_OVERBUFFER_LEN; |
|
274 |
+ rb->buffer = (char*)shm_resize( rb->buffer, buf_len ); |
|
275 |
+ /* puts the reply's buffer to uas.response */ |
|
276 |
+ if (! rb->buffer ) { |
|
277 |
+ LOG(L_ERR, "ERROR: t_reply: cannot allocate shmem buffer\n"); |
|
278 |
+ goto error3; |
|
279 |
+ } |
|
280 |
+ update_local_tags(trans, bm, rb->buffer, buf); |
|
281 |
+ |
|
282 |
+ rb->buffer_len = len ; |
|
283 |
+ memcpy( rb->buffer , buf , len ); |
|
284 |
+ /* needs to be protected too because what timers are set depends |
|
285 |
+ on current transactions status */ |
|
286 |
+ /* t_update_timers_after_sending_reply( rb ); */ |
|
287 |
+ update_reply_stats( code ); |
|
288 |
+ trans->relaied_reply_branch=-2; |
|
289 |
+ tm_stats->replied_localy++; |
|
290 |
+ if (lock) UNLOCK_REPLIES( trans ); |
|
291 |
+ |
|
292 |
+ /* do UAC cleanup procedures in case we generated |
|
293 |
+ a final answer whereas there are pending UACs */ |
|
294 |
+ if (code>=200) { |
|
295 |
+ if (trans->local) { |
|
296 |
+ DBG("DEBUG: local transaction completed from _reply\n"); |
|
297 |
+ callback_event( TMCB_LOCAL_COMPLETED, trans, FAKED_REPLY, code ); |
|
298 |
+ if (trans->completion_cb) |
|
299 |
+ trans->completion_cb( trans, FAKED_REPLY, code, 0 /* empty param */); |
|
300 |
+ } else { |
|
301 |
+ callback_event( TMCB_RESPONSE_OUT, trans, FAKED_REPLY, code ); |
|
302 |
+ } |
|
303 |
+ |
|
304 |
+ cleanup_uac_timers( trans ); |
|
305 |
+ if (trans->is_invite) cancel_uacs( trans, cancel_bitmap ); |
|
306 |
+ set_final_timer( trans ); |
|
307 |
+ } |
|
308 |
+ |
|
309 |
+ /* send it out */ |
|
310 |
+ /* first check if we managed to resolve topmost Via -- if |
|
311 |
+ not yet, don't try to retransmit |
|
312 |
+ */ |
|
313 |
+ if (!trans->uas.response.dst.send_sock) { |
|
314 |
+ LOG(L_ERR, "ERROR: _reply: no resolved dst to send reply to\n"); |
|
315 |
+ } else { |
|
316 |
+ SEND_PR_BUFFER( rb, buf, len ); |
|
317 |
+ DBG("DEBUG: reply sent out. buf=%p: %.9s..., shmem=%p: %.9s\n", |
|
318 |
+ buf, buf, rb->buffer, rb->buffer ); |
|
319 |
+ } |
|
320 |
+ pkg_free( buf ) ; |
|
321 |
+ DBG("DEBUG: t_reply: finished\n"); |
|
322 |
+ return 1; |
|
323 |
+ |
|
324 |
+error3: |
|
325 |
+error2: |
|
326 |
+ if (lock) UNLOCK_REPLIES( trans ); |
|
327 |
+ pkg_free ( buf ); |
|
328 |
+error: |
|
329 |
+ /* do UAC cleanup */ |
|
330 |
+ cleanup_uac_timers( trans ); |
|
331 |
+ if (trans->is_invite) cancel_uacs( trans, cancel_bitmap ); |
|
332 |
+ /* we did not succeed -- put the transaction on wait */ |
|
333 |
+ put_on_wait(trans); |
|
334 |
+ return -1; |
|
335 |
+} |
|
336 |
+ |
|
337 |
+ |
|
338 |
+/* send a UAS reply |
|
339 |
+ * returns 1 if everything was OK or -1 for error |
|
340 |
+ */ |
|
341 |
+static int _reply( struct cell *trans, struct sip_msg* p_msg, |
|
342 |
+ unsigned int code, char * text, int lock ) |
|
343 |
+{ |
|
344 |
+ unsigned int len; |
|
345 |
+ char * buf; |
|
346 |
+ struct bookmark bm; |
|
347 |
+ |
|
348 |
+ if (code>=200) set_kr(REQ_RPLD); |
|
349 |
+ /* compute the buffer in private memory prior to entering lock; |
|
350 |
+ * create to-tag if needed */ |
|
351 |
+ if (code>=180 && p_msg->to |
|
352 |
+ && (get_to(p_msg)->tag_value.s==0 |
|
353 |
+ || get_to(p_msg)->tag_value.len==0)) { |
|
354 |
+ calc_crc_suffix( p_msg, tm_tag_suffix ); |
|
355 |
+ buf = build_res_buf_from_sip_req(code,text, |
|
356 |
+ tm_tags, TOTAG_VALUE_LEN, |
|
357 |
+ p_msg,&len, &bm); |
|
358 |
+ |
|
359 |
+ return _reply_light(trans,buf,len,code,text, |
|
360 |
+ tm_tags, TOTAG_VALUE_LEN, |
|
361 |
+ lock, &bm); |
|
362 |
+ } else { |
|
363 |
+ buf = build_res_buf_from_sip_req(code,text, 0,0, /* no to-tag */ |
|
364 |
+ p_msg,&len, &bm); |
|
365 |
+ |
|
366 |
+ return _reply_light(trans,buf,len,code,text, |
|
367 |
+ 0,0, /* no to-tag */ |
|
368 |
+ lock, &bm); |
|
369 |
+ } |
|
370 |
+} |
|
371 |
+ |
|
216 | 372 |
|
217 | 373 |
/* create a temporary faked message environment in which a conserved |
218 | 374 |
* t->uas.request in shmem is partially duplicated to pkgmem |
... | ... |
@@ -257,7 +413,7 @@ static int faked_env(struct sip_msg *fake, |
257 | 413 |
* for example t_reply needs to know that |
258 | 414 |
*/ |
259 | 415 |
backup_mode=rmode; |
260 |
- rmode=MODE_ONREPLY_REQUEST; |
|
416 |
+ rmode=MODE_ONFAILURE; |
|
261 | 417 |
/* also, tm actions look in beginning whether tranaction is |
262 | 418 |
* set -- whether we are called from a reply-processing |
263 | 419 |
* or a timer process, we need to set current transaction; |
... | ... |
@@ -309,11 +465,68 @@ restore: |
309 | 465 |
return 0; |
310 | 466 |
} |
311 | 467 |
|
468 |
+/* return 1 if a failure_route processes */ |
|
469 |
+int failure_route(struct cell *t) |
|
470 |
+{ |
|
471 |
+ struct sip_msg faked_msg; |
|
472 |
+ |
|
473 |
+ /* don't do anything if we don't have to */ |
|
474 |
+ if (!t->on_negative) return 0; |
|
475 |
+ |
|
476 |
+ /* if fake message creation failes, return error too */ |
|
477 |
+ if (!faked_env(&faked_msg, t, t->uas.request, 0 /* create fake */ )) { |
|
478 |
+ LOG(L_ERR, "ERROR: on_negative_reply: faked_env failed\n"); |
|
479 |
+ return 0; |
|
480 |
+ } |
|
481 |
+ |
|
482 |
+ /* avoid recursion -- if failure_route forwards, and does not |
|
483 |
+ * set next failure route, failure_route will not be rentered |
|
484 |
+ * on failure */ |
|
485 |
+ t_on_negative(0); |
|
486 |
+ /* run a reply_route action if some was marked */ |
|
487 |
+ if (run_actions(failure_rlist[t->on_negative], &faked_msg)<0) |
|
488 |
+ LOG(L_ERR, "ERROR: on_negative_reply: " |
|
489 |
+ "Error in do_action\n"); |
|
490 |
+ /* restore original environment */ |
|
491 |
+ faked_env(&faked_msg, 0, 0, 1 ); |
|
492 |
+ return 1; |
|
493 |
+} |
|
312 | 494 |
|
313 | 495 |
|
314 |
-/* the main code of stateful replying */ |
|
315 |
-static int _reply( struct cell *t, struct sip_msg* p_msg, unsigned int code, |
|
316 |
- char * text, int lock ); |
|
496 |
+/* select a branch for forwarding; returns: |
|
497 |
+ * 0..X ... branch number |
|
498 |
+ * -1 ... error |
|
499 |
+ * -2 ... can't decide yet -- incomplete branches present |
|
500 |
+ */ |
|
501 |
+static int pick_branch( int inc_branch, int inc_code, |
|
502 |
+ struct cell *t, int *res_code) |
|
503 |
+{ |
|
504 |
+ int lowest_b, lowest_s, b; |
|
505 |
+ |
|
506 |
+ lowest_b=-1; lowest_s=999; |
|
507 |
+ for ( b=0; b<t->nr_of_outgoings ; b++ ) { |
|
508 |
+ /* "fake" for the currently processed branch */ |
|
509 |
+ if (b==inc_branch) { |
|
510 |
+ if (inc_code<lowest_s) { |
|
511 |
+ lowest_b=b; |
|
512 |
+ lowest_s=inc_code; |
|
513 |
+ } |
|
514 |
+ continue; |
|
515 |
+ } |
|
516 |
+ /* skip 'empty branches' */ |
|
517 |
+ if (!t->uac[b].request.buffer) continue; |
|
518 |
+ /* there is still an unfinished UAC transaction; wait now! */ |
|
519 |
+ if ( t->uac[b].last_received<200 ) |
|
520 |
+ return -2; |
|
521 |
+ if ( t->uac[b].last_received<lowest_s ) { |
|
522 |
+ lowest_b =b; |
|
523 |
+ lowest_s = t->uac[b].last_received; |
|
524 |
+ } |
|
525 |
+ } /* find lowest branch */ |
|
526 |
+ |
|
527 |
+ *res_code=lowest_s; |
|
528 |
+ return lowest_b; |
|
529 |
+} |
|
317 | 530 |
|
318 | 531 |
/* This is the neuralgical point of reply processing -- called |
319 | 532 |
* from within a REPLY_LOCK, t_should_relay_response decides |
... | ... |
@@ -330,9 +543,10 @@ static enum rps t_should_relay_response( struct cell *Trans , int new_code, |
330 | 543 |
int branch , int *should_store, int *should_relay, |
331 | 544 |
branch_bm_t *cancel_bitmap, struct sip_msg *reply ) |
332 | 545 |
{ |
333 |
- int b, lowest_b, lowest_s, dummy; |
|
334 |
- struct sip_msg faked_msg, *origin_rq; |
|
335 |
- unsigned int on_neg; |
|
546 |
+ |
|
547 |
+ int branch_cnt; |
|
548 |
+ int picked_branch; |
|
549 |
+ int picked_code; |
|
336 | 550 |
|
337 | 551 |
/* note: this code never lets replies to CANCEL go through; |
338 | 552 |
we generate always a local 200 for CANCEL; 200s are |
... | ... |
@@ -378,63 +592,31 @@ static enum rps t_should_relay_response( struct cell *Trans , int new_code, |
378 | 592 |
} |
379 | 593 |
|
380 | 594 |
Trans->uac[branch].last_received=new_code; |
595 |
+ |
|
596 |
+ |
|
381 | 597 |
/* if all_final return lowest */ |
382 |
- lowest_b=-1; lowest_s=999; |
|
383 |
- for ( b=0; b<Trans->nr_of_outgoings ; b++ ) { |
|
384 |
- /* "fake" for the currently processed branch */ |
|
385 |
- if (b==branch) { |
|
386 |
- if (new_code<lowest_s) { |
|
387 |
- lowest_b=b; |
|
388 |
- lowest_s=new_code; |
|
389 |
- } |
|
390 |
- continue; |
|
391 |
- } |
|
392 |
- /* skip 'empty branches' */ |
|
393 |
- if (!Trans->uac[b].request.buffer) continue; |
|
394 |
- /* there is still an unfinished UAC transaction; wait now! */ |
|
395 |
- if ( Trans->uac[b].last_received<200 ) { |
|
396 |
- *should_store=1; |
|
397 |
- *should_relay=-1; |
|
398 |
- return RPS_STORE; |
|
399 |
- } |
|
400 |
- if ( Trans->uac[b].last_received<lowest_s ) |
|
401 |
- { |
|
402 |
- lowest_b =b; |
|
403 |
- lowest_s = Trans->uac[b].last_received; |
|
404 |
- } |
|
405 |
- } /* find lowest branch */ |
|
406 |
- if (lowest_b==-1) { |
|
598 |
+ picked_branch=pick_branch(branch,new_code, Trans, &picked_code); |
|
599 |
+ if (picked_branch==-2) { /* branches open yet */ |
|
600 |
+ *should_store=1; |
|
601 |
+ *should_relay=-1; |
|
602 |
+ return RPS_STORE; |
|
603 |
+ } |
|
604 |
+ if (picked_branch==-1) { |
|
407 | 605 |
LOG(L_CRIT, "ERROR: t_should_relay_response: lowest==-1\n"); |
606 |
+ goto error; |
|
408 | 607 |
} |
608 |
+ |
|
409 | 609 |
/* no more pending branches -- try if that changes after |
410 |
- a callback |
|
610 |
+ a callback; save banch count to be able to determine |
|
611 |
+ later if new branches were initiated |
|
411 | 612 |
*/ |
613 |
+ branch_cnt=Trans->nr_of_outgoings; |
|
412 | 614 |
callback_event( TMCB_ON_FAILURE, Trans, |
413 |
- lowest_b==branch?reply:Trans->uac[lowest_b].reply, |
|
414 |
- lowest_s ); |
|
415 |
- |
|
615 |
+ picked_branch==branch?reply:Trans->uac[picked_branch].reply, |
|
616 |
+ picked_code); |
|
416 | 617 |
/* here, we create a faked environment, from which we |
417 | 618 |
* return to request processing, if marked to do so */ |
418 |
- origin_rq=Trans->uas.request; |
|
419 |
- on_neg=Trans->on_negative; |
|
420 |
- if (on_neg) { |
|
421 |
- DBG("DBG: on_negative_reply processed for transaction %p\n", |
|
422 |
- Trans); |
|
423 |
- if (faked_env(&faked_msg, Trans, Trans->uas.request, |
|
424 |
- 0 /* create fake */ )) |
|
425 |
- { |
|
426 |
- /* use the faked message later in forwarding */ |
|
427 |
- origin_rq=&faked_msg; |
|
428 |
- /* run a reply_route action if some was marked */ |
|
429 |
- if (run_actions(reply_rlist[on_neg], &faked_msg )<0) |
|
430 |
- LOG(L_ERR, "ERROR: on_negative_reply: " |
|
431 |
- "Error in do_action\n"); |
|
432 |
- } else { /* faked_env creation error */ |
|
433 |
- LOG(L_ERR, "ERROR: on_negative_reply: faked_env failed\n"); |
|
434 |
- on_neg=0; |
|
435 |
- } |
|
436 |
- } /* if (on_neg) */ |
|
437 |
- |
|
619 |
+ failure_route(Trans); |
|
438 | 620 |
|
439 | 621 |
/* look if the callback perhaps replied transaction; it also |
440 | 622 |
covers the case in which a transaction is replied localy |
... | ... |
@@ -450,34 +632,19 @@ static enum rps t_should_relay_response( struct cell *Trans , int new_code, |
450 | 632 |
put it on wait again; perhaps splitting put_on_wait |
451 | 633 |
from send_reply or a new RPS_ code would be healthy |
452 | 634 |
*/ |
453 |
- if (on_neg) faked_env(&faked_msg, 0, 0, 1 ); |
|
454 | 635 |
return RPS_COMPLETED; |
455 | 636 |
} |
456 |
- /* look if the callback introduced new branches ... */ |
|
457 |
- init_branch_iterator(); |
|
458 |
- if (next_branch(&dummy)) { |
|
459 |
- if (t_forward_nonack(Trans, origin_rq, |
|
460 |
- (struct proxy_l *) 0, |
|
461 |
- Trans->uas.response.dst.proto)<0) { |
|
462 |
- /* error ... behave as if we did not try to |
|
463 |
- add a new branch */ |
|
464 |
- *should_store=0; |
|
465 |
- *should_relay=lowest_b; |
|
466 |
- if (on_neg) faked_env(&faked_msg, 0, 0, 1 ); |
|
467 |
- return RPS_COMPLETED; |
|
468 |
- } |
|
469 |
- /* we succeded to launch new branches -- await |
|
470 |
- result |
|
471 |
- */ |
|
637 |
+ /* look if the callback/failure_route introduced new branches ... */ |
|
638 |
+ if (branch_cnt<Trans->nr_of_outgoings) { |
|
639 |
+ /* await then result of new branches */ |
|
472 | 640 |
*should_store=1; |
473 | 641 |
*should_relay=-1; |
474 |
- if (on_neg) faked_env(&faked_msg, 0, 0, 1 ); |
|
475 | 642 |
return RPS_STORE; |
476 | 643 |
} |
644 |
+ |
|
477 | 645 |
/* really no more pending branches -- return lowest code */ |
478 | 646 |
*should_store=0; |
479 |
- *should_relay=lowest_b; |
|
480 |
- if (on_neg) faked_env(&faked_msg, 0, 0, 1 ); |
|
647 |
+ *should_relay=picked_branch; |
|
481 | 648 |
/* we dont need 'which_cancel' here -- all branches |
482 | 649 |
known to have completed */ |
483 | 650 |
/* which_cancel( Trans, cancel_bitmap ); */ |
... | ... |
@@ -496,6 +663,7 @@ static enum rps t_should_relay_response( struct cell *Trans , int new_code, |
496 | 663 |
} else return RPS_PROVISIONAL; |
497 | 664 |
} |
498 | 665 |
|
666 |
+error: |
|
499 | 667 |
/* reply_status didn't match -- it must be something weird */ |
500 | 668 |
LOG(L_CRIT, "ERROR: Oh my gooosh! We don't know whether to relay %d\n", |
501 | 669 |
new_code); |
... | ... |
@@ -567,150 +735,8 @@ int t_reply_unsafe( struct cell *t, struct sip_msg* p_msg, unsigned int code, |
567 | 735 |
} |
568 | 736 |
|
569 | 737 |
|
570 |
-static inline void update_local_tags(struct cell *trans, |
|
571 |
- struct bookmark *bm, char *dst_buffer, |
|
572 |
- char *src_buffer /* to which bm refers */) |
|
573 |
-{ |
|
574 |
- if (bm->to_tag_val.s) { |
|
575 |
- trans->uas.local_totag.s=bm->to_tag_val.s-src_buffer+dst_buffer; |
|
576 |
- trans->uas.local_totag.len=bm->to_tag_val.len; |
|
577 |
- } |
|
578 |
-} |
|
579 |
- |
|
580 |
- |
|
581 |
-static int _reply_light( struct cell *trans, char* buf, unsigned int len, |
|
582 |
- unsigned int code, char * text, |
|
583 |
- char *to_tag, unsigned int to_tag_len, int lock, |
|
584 |
- struct bookmark *bm ) |
|
585 |
-{ |
|
586 |
- struct retr_buf *rb; |
|
587 |
- unsigned int buf_len; |
|
588 |
- branch_bm_t cancel_bitmap; |
|
589 |
- |
|
590 |
- if (!buf) |
|
591 |
- { |
|
592 |
- DBG("DEBUG: t_reply: response building failed\n"); |
|
593 |
- /* determine if there are some branches to be cancelled */ |
|
594 |
- if (trans->is_invite) { |
|
595 |
- if (lock) LOCK_REPLIES( trans ); |
|
596 |
- which_cancel(trans, &cancel_bitmap ); |
|
597 |
- if (lock) UNLOCK_REPLIES( trans ); |
|
598 |
- } |
|
599 |
- /* and clean-up, including cancellations, if needed */ |
|
600 |
- goto error; |
|
601 |
- } |
|
602 |
- |
|
603 |
- cancel_bitmap=0; |
|
604 |
- if (lock) LOCK_REPLIES( trans ); |
|
605 |
- if (trans->is_invite) which_cancel(trans, &cancel_bitmap ); |
|
606 |
- if (trans->uas.status>=200) { |
|
607 |
- LOG( L_ERR, "ERROR: t_reply: can't generate %d reply" |
|
608 |
- " when a final %d was sent out\n", code, trans->uas.status); |
|
609 |
- goto error2; |
|
610 |
- } |
|
611 |
- |
|
612 | 738 |
|
613 |
- rb = & trans->uas.response; |
|
614 |
- rb->activ_type=code; |
|
615 | 739 |
|
616 |
- trans->uas.status = code; |
|
617 |
- buf_len = rb->buffer ? len : len + REPLY_OVERBUFFER_LEN; |
|
618 |
- rb->buffer = (char*)shm_resize( rb->buffer, buf_len ); |
|
619 |
- /* puts the reply's buffer to uas.response */ |
|
620 |
- if (! rb->buffer ) { |
|
621 |
- LOG(L_ERR, "ERROR: t_reply: cannot allocate shmem buffer\n"); |
|
622 |
- goto error3; |
|
623 |
- } |
|
624 |
- update_local_tags(trans, bm, rb->buffer, buf); |
|
625 |
- |
|
626 |
- rb->buffer_len = len ; |
|
627 |
- memcpy( rb->buffer , buf , len ); |
|
628 |
- /* needs to be protected too because what timers are set depends |
|
629 |
- on current transactions status */ |
|
630 |
- /* t_update_timers_after_sending_reply( rb ); */ |
|
631 |
- update_reply_stats( code ); |
|
632 |
- trans->relaied_reply_branch=-2; |
|
633 |
- tm_stats->replied_localy++; |
|
634 |
- if (lock) UNLOCK_REPLIES( trans ); |
|
635 |
- |
|
636 |
- /* do UAC cleanup procedures in case we generated |
|
637 |
- a final answer whereas there are pending UACs */ |
|
638 |
- if (code>=200) { |
|
639 |
- if (trans->local) { |
|
640 |
- DBG("DEBUG: local transaction completed from _reply\n"); |
|
641 |
- callback_event( TMCB_LOCAL_COMPLETED, trans, FAKED_REPLY, code ); |
|
642 |
- if (trans->completion_cb) |
|
643 |
- trans->completion_cb( trans, FAKED_REPLY, code, 0 /* empty param */); |
|
644 |
- } else { |
|
645 |
- callback_event( TMCB_RESPONSE_OUT, trans, FAKED_REPLY, code ); |
|
646 |
- } |
|
647 |
- |
|
648 |
- cleanup_uac_timers( trans ); |
|
649 |
- if (trans->is_invite) cancel_uacs( trans, cancel_bitmap ); |
|
650 |
- set_final_timer( trans ); |
|
651 |
- } |
|
652 |
- |
|
653 |
- /* send it out */ |
|
654 |
- /* first check if we managed to resolve topmost Via -- if |
|
655 |
- not yet, don't try to retransmit |
|
656 |
- */ |
|
657 |
- if (!trans->uas.response.dst.send_sock) { |
|
658 |
- LOG(L_ERR, "ERROR: _reply: no resolved dst to send reply to\n"); |
|
659 |
- } else { |
|
660 |
- SEND_PR_BUFFER( rb, buf, len ); |
|
661 |
- DBG("DEBUG: reply sent out. buf=%p: %.9s..., shmem=%p: %.9s\n", |
|
662 |
- buf, buf, rb->buffer, rb->buffer ); |
|
663 |
- } |
|
664 |
- pkg_free( buf ) ; |
|
665 |
- DBG("DEBUG: t_reply: finished\n"); |
|
666 |
- return 1; |
|
667 |
- |
|
668 |
-error3: |
|
669 |
-error2: |
|
670 |
- if (lock) UNLOCK_REPLIES( trans ); |
|
671 |
- pkg_free ( buf ); |
|
672 |
-error: |
|
673 |
- /* do UAC cleanup */ |
|
674 |
- cleanup_uac_timers( trans ); |
|
675 |
- if (trans->is_invite) cancel_uacs( trans, cancel_bitmap ); |
|
676 |
- /* we did not succeed -- put the transaction on wait */ |
|
677 |
- put_on_wait(trans); |
|
678 |
- return -1; |
|
679 |
-} |
|
680 |
- |
|
681 |
-/* send a UAS reply |
|
682 |
- * returns 1 if everything was OK or -1 for error |
|
683 |
- */ |
|
684 |
-static int _reply( struct cell *trans, struct sip_msg* p_msg, |
|
685 |
- unsigned int code, char * text, int lock ) |
|
686 |
-{ |
|
687 |
- unsigned int len; |
|
688 |
- char * buf; |
|
689 |
- struct bookmark bm; |
|
690 |
- |
|
691 |
- if (code>=200) set_kr(REQ_RPLD); |
|
692 |
- /* compute the buffer in private memory prior to entering lock; |
|
693 |
- * create to-tag if needed */ |
|
694 |
- if (code>=180 && p_msg->to |
|
695 |
- && (get_to(p_msg)->tag_value.s==0 |
|
696 |
- || get_to(p_msg)->tag_value.len==0)) { |
|
697 |
- calc_crc_suffix( p_msg, tm_tag_suffix ); |
|
698 |
- buf = build_res_buf_from_sip_req(code,text, |
|
699 |
- tm_tags, TOTAG_VALUE_LEN, |
|
700 |
- p_msg,&len, &bm); |
|
701 |
- |
|
702 |
- return _reply_light(trans,buf,len,code,text, |
|
703 |
- tm_tags, TOTAG_VALUE_LEN, |
|
704 |
- lock, &bm); |
|
705 |
- } else { |
|
706 |
- buf = build_res_buf_from_sip_req(code,text, 0,0, /* no to-tag */ |
|
707 |
- p_msg,&len, &bm); |
|
708 |
- |
|
709 |
- return _reply_light(trans,buf,len,code,text, |
|
710 |
- 0,0, /* no to-tag */ |
|
711 |
- lock, &bm); |
|
712 |
- } |
|
713 |
-} |
|
714 | 740 |
|
715 | 741 |
void set_final_timer( /* struct s_table *h_table, */ struct cell *t ) |
716 | 742 |
{ |
... | ... |
@@ -1017,7 +1043,7 @@ error: |
1017 | 1043 |
* Returns : 0 - core router stops |
1018 | 1044 |
* 1 - core router relay statelessly |
1019 | 1045 |
*/ |
1020 |
-int t_on_reply( struct sip_msg *p_msg ) |
|
1046 |
+int reply_received( struct sip_msg *p_msg ) |
|
1021 | 1047 |
{ |
1022 | 1048 |
|
1023 | 1049 |
int msg_status; |
... | ... |
@@ -1068,6 +1094,13 @@ int t_on_reply( struct sip_msg *p_msg ) |
1068 | 1094 |
if ( msg_status >= 200 ) |
1069 | 1095 |
reset_timer( &uac->request.fr_timer); |
1070 | 1096 |
|
1097 |
+ /* processing of on_reply block */ |
|
1098 |
+ if (t->on_reply) { |
|
1099 |
+ rmode=MODE_ONREPLY; |
|
1100 |
+ if (run_actions(onreply_rlist[t->on_reply], p_msg)<0) |
|
1101 |
+ LOG(L_ERR, "ERROR: on_reply processing failed\n"); |
|
1102 |
+ } |
|
1103 |
+ |
|
1071 | 1104 |
LOCK_REPLIES( t ); |
1072 | 1105 |
if (t->local) { |
1073 | 1106 |
reply_status=local_reply( t, p_msg, branch, msg_status, &cancel_bitmap ); |
... | ... |
@@ -51,7 +51,7 @@ enum rps { |
51 | 51 |
RPS_PROVISIONAL |
52 | 52 |
}; |
53 | 53 |
|
54 |
-enum route_mode { MODE_REQUEST=1, MODE_ONREPLY_REQUEST }; |
|
54 |
+enum route_mode { MODE_REQUEST=1, MODE_ONREPLY, MODE_ONFAILURE }; |
|
55 | 55 |
extern enum route_mode rmode; |
56 | 56 |
|
57 | 57 |
/* has this to-tag been never seen in previous 200/INVs? */ |
... | ... |
@@ -74,7 +74,7 @@ typedef int (*treply_wb_f)( struct cell* trans, |
74 | 74 |
* Returns : 0 - core router stops |
75 | 75 |
* 1 - core router relay statelessly |
76 | 76 |
*/ |
77 |
-int t_on_reply( struct sip_msg *p_msg ) ; |
|
77 |
+int reply_received( struct sip_msg *p_msg ) ; |
|
78 | 78 |
|
79 | 79 |
|
80 | 80 |
/* Retransmits the last sent inbound reply. |
... | ... |
@@ -126,8 +126,10 @@ void on_negative_reply( struct cell* t, struct sip_msg* msg, |
126 | 126 |
/* set which 'reply' structure to take if only negative |
127 | 127 |
replies arrive |
128 | 128 |
*/ |
129 |
-int t_on_negative( unsigned int go_to ); |
|
129 |
+void t_on_negative( unsigned int go_to ); |
|
130 | 130 |
unsigned int get_on_negative(); |
131 |
+void t_on_reply( unsigned int go_to ); |
|
132 |
+unsigned int get_on_reply(); |
|
131 | 133 |
|
132 | 134 |
int t_retransmit_reply( struct cell *t ); |
133 | 135 |
|
... | ... |
@@ -62,6 +62,7 @@ |
62 | 62 |
* 2003-03-16 flags export parameter added (janakj) |
63 | 63 |
* 2003-03-19 replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei) |
64 | 64 |
* 2003-03-30 set_kr for requests only (jiri) |
65 |
+ * 2003-04-05 s/reply_route/failure_route, onreply_route introduced (jiri) |
|
65 | 66 |
*/ |
66 | 67 |
|
67 | 68 |
|
... | ... |
@@ -125,6 +126,7 @@ inline static int w_t_forward_nonack_udp(struct sip_msg* msg, char* str,char*); |
125 | 126 |
inline static int w_t_forward_nonack_tcp(struct sip_msg* msg, char* str,char*); |
126 | 127 |
inline static int fixup_hostport2proxy(void** param, int param_no); |
127 | 128 |
inline static int w_t_on_negative( struct sip_msg* msg, char *go_to, char *foo ); |
129 |
+inline static int w_t_on_reply( struct sip_msg* msg, char *go_to, char *foo ); |
|
128 | 130 |
|
129 | 131 |
|
130 | 132 |
static int mod_init(void); |
... | ... |
@@ -135,23 +137,29 @@ static int child_init(int rank); |
135 | 137 |
static cmd_export_t cmds[]={ |
136 | 138 |
{"t_newtran", w_t_newtran, 0, 0, REQUEST_ROUTE}, |
137 | 139 |
{"t_lookup_request", w_t_check, 0, 0, REQUEST_ROUTE}, |
138 |
- {T_REPLY, w_t_reply, 2, fixup_t_send_reply, REQUEST_ROUTE}, |
|
140 |
+ {T_REPLY, w_t_reply, 2, fixup_t_send_reply, |
|
141 |
+ REQUEST_ROUTE | FAILURE_ROUTE }, |
|
139 | 142 |
{"t_retransmit_reply", w_t_retransmit_reply, 0, 0, REQUEST_ROUTE}, |
140 | 143 |
{"t_release", w_t_release, 0, 0, REQUEST_ROUTE}, |
141 |
- {T_RELAY_TO, w_t_relay_to, 2, fixup_hostport2proxy, REQUEST_ROUTE}, |
|
144 |
+ {T_RELAY_TO, w_t_relay_to, 2, fixup_hostport2proxy, |
|
145 |
+ REQUEST_ROUTE | FAILURE_ROUTE }, |
|
142 | 146 |
{T_RELAY_TO_UDP, w_t_relay_to_udp, 2, fixup_hostport2proxy, REQUEST_ROUTE}, |
143 | 147 |
{T_RELAY_TO_TCP, w_t_relay_to_tcp, 2, fixup_hostport2proxy, REQUEST_ROUTE}, |
144 | 148 |
{"t_replicate", w_t_replicate, 2, fixup_hostport2proxy, REQUEST_ROUTE}, |
145 | 149 |
{"t_replicate_udp", w_t_replicate_udp, 2, fixup_hostport2proxy, REQUEST_ROUTE}, |
146 | 150 |
{"t_replicate_tcp", w_t_replicate_tcp, 2, fixup_hostport2proxy, REQUEST_ROUTE}, |
147 |
- {T_RELAY, w_t_relay, 0, 0, REQUEST_ROUTE}, |
|
151 |
+ {T_RELAY, w_t_relay, 0, 0, |
|
152 |
+ REQUEST_ROUTE | FAILURE_ROUTE }, |
|
148 | 153 |
{T_RELAY_UDP, w_t_relay_udp, 0, 0, REQUEST_ROUTE}, |
149 | 154 |
{T_RELAY_TCP, w_t_relay_tcp, 0, 0, REQUEST_ROUTE}, |
150 | 155 |
{T_FORWARD_NONACK, w_t_forward_nonack, 2, fixup_hostport2proxy, REQUEST_ROUTE}, |
151 | 156 |
{T_FORWARD_NONACK_UDP, w_t_forward_nonack_udp, 2, fixup_hostport2proxy, REQUEST_ROUTE}, |
152 | 157 |
{T_FORWARD_NONACK_TCP, w_t_forward_nonack_tcp, 2, fixup_hostport2proxy, REQUEST_ROUTE}, |
153 |
- {"t_on_negative", w_t_on_negative, 1, fixup_str2int, REQUEST_ROUTE}, |
|
154 |
- /* not applicable from the script -- ugly hack */ |
|
158 |
+ {"t_on_failure", w_t_on_negative, 1, fixup_str2int, |
|
159 |
+ REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE }, |
|
160 |
+ {"t_on_reply", w_t_on_reply, 1, fixup_str2int, |
|
161 |
+ REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE }, |
|
162 |
+ /* not applicable from the script */ |
|
155 | 163 |
{"register_tmcb", (cmd_function)register_tmcb, NO_SCRIPT, 0, 0}, |
156 | 164 |
{T_UAC_DLG, (cmd_function)t_uac_dlg, NO_SCRIPT, 0, 0}, |
157 | 165 |
{"load_tm", (cmd_function)load_tm, NO_SCRIPT, 0, 0}, |
... | ... |
@@ -191,7 +199,7 @@ struct module_exports exports= { |
191 | 199 |
params, |
192 | 200 |
|
193 | 201 |
mod_init, /* module initialization function */ |
194 |
- (response_function) t_on_reply, |
|
202 |
+ (response_function) reply_received, |
|
195 | 203 |
(destroy_function) tm_shutdown, |
196 | 204 |
0, /* w_onbreak, */ |
197 | 205 |
child_init /* per-child init function */ |
... | ... |
@@ -234,9 +242,12 @@ static int script_init( struct sip_msg *foo, void *bar) |
234 | 242 |
message's t_on_negative value |
235 | 243 |
*/ |
236 | 244 |
t_on_negative( 0 ); |
237 |
- |
|
245 |
+ t_on_reply(0); |
|
238 | 246 |
/* reset the kr status */ |
239 | 247 |
set_kr(0); |
248 |
+ /* set request mode so that multiple-mode actions know |
|
249 |
+ * how to behave */ |
|
250 |
+ rmode=MODE_REQUEST; |
|
240 | 251 |
} |
241 | 252 |
|
242 | 253 |
return 1; |
... | ... |
@@ -456,11 +467,14 @@ inline static int w_t_reply(struct sip_msg* msg, char* str, char* str2) |
456 | 467 |
* is called; we are already in a mutex and another mutex in |
457 | 468 |
* the safe version would lead to a deadlock |
458 | 469 |
*/ |
459 |
- if (rmode==MODE_ONREPLY_REQUEST) { |
|
470 |
+ if (rmode==MODE_ONFAILURE) { |
|
460 | 471 |
DBG("DEBUG: t_reply_unsafe called from w_t_reply\n"); |
461 | 472 |
return t_reply_unsafe(t, msg, (unsigned int)(long) str, str2); |
462 |
- } else { |
|
473 |
+ } else if (rmode==MODE_REQUEST) { |
|
463 | 474 |
return t_reply( t, msg, (unsigned int)(long) str, str2); |
475 |
+ } else { |
|
476 |
+ LOG(L_CRIT, "BUG: w_t_reply entered in unsupported mode\n"); |
|
477 |
+ return -1; |
|
464 | 478 |
} |
465 | 479 |
} |
466 | 480 |
|
... | ... |
@@ -516,15 +530,74 @@ inline static int w_t_newtran( struct sip_msg* p_msg, char* foo, char* bar ) |
516 | 530 |
|
517 | 531 |
inline static int w_t_on_negative( struct sip_msg* msg, char *go_to, char *foo ) |
518 | 532 |
{ |
519 |
- return t_on_negative( (unsigned int )(long) go_to ); |
|
533 |
+ struct cell *t; |
|
534 |
+ |
|
535 |
+ if (rmode==MODE_REQUEST || rmode==MODE_ONFAILURE) { |
|
536 |
+ t_on_negative( (unsigned int )(long) go_to ); |
|
537 |
+ return 1; |
|
538 |
+ } |
|
539 |
+ if (rmode==MODE_ONREPLY ) { |
|
540 |
+ /* transaction state is established */ |
|
541 |
+ t=get_t(); |
|
542 |
+ if (!t || t==T_UNDEFINED) { |
|
543 |
+ LOG(L_CRIT, "BUG: w_t_on_negative entered without t\n"); |
|
544 |
+ return -1; |
|
545 |
+ } |
|
546 |
+ t->on_negative=(unsigned int)(long)go_to; |
|
547 |
+ return 1; |
|
548 |
+ } |
|
549 |
+ LOG(L_CRIT, "BUG: w_t_on_negative entered in unsupported mode\n"); |
|
550 |
+ return -1; |
|
551 |
+} |
|
552 |
+inline static int w_t_on_reply( struct sip_msg* msg, char *go_to, char *foo ) |
|
553 |
+{ |
|
554 |
+ struct cell *t; |
|
555 |
+ |
|
556 |
+ if (rmode==MODE_REQUEST) { |
|
557 |
+ /* it's still in initial request processing stage, transaction |
|
558 |
+ * state is not estabslihed yet, store it in private memory ... |
|
559 |
+ * it will be copied to transaction state when it is set up */ |
|
560 |
+ t_on_reply( (unsigned int )(long) go_to ); |
|
561 |
+ return 1; |
|
562 |
+ } |
|
563 |
+ if (rmode==MODE_ONREPLY || rmode==MODE_ONFAILURE) { |
|
564 |
+ /* transaction state is established */ |
|
565 |
+ t=get_t(); |
|
566 |
+ if (!t || t==T_UNDEFINED) { |
|
567 |
+ LOG(L_CRIT, "BUG: w_t_on_reply entered without t\n"); |
|
568 |
+ return -1; |
|
569 |
+ } |
|
570 |
+ t->on_reply=(unsigned int) (long)go_to; |
|
571 |
+ return 1; |
|
572 |
+ } |
|
573 |
+ LOG(L_CRIT, "BUG: w_t_on_reply entered in unsupported mode\n"); |
|
574 |
+ return -1; |
|
520 | 575 |
} |
521 | 576 |
|
522 | 577 |
inline static int w_t_relay_to( struct sip_msg *p_msg , |
523 | 578 |
char *proxy, /* struct proxy_l *proxy expected */ |
524 | 579 |
char *_foo /* nothing expected */ ) |
525 | 580 |
{ |
526 |
- return t_relay_to( p_msg, ( struct proxy_l *) proxy, p_msg->rcv.proto, |
|
527 |
- 0 /* no replication */ ); |
|
581 |
+ struct cell *t; |
|
582 |
+ |
|
583 |
+ if (rmode==MODE_ONFAILURE) { |
|
584 |
+ t=get_t(); |
|
585 |
+ if (!t || t==T_UNDEFINED) { |
|
586 |
+ LOG(L_CRIT, "BUG: w_t_relay_to: undefined T\n"); |
|
587 |
+ return -1; |
|
588 |
+ } |
|
589 |
+ if (t_forward_nonack(t, p_msg, |
|
590 |
+ ( struct proxy_l *) proxy, p_msg->rcv.proto)<=0 ) { |
|
591 |
+ LOG(L_ERR, "ERROR: failure_route: t_relay_to failed\n"); |
|
592 |
+ return -1; |
|
593 |
+ } |
|
594 |
+ return 1; |
|
595 |
+ } |
|
596 |
+ if (rmode==MODE_REQUEST) |
|
597 |
+ return t_relay_to( p_msg, ( struct proxy_l *) proxy, p_msg->rcv.proto, |
|
598 |
+ 0 /* no replication */ ); |
|
599 |
+ LOG(L_CRIT, "ERROR: w_t_relay_to: unsupported mode: %d\n", rmode); |
|
600 |
+ return 0; |
|
528 | 601 |
} |
529 | 602 |
|
530 | 603 |
inline static int w_t_relay_to_udp( struct sip_msg *p_msg , |
... | ... |
@@ -571,9 +644,26 @@ inline static int w_t_replicate_tcp( struct sip_msg *p_msg , |
571 | 644 |
inline static int w_t_relay( struct sip_msg *p_msg , |
572 | 645 |
char *_foo, char *_bar) |
573 | 646 |
{ |
574 |
- return t_relay_to( p_msg, |
|
647 |
+ struct cell *t; |
|
648 |
+ |
|
649 |
+ if (rmode==MODE_ONFAILURE) { |
|
650 |
+ t=get_t(); |
|
651 |
+ if (!t || t==T_UNDEFINED) { |
|
652 |
+ LOG(L_CRIT, "BUG: w_t_relay: undefined T\n"); |
|
653 |
+ return -1; |
|
654 |
+ } |
|
655 |
+ if (t_forward_nonack(t, p_msg, ( struct proxy_l *) 0, p_msg->rcv.proto)<=0) { |
|
656 |
+ LOG(L_ERR, "ERROR: w_t_relay (failure mode): forwarding failed\n"); |
|
657 |
+ return -1; |
|
658 |
+ } |
|
659 |
+ return 1; |
|
660 |
+ } |
|
661 |
+ if (rmode==MODE_REQUEST) |
|
662 |
+ return t_relay_to( p_msg, |
|
575 | 663 |
(struct proxy_l *) 0 /* no proxy */, p_msg->rcv.proto, |
576 | 664 |
0 /* no replication */ ); |
665 |
+ LOG(L_CRIT, "ERROR: w_t_relay_to: unsupported mode: %d\n", rmode); |
|
666 |
+ return 0; |
|
577 | 667 |
} |
578 | 668 |
|
579 | 669 |
|
... | ... |
@@ -322,6 +322,9 @@ int t_uac_dlg(str* msg, /* Type of the message - MESSAGE, OP |
322 | 322 |
|| !to || !to->s ) { |
323 | 323 |
LOG(L_ERR, "ERROR: t_uac_dlg: invalid parameters\n"); |
324 | 324 |
ser_error = ret = E_INVALID_PARAMS; |
325 |
+#ifdef XL_DEBUG |
|
326 |
+ abort(); |
|
327 |
+#endif |
|
325 | 328 |
goto done; |
326 | 329 |
} |
327 | 330 |
|
... | ... |
@@ -35,6 +35,7 @@ |
35 | 35 |
* 2003-03-19 replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei) |
36 | 36 |
* 2003-04-01 added dst_port, proto, af; renamed comp_port to comp_no, |
37 | 37 |
* inlined all the comp_* functions (andrei) |
38 |
+ * 2003-04-05 s/reply_route/failure_route, onreply_route introduced (jiri) |
|
38 | 39 |
*/ |
39 | 40 |
|
40 | 41 |
|
... | ... |
@@ -63,7 +64,8 @@ |
63 | 64 |
/* main routing script table */ |
64 | 65 |
struct action* rlist[RT_NO]; |
65 | 66 |
/* reply routing table */ |
66 |
-struct action* reply_rlist[REPLY_RT_NO]; |
|
67 |
+struct action* onreply_rlist[ONREPLY_RT_NO]; |
|
68 |
+struct action* failure_rlist[FAILURE_RT_NO]; |
|
67 | 69 |
|
68 | 70 |
|
69 | 71 |
static int fix_actions(struct action* a); /*fwd declaration*/ |
... | ... |
@@ -559,9 +561,16 @@ int fix_rls() |
559 | 561 |
} |
560 | 562 |
} |
561 | 563 |
} |
562 |
- for(i=0;i<REPLY_RT_NO;i++){ |
|
563 |
- if(reply_rlist[i]){ |
|
564 |
- if ((ret=fix_actions(reply_rlist[i]))!=0){ |
|
564 |
+ for(i=0;i<ONREPLY_RT_NO;i++){ |
|
565 |
+ if(onreply_rlist[i]){ |
|
566 |
+ if ((ret=fix_actions(onreply_rlist[i]))!=0){ |
|
567 |
+ return ret; |
|
568 |
+ } |
|
569 |
+ } |
|
570 |
+ } |
|
571 |
+ for(i=0;i<FAILURE_RT_NO;i++){ |
|
572 |
+ if(failure_rlist[i]){ |
|
573 |
+ if ((ret=fix_actions(failure_rlist[i]))!=0){ |
|
565 | 574 |
return ret; |
566 | 575 |
} |
567 | 576 |
} |
... | ... |
@@ -587,13 +596,22 @@ void print_rl() |
587 | 596 |
} |
588 | 597 |
DBG("\n"); |
589 | 598 |
} |
590 |
- for(j=0; j<REPLY_RT_NO; j++){ |
|
591 |
- if (reply_rlist[j]==0){ |
|
592 |
- if (j==0) DBG("WARNING: the main reply routing table is empty\n"); |
|
599 |
+ for(j=0; j<ONREPLY_RT_NO; j++){ |
|
600 |
+ if (onreply_rlist[j]==0){ |
|
593 | 601 |
continue; |
594 | 602 |
} |
595 |
- DBG("routing table %d:\n",j); |
|
596 |
- for (t=reply_rlist[j],i=0; t; i++, t=t->next){ |
|
603 |
+ DBG("onreply routing table %d:\n",j); |
|
604 |
+ for (t=onreply_rlist[j],i=0; t; i++, t=t->next){ |
|
605 |
+ print_action(t); |
|
606 |
+ } |
|
607 |
+ DBG("\n"); |
|
608 |
+ } |
|
609 |
+ for(j=0; j<FAILURE_RT_NO; j++){ |
|
610 |
+ if (failure_rlist[j]==0){ |
|
611 |
+ continue; |
|
612 |
+ } |
|
613 |
+ DBG("failure routing table %d:\n",j); |
|
614 |
+ for (t=failure_rlist[j],i=0; t; i++, t=t->next){ |
|
597 | 615 |
print_action(t); |
598 | 616 |
} |
599 | 617 |
DBG("\n"); |
... | ... |
@@ -44,7 +44,8 @@ |
44 | 44 |
/* main "script table" */ |
45 | 45 |
extern struct action* rlist[RT_NO]; |
46 | 46 |
/* main reply route table */ |
47 |
-extern struct action* reply_rlist[RT_NO]; |
|
47 |
+extern struct action* onreply_rlist[RT_NO]; |
|
48 |
+extern struct action* failure_rlist[RT_NO]; |
|
48 | 49 |
|
49 | 50 |
|
50 | 51 |
void push(struct action* a, struct action** head); |
... | ... |
@@ -32,6 +32,7 @@ |
32 | 32 |
* 2003-03-10 changed module exports interface: added struct cmd_export |
33 | 33 |
* and param_export (andrei) |
34 | 34 |
* 2003-03-16 Added flags field to cmd_export_ (janakj) |
35 |
+ * 2003-04-05 s/reply_route/failure_route, onreply_route introduced (jiri) |
|
35 | 36 |
*/ |
36 | 37 |
|
37 | 38 |
|
... | ... |
@@ -55,8 +56,9 @@ typedef enum { |
55 | 56 |
INT_PARAM, /* Integer parameter type */ |
56 | 57 |
} modparam_t; /* Allowed types of parameters */ |
57 | 58 |
|
58 |
-#define REQUEST_ROUTE 1 /* Function can be used in request route blocks */ |
|
59 |
-#define REPLY_ROUTE 2 /* Function can be used in reply route blocks */ |
|
59 |
+#define REQUEST_ROUTE 1 /* Function can be used in request route blocks */ |
|
60 |
+#define FAILURE_ROUTE 2 /* Function can be used in reply route blocks */ |
|
61 |
+#define ONREPLY_ROUTE 4 /* Function can be used in on_reply */ |
|
60 | 62 |
|
61 | 63 |
/* Macros - used as rank in child_init function */ |
62 | 64 |
#define PROC_MAIN 0 /* Main ser process */ |