- dialog support added
[sip-router] / modules / tm / tm.c
1 /*
2  * $Id$
3  *
4  * TM module
5  *
6  *
7  * ***************************************************
8  * * Jiri's Source Memorial                          *
9  * *                                                 *
10  * * Welcome, pilgrim ! This is the greatest place   *
11  * * where dramatic changes happend. There are not   *
12  * * many places with a history like this, as there  *
13  * * are not so many people like Jiri, one of the    *
14  * * ser's fathers, who brought everywhere the wind  *
15  * * of change, the flood of clean-up. We all felt   *
16  * * his fatherly eye watching over us day and night.*
17  * *                                                 *
18  * * Please, preserve this codework heritage, as     *
19  * * it's unlikly for fresh, juicy pices of code to  *
20  * * arise to give him the again the chance to       *
21  * * demonstrate his clean-up and improvement skills.*
22  * *                                                 *
23  * * Hereby, we solicit you to adopt this historical *
24  * * piece of code. For $100, your name will be      *
25  * * be printed in this banner and we will use       *
26  * * collected funds to create and display an ASCII  *
27  * * statue of Jiri  .                               *
28  * ***************************************************
29  *
30  *
31  * Copyright (C) 2001-2003 Fhg Fokus
32  *
33  * This file is part of ser, a free SIP server.
34  *
35  * ser is free software; you can redistribute it and/or modify
36  * it under the terms of the GNU General Public License as published by
37  * the Free Software Foundation; either version 2 of the License, or
38  * (at your option) any later version
39  *
40  * For a license to use the ser software under conditions
41  * other than those described here, or to purchase support for this
42  * software, please contact iptel.org by e-mail at the following addresses:
43  *    info@iptel.org
44  *
45  * ser is distributed in the hope that it will be useful,
46  * but WITHOUT ANY WARRANTY; without even the implied warranty of
47  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
48  * GNU General Public License for more details.
49  *
50  * You should have received a copy of the GNU General Public License 
51  * along with this program; if not, write to the Free Software 
52  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
53  */
54 /*
55  * History:
56  * --------
57  *  2003-02-18  added t_forward_nonack_{udp, tcp}, t_relay_to_{udp,tcp},
58  *               t_replicate_{udp, tcp} (andrei)
59  *  2003-02-19  added t_rely_{udp, tcp} (andrei)
60  *  2003-03-06  voicemail changes accepted (jiri)
61  *  2003-03-10  module export interface updated to the new format (andrei)
62  *  2003-03-16  flags export parameter added (janakj)
63  *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
64  *  2003-03-30  set_kr for requests only (jiri)
65  *  2003-04-05  s/reply_route/failure_route, onreply_route introduced (jiri)
66  *  2003-04-14  use protocol from uri (jiri)
67  */
68
69
70 #include "defs.h"
71
72
73 #include <stdio.h>
74 #include <string.h>
75 #include <netdb.h>
76
77 #include "../../sr_module.h"
78 #include "../../dprint.h"
79 #include "../../error.h"
80 #include "../../ut.h"
81 #include "../../script_cb.h"
82 #include "../../fifo_server.h"
83 #include "../../mem/mem.h"
84
85 #include "sip_msg.h"
86 #include "h_table.h"
87 #include "t_funcs.h"
88 #include "t_hooks.h"
89 #include "tm_load.h"
90 #include "ut.h"
91 #include "t_reply.h"
92 #include "uac.h"
93 #include "uac_fifo.h"
94 #include "t_fwd.h"
95 #include "t_lookup.h"
96 #include "t_stats.h"
97 #include "callid.h"
98
99 MODULE_VERSION
100
101 inline static int w_t_check(struct sip_msg* msg, char* str, char* str2);
102 inline static int w_t_reply(struct sip_msg* msg, char* str, char* str2);
103
104 inline static int w_t_release(struct sip_msg* msg, char* str, char* str2);
105 inline static int fixup_t_send_reply(void** param, int param_no);
106 inline static int fixup_str2int( void** param, int param_no);
107 inline static int w_t_retransmit_reply(struct sip_msg* p_msg, char* foo, char* bar );
108 inline static int w_t_newtran(struct sip_msg* p_msg, char* foo, char* bar );
109 inline static int w_t_relay( struct sip_msg  *p_msg , char *_foo, char *_bar);
110 inline static int w_t_relay_to_udp( struct sip_msg  *p_msg , char *proxy, 
111                                     char *);
112 inline static int w_t_relay_to_tcp( struct sip_msg  *p_msg , char *proxy,
113                                     char *);
114 inline static int w_t_replicate( struct sip_msg  *p_msg , 
115                                  char *proxy, /* struct proxy_l *proxy expected */
116                                  char *_foo       /* nothing expected */ );
117 inline static int w_t_replicate_udp( struct sip_msg  *p_msg , 
118                                      char *proxy, /* struct proxy_l *proxy expected */
119                                      char *_foo       /* nothing expected */ );
120 inline static int w_t_replicate_tcp( struct sip_msg  *p_msg , 
121                                      char *proxy, /* struct proxy_l *proxy expected */
122                                      char *_foo       /* nothing expected */ );
123 inline static int w_t_forward_nonack(struct sip_msg* msg, char* str, char* );
124 inline static int w_t_forward_nonack_udp(struct sip_msg* msg, char* str,char*);
125 inline static int w_t_forward_nonack_tcp(struct sip_msg* msg, char* str,char*);
126 inline static int fixup_hostport2proxy(void** param, int param_no);
127 inline static int w_t_on_negative( struct sip_msg* msg, char *go_to, char *foo );
128 inline static int w_t_on_reply( struct sip_msg* msg, char *go_to, char *foo );
129
130
131 static int mod_init(void);
132
133 static int child_init(int rank);
134
135
136 static cmd_export_t cmds[]={
137         {"t_newtran",          w_t_newtran,             0, 0,                    REQUEST_ROUTE},
138         {"t_lookup_request",   w_t_check,               0, 0,                    REQUEST_ROUTE},
139         {T_REPLY,              w_t_reply,               2, fixup_t_send_reply,   
140                         REQUEST_ROUTE | FAILURE_ROUTE },
141         {"t_retransmit_reply", w_t_retransmit_reply,    0, 0,                    REQUEST_ROUTE},
142         {"t_release",          w_t_release,             0, 0,                    REQUEST_ROUTE},
143         {T_RELAY_TO_UDP,       w_t_relay_to_udp,        2, fixup_hostport2proxy, REQUEST_ROUTE|FAILURE_ROUTE},
144         {T_RELAY_TO_TCP,       w_t_relay_to_tcp,        2, fixup_hostport2proxy, REQUEST_ROUTE|FAILURE_ROUTE},
145         {"t_replicate",        w_t_replicate,           2, fixup_hostport2proxy, REQUEST_ROUTE},
146         {"t_replicate_udp",    w_t_replicate_udp,       2, fixup_hostport2proxy, REQUEST_ROUTE},
147         {"t_replicate_tcp",    w_t_replicate_tcp,       2, fixup_hostport2proxy, REQUEST_ROUTE},
148         {T_RELAY,              w_t_relay,               0, 0,                    
149                         REQUEST_ROUTE | FAILURE_ROUTE },
150         {T_FORWARD_NONACK,     w_t_forward_nonack,      2, fixup_hostport2proxy, REQUEST_ROUTE},
151         {T_FORWARD_NONACK_UDP, w_t_forward_nonack_udp,  2, fixup_hostport2proxy, REQUEST_ROUTE},
152         {T_FORWARD_NONACK_TCP, w_t_forward_nonack_tcp,  2, fixup_hostport2proxy, REQUEST_ROUTE},
153         {"t_on_failure",       w_t_on_negative,         1, fixup_str2int,
154                         REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE },
155         {"t_on_reply",         w_t_on_reply,            1, fixup_str2int,
156                         REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE },
157         /* not applicable from the script */
158         {"register_tmcb",      (cmd_function)register_tmcb,     NO_SCRIPT,     0, 0},
159         {"load_tm",            (cmd_function)load_tm,           NO_SCRIPT,     0, 0},
160         {T_REPLY_WB,           (cmd_function)t_reply_with_body, NO_SCRIPT,     0, 0},
161         {T_IS_LOCAL,           (cmd_function)t_is_local,        NO_SCRIPT,     0, 0},
162         {T_GET_TI,             (cmd_function)t_get_trans_ident, NO_SCRIPT,     0, 0},
163         {T_LOOKUP_IDENT,       (cmd_function)t_lookup_ident,    NO_SCRIPT,     0, 0},
164         {T_ADDBLIND,           (cmd_function)add_blind_uac,     NO_SCRIPT,     0, 0},
165         {"t_request_within",   (cmd_function)req_within,        NO_SCRIPT,     0, 0},
166         {"t_request_outside",  (cmd_function)req_outside,       NO_SCRIPT,     0, 0},
167         {"t_request",          (cmd_function)request,           NO_SCRIPT,     0, 0},
168         {"new_dlg_uac",        (cmd_function)new_dlg_uac,       NO_SCRIPT,     0, 0},
169         {"dlg_response_uac",   (cmd_function)dlg_response_uac,  NO_SCRIPT,     0, 0},
170         {"new_dlg_uas",        (cmd_function)new_dlg_uas,       NO_SCRIPT,     0, 0},
171         {"dlg_request_uas",    (cmd_function)dlg_request_uas,   NO_SCRIPT,     0, 0},
172         {"free_dlg",           (cmd_function)free_dlg,          NO_SCRIPT,     0, 0},
173         {"print_dlg",          (cmd_function)print_dlg,         NO_SCRIPT,     0, 0},
174         {0,0,0,0,0}
175 };
176
177 static param_export_t params[]={
178         {"ruri_matching", INT_PARAM, &ruri_matching                         },
179         {"fr_timer",      INT_PARAM, &(timer_id2timeout[FR_TIMER_LIST])     },
180         {"fr_inv_timer",  INT_PARAM, &(timer_id2timeout[FR_INV_TIMER_LIST]) },
181         {"wt_timer",      INT_PARAM, &(timer_id2timeout[WT_TIMER_LIST])     },
182         {"delete_timer",  INT_PARAM, &(timer_id2timeout[DELETE_LIST])       },
183         {"retr_timer1p1", INT_PARAM, &(timer_id2timeout[RT_T1_TO_1])        },
184         {"retr_timer1p2", INT_PARAM, &(timer_id2timeout[RT_T1_TO_2])        },
185         {"retr_timer1p3", INT_PARAM, &(timer_id2timeout[RT_T1_TO_3])        },
186         {"retr_timer2",   INT_PARAM, &(timer_id2timeout[RT_T2])             },
187         {"noisy_ctimer",  INT_PARAM, &noisy_ctimer                          },
188         {"uac_from",      STR_PARAM, &uac_from                              },
189         {0,0,0}
190 };
191
192
193 #ifdef STATIC_TM
194 struct module_exports tm_exports = {
195 #else
196 struct module_exports exports= {
197 #endif
198         "tm",
199         /* -------- exported functions ----------- */
200         cmds,
201         /* ------------ exported variables ---------- */
202         params,
203         
204         mod_init, /* module initialization function */
205         (response_function) reply_received,
206         (destroy_function) tm_shutdown,
207         0, /* w_onbreak, */
208         child_init /* per-child init function */
209 };
210
211 inline static int fixup_str2int( void** param, int param_no)
212 {
213         unsigned long go_to;
214         int err;
215
216         if (param_no==1) {
217                 go_to=str2s(*param, strlen(*param), &err );
218                 if (err==0) {
219                         pkg_free(*param);
220                         *param=(void *)go_to;
221                         return 0;
222                 } else {
223                         LOG(L_ERR, "ERROR: fixup_str2int: bad number <%s>\n",
224                                 (char *)(*param));
225                         return E_CFG;
226                 }
227         }
228         return 0;
229 }
230
231 static int w_t_unref( struct sip_msg *foo, void *bar)
232 {
233         return t_unref(foo);
234 }
235
236 static int script_init( struct sip_msg *foo, void *bar)
237 {   
238         /* we primarily reset all private memory here to make sure
239            private values left over from previous message will
240            not be used again
241     */
242
243         if (foo->first_line.type==SIP_REQUEST){
244                 /* make sure the new message will not inherit previous
245                         message's t_on_negative value
246                 */
247                 t_on_negative( 0 );
248                 t_on_reply(0);
249                 /* reset the kr status */
250                 set_kr(0);
251                 /* set request mode so that multiple-mode actions know
252                  * how to behave */
253                 rmode=MODE_REQUEST;
254         }
255
256         return 1;
257 }
258
259 static int mod_init(void)
260 {
261
262         DBG( "TM - initializing...\n");
263         /* checking if we have sufficient bitmap capacity for given
264            maximum number of  branches */
265         if (MAX_BRANCHES+1>31) {
266                 LOG(L_CRIT, "Too many max UACs for UAC branch_bm_t bitmap: %d\n",
267                         MAX_BRANCHES );
268                 return -1;
269         }
270
271         if (init_callid() < 0) {
272                 LOG(L_CRIT, "Error while initializin Call-ID generator\n");
273                 return -1;
274         }
275
276         if (register_fifo_cmd(fifo_uac, "t_uac_dlg", 0) < 0) {
277                 LOG(L_CRIT, "cannot register fifo t_uac\n");
278                 return -1;
279         }
280
281         if (register_fifo_cmd(fifo_hash, "t_hash", 0)<0) {
282                 LOG(L_CRIT, "cannot register hash\n");
283                 return -1;
284         }
285
286         if (!init_hash_table()) {
287                 LOG(L_ERR, "ERROR: mod_init: initializing hash_table failed\n");
288                 return -1;
289         }
290
291
292         /* init static hidden values */
293         init_t();
294
295         if (!tm_init_timers()) {
296                 LOG(L_ERR, "ERROR: mod_init: timer init failed\n");
297                 return -1;
298         }
299         /* register the timer function */
300         register_timer( timer_routine , 0 /* empty attr */, 1 );
301
302         /* init_tm_stats calls process_count, which should
303          * NOT be called from mod_init, because one does not
304          * now, if a timer is used and thus how many processes
305          * will be started; however we started already our
306          * timers, so we know and process_count should not
307          * change any more
308          */     
309         if (init_tm_stats()<0) {
310                 LOG(L_CRIT, "ERROR: mod_init: failed to init stats\n");
311                 return -1;
312         }
313
314         /* building the hash table*/
315
316         if (uac_init()==-1) {
317                 LOG(L_ERR, "ERROR: mod_init: uac_init failed\n");
318                 return -1;
319         }
320         /* register post-script clean-up function */
321         register_script_cb( w_t_unref, POST_SCRIPT_CB, 
322                         0 /* empty param */ );
323         register_script_cb( script_init, PRE_SCRIPT_CB , 
324                         0 /* empty param */ );
325
326         tm_init_tags();
327
328         return 0;
329 }
330
331 static int child_init(int rank) {
332         if (child_init_callid(rank) < 0) {
333                 LOG(L_ERR, "ERROR: child_init: Error while initializing Call-ID generator\n");
334                 return -2;
335         }
336
337         return 0;
338 }
339
340
341 /* (char *hostname, char *port_nr) ==> (struct proxy_l *, -)  */
342
343 inline static int fixup_hostport2proxy(void** param, int param_no)
344 {
345         unsigned int port;
346         char *host;
347         int err;
348         struct proxy_l *proxy;
349         str s;
350         
351         DBG("TM module: fixup_t_forward(%s, %d)\n", (char*)*param, param_no);
352         if (param_no==1){
353                 DBG("TM module: fixup_t_forward: param 1.. do nothing, wait for #2\n");
354                 return 0;
355         } else if (param_no==2) {
356
357                 host=(char *) (*(param-1)); 
358                 port=str2s(*param, strlen(*param), &err);
359                 if (err!=0) {
360                         LOG(L_ERR, "TM module:fixup_t_forward: bad port number <%s>\n",
361                                 (char*)(*param));
362                          return E_UNSPEC;
363                 }
364                 s.s = host;
365                 s.len = strlen(host);
366                 proxy=mk_proxy(&s, port, 0); /* FIXME: udp or tcp? */
367                 if (proxy==0) {
368                         LOG(L_ERR, "ERROR: fixup_t_forwardv6: bad host name in URI <%s>\n",
369                                 host );
370                         return E_BAD_ADDRESS;
371                 }
372                 /* success -- fix the first parameter to proxy now ! */
373
374                 /* FIXME: janakj, mk_proxy doesn't make copy of host !! */
375                 /*pkg_free( *(param-1)); you're right --andrei*/
376                 *(param-1)=proxy;
377                 return 0;
378         } else {
379                 LOG(L_ERR, "ERROR: fixup_t_forwardv6 called with parameter #<>{1,2}\n");
380                 return E_BUG;
381         }
382 }
383
384
385 /* (char *code, char *reason_phrase)==>(int code, r_p as is) */
386 inline static int fixup_t_send_reply(void** param, int param_no)
387 {
388         unsigned long code;
389         int err;
390
391         if (param_no==1){
392                 code=str2s(*param, strlen(*param), &err);
393                 if (err==0){
394                         pkg_free(*param);
395                         *param=(void*)code;
396                         return 0;
397                 }else{
398                         LOG(L_ERR, "TM module:fixup_t_send_reply: bad  number <%s>\n",
399                                         (char*)(*param));
400                         return E_UNSPEC;
401                 }
402         }
403         /* second param => no conversion*/
404         return 0;
405 }
406
407
408
409
410 inline static int w_t_check(struct sip_msg* msg, char* str, char* str2)
411 {
412         return t_check( msg , 0  ) ? 1 : -1;
413 }
414
415
416
417 inline static int _w_t_forward_nonack(struct sip_msg* msg, char* proxy,
418                                                                          char* _foo, int proto)
419 {
420         struct cell *t;
421         if (t_check( msg , 0 )==-1) {
422                 LOG(L_ERR, "ERROR: forward_nonack: "
423                                 "can't forward when no transaction was set up\n");
424                 return -1;
425         }
426         t=get_t();
427         if ( t && t!=T_UNDEFINED ) {
428                 if (msg->REQ_METHOD==METHOD_ACK) {
429                         LOG(L_WARN,"WARNING: you don't really want to fwd hbh ACK\n");
430                         return -1;
431                 }
432                 return t_forward_nonack(t, msg, ( struct proxy_l *) proxy, proto );
433         } else {
434                 DBG("DEBUG: t_forward_nonack: no transaction found\n");
435                 return -1;
436         }
437 }
438
439
440 inline static int w_t_forward_nonack( struct sip_msg* msg, char* proxy,
441                                                                                 char* foo)
442 {
443         return _w_t_forward_nonack(msg, proxy, foo, PROTO_NONE);
444 }
445
446 inline static int w_t_forward_nonack_udp( struct sip_msg* msg, char* proxy,
447                                                                                 char* foo)
448 {
449         return _w_t_forward_nonack(msg, proxy, foo, PROTO_UDP);
450 }
451
452 inline static int w_t_forward_nonack_tcp( struct sip_msg* msg, char* proxy,
453                                                                                 char* foo)
454 {
455         return _w_t_forward_nonack(msg, proxy, foo, PROTO_TCP);
456 }
457
458
459
460 inline static int w_t_reply(struct sip_msg* msg, char* str, char* str2)
461 {
462         struct cell *t;
463
464         if (msg->REQ_METHOD==METHOD_ACK) {
465                 LOG(L_WARN, "WARNING: t_reply: ACKs are not replied\n");
466                 return -1;
467         }
468         if (t_check( msg , 0 )==-1) return -1;
469         t=get_t();
470         if (!t) {
471                 LOG(L_ERR, "ERROR: t_reply: cannot send a t_reply to a message "
472                         "for which no T-state has been established\n");
473                 return -1;
474         }
475         /* if called from reply_route, make sure that unsafe version
476          * is called; we are already in a mutex and another mutex in
477          * the safe version would lead to a deadlock
478          */
479         if (rmode==MODE_ONFAILURE) { 
480                 DBG("DEBUG: t_reply_unsafe called from w_t_reply\n");
481                 return t_reply_unsafe(t, msg, (unsigned int)(long) str, str2);
482         } else if (rmode==MODE_REQUEST) {
483                 return t_reply( t, msg, (unsigned int)(long) str, str2);
484         } else {
485                 LOG(L_CRIT, "BUG: w_t_reply entered in unsupported mode\n");
486                 return -1;
487         }
488 }
489
490
491 inline static int w_t_release(struct sip_msg* msg, char* str, char* str2)
492 {
493         struct cell *t;
494         if (t_check( msg  , 0  )==-1) return -1;
495         t=get_t();
496         if ( t && t!=T_UNDEFINED ) 
497                 return t_release_transaction( t );
498         return 1;
499 }
500
501
502
503
504 inline static int w_t_retransmit_reply( struct sip_msg* p_msg, char* foo, char* bar)
505 {
506         struct cell *t;
507
508
509         if (t_check( p_msg  , 0 )==-1) 
510                 return 1;
511         t=get_t();
512         if (t) {
513                 if (p_msg->REQ_METHOD==METHOD_ACK) {
514                         LOG(L_WARN, "WARNING: : ACKs ansmit_replies not replied\n");
515                         return -1;
516                 }
517                 return t_retransmit_reply( t );
518         } else 
519                 return -1;
520 }
521
522
523 inline static int w_t_newtran( struct sip_msg* p_msg, char* foo, char* bar ) 
524 {
525         /* t_newtran returns 0 on error (negative value means
526            'transaction exists'
527         */
528         return t_newtran( p_msg );
529 }
530
531
532 inline static int w_t_on_negative( struct sip_msg* msg, char *go_to, char *foo )
533 {
534         struct cell *t;
535
536         if (rmode==MODE_REQUEST || rmode==MODE_ONFAILURE) {
537                 t_on_negative( (unsigned int )(long) go_to );
538                 return 1;
539         }
540         if (rmode==MODE_ONREPLY ) {
541                 /* transaction state is established */
542                 t=get_t();
543                 if (!t || t==T_UNDEFINED) {
544                         LOG(L_CRIT, "BUG: w_t_on_negative entered without t\n");
545                         return -1;
546                 }
547                 t->on_negative=(unsigned int)(long)go_to;
548                 return 1;
549         }
550         LOG(L_CRIT, "BUG: w_t_on_negative entered in unsupported mode\n");
551         return -1;
552 }
553 inline static int w_t_on_reply( struct sip_msg* msg, char *go_to, char *foo )
554 {
555         struct cell *t;
556
557         if (rmode==MODE_REQUEST) {
558                 /* it's still in initial request processing stage, transaction
559                  * state is not estabslihed yet, store it in private memory ...
560                  * it will be copied to transaction state when it is set up */
561                 t_on_reply( (unsigned int )(long) go_to );
562                 return 1;
563         }
564         if (rmode==MODE_ONREPLY || rmode==MODE_ONFAILURE) {
565                 /* transaction state is established */
566                 t=get_t();
567                 if (!t || t==T_UNDEFINED) {
568                         LOG(L_CRIT, "BUG: w_t_on_reply entered without t\n");
569                         return -1;
570                 }
571                 t->on_reply=(unsigned int) (long)go_to;
572                 return 1;
573         }
574         LOG(L_CRIT, "BUG: w_t_on_reply entered in unsupported mode\n");
575         return -1;
576 }
577
578 inline static int _w_t_relay_to( struct sip_msg  *p_msg , 
579         struct proxy_l *proxy )
580 {
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, proxy, PROTO_NONE)<=0 ) {
590                         LOG(L_ERR, "ERROR: failure_route: t_relay_to failed\n");
591                         return -1;
592                 }
593                 return 1;
594         }
595         if (rmode==MODE_REQUEST) 
596                 return t_relay_to( p_msg, proxy, PROTO_NONE,
597                         0 /* no replication */ );
598         LOG(L_CRIT, "ERROR: w_t_relay_to: unsupported mode: %d\n", rmode);
599         return 0;
600 }
601
602 inline static int w_t_relay_to_udp( struct sip_msg  *p_msg , 
603         char *proxy, /* struct proxy_l *proxy expected */
604         char *_foo       /* nothing expected */ )
605 {
606         ((struct proxy_l *)proxy)->proto=PROTO_UDP;
607         return _w_t_relay_to( p_msg, ( struct proxy_l *) proxy);
608 }
609
610 inline static int w_t_relay_to_tcp( struct sip_msg  *p_msg , 
611         char *proxy, /* struct proxy_l *proxy expected */
612         char *_foo       /* nothing expected */ )
613 {
614         ((struct proxy_l *)proxy)->proto=PROTO_TCP;
615         return _w_t_relay_to( p_msg, ( struct proxy_l *) proxy);
616 }
617
618
619
620 inline static int w_t_replicate( struct sip_msg  *p_msg , 
621         char *proxy, /* struct proxy_l *proxy expected */
622         char *_foo       /* nothing expected */ )
623 {
624         return t_replicate(p_msg, ( struct proxy_l *) proxy, p_msg->rcv.proto );
625 }
626
627 inline static int w_t_replicate_udp( struct sip_msg  *p_msg , 
628         char *proxy, /* struct proxy_l *proxy expected */
629         char *_foo       /* nothing expected */ )
630 {
631         return t_replicate(p_msg, ( struct proxy_l *) proxy, PROTO_UDP );
632 }
633
634 inline static int w_t_replicate_tcp( struct sip_msg  *p_msg , 
635         char *proxy, /* struct proxy_l *proxy expected */
636         char *_foo       /* nothing expected */ )
637 {
638         return t_replicate(p_msg, ( struct proxy_l *) proxy, PROTO_TCP );
639 }
640
641
642
643 inline static int w_t_relay( struct sip_msg  *p_msg , 
644                                                 char *_foo, char *_bar)
645 {
646         struct cell *t;
647
648         if (rmode==MODE_ONFAILURE) { 
649                 t=get_t();
650                 if (!t || t==T_UNDEFINED) {
651                         LOG(L_CRIT, "BUG: w_t_relay: undefined T\n");
652                         return -1;
653                 } 
654                 if (t_forward_nonack(t, p_msg, ( struct proxy_l *) 0, PROTO_NONE)<=0) {
655                         LOG(L_ERR, "ERROR: w_t_relay (failure mode): forwarding failed\n");
656                         return -1;
657                 }
658                 return 1;
659         }
660         if (rmode==MODE_REQUEST) 
661                 return t_relay_to( p_msg, 
662                 (struct proxy_l *) 0 /* no proxy */, PROTO_NONE,
663                 0 /* no replication */ );
664         LOG(L_CRIT, "ERROR: w_t_relay_to: unsupported mode: %d\n", rmode);
665         return 0;
666 }
667
668
669 inline static int w_t_relay_udp( struct sip_msg  *p_msg , 
670                                                 char *_foo, char *_bar)
671 {
672         return t_relay_to( p_msg, 
673                 (struct proxy_l *) 0 /* no proxy */, PROTO_UDP,
674                 0 /* no replication */ );
675 }
676
677
678 inline static int w_t_relay_tcp( struct sip_msg  *p_msg , 
679                                                 char *_foo, char *_bar)
680 {
681         return t_relay_to( p_msg, 
682                 (struct proxy_l *) 0 /* no proxy */, PROTO_TCP,
683                 0 /* no replication */ );
684 }