- e2ecancel is sent hop by hop (closes SER-68)
[sip-router] / modules / tm / uac.c
1 /*
2  * $Id$
3  *
4  * simple UAC for things such as SUBSCRIBE or SMS gateway;
5  * no authentication and other UAC features -- just send
6  * a message, retransmit and await a reply; forking is not
7  * supported during client generation, in all other places
8  * it is -- adding it should be simple
9  *
10  * Copyright (C) 2001-2003 FhG Fokus
11  *
12  * This file is part of ser, a free SIP server.
13  *
14  * ser is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version
18  *
19  * For a license to use the ser software under conditions
20  * other than those described here, or to purchase support for this
21  * software, please contact iptel.org by e-mail at the following addresses:
22  *    info@iptel.org
23  *
24  * ser is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License 
30  * along with this program; if not, write to the Free Software 
31  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
32  *
33  * History:
34  * --------
35  *  2003-01-23  t_uac_dlg now uses get_out_socket (jiri)
36  *  2003-01-27  fifo:t_uac_dlg completed (jiri)
37  *  2003-01-29  scratchpad removed (jiri)
38  *  2003-02-13  t_uac, t _uac_dlg, gethfblock, uri2proxy changed to use 
39  *               proto & rb->dst (andrei)
40  *  2003-02-27  FIFO/UAC now dumps reply -- good for CTD (jiri)
41  *  2003-02-28  scratchpad compatibility abandoned (jiri)
42  *  2003-03-01  kr set through a function now (jiri)
43  *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
44  *  2003-04-02  port_no_str does not contain a leading ':' anymore (andrei)
45  *  2003-07-08  appropriate log messages in check_params(...), 
46  *               call calculate_hooks if next_hop==NULL in t_uac (dcm) 
47  *  2003-10-24  updated to the new socket_info lists (andrei)
48  *  2003-12-03  completion filed removed from transaction and uac callbacks
49  *              merged in transaction callbacks as LOCAL_COMPLETED (bogdan)
50  *  2004-02-11  FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri)
51  *  2004-02-13  t->is_invite, t->local, t->noisy_ctimer replaced (bogdan)
52  *  2004-08-23  avp support in t_uac (bogdan)
53  *  2005-12-16  t_uac will set the new_cell timers to the default values,
54  *               fixes 0 fr_timer bug (andrei)
55  *  2006-08-11  t_uac uses dns failover until it finds a send socket (andrei)
56  *  2007-03-15  TMCB_ONSEND callbacks support added (andrei)
57  *  2007-03-23  TMCB_LOCAL_REQUEST_IN callbacks support (andrei)
58  *  2007-04-23  per dialog callbacks support (andrei)
59  *  2007-06-01  support for per transaction different retransmissions intervals
60  *              (andrei)
61  */
62
63 #include <string.h>
64 #include "../../mem/shm_mem.h"
65 #include "../../dprint.h"
66 #include "../../globals.h"
67 #include "../../md5.h"
68 #include "../../crc.h"
69 #include "../../ip_addr.h"
70 #include "../../socket_info.h"
71 #include "../../compiler_opt.h"
72 #include "ut.h"
73 #include "h_table.h"
74 #include "t_hooks.h"
75 #include "t_funcs.h"
76 #include "t_msgbuilder.h"
77 #include "callid.h"
78 #include "uac.h"
79
80
81 #define FROM_TAG_LEN (MD5_LEN + 1 /* - */ + CRC16_LEN) /* length of FROM tags */
82
83 static char from_tag[FROM_TAG_LEN + 1];
84
85 char* uac_from = "sip:foo@foo.bar"; /* Module parameter */
86
87 /* Enable/disable passing of provisional replies to FIFO applications */
88 int pass_provisional_replies = 0;
89
90 /*
91  * Initialize UAC
92  */
93 int uac_init(void) 
94 {
95         str src[3];
96         struct socket_info *si;
97
98         if (RAND_MAX < TABLE_ENTRIES) {
99                 LOG(L_WARN, "Warning: uac does not spread "
100                     "across the whole hash table\n");
101         }
102         /* on tcp/tls bind_address is 0 so try to get the first address we listen
103          * on no matter the protocol */
104         si=bind_address?bind_address:get_first_socket();
105         if (si==0){
106                 LOG(L_CRIT, "BUG: uac_init: null socket list\n");
107                 return -1;
108         }
109
110         /* calculate the initial From tag */
111         src[0].s = "Long live SER server";
112         src[0].len = strlen(src[0].s);
113         src[1].s = si->address_str.s;
114         src[1].len = strlen(src[1].s);
115         src[2].s = si->port_no_str.s;
116         src[2].len = strlen(src[2].s);
117
118         MDStringArray(from_tag, src, 3);
119         from_tag[MD5_LEN] = '-';
120         return 1;
121 }
122
123
124 /*
125  * Generate a From tag
126  */
127 void generate_fromtag(str* tag, str* callid)
128 {
129              /* calculate from tag from callid */
130         crcitt_string_array(&from_tag[MD5_LEN + 1], callid, 1);
131         tag->s = from_tag; 
132         tag->len = FROM_TAG_LEN;
133 }
134
135
136 /*
137  * Check value of parameters
138  */
139 static inline int check_params(str* method, str* to, str* from, dlg_t** dialog)
140 {
141         if (!method || !to || !from || !dialog) {
142                 LOG(L_ERR, "check_params(): Invalid parameter value\n");
143                 return -1;
144         }
145
146         if (!method->s || !method->len) {
147                 LOG(L_ERR, "check_params(): Invalid request method\n");
148                 return -2;
149         }
150
151         if (!to->s || !to->len) {
152                 LOG(L_ERR, "check_params(): Invalid To URI\n");
153                 return -4;
154         }
155
156         if (!from->s || !from->len) {
157                 LOG(L_ERR, "check_params(): Invalid From URI\n");
158                 return -5;
159         }
160         return 0;
161 }
162
163 static inline unsigned int dlg2hash( dlg_t* dlg )
164 {
165         str cseq_nr;
166         unsigned int hashid;
167
168         cseq_nr.s=int2str(dlg->loc_seq.value, &cseq_nr.len);
169         hashid=hash(dlg->id.call_id, cseq_nr);
170         DBG("DEBUG: dlg2hash: %d\n", hashid);
171         return hashid;
172 }
173
174
175 /* WARNING: - dst_cell contains the created cell, but it is un-referenced
176  *            (before using it make sure you REF() it first)
177  *          - if  ACK (method==ACK), a cell will be created but it will not
178  *            be added in the hash table (should be either deleted by the 
179  *            caller) 
180  */
181 static inline int t_uac_prepare(str* method, str* headers, str* body, 
182                 dlg_t* dialog, transaction_cb cb, void* cbp, struct retr_buf **dst_req,
183                 struct cell **dst_cell)
184 {
185         struct dest_info dst;
186         struct cell *new_cell;
187         struct retr_buf *request;
188         char* buf;
189         int buf_len, ret, flags;
190         unsigned int hi;
191         int is_ack;
192         ticks_t lifetime;
193 #ifdef USE_DNS_FAILOVER
194         struct dns_srv_handle dns_h;
195 #endif
196
197         ret=-1;
198         hi=0; /* make gcc happy */
199         /*if (dst_req) *dst_req = NULL;*/
200         is_ack = (((method->len == 3) && (memcmp("ACK", method->s, 3)==0)) ? 1 : 0);
201         
202         /*** added by dcm 
203          * - needed by external ua to send a request within a dlg
204          */
205         if (w_calculate_hooks(dialog)<0 && !dialog->hooks.next_hop)
206                 goto error2;
207
208         if (!dialog->loc_seq.is_set) {
209                 /* this is the first request in the dialog,
210                 set cseq to default value now - Miklos */
211                 dialog->loc_seq.value = DEFAULT_CSEQ;
212                 dialog->loc_seq.is_set = 1;
213         }
214
215         DBG("DEBUG:tm:t_uac: next_hop=<%.*s>\n",dialog->hooks.next_hop->len,
216                         dialog->hooks.next_hop->s);
217         /* it's a new message, so we will take the default socket */
218 #ifdef USE_DNS_FAILOVER
219         if (use_dns_failover){
220                 dns_srv_handle_init(&dns_h);
221                 if ((uri2dst(&dns_h, &dst, 0, dialog->hooks.next_hop, PROTO_NONE)==0)
222                                 || (dst.send_sock==0)){
223                         dns_srv_handle_put(&dns_h);
224                         ser_error = E_NO_SOCKET;
225                         ret=ser_error;
226                         LOG(L_ERR, "t_uac: no socket found\n");
227                         goto error2;
228                 }
229                 dns_srv_handle_put(&dns_h); /* not needed anymore */
230         }else{
231                 if ((uri2dst(0, &dst, 0, dialog->hooks.next_hop, PROTO_NONE)==0) ||
232                                 (dst.send_sock==0)){
233                         ser_error = E_NO_SOCKET;
234                         ret=ser_error;
235                         LOG(L_ERR, "t_uac: no socket found\n");
236                         goto error2;
237                 }
238         }
239 #else
240         if ((uri2dst(&dst, 0, dialog->hooks.next_hop, PROTO_NONE)==0) ||
241                         (dst.send_sock==0)){
242                 ser_error = E_NO_SOCKET;
243                 ret=ser_error;
244                 LOG(L_ERR, "t_uac: no socket found\n");
245                 goto error2;
246         }
247 #endif
248
249         new_cell = build_cell(0); 
250         if (!new_cell) {
251                 ret=E_OUT_OF_MEM;
252                 LOG(L_ERR, "t_uac: short of cell shmem\n");
253                 goto error2;
254         }
255         if (method->len==INVITE_LEN && memcmp(method->s, INVITE, INVITE_LEN)==0){
256                 new_cell->flags |= T_IS_INVITE_FLAG;
257                 new_cell->flags|=T_AUTO_INV_100 & (!tm_auto_inv_100 -1);
258                 lifetime=tm_max_inv_lifetime;
259         }else
260                 lifetime=tm_max_noninv_lifetime;
261         new_cell->flags |= T_IS_LOCAL_FLAG;
262         /* init timers hack, new_cell->fr_timer and new_cell->fr_inv_timer
263          * must be set, or else the fr will happen immediately
264          * we can't call init_new_t() because we don't have a sip msg
265          * => we'll ignore t_set_fr() or avp timer value and will use directly the
266          * module params fr_inv_timer and fr_timer -- andrei */
267         new_cell->fr_timeout=fr_timeout;
268         new_cell->fr_inv_timeout=fr_inv_timeout;
269         new_cell->end_of_life=get_ticks_raw()+lifetime;
270 #ifdef TM_DIFF_RT_TIMEOUT
271         /* same as above for retransmission intervals */
272         new_cell->rt_t1_timeout=rt_t1_timeout;
273         new_cell->rt_t2_timeout=rt_t2_timeout;
274 #endif
275
276         /* better reset avp list now - anyhow, it's useless from
277          * this point (bogdan) */
278         reset_avps();
279
280         /* add the callback the the transaction for LOCAL_COMPLETED event */
281  
282         flags = TMCB_LOCAL_COMPLETED;
283         /* Add also TMCB_LOCAL_REPLY_OUT if provisional replies are desired */
284         if (pass_provisional_replies) flags |= TMCB_LOCAL_RESPONSE_OUT;
285
286         if(cb && insert_tmcb(&(new_cell->tmcb_hl), flags, cb, cbp)!=1){
287                 ret=E_OUT_OF_MEM; 
288                 LOG(L_ERR, "t_uac: short of tmcb shmem\n");
289                 goto error2;
290         }
291
292         set_kr(REQ_FWDED);
293
294         request = &new_cell->uac[0].request;
295         
296         request->dst = dst;
297
298         if (!is_ack) {
299 #ifdef TM_DEL_UNREF
300                 INIT_REF(new_cell, 1); /* ref'ed only from the hash */
301 #endif
302                 hi=dlg2hash(dialog);
303                 LOCK_HASH(hi);
304                 insert_into_hash_table_unsafe(new_cell, hi);
305                 UNLOCK_HASH(hi);
306         }
307
308         buf = build_uac_req(method, headers, body, dialog, 0, new_cell,
309                 &buf_len, &dst);
310         if (!buf) {
311                 LOG(L_ERR, "t_uac: Error while building message\n");
312                 ret=E_OUT_OF_MEM;
313                 goto error1;
314         }
315
316         new_cell->method.s = buf;
317         new_cell->method.len = method->len;
318
319         request->buffer = buf;
320         request->buffer_len = buf_len;
321         new_cell->nr_of_outgoings++;
322         
323         if (has_local_reqin_tmcbs())
324                         run_local_reqin_callbacks(new_cell, 0, 0);
325 #ifdef DIALOG_CALLBACKS
326         run_trans_dlg_callbacks(dialog, new_cell, request);
327 #endif /* DIALOG_CALLBACKS */
328         if (dst_req) *dst_req = request;
329         if (dst_cell) *dst_cell = new_cell;
330         else if(is_ack && dst_req==0){
331                 free_cell(new_cell);
332         }
333         
334         return 1;
335
336  error1:
337         if (!is_ack) {
338                 LOCK_HASH(hi);
339                 remove_from_hash_table_unsafe(new_cell);
340                 UNLOCK_HASH(hi);
341 #ifdef TM_DEL_UNREF
342                 UNREF_FREE(new_cell);
343         }else
344 #else
345         }
346 #endif
347                 free_cell(new_cell);
348 error2:
349         return ret;
350 }
351
352 /*
353  * Prepare a message within a dialog
354  */
355 int prepare_req_within(str* method, str* headers, 
356                 str* body, dlg_t* dialog, transaction_cb completion_cb, 
357                 void* cbp, struct retr_buf **dst_req)
358 {
359         if (!method || !dialog) {
360                 LOG(L_ERR, "req_within: Invalid parameter value\n");
361                 goto err;
362         }
363
364         if (dialog->state != DLG_CONFIRMED) {
365                 LOG(L_ERR, "req_within: Dialog is not confirmed yet\n");
366                 goto err;
367         }
368
369         if ((method->len == 3) && (!memcmp("ACK", method->s, 3))) goto send;
370         if ((method->len == 6) && (!memcmp("CANCEL", method->s, 6))) goto send;
371         dialog->loc_seq.value++; /* Increment CSeq */
372  send:
373         return t_uac_prepare(method, headers, body, dialog, completion_cb, cbp, dst_req, 0);
374
375  err:
376         /* if (cbp) shm_free(cbp); */
377         /* !! never free cbp here because if t_uac_prepare fails, cbp is not freed
378          * and thus caller has no chance to discover if it is freed or not !! */
379         return -1;
380 }
381
382 static inline void send_prepared_request_impl(struct retr_buf *request, int retransmit)
383 {
384         if (SEND_BUFFER(request) == -1) {
385                 LOG(L_ERR, "t_uac: Attempt to send to precreated request failed\n");
386         }
387 #ifdef TMCB_ONSEND
388         else if (unlikely(has_tran_tmcbs(request->my_T, TMCB_REQUEST_SENT)))
389                 /* we don't know the method here */
390                         run_onsend_callbacks(TMCB_REQUEST_SENT, request, 0, 0,
391                                                                         TMCB_LOCAL_F);
392 #endif
393         
394         if (retransmit && (start_retr(request)!=0))
395                 LOG(L_CRIT, "BUG: t_uac: failed to start retr. for %p\n", request);
396 }
397
398 void send_prepared_request(struct retr_buf *request)
399 {
400         send_prepared_request_impl(request, 1 /* retransmit */);
401 }
402
403 /*
404  * Send a request using data from the dialog structure
405  */
406 int t_uac(str* method, str* headers, str* body, dlg_t* dialog,
407           transaction_cb cb, void* cbp)
408 {
409         struct retr_buf *request;
410         struct cell *cell;
411         int ret;
412         int is_ack;
413
414         ret = t_uac_prepare(method, headers, body, dialog, cb, cbp, &request, &cell);
415         if (ret < 0) return ret;
416         is_ack = (method->len == 3) && (memcmp("ACK", method->s, 3)==0) ? 1 : 0;
417         send_prepared_request_impl(request, !is_ack /* retransmit */);
418         if (cell && is_ack)
419                 free_cell(cell);
420         return ret;
421 }
422
423 /*
424  * Send a request using data from the dialog structure
425  * ret_index and ret_label will identify the new cell
426  */
427 int t_uac_with_ids(str* method, str* headers, str* body, dlg_t* dialog,
428         transaction_cb cb, void* cbp,
429         unsigned int *ret_index, unsigned int *ret_label)
430 {
431         struct retr_buf *request;
432         struct cell *cell;
433         int ret;
434         int is_ack;
435
436         ret = t_uac_prepare(method, headers, body, dialog, cb, cbp, &request, &cell);
437         if (ret < 0) return ret;
438         is_ack = (method->len == 3) && (memcmp("ACK", method->s, 3)==0) ? 1 : 0;
439         send_prepared_request_impl(request, !is_ack /* retransmit */);
440         if (is_ack) {
441                 if (cell) free_cell(cell);
442                 if (ret_index && ret_label)
443                         *ret_index = *ret_label = 0;
444         } else {
445                 if (ret_index && ret_label) {
446                         *ret_index = cell->hash_index;
447                         *ret_label = cell->label;
448                 }
449         }
450         return ret;
451 }
452
453 /*
454  * Send a message within a dialog
455  */
456 int req_within(str* method, str* headers, str* body, dlg_t* dialog, transaction_cb completion_cb, void* cbp)
457 {
458         if (!method || !dialog) {
459                 LOG(L_ERR, "req_within: Invalid parameter value\n");
460                 goto err;
461         }
462
463         if ((method->len == 3) && (!memcmp("ACK", method->s, 3))) goto send;
464         if ((method->len == 6) && (!memcmp("CANCEL", method->s, 6))) goto send;
465         dialog->loc_seq.value++; /* Increment CSeq */
466  send:
467         return t_uac(method, headers, body, dialog, completion_cb, cbp);
468
469  err:
470         if (cbp) shm_free(cbp);
471         return -1;
472 }
473
474
475 /*
476  * Send an initial request that will start a dialog
477  */
478 int req_outside(str* method, str* to, str* from, str* headers, str* body, dlg_t** dialog, transaction_cb cb, void* cbp)
479 {
480         str callid, fromtag;
481
482         if (check_params(method, to, from, dialog) < 0) goto err;
483         
484         generate_callid(&callid);
485         generate_fromtag(&fromtag, &callid);
486
487         if (new_dlg_uac(&callid, &fromtag, DEFAULT_CSEQ, from, to, dialog) < 0) {
488                 LOG(L_ERR, "req_outside(): Error while creating new dialog\n");
489                 goto err;
490         }
491
492         return t_uac(method, headers, body, *dialog, cb, cbp);
493
494  err:
495         if (cbp) shm_free(cbp);
496         return -1;
497 }
498
499
500 /*
501  * Send a transactional request, no dialogs involved
502  */
503 int request(str* m, str* ruri, str* to, str* from, str* h, str* b, str *next_hop, transaction_cb c, void* cp)
504 {
505         str callid, fromtag;
506         dlg_t* dialog;
507         int res;
508
509         if (check_params(m, to, from, &dialog) < 0) goto err;
510
511         generate_callid(&callid);
512         generate_fromtag(&fromtag, &callid);
513
514         if (new_dlg_uac(&callid, &fromtag, DEFAULT_CSEQ, from, to, &dialog) < 0) {
515                 LOG(L_ERR, "request(): Error while creating temporary dialog\n");
516                 goto err;
517         }
518
519         if (ruri) {
520                 dialog->rem_target.s = ruri->s;
521                 dialog->rem_target.len = ruri->len;
522                 /* hooks will be set from w_calculate_hooks */
523         }
524
525         if (next_hop) dialog->dst_uri = *next_hop;
526         w_calculate_hooks(dialog);
527
528         /* WARNING:
529          * to be clean it should be called 
530          *   set_dlg_target(dialog, ruri, next_hop);
531          * which sets both uris if given [but it duplicates them in shm!]
532          *
533          * but in this case the _ruri parameter in set_dlg_target
534          * must be optional (it is needed now) and following hacks
535          *   dialog->rem_target.s = 0;
536          *   dialog->dst_uri.s = 0;
537          * before freeing dialog here must be removed
538          */
539
540         res = t_uac(m, h, b, dialog, c, cp);
541         dialog->rem_target.s = 0;
542         dialog->dst_uri.s = 0;
543         free_dlg(dialog);
544         return res;
545
546  err:
547         if (cp) shm_free(cp);
548         return -1;
549 }