7 * ***************************************************
8 * * Jiri's Source Memorial *
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.*
18 * * Please, preserve this codework heritage, as *
19 * * it's unlikely for fresh, juicy pieces of code to *
20 * * arise to give him the again the chance to *
21 * * demonstrate his clean-up and improvement skills.*
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 * ***************************************************
31 * Copyright (C) 2001-2003 FhG Fokus
33 * This file is part of ser, a free SIP server.
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
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:
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.
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
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 * 2003-07-07 added t_relay_to_tls, t_replicate_tls, t_forward_nonack_tls
68 * added #ifdef USE_TCP, USE_TLS
69 * removed t_relay_{udp,tcp,tls} (andrei)
70 * 2003-09-26 added t_forward_nonack_uri() - same as t_forward_nonack() but
71 * takes no parameters -> forwards to uri (bogdan)
72 * 2004-02-11 FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri)
73 * 2004-02-18 t_reply exported via FIFO - imported from VM (bogdan)
74 * 2004-10-01 added a new param.: restart_fr_on_each_reply (andrei)
75 * 2005-11-14 new timer support, changed timer related module params (andrei)
76 * 2005-12-09 fixup_hostport2proxy uses route_struct to access param #1
77 * when fixing param #2
78 * 2005-12-09 added t_set_fr() (andrei)
79 * 2006-02-07 named routes support (andrei)
80 * 2006-09-28 added t_branch_replied, t_branch_timeout, t_any_replied,
81 * t_any_timeout, t_is_canceled (andrei)
82 * 2006-10-16 added a new param.: aggregate challenges (andrei)
83 * 2007-05-28 two new params: reparse_invite, ac_extra_hdrs
84 * added w_t_relay_cancel() (Miklos)
85 * 2007-06-05 added t_set_auto_inv_100() and auto_inv_100 (param);
86 * t_set_max_lifetime(), max_{non}inv_lifetime (andrei)
87 * 2008-02-05 module config parameters use the configuration framework (Miklos)
88 * 2008-02-29 added t_grep_status(code) (andrei)
99 #include "../../sr_module.h"
100 #include "../../dprint.h"
101 #include "../../error.h"
102 #include "../../ut.h"
103 #include "../../script_cb.h"
104 #include "../../usr_avp.h"
105 #include "../../mem/mem.h"
106 #include "../../route_struct.h"
107 #include "../../route.h"
108 #include "../../cfg/cfg.h"
109 #include "../../globals.h"
120 #include "t_lookup.h"
123 #include "t_cancel.h"
126 #include "t_msgbuilder.h"
131 /* fixup functions */
132 static int fixup_hostport2proxy(void** param, int param_no);
133 static int fixup_proto_hostport2proxy(void** param, int param_no);
134 static int fixup_on_failure(void** param, int param_no);
135 static int fixup_on_reply(void** param, int param_no);
136 static int fixup_on_branch(void** param, int param_no);
137 static int fixup_t_reply(void** param, int param_no);
141 static int mod_init(void);
142 static int child_init(int rank);
145 /* exported functions */
146 inline static int w_t_check(struct sip_msg* msg, char* str, char* str2);
147 inline static int w_t_lookup_cancel(struct sip_msg* msg, char* str, char* str2);
148 inline static int w_t_reply(struct sip_msg* msg, char* str, char* str2);
149 inline static int w_t_release(struct sip_msg* msg, char* str, char* str2);
150 inline static int w_t_retransmit_reply(struct sip_msg* p_msg, char* foo,
152 inline static int w_t_newtran(struct sip_msg* p_msg, char* foo, char* bar );
153 inline static int w_t_relay( struct sip_msg *p_msg , char *_foo, char *_bar);
154 inline static int w_t_relay_to_udp( struct sip_msg *p_msg , char *proxy,
157 inline static int w_t_relay_to_tcp( struct sip_msg *p_msg , char *proxy,
161 inline static int w_t_relay_to_tls( struct sip_msg *p_msg , char *proxy,
164 inline static int w_t_relay_to(struct sip_msg* msg, char* str,char*);
165 inline static int w_t_replicate( struct sip_msg *p_msg ,
166 char *proxy, /* struct proxy_l *proxy expected */
167 char *_foo /* nothing expected */ );
168 inline static int w_t_replicate_udp( struct sip_msg *p_msg ,
169 char *proxy, /* struct proxy_l *proxy expected */
170 char *_foo /* nothing expected */ );
172 inline static int w_t_replicate_tcp( struct sip_msg *p_msg ,
173 char *proxy, /* struct proxy_l *proxy expected */
174 char *_foo /* nothing expected */ );
177 inline static int w_t_replicate_tls( struct sip_msg *p_msg ,
178 char *proxy, /* struct proxy_l *proxy expected */
179 char *_foo /* nothing expected */ );
181 inline static int w_t_replicate_to(struct sip_msg* msg, char* str,char*);
182 inline static int w_t_forward_nonack(struct sip_msg* msg, char* str, char* );
183 inline static int w_t_forward_nonack_uri(struct sip_msg* msg, char* str,char*);
184 inline static int w_t_forward_nonack_udp(struct sip_msg* msg, char* str,char*);
186 inline static int w_t_forward_nonack_tcp(struct sip_msg* msg, char* str,char*);
189 inline static int w_t_forward_nonack_tls(struct sip_msg* msg, char* str,char*);
191 inline static int w_t_forward_nonack_to(struct sip_msg* msg, char* str,char*);
192 inline static int w_t_relay_cancel(struct sip_msg *p_msg, char *_foo, char *_bar);
193 inline static int w_t_on_negative(struct sip_msg* msg, char *go_to, char *foo);
194 inline static int w_t_on_branch(struct sip_msg* msg, char *go_to, char *foo);
195 inline static int w_t_on_reply(struct sip_msg* msg, char *go_to, char *foo );
196 inline static int t_check_status(struct sip_msg* msg, char *match, char *foo);
197 static int t_set_fr_inv(struct sip_msg* msg, char* fr_inv, char* foo);
198 static int t_set_fr_all(struct sip_msg* msg, char* fr_inv, char* fr);
199 static int w_t_reset_fr(struct sip_msg* msg, char* foo, char* bar);
200 static int w_t_set_retr(struct sip_msg* msg, char* retr_t1, char* retr_t2);
201 static int w_t_reset_retr(struct sip_msg* msg, char* foo, char* bar);
202 static int w_t_set_max_lifetime(struct sip_msg* msg, char* inv, char* noninv);
203 static int w_t_reset_max_lifetime(struct sip_msg* msg, char* foo, char* bar);
204 static int t_set_auto_inv_100(struct sip_msg* msg, char* on_off, char* foo);
205 static int t_branch_timeout(struct sip_msg* msg, char*, char*);
206 static int t_branch_replied(struct sip_msg* msg, char*, char*);
207 static int t_any_timeout(struct sip_msg* msg, char*, char*);
208 static int t_any_replied(struct sip_msg* msg, char*, char*);
209 static int t_is_canceled(struct sip_msg* msg, char*, char*);
210 static int t_grep_status(struct sip_msg* msg, char*, char*);
213 /* by default the fr timers avps are not set, so that the avps won't be
214 * searched for nothing each time a new transaction is created */
215 static char *fr_timer_param = 0 /*FR_TIMER_AVP*/;
216 static char *fr_inv_timer_param = 0 /*FR_INV_TIMER_AVP*/;
218 static rpc_export_t tm_rpc[];
220 static int fixup_t_check_status(void** param, int param_no);
222 static cmd_export_t cmds[]={
223 {"t_newtran", w_t_newtran, 0, 0,
225 {"t_lookup_request", w_t_check, 0, 0,
227 {"t_lookup_cancel", w_t_lookup_cancel, 0, 0,
229 {T_REPLY, w_t_reply, 2, fixup_t_reply,
230 REQUEST_ROUTE | FAILURE_ROUTE },
231 {"t_retransmit_reply", w_t_retransmit_reply, 0, 0,
233 {"t_release", w_t_release, 0, 0,
235 {T_RELAY_TO_UDP, w_t_relay_to_udp, 2, fixup_hostport2proxy,
236 REQUEST_ROUTE|FAILURE_ROUTE},
238 {T_RELAY_TO_TCP, w_t_relay_to_tcp, 2, fixup_hostport2proxy,
239 REQUEST_ROUTE|FAILURE_ROUTE},
242 {T_RELAY_TO_TLS, w_t_relay_to_tls, 2, fixup_hostport2proxy,
243 REQUEST_ROUTE|FAILURE_ROUTE},
245 {"t_replicate", w_t_replicate, 2, fixup_hostport2proxy,
247 {"t_replicate_udp", w_t_replicate_udp, 2, fixup_hostport2proxy,
250 {"t_replicate_tcp", w_t_replicate_tcp, 2, fixup_hostport2proxy,
254 {"t_replicate_tls", w_t_replicate_tls, 2, fixup_hostport2proxy,
257 {"t_replicate_to", w_t_replicate_to, 2, fixup_proto_hostport2proxy,
259 {T_RELAY, w_t_relay, 0, 0,
260 REQUEST_ROUTE | FAILURE_ROUTE },
261 {"t_relay_to", w_t_relay_to, 2, fixup_proto_hostport2proxy,
263 {T_FORWARD_NONACK, w_t_forward_nonack, 2, fixup_hostport2proxy,
265 {T_FORWARD_NONACK_URI, w_t_forward_nonack_uri, 0, 0,
267 {T_FORWARD_NONACK_UDP, w_t_forward_nonack_udp, 2, fixup_hostport2proxy,
270 {T_FORWARD_NONACK_TCP, w_t_forward_nonack_tcp, 2, fixup_hostport2proxy,
274 {T_FORWARD_NONACK_TLS, w_t_forward_nonack_tls, 2, fixup_hostport2proxy,
277 {"t_forward_nonack_to", w_t_forward_nonack_to, 2, fixup_proto_hostport2proxy,
279 {"t_relay_cancel", w_t_relay_cancel, 0, 0,
281 {"t_on_failure", w_t_on_negative, 1, fixup_on_failure,
282 REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE },
283 {"t_on_reply", w_t_on_reply, 1, fixup_on_reply,
284 REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE },
285 {"t_on_branch", w_t_on_branch, 1, fixup_on_branch,
286 REQUEST_ROUTE | FAILURE_ROUTE },
287 {"t_check_status", t_check_status, 1, fixup_t_check_status,
288 REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE },
289 {"t_write_req", t_write_req, 2, fixup_t_write,
290 REQUEST_ROUTE | FAILURE_ROUTE },
291 {"t_write_unix", t_write_unix, 2, fixup_t_write,
292 REQUEST_ROUTE | FAILURE_ROUTE },
293 {"t_set_fr", t_set_fr_inv, 1, fixup_var_int_1,
294 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE },
295 {"t_set_fr", t_set_fr_all, 2, fixup_var_int_12,
296 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE },
297 {"t_reset_fr", w_t_reset_fr, 0, 0,
298 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE },
299 {"t_set_retr", w_t_set_retr, 2, fixup_var_int_12,
300 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE },
301 {"t_reset_retr", w_t_reset_retr, 0, 0,
302 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE },
303 {"t_set_max_lifetime", w_t_set_max_lifetime, 2, fixup_var_int_12,
304 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE },
305 {"t_reset_max_lifetime", w_t_reset_max_lifetime, 0, 0,
306 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE },
307 {"t_set_auto_inv_100", t_set_auto_inv_100, 1, fixup_var_int_1,
309 {"t_branch_timeout", t_branch_timeout, 0, 0, FAILURE_ROUTE},
310 {"t_branch_replied", t_branch_replied, 0, 0, FAILURE_ROUTE},
311 {"t_any_timeout", t_any_timeout, 0, 0,
312 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE },
313 {"t_any_replied", t_any_replied, 0, 0,
314 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE },
315 {"t_is_canceled", t_is_canceled, 0, 0,
316 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE },
317 {"t_grep_status", t_grep_status, 1, fixup_var_int_1,
318 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE },
320 /* not applicable from the script */
321 {"register_tmcb", (cmd_function)register_tmcb, NO_SCRIPT, 0, 0},
322 {"load_tm", (cmd_function)load_tm, NO_SCRIPT, 0, 0},
323 {T_REPLY_WB, (cmd_function)t_reply_with_body, NO_SCRIPT, 0, 0},
324 {T_IS_LOCAL, (cmd_function)t_is_local, NO_SCRIPT, 0, 0},
325 {T_GET_TI, (cmd_function)t_get_trans_ident, NO_SCRIPT, 0, 0},
326 {T_LOOKUP_IDENT, (cmd_function)t_lookup_ident, NO_SCRIPT, 0, 0},
327 {T_ADDBLIND, (cmd_function)add_blind_uac, NO_SCRIPT, 0, 0},
328 {"t_request_within", (cmd_function)req_within, NO_SCRIPT, 0, 0},
329 {"t_request_outside", (cmd_function)req_outside, NO_SCRIPT, 0, 0},
330 {"t_request", (cmd_function)request, NO_SCRIPT, 0, 0},
331 {"new_dlg_uac", (cmd_function)new_dlg_uac, NO_SCRIPT, 0, 0},
332 {"dlg_response_uac", (cmd_function)dlg_response_uac, NO_SCRIPT, 0, 0},
333 {"new_dlg_uas", (cmd_function)new_dlg_uas, NO_SCRIPT, 0, 0},
334 {"update_dlg_uas", (cmd_function)update_dlg_uas, NO_SCRIPT, 0, 0},
335 {"dlg_request_uas", (cmd_function)dlg_request_uas, NO_SCRIPT, 0, 0},
336 {"set_dlg_target", (cmd_function)set_dlg_target, NO_SCRIPT, 0, 0},
337 {"free_dlg", (cmd_function)free_dlg, NO_SCRIPT, 0, 0},
338 {"print_dlg", (cmd_function)print_dlg, NO_SCRIPT, 0, 0},
339 {T_GETT, (cmd_function)get_t, NO_SCRIPT, 0, 0},
340 {"calculate_hooks", (cmd_function)w_calculate_hooks, NO_SCRIPT, 0, 0},
341 {"t_uac", (cmd_function)t_uac, NO_SCRIPT, 0, 0},
342 {"t_uac_with_ids", (cmd_function)t_uac_with_ids, NO_SCRIPT, 0, 0},
343 {"t_unref", (cmd_function)t_unref, NO_SCRIPT, 0, 0},
344 {"run_failure_handlers", (cmd_function)run_failure_handlers, NO_SCRIPT, 0, 0},
345 {"cancel_uacs", (cmd_function)cancel_uacs, NO_SCRIPT, 0, 0},
350 static param_export_t params[]={
351 {"ruri_matching", PARAM_INT, &default_tm_cfg.ruri_matching },
352 {"via1_matching", PARAM_INT, &default_tm_cfg.via1_matching },
353 {"fr_timer", PARAM_INT, &default_tm_cfg.fr_timeout },
354 {"fr_inv_timer", PARAM_INT, &default_tm_cfg.fr_inv_timeout },
355 {"wt_timer", PARAM_INT, &default_tm_cfg.wait_timeout },
356 {"delete_timer", PARAM_INT, &default_tm_cfg.delete_timeout },
357 {"retr_timer1", PARAM_INT, &default_tm_cfg.rt_t1_timeout },
358 {"retr_timer2" , PARAM_INT, &default_tm_cfg.rt_t2_timeout },
359 {"max_inv_lifetime", PARAM_INT, &default_tm_cfg.tm_max_inv_lifetime },
360 {"max_noninv_lifetime", PARAM_INT, &default_tm_cfg.tm_max_noninv_lifetime},
361 {"noisy_ctimer", PARAM_INT, &default_tm_cfg.noisy_ctimer },
362 {"auto_inv_100", PARAM_INT, &default_tm_cfg.tm_auto_inv_100 },
363 {"unix_tx_timeout", PARAM_INT, &default_tm_cfg.tm_unix_tx_timeout },
364 {"restart_fr_on_each_reply", PARAM_INT,
365 &default_tm_cfg.restart_fr_on_each_reply},
366 {"fr_timer_avp", PARAM_STRING, &fr_timer_param },
367 {"fr_inv_timer_avp", PARAM_STRING, &fr_inv_timer_param },
368 {"tw_append", PARAM_STRING|PARAM_USE_FUNC,
369 (void*)parse_tw_append },
370 {"pass_provisional_replies", PARAM_INT,
371 &default_tm_cfg.pass_provisional_replies },
372 {"aggregate_challenges", PARAM_INT, &default_tm_cfg.tm_aggregate_auth },
373 {"unmatched_cancel", PARAM_INT, &default_tm_cfg.unmatched_cancel },
374 {"default_code", PARAM_INT, &default_tm_cfg.default_code },
375 {"default_reason", PARAM_STRING, &default_tm_cfg.default_reason },
376 {"reparse_invite", PARAM_INT, &default_tm_cfg.reparse_invite },
377 {"ac_extra_hdrs", PARAM_STR, &default_tm_cfg.ac_extra_hdrs },
378 {"blst_503", PARAM_INT, &default_tm_cfg.tm_blst_503 },
379 {"blst_503_def_timeout",PARAM_INT, &default_tm_cfg.tm_blst_503_default },
380 {"blst_503_min_timeout",PARAM_INT, &default_tm_cfg.tm_blst_503_min },
381 {"blst_503_max_timeout",PARAM_INT, &default_tm_cfg.tm_blst_503_max },
382 {"blst_methods_add", PARAM_INT, &default_tm_cfg.tm_blst_methods_add },
383 {"blst_methods_lookup", PARAM_INT, &default_tm_cfg.tm_blst_methods_lookup},
384 {"cancel_b_method", PARAM_INT, &default_tm_cfg.cancel_b_flags},
385 {"reparse_on_dns_failover", PARAM_INT, &default_tm_cfg.reparse_on_dns_failover},
390 struct module_exports tm_exports = {
392 struct module_exports exports= {
395 /* -------- exported functions ----------- */
397 tm_rpc, /* RPC methods */
398 /* ------------ exported variables ---------- */
401 mod_init, /* module initialization function */
402 (response_function) reply_received,
403 (destroy_function) tm_shutdown,
405 child_init /* per-child init function */
410 /* helper for fixup_on_* */
411 static int fixup_routes(char* r_type, struct route_list* rt, void** param)
415 i=route_get(rt, (char*)*param);
417 LOG(L_ERR, "ERROR: tm: fixup_routes: route_get failed\n");
420 if (rt->rlist[i]==0){
421 LOG(L_WARN, "WARNING: %s(\"%s\"): empty/non existing route\n",
422 r_type, (char*)*param);
424 *param=(void*)(long)i;
428 static int fixup_t_reply(void** param, int param_no)
433 ret = fix_param(FPARAM_AVP, param);
434 if (ret <= 0) return ret;
435 if (fix_param(FPARAM_INT, param) != 0) return -1;
436 } else if (param_no == 2) {
437 return fixup_var_str_12(param, 2);
442 static int fixup_on_failure(void** param, int param_no)
445 return fixup_routes("t_on_failure", &failure_rt, param);
452 static int fixup_on_reply(void** param, int param_no)
455 return fixup_routes("t_on_reply", &onreply_rt, param);
462 static int fixup_on_branch(void** param, int param_no)
465 return fixup_routes("t_on_branch", &branch_rt, param);
472 /* (char *hostname, char *port_nr) ==> (struct proxy_l *, -) */
473 static int fixup_hostport2proxy(void** param, int param_no)
478 struct proxy_l *proxy;
482 DBG("TM module: fixup_hostport2proxy(%s, %d)\n", (char*)*param, param_no);
485 } else if (param_no==2) {
486 a = fixup_get_param(param, param_no, 1);
488 port=str2s(*param, strlen(*param), &err);
490 LOG(L_ERR, "TM module:fixup_hostport2proxy: bad port number <%s>\n",
495 s.len = strlen(host);
496 proxy=mk_proxy(&s, port, 0); /* FIXME: udp or tcp? */
498 LOG(L_ERR, "ERROR: fixup_hostport2proxy: bad host name in URI <%s>\n",
500 return E_BAD_ADDRESS;
502 /* success -- fix the first parameter to proxy now ! */
507 LOG(L_ERR,"ERROR: fixup_hostport2proxy called with parameter #<>{1,2}\n");
512 /* (char *$proto, char *$host:port) ==> (fparam, fparam) */
513 static int fixup_proto_hostport2proxy(void** param, int param_no) {
516 ret = fix_param(FPARAM_AVP, param);
517 if (ret <= 0) return ret;
518 /* if (param_no = 1) { FIXME: param_str currently does not offer INT/STR overloading
519 ret = fix_param(FPARAM_INT, param);
520 if (ret <= 0) return ret;
522 if (fix_param(FPARAM_STRING, param) != 0) return -1;
527 static int fixup_t_check_status(void** param, int param_no)
531 ret = fix_param(FPARAM_AVP, param);
532 if (ret <= 0) return ret;
534 ret = fix_param(FPARAM_SELECT, param);
535 if (ret <= 0) return ret;
537 if (fix_param(FPARAM_REGEX, param) != 0) return -1;
542 /***************************** init functions *****************************/
543 static int w_t_unref( struct sip_msg *foo, void *bar)
549 static int script_init( struct sip_msg *foo, void *bar)
551 /* we primarily reset all private memory here to make sure
552 * private values left over from previous message will
553 * not be used again */
555 /* make sure the new message will not inherit previous
556 message's t_on_negative value
561 /* reset the kr status */
563 /* set request mode so that multiple-mode actions know
570 static int mod_init(void)
572 DBG( "TM - (sizeof cell=%ld, sip_msg=%ld) initializing...\n",
573 (long)sizeof(struct cell), (long)sizeof(struct sip_msg));
575 /* checking if we have sufficient bitmap capacity for given
576 maximum number of branches */
577 if (MAX_BRANCHES+1>31) {
578 LOG(L_CRIT, "Too many max UACs for UAC branch_bm_t bitmap: %d\n",
583 if (init_callid() < 0) {
584 LOG(L_CRIT, "Error while initializing Call-ID generator\n");
588 /* building the hash table*/
589 if (!init_hash_table()) {
590 LOG(L_ERR, "ERROR: mod_init: initializing hash_table failed\n");
594 /* init static hidden values */
597 if (tm_init_selects()==-1) {
598 LOG(L_ERR, "ERROR: mod_init: select init failed\n");
602 /* the default timer values must be fixed-up before
603 * declaring the configuration (Miklos) */
604 if (tm_init_timers()==-1) {
605 LOG(L_ERR, "ERROR: mod_init: timer init failed\n");
609 /* the cancel branch flags must be fixed before declaring the
611 if (cancel_b_flags_get(&default_tm_cfg.cancel_b_flags,
612 default_tm_cfg.cancel_b_flags)<0){
613 LOG(L_ERR, "ERROR: mod_init: bad cancel branch method\n");
617 #ifdef USE_DNS_FAILOVER
618 if (default_tm_cfg.reparse_on_dns_failover && mhomed) {
619 LOG(L_WARN, "WARNING: mod_init: "
620 "reparse_on_dns_failover is enabled on a "
621 "multihomed host -- check the readme of tm module!\n");
625 /* declare the configuration */
626 if (cfg_declare("tm", tm_cfg_def, &default_tm_cfg, cfg_size(tm),
628 LOG(L_ERR, "ERROR: mod_init: failed to declare the configuration\n");
632 /* First tm_stat initialization function only allocates the top level stat
633 * structure in shared memory, the initialization will complete in child
634 * init with init_tm_stats_child when the final value of estimated_process_count is
637 if (init_tm_stats() < 0) {
638 LOG(L_CRIT, "ERROR: mod_init: failed to init stats\n");
642 if (uac_init()==-1) {
643 LOG(L_ERR, "ERROR: mod_init: uac_init failed\n");
647 if (init_tmcb_lists()!=1) {
648 LOG(L_CRIT, "ERROR:tm:mod_init: failed to init tmcb lists\n");
654 if (init_twrite_sock() < 0) {
655 LOG(L_ERR, "ERROR:tm:mod_init: Unable to create socket\n");
659 /* register post-script clean-up function */
660 if (register_script_cb( w_t_unref, POST_SCRIPT_CB|REQ_TYPE_CB, 0)<0 ) {
661 LOG(L_ERR,"ERROR:tm:mod_init: failed to register POST request "
665 if (register_script_cb( script_init, PRE_SCRIPT_CB|REQ_TYPE_CB , 0)<0 ) {
666 LOG(L_ERR,"ERROR:tm:mod_init: failed to register PRE request "
671 if (init_avp_params( fr_timer_param, fr_inv_timer_param)<0 ){
672 LOG(L_ERR,"ERROR:tm:mod_init: failed to process timer AVPs\n");
679 static int child_init(int rank)
681 if (rank == PROC_INIT) {
682 /* we must init stats when rank==PROC_INIT: after mod_init we know
683 * the exact number of processes and we must init the shared structure
684 * before any other process is starting (or else some new process
685 * might try to use the stats before the stats array is allocated) */
686 if (init_tm_stats_child() < 0) {
687 ERR("Error while initializing tm statistics structures\n");
690 }else if (child_init_callid(rank) < 0) {
691 /* don't init callid for PROC_INIT*/
692 LOG(L_ERR, "ERROR: child_init: Error while initializing Call-ID"
703 /**************************** wrapper functions ***************************/
704 static int t_check_status(struct sip_msg* msg, char *p1, char *foo)
708 char *status, *s = NULL;
710 int lowest_status, n;
717 /* first get the transaction */
718 if (t_check(msg, 0 ) == -1) return -1;
719 if ((t = get_t()) == 0) {
720 LOG(L_ERR, "ERROR: t_check_status: cannot check status for a reply "
721 "which has no T-state established\n");
732 /* AVP or select, get the value and compile the regex */
733 if (get_str_fparam(&tmp, msg, fp) < 0) goto error;
734 s = pkg_malloc(tmp.len + 1);
736 ERR("Out of memory\n");
739 memcpy(s, tmp.s, tmp.len);
742 if ((re = pkg_malloc(sizeof(regex_t))) == 0) {
743 ERR("No memory left\n");
747 if (regcomp(re, s, REG_EXTENDED|REG_ICASE|REG_NEWLINE)) {
748 ERR("Bad regular expression '%s'\n", s);
756 /* use the status of the last sent reply */
757 status = int2str( t->uas.status, 0);
761 /* use the status of the current reply */
762 status = msg->first_line.u.reply.status.s;
763 backup = status[msg->first_line.u.reply.status.len];
764 status[msg->first_line.u.reply.status.len] = 0;
768 /* use the status of the winning reply */
769 if (t_pick_branch( -1, 0, t, &lowest_status)<0 ) {
770 LOG(L_CRIT,"BUG:t_check_status: t_pick_branch failed to get "
771 " a final response in MODE_ONFAILURE\n");
774 status = int2str( lowest_status , 0);
778 LOG(L_ERR,"ERROR:t_check_status: unsupported mode %d\n",rmode);
782 DBG("DEBUG:t_check_status: checked status is <%s>\n",status);
783 /* do the checking */
784 n = regexec(re, status, 1, &pmatch, 0);
786 if (backup) status[msg->first_line.u.reply.status.len] = backup;
788 if ((fp->type != FPARAM_REGEX) && re) {
798 if ((fp->type != FPARAM_REGEX) && re) {
806 inline static int w_t_check(struct sip_msg* msg, char* str, char* str2)
808 return t_check( msg , 0 ) ? 1 : -1;
811 inline static int w_t_lookup_cancel(struct sip_msg* msg, char* str, char* str2)
814 if (msg->REQ_METHOD==METHOD_CANCEL) {
815 ret = t_lookupOriginalT( msg );
816 DBG("lookup_original: t_lookupOriginalT returned: %p\n", ret);
817 if (ret != T_NULL_CELL) {
818 /* The cell is reffed by t_lookupOriginalT, but T is not set.
819 So we must unref it before returning. */
826 LOG(L_WARN, "WARNING: script error t_lookup_cancel() called for non-CANCEL request\n");
831 inline static int str2proto(char *s, int len) {
832 if (len == 3 && !strncasecmp(s, "udp", 3))
834 else if (len == 3 && !strncasecmp(s, "tcp", 3)) /* tcp&tls checks will be passed in getproto() */
836 else if (len == 3 && !strncasecmp(s, "tls", 3))
842 inline static struct proxy_l* t_protoaddr2proxy(char *proto_par, char *addr_par) {
843 struct proxy_l *proxy = 0;
846 int proto, port, err;
850 switch(((fparam_t *)proto_par)->type) {
852 if (!(avp = search_first_avp(((fparam_t *)proto_par)->v.avp.flags, ((fparam_t *)proto_par)->v.avp.name, &val, 0))) {
855 if (avp->flags & AVP_VAL_STR) {
856 proto = str2proto(val.s.s, val.s.len);
865 proto = ((fparam_t *)proto_par)->v.i;
868 proto = str2proto( ((fparam_t *)proto_par)->v.asciiz, strlen(((fparam_t *)proto_par)->v.asciiz));
871 ERR("BUG: Invalid proto parameter value in t_protoaddr2proxy\n");
876 switch(((fparam_t *)addr_par)->type) {
878 if (!(avp = search_first_avp(((fparam_t *)addr_par)->v.avp.flags, ((fparam_t *)addr_par)->v.avp.name, &val, 0))) {
881 if ((avp->flags & AVP_VAL_STR) == 0) {
882 LOG(L_ERR, "tm:t_protoaddr2proxy: avp <%.*s> value is not string\n",
883 ((fparam_t *)addr_par)->v.avp.name.s.len, ((fparam_t *)addr_par)->v.avp.name.s.s);
891 s.s = ((fparam_t *) addr_par)->v.asciiz;
896 ERR("BUG: Invalid addr parameter value in t_protoaddr2proxy\n");
902 c = memchr(s.s, ':', s.len);
904 port = str2s(c+1, s.len-(c-s.s+1), &err);
906 LOG(L_ERR, "tm:t_protoaddr2proxy: bad port number <%.*s>\n",
914 LOG(L_ERR, "tm: protoaddr2proxy: host name is empty\n");
917 proxy=mk_proxy(&s, port, proto);
919 LOG(L_ERR, "tm: protoaddr2proxy: bad host name in URI <%.*s>\n",
926 inline static int _w_t_forward_nonack(struct sip_msg* msg, struct proxy_l* proxy,
930 if (t_check( msg , 0 )==-1) {
931 LOG(L_ERR, "ERROR: forward_nonack: "
932 "can't forward when no transaction was set up\n");
936 if ( t && t!=T_UNDEFINED ) {
937 if (msg->REQ_METHOD==METHOD_ACK) {
938 LOG(L_WARN,"WARNING: you don't really want to fwd hbh ACK\n");
941 return t_forward_nonack(t, msg, proxy, proto );
943 DBG("DEBUG: forward_nonack: no transaction found\n");
949 inline static int w_t_forward_nonack( struct sip_msg* msg, char* proxy,
952 return _w_t_forward_nonack(msg, ( struct proxy_l *) proxy, PROTO_NONE);
956 inline static int w_t_forward_nonack_uri(struct sip_msg* msg, char *foo,
959 return _w_t_forward_nonack(msg, 0, PROTO_NONE);
963 inline static int w_t_forward_nonack_udp( struct sip_msg* msg, char* proxy,
966 return _w_t_forward_nonack(msg, ( struct proxy_l *) proxy, PROTO_UDP);
971 inline static int w_t_forward_nonack_tcp( struct sip_msg* msg, char* proxy,
974 return _w_t_forward_nonack(msg, ( struct proxy_l *) proxy, PROTO_TCP);
980 inline static int w_t_forward_nonack_tls( struct sip_msg* msg, char* proxy,
983 return _w_t_forward_nonack(msg, ( struct proxy_l *) proxy, PROTO_TLS);
987 inline static int w_t_forward_nonack_to( struct sip_msg *p_msg ,
991 struct proxy_l *proxy;
993 proxy = t_protoaddr2proxy(proto_par, addr_par);
995 r = _w_t_forward_nonack(p_msg, proxy, proxy->proto);
1002 inline static int w_t_reply(struct sip_msg* msg, char* p1, char* p2)
1009 if (msg->REQ_METHOD==METHOD_ACK) {
1010 LOG(L_WARN, "WARNING: t_reply: ACKs are not replied\n");
1013 if (t_check( msg , 0 )==-1) return -1;
1016 LOG(L_ERR, "ERROR: t_reply: cannot send a t_reply to a message "
1017 "for which no T-state has been established\n");
1021 if (get_int_fparam(&code, msg, (fparam_t*)p1) < 0) {
1022 code = cfg_get(tm, tm_cfg, default_code);
1025 if (get_str_fparam(&reason, msg, (fparam_t*)p2) < 0) {
1026 r = cfg_get(tm, tm_cfg, default_reason);
1028 r = as_asciiz(&reason);
1029 if (r == NULL) r = cfg_get(tm, tm_cfg, default_reason);
1032 /* if called from reply_route, make sure that unsafe version
1033 * is called; we are already in a mutex and another mutex in
1034 * the safe version would lead to a deadlock
1037 if (rmode==MODE_ONFAILURE) {
1038 DBG("DEBUG: t_reply_unsafe called from w_t_reply\n");
1039 ret = t_reply_unsafe(t, msg, code, r);
1040 } else if (rmode==MODE_REQUEST) {
1041 ret = t_reply( t, msg, code, r);
1043 LOG(L_CRIT, "BUG: w_t_reply entered in unsupported mode\n");
1047 if (r && (r != cfg_get(tm, tm_cfg, default_reason))) pkg_free(r);
1052 inline static int w_t_release(struct sip_msg* msg, char* str, char* str2)
1057 if (t_check( msg , 0 )==-1) return -1;
1059 if ( t && t!=T_UNDEFINED ) {
1060 ret = t_release_transaction( t );
1068 inline static int w_t_retransmit_reply( struct sip_msg* p_msg, char* foo, char* bar)
1073 if (t_check( p_msg , 0 )==-1)
1077 if (p_msg->REQ_METHOD==METHOD_ACK) {
1078 LOG(L_WARN, "WARNING: : ACKs transmit_replies not replied\n");
1081 return t_retransmit_reply( t );
1087 inline static int w_t_newtran( struct sip_msg* p_msg, char* foo, char* bar )
1089 /* t_newtran returns 0 on error (negative value means
1090 'transaction exists' */
1092 ret = t_newtran( p_msg );
1093 if (ret==E_SCRIPT) {
1094 LOG(L_ERR, "ERROR: t_newtran: "
1095 "transaction already in process %p\n", get_t() );
1101 inline static int w_t_on_negative( struct sip_msg* msg, char *go_to, char *foo)
1103 t_on_negative( (unsigned int )(long) go_to );
1107 inline static int w_t_on_branch( struct sip_msg* msg, char *go_to, char *foo)
1109 t_on_branch( (unsigned int )(long) go_to );
1114 inline static int w_t_on_reply( struct sip_msg* msg, char *go_to, char *foo )
1116 t_on_reply( (unsigned int )(long) go_to );
1122 inline static int _w_t_relay_to( struct sip_msg *p_msg ,
1123 struct proxy_l *proxy )
1127 if (rmode==MODE_ONFAILURE) {
1129 if (!t || t==T_UNDEFINED) {
1130 LOG(L_CRIT, "BUG: w_t_relay_to: undefined T\n");
1133 if (t_forward_nonack(t, p_msg, proxy, PROTO_NONE)<=0 ) {
1134 LOG(L_ERR, "ERROR: w_t_relay_to: t_relay_to failed\n");
1139 if (rmode==MODE_REQUEST)
1140 return t_relay_to( p_msg, proxy, PROTO_NONE,
1141 0 /* no replication */ );
1142 LOG(L_CRIT, "ERROR: w_t_relay_to: unsupported mode: %d\n", rmode);
1147 inline static int w_t_relay_to_udp( struct sip_msg *p_msg ,
1148 char *proxy, /* struct proxy_l *proxy expected */
1149 char *_foo /* nothing expected */ )
1151 ((struct proxy_l *)proxy)->proto=PROTO_UDP;
1152 return _w_t_relay_to( p_msg, ( struct proxy_l *) proxy);
1157 inline static int w_t_relay_to_tcp( struct sip_msg *p_msg ,
1158 char *proxy, /* struct proxy_l *proxy expected */
1159 char *_foo /* nothing expected */ )
1161 ((struct proxy_l *)proxy)->proto=PROTO_TCP;
1162 return _w_t_relay_to( p_msg, ( struct proxy_l *) proxy);
1168 inline static int w_t_relay_to_tls( struct sip_msg *p_msg ,
1169 char *proxy, /* struct proxy_l *proxy expected */
1170 char *_foo /* nothing expected */ )
1172 ((struct proxy_l *)proxy)->proto=PROTO_TLS;
1173 return _w_t_relay_to( p_msg, ( struct proxy_l *) proxy);
1177 inline static int w_t_relay_to( struct sip_msg *p_msg ,
1181 struct proxy_l *proxy;
1183 proxy = t_protoaddr2proxy(proto_par, addr_par);
1185 r = _w_t_relay_to(p_msg, proxy);
1192 inline static int w_t_replicate( struct sip_msg *p_msg ,
1193 char *proxy, /* struct proxy_l *proxy expected */
1194 char *_foo /* nothing expected */ )
1196 return t_replicate(p_msg, ( struct proxy_l *) proxy, p_msg->rcv.proto );
1199 inline static int w_t_replicate_udp( struct sip_msg *p_msg ,
1200 char *proxy, /* struct proxy_l *proxy expected */
1201 char *_foo /* nothing expected */ )
1203 return t_replicate(p_msg, ( struct proxy_l *) proxy, PROTO_UDP );
1208 inline static int w_t_replicate_tcp( struct sip_msg *p_msg ,
1209 char *proxy, /* struct proxy_l *proxy expected */
1210 char *_foo /* nothing expected */ )
1212 return t_replicate(p_msg, ( struct proxy_l *) proxy, PROTO_TCP );
1218 inline static int w_t_replicate_tls( struct sip_msg *p_msg ,
1219 char *proxy, /* struct proxy_l *proxy expected */
1220 char *_foo /* nothing expected */ )
1222 return t_replicate(p_msg, ( struct proxy_l *) proxy, PROTO_TLS );
1226 inline static int w_t_replicate_to( struct sip_msg *p_msg ,
1230 struct proxy_l *proxy;
1232 proxy = t_protoaddr2proxy(proto_par, addr_par);
1234 r = t_replicate(p_msg, proxy, proxy->proto);
1240 inline static int w_t_relay( struct sip_msg *p_msg ,
1241 char *_foo, char *_bar)
1245 if (rmode==MODE_ONFAILURE) {
1247 if (!t || t==T_UNDEFINED) {
1248 LOG(L_CRIT, "BUG: w_t_relay: undefined T\n");
1251 if (t_forward_nonack(t, p_msg, ( struct proxy_l *) 0, PROTO_NONE)<=0) {
1252 LOG(L_ERR, "ERROR: w_t_relay (failure mode): forwarding failed\n");
1257 if (rmode==MODE_REQUEST)
1258 return t_relay_to( p_msg,
1259 (struct proxy_l *) 0 /* no proxy */, PROTO_NONE,
1260 0 /* no replication */ );
1261 LOG(L_CRIT, "ERROR: w_t_relay_to: unsupported mode: %d\n", rmode);
1265 /* relays CANCEL at the beginning of the script */
1266 inline static int w_t_relay_cancel( struct sip_msg *p_msg ,
1267 char *_foo, char *_bar)
1269 if (p_msg->REQ_METHOD!=METHOD_CANCEL)
1272 /* it makes no sense to use this function without reparse_invite=1 */
1273 if (!cfg_get(tm, tm_cfg, reparse_invite))
1274 LOG(L_WARN, "WARNING: t_relay_cancel is probably used with "
1275 "wrong configuration, check the readme for details\n");
1277 return t_relay_cancel(p_msg);
1280 /* set fr_inv_timeout & or fr_timeout; 0 means: use the default value */
1281 static int t_set_fr_all(struct sip_msg* msg, char* p1, char* p2)
1285 if (get_int_fparam(&fr_inv, msg, (fparam_t*)p1) < 0) return -1;
1287 if (get_int_fparam(&fr, msg, (fparam_t*)p2) < 0) return -1;
1292 return t_set_fr(msg, fr_inv, fr);
1295 static int t_set_fr_inv(struct sip_msg* msg, char* fr_inv, char* foo)
1297 return t_set_fr_all(msg, fr_inv, (char*)0);
1300 /* reset fr_timer and fr_inv_timer to the default values */
1301 static int w_t_reset_fr(struct sip_msg* msg, char* foo, char* bar)
1303 return t_reset_fr();
1306 /* set retr. intervals per transaction; 0 means: use the default value */
1307 static int w_t_set_retr(struct sip_msg* msg, char* p1, char* p2)
1311 if (get_int_fparam(&t1, msg, (fparam_t*)p1) < 0) return -1;
1313 if (get_int_fparam(&t2, msg, (fparam_t*)p2) < 0) return -1;
1317 #ifdef TM_DIFF_RT_TIMEOUT
1318 return t_set_retr(msg, t1, t2);
1320 ERR("w_t_set_retr: support for changing retransmission intervals on "
1321 "the fly not compiled in (re-compile tm with"
1322 " -DTM_DIFF_RT_TIMEOUT)\n");
1327 /* reset retr. t1 and t2 to the default values */
1328 int w_t_reset_retr(struct sip_msg* msg, char* foo, char* bar)
1330 #ifdef TM_DIFF_RT_TIMEOUT
1331 return t_reset_retr();
1333 ERR("w_t_reset_retr: support for changing retransmission intervals on "
1334 "the fly not compiled in (re-compile tm with"
1335 " -DTM_DIFF_RT_TIMEOUT)\n");
1340 /* set maximum transaction lifetime for inv & noninv */
1341 static int w_t_set_max_lifetime(struct sip_msg* msg, char* p1, char* p2)
1345 if (get_int_fparam(&t1, msg, (fparam_t*)p1) < 0) return -1;
1347 if (get_int_fparam(&t2, msg, (fparam_t*)p2) < 0) return -1;
1351 return t_set_max_lifetime(msg, t1, t2);
1354 /* reset maximum invite/non-invite lifetime to the default value */
1355 int w_t_reset_max_lifetime(struct sip_msg* msg, char* foo, char* bar)
1357 return t_reset_max_lifetime();
1360 /* set automatically sending 100 replies on/off for the current or
1361 * next to be created transaction */
1362 static int t_set_auto_inv_100(struct sip_msg* msg, char* p1, char* p2)
1367 if (get_int_fparam(&state, msg, (fparam_t*)p1) < 0) return -1;
1369 /* in MODE_REPLY and MODE_ONFAILURE T will be set to current transaction;
1370 * in MODE_REQUEST T will be set only if the transaction was already
1371 * created; if not -> use the static variables */
1372 if (!t || t==T_UNDEFINED ){
1374 set_msgid_val(user_auto_inv_100, msg->id, int, 1); /* set */
1376 set_msgid_val(user_auto_inv_100, msg->id, int, -1); /* reset */
1379 t->flags|=T_AUTO_INV_100;
1381 t->flags&=~T_AUTO_INV_100;
1388 /* script function, FAILURE_ROUTE only, returns true if the
1389 * choosed "failure" branch failed because of a timeout,
1391 int t_branch_timeout(struct sip_msg* msg, char* foo, char* bar)
1393 return (msg->msg_flags & FL_TIMEOUT)?1:-1;
1398 /* script function, FAILURE_ROUTE only, returns true if the
1399 * choosed "failure" branch ever received a reply, -1 otherwise */
1400 int t_branch_replied(struct sip_msg* msg, char* foo, char* bar)
1402 return (msg->msg_flags & FL_REPLIED)?1:-1;
1407 /* script function, returns: 1 if the transaction was canceled, -1 if not */
1408 int t_is_canceled(struct sip_msg* msg, char* foo, char* bar)
1414 if (t_check( msg , 0 )==-1) return -1;
1416 if ((t==0) || (t==T_UNDEFINED)){
1417 LOG(L_ERR, "ERROR: t_is_canceled: cannot check a message "
1418 "for which no T-state has been established\n");
1421 ret=(t->flags & T_CANCELED)?1:-1;
1428 /* script function, returns: 1 if any of the branches did timeout, -1 if not */
1429 int t_any_timeout(struct sip_msg* msg, char* foo, char* bar)
1434 if (t_check( msg , 0 )==-1) return -1;
1436 if ((t==0) || (t==T_UNDEFINED)){
1437 LOG(L_ERR, "ERROR: t_any_timeout: cannot check a message "
1438 "for which no T-state has been established\n");
1441 for (r=0; r<t->nr_of_outgoings; r++){
1442 if (t->uac[r].request.flags & F_RB_TIMEOUT)
1451 /* script function, returns: 1 if any of the branches received at leat one
1452 * reply, -1 if not */
1453 int t_any_replied(struct sip_msg* msg, char* foo, char* bar)
1458 if (t_check( msg , 0 )==-1) return -1;
1460 if ((t==0) || (t==T_UNDEFINED)){
1461 LOG(L_ERR, "ERROR: t_any_replied: cannot check a message "
1462 "for which no T-state has been established\n");
1465 for (r=0; r<t->nr_of_outgoings; r++){
1466 if (t->uac[r].request.flags & F_RB_REPLIED)
1475 /* script function, returns: 1 if any of the branches received the
1476 * reply code "status" */
1477 int t_grep_status(struct sip_msg* msg, char* status, char* bar)
1483 if (get_int_fparam(&code, msg, (fparam_t*)status) < 0) return -1;
1484 if (t_check( msg , 0 )==-1) return -1;
1486 if ((t==0) || (t==T_UNDEFINED)){
1487 LOG(L_ERR, "ERROR: t_any_replied: cannot check a message "
1488 "for which no T-state has been established\n");
1491 for (r=0; r<t->nr_of_outgoings; r++){
1492 if ((t->uac[r].last_received==code) &&
1493 (t->uac[r].request.flags & F_RB_REPLIED))
1502 static rpc_export_t tm_rpc[] = {
1503 {"tm.cancel", rpc_cancel, rpc_cancel_doc, 0},
1504 {"tm.reply", rpc_reply, rpc_reply_doc, 0},
1505 {"tm.stats", tm_rpc_stats, tm_rpc_stats_doc, 0},
1506 {"tm.hash_stats", tm_rpc_hash_stats, tm_rpc_hash_stats_doc, 0},
1510 /* wrapper function needed after changes in w_t_reply */
1511 int w_t_reply_wrp(struct sip_msg *m, unsigned int code, char *txt)
1516 c.type = FPARAM_INT;
1517 c.orig = NULL; /* ? */
1520 r.type = FPARAM_STRING;
1521 r.orig = NULL; /* ? */
1524 return w_t_reply(m, (char *)&c, (char*)&r);