55f86ad3c6d4a9e6cb7acb7f64405170b8c03b10
[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 #include "t_stats.h"
80
81
82 #define FROM_TAG_LEN (MD5_LEN + 1 /* - */ + CRC16_LEN) /* length of FROM tags */
83
84 static char from_tag[FROM_TAG_LEN + 1];
85
86 char* uac_from = "sip:foo@foo.bar"; /* Module parameter */
87
88 /* Enable/disable passing of provisional replies to FIFO applications */
89 int pass_provisional_replies = 0;
90
91 /*
92  * Initialize UAC
93  */
94 int uac_init(void) 
95 {
96         str src[3];
97         struct socket_info *si;
98
99         if (RAND_MAX < TABLE_ENTRIES) {
100                 LOG(L_WARN, "Warning: uac does not spread "
101                     "across the whole hash table\n");
102         }
103         /* on tcp/tls bind_address is 0 so try to get the first address we listen
104          * on no matter the protocol */
105         si=bind_address?bind_address:get_first_socket();
106         if (si==0){
107                 LOG(L_CRIT, "BUG: uac_init: null socket list\n");
108                 return -1;
109         }
110
111         /* calculate the initial From tag */
112         src[0].s = "Long live SER server";
113         src[0].len = strlen(src[0].s);
114         src[1].s = si->address_str.s;
115         src[1].len = strlen(src[1].s);
116         src[2].s = si->port_no_str.s;
117         src[2].len = strlen(src[2].s);
118
119         MDStringArray(from_tag, src, 3);
120         from_tag[MD5_LEN] = '-';
121         return 1;
122 }
123
124
125 /*
126  * Generate a From tag
127  */
128 void generate_fromtag(str* tag, str* callid)
129 {
130              /* calculate from tag from callid */
131         crcitt_string_array(&from_tag[MD5_LEN + 1], callid, 1);
132         tag->s = from_tag; 
133         tag->len = FROM_TAG_LEN;
134 }
135
136
137 /*
138  * Check value of parameters
139  */
140 static inline int check_params(uac_req_t *uac_r, str* to, str* from)
141 {
142         if (!uac_r || !uac_r->method || !to || !from) {
143                 LOG(L_ERR, "check_params(): Invalid parameter value\n");
144                 return -1;
145         }
146
147         if (!uac_r->method->s || !uac_r->method->len) {
148                 LOG(L_ERR, "check_params(): Invalid request method\n");
149                 return -2;
150         }
151
152         if (!to->s || !to->len) {
153                 LOG(L_ERR, "check_params(): Invalid To URI\n");
154                 return -4;
155         }
156
157         if (!from->s || !from->len) {
158                 LOG(L_ERR, "check_params(): Invalid From URI\n");
159                 return -5;
160         }
161         return 0;
162 }
163
164 static inline unsigned int dlg2hash( dlg_t* dlg )
165 {
166         str cseq_nr;
167         unsigned int hashid;
168
169         cseq_nr.s=int2str(dlg->loc_seq.value, &cseq_nr.len);
170         hashid=hash(dlg->id.call_id, cseq_nr);
171         DBG("DEBUG: dlg2hash: %d\n", hashid);
172         return hashid;
173 }
174
175
176 /* WARNING: - dst_cell contains the created cell, but it is un-referenced
177  *            (before using it make sure you REF() it first)
178  *          - if  ACK (method==ACK), a cell will be created but it will not
179  *            be added in the hash table (should be either deleted by the 
180  *            caller) 
181  */
182 static inline int t_uac_prepare(uac_req_t *uac_r, 
183                 struct retr_buf **dst_req,
184                 struct cell **dst_cell)
185 {
186         struct dest_info dst;
187         struct cell *new_cell;
188         struct retr_buf *request;
189         char* buf;
190         int buf_len, ret;
191         unsigned int hi;
192         int is_ack;
193         ticks_t lifetime;
194 #ifdef USE_DNS_FAILOVER
195         struct dns_srv_handle dns_h;
196 #endif
197
198         ret=-1;
199         hi=0; /* make gcc happy */
200         /*if (dst_req) *dst_req = NULL;*/
201         is_ack = (((uac_r->method->len == 3) && (memcmp("ACK", uac_r->method->s, 3)==0)) ? 1 : 0);
202         
203         /*** added by dcm 
204          * - needed by external ua to send a request within a dlg
205          */
206         if (w_calculate_hooks(uac_r->dialog)<0 && !uac_r->dialog->hooks.next_hop)
207                 goto error2;
208
209         if (!uac_r->dialog->loc_seq.is_set) {
210                 /* this is the first request in the dialog,
211                 set cseq to default value now - Miklos */
212                 uac_r->dialog->loc_seq.value = DEFAULT_CSEQ;
213                 uac_r->dialog->loc_seq.is_set = 1;
214         }
215
216         DBG("DEBUG:tm:t_uac: next_hop=<%.*s>\n",uac_r->dialog->hooks.next_hop->len,
217                         uac_r->dialog->hooks.next_hop->s);
218         /* it's a new message, so we will take the default socket */
219 #ifdef USE_DNS_FAILOVER
220         if (use_dns_failover){
221                 dns_srv_handle_init(&dns_h);
222                 if ((uri2dst(&dns_h, &dst, 0, uac_r->dialog->hooks.next_hop, PROTO_NONE)==0)
223                                 || (dst.send_sock==0)){
224                         dns_srv_handle_put(&dns_h);
225                         ser_error = E_NO_SOCKET;
226                         ret=ser_error;
227                         LOG(L_ERR, "t_uac: no socket found\n");
228                         goto error2;
229                 }
230                 dns_srv_handle_put(&dns_h); /* not needed anymore */
231         }else{
232                 if ((uri2dst(0, &dst, 0, uac_r->dialog->hooks.next_hop, PROTO_NONE)==0) ||
233                                 (dst.send_sock==0)){
234                         ser_error = E_NO_SOCKET;
235                         ret=ser_error;
236                         LOG(L_ERR, "t_uac: no socket found\n");
237                         goto error2;
238                 }
239         }
240 #else
241         if ((uri2dst(&dst, 0, uac_r->dialog->hooks.next_hop, PROTO_NONE)==0) ||
242                         (dst.send_sock==0)){
243                 ser_error = E_NO_SOCKET;
244                 ret=ser_error;
245                 LOG(L_ERR, "t_uac: no socket found\n");
246                 goto error2;
247         }
248 #endif
249
250         new_cell = build_cell(0); 
251         if (!new_cell) {
252                 ret=E_OUT_OF_MEM;
253                 LOG(L_ERR, "t_uac: short of cell shmem\n");
254                 goto error2;
255         }
256         if (uac_r->method->len==INVITE_LEN && memcmp(uac_r->method->s, INVITE, INVITE_LEN)==0){
257                 new_cell->flags |= T_IS_INVITE_FLAG;
258                 new_cell->flags|=T_AUTO_INV_100 & (!tm_auto_inv_100 -1);
259                 lifetime=tm_max_inv_lifetime;
260         }else
261                 lifetime=tm_max_noninv_lifetime;
262         new_cell->flags |= T_IS_LOCAL_FLAG;
263         /* init timers hack, new_cell->fr_timer and new_cell->fr_inv_timer
264          * must be set, or else the fr will happen immediately
265          * we can't call init_new_t() because we don't have a sip msg
266          * => we'll ignore t_set_fr() or avp timer value and will use directly the
267          * module params fr_inv_timer and fr_timer -- andrei */
268         new_cell->fr_timeout=fr_timeout;
269         new_cell->fr_inv_timeout=fr_inv_timeout;
270         new_cell->end_of_life=get_ticks_raw()+lifetime;
271 #ifdef TM_DIFF_RT_TIMEOUT
272         /* same as above for retransmission intervals */
273         new_cell->rt_t1_timeout=rt_t1_timeout;
274         new_cell->rt_t2_timeout=rt_t2_timeout;
275 #endif
276
277         /* better reset avp list now - anyhow, it's useless from
278          * this point (bogdan) */
279         reset_avps();
280
281         set_kr(REQ_FWDED);
282
283         request = &new_cell->uac[0].request;
284         
285         request->dst = dst;
286
287         if (!is_ack) {
288 #ifdef TM_DEL_UNREF
289                 INIT_REF(new_cell, 1); /* ref'ed only from the hash */
290 #endif
291                 hi=dlg2hash(uac_r->dialog);
292                 LOCK_HASH(hi);
293                 insert_into_hash_table_unsafe(new_cell, hi);
294                 UNLOCK_HASH(hi);
295         }
296
297         buf = build_uac_req(uac_r->method, uac_r->headers, uac_r->body, uac_r->dialog, 0, new_cell,
298                 &buf_len, &dst);
299         if (!buf) {
300                 LOG(L_ERR, "t_uac: Error while building message\n");
301                 ret=E_OUT_OF_MEM;
302                 goto error1;
303         }
304
305         new_cell->method.s = buf;
306         new_cell->method.len = uac_r->method->len;
307
308         request->buffer = buf;
309         request->buffer_len = buf_len;
310         new_cell->nr_of_outgoings++;
311
312         /* Register the callbacks after everything is successful and nothing can fail.
313         Otherwise the callback parameter would be freed twise, once from TMCB_DESTROY,
314         and again because of the negative return code. */
315         if(uac_r->cb && insert_tmcb(&(new_cell->tmcb_hl), uac_r->cb_flags, *(uac_r->cb), uac_r->cbp)!=1){
316                 ret=E_OUT_OF_MEM; 
317                 LOG(L_ERR, "t_uac: short of tmcb shmem\n");
318                 goto error1;
319         }
320         if (has_local_reqin_tmcbs())
321                         run_local_reqin_callbacks(new_cell, 0, 0);
322 #ifdef DIALOG_CALLBACKS
323         run_trans_dlg_callbacks(uac_r->dialog, new_cell, request);
324 #endif /* DIALOG_CALLBACKS */
325         if (dst_req) *dst_req = request;
326         if (dst_cell) *dst_cell = new_cell;
327         else if(is_ack && dst_req==0){
328                 free_cell(new_cell);
329         }
330         
331         return 1;
332
333  error1:
334         if (!is_ack) {
335                 LOCK_HASH(hi);
336                 remove_from_hash_table_unsafe(new_cell);
337                 UNLOCK_HASH(hi);
338 #ifdef TM_DEL_UNREF
339                 UNREF_FREE(new_cell);
340         }else
341 #else
342         }
343 #endif
344                 free_cell(new_cell);
345 error2:
346         return ret;
347 }
348
349 /*
350  * Prepare a message within a dialog
351  */
352 int prepare_req_within(uac_req_t *uac_r,
353                 struct retr_buf **dst_req)
354 {
355         if (!uac_r || !uac_r->method || !uac_r->dialog) {
356                 LOG(L_ERR, "req_within: Invalid parameter value\n");
357                 goto err;
358         }
359
360         if (uac_r->dialog->state != DLG_CONFIRMED) {
361                 LOG(L_ERR, "req_within: Dialog is not confirmed yet\n");
362                 goto err;
363         }
364
365         if ((uac_r->method->len == 3) && (!memcmp("ACK", uac_r->method->s, 3))) goto send;
366         if ((uac_r->method->len == 6) && (!memcmp("CANCEL", uac_r->method->s, 6))) goto send;
367         uac_r->dialog->loc_seq.value++; /* Increment CSeq */
368  send:
369         return t_uac_prepare(uac_r, dst_req, 0);
370
371  err:
372         /* if (cbp) shm_free(cbp); */
373         /* !! never free cbp here because if t_uac_prepare fails, cbp is not freed
374          * and thus caller has no chance to discover if it is freed or not !! */
375         return -1;
376 }
377
378 static inline void send_prepared_request_impl(struct retr_buf *request, int retransmit)
379 {
380         if (SEND_BUFFER(request) == -1) {
381                 LOG(L_ERR, "t_uac: Attempt to send to precreated request failed\n");
382         }
383 #ifdef TMCB_ONSEND
384         else if (unlikely(has_tran_tmcbs(request->my_T, TMCB_REQUEST_SENT)))
385                 /* we don't know the method here */
386                         run_onsend_callbacks(TMCB_REQUEST_SENT, request, 0, 0,
387                                                                         TMCB_LOCAL_F);
388 #endif
389         
390         if (retransmit && (start_retr(request)!=0))
391                 LOG(L_CRIT, "BUG: t_uac: failed to start retr. for %p\n", request);
392 }
393
394 void send_prepared_request(struct retr_buf *request)
395 {
396         send_prepared_request_impl(request, 1 /* retransmit */);
397 }
398
399 /*
400  * Send a request using data from the dialog structure
401  */
402 int t_uac(uac_req_t *uac_r)
403 {
404         struct retr_buf *request;
405         struct cell *cell;
406         int ret;
407         int is_ack;
408
409         ret = t_uac_prepare(uac_r, &request, &cell);
410         if (ret < 0) return ret;
411         is_ack = (uac_r->method->len == 3) && (memcmp("ACK", uac_r->method->s, 3)==0) ? 1 : 0;
412         send_prepared_request_impl(request, !is_ack /* retransmit */);
413         if (cell && is_ack)
414                 free_cell(cell);
415         return ret;
416 }
417
418 /*
419  * Send a request using data from the dialog structure
420  * ret_index and ret_label will identify the new cell
421  */
422 int t_uac_with_ids(uac_req_t *uac_r,
423         unsigned int *ret_index, unsigned int *ret_label)
424 {
425         struct retr_buf *request;
426         struct cell *cell;
427         int ret;
428         int is_ack;
429
430         ret = t_uac_prepare(uac_r, &request, &cell);
431         if (ret < 0) return ret;
432         is_ack = (uac_r->method->len == 3) && (memcmp("ACK", uac_r->method->s, 3)==0) ? 1 : 0;
433         send_prepared_request_impl(request, !is_ack /* retransmit */);
434         if (is_ack) {
435                 if (cell) free_cell(cell);
436                 if (ret_index && ret_label)
437                         *ret_index = *ret_label = 0;
438         } else {
439                 if (ret_index && ret_label) {
440                         *ret_index = cell->hash_index;
441                         *ret_label = cell->label;
442                 }
443         }
444         return ret;
445 }
446
447 /*
448  * Send a message within a dialog
449  */
450 int req_within(uac_req_t *uac_r)
451 {
452         if (!uac_r || !uac_r->method || !uac_r->dialog) {
453                 LOG(L_ERR, "req_within: Invalid parameter value\n");
454                 goto err;
455         }
456
457         if ((uac_r->method->len == 3) && (!memcmp("ACK", uac_r->method->s, 3))) goto send;
458         if ((uac_r->method->len == 6) && (!memcmp("CANCEL", uac_r->method->s, 6))) goto send;
459         uac_r->dialog->loc_seq.value++; /* Increment CSeq */
460  send:
461         return t_uac(uac_r);
462
463  err:
464         /* callback parameter must be freed outside of tm module
465         if (cbp) shm_free(cbp); */
466         return -1;
467 }
468
469
470 /*
471  * Send an initial request that will start a dialog
472  * WARNING: writes uac_r->dialog
473  */
474 int req_outside(uac_req_t *uac_r, str* to, str* from)
475 {
476         str callid, fromtag;
477
478         if (check_params(uac_r, to, from) < 0) goto err;
479         
480         generate_callid(&callid);
481         generate_fromtag(&fromtag, &callid);
482
483         if (new_dlg_uac(&callid, &fromtag, DEFAULT_CSEQ, from, to, &uac_r->dialog) < 0) {
484                 LOG(L_ERR, "req_outside(): Error while creating new dialog\n");
485                 goto err;
486         }
487
488         return t_uac(uac_r);
489
490  err:
491         /* callback parameter must be freed outside of tm module
492         if (cbp) shm_free(cbp); */
493         return -1;
494 }
495
496
497 /*
498  * Send a transactional request, no dialogs involved
499  * WARNING: writes uac_r->dialog
500  */
501 int request(uac_req_t *uac_r, str* ruri, str* to, str* from, str *next_hop)
502 {
503         str callid, fromtag;
504         dlg_t* dialog;
505         int res;
506
507         if (check_params(uac_r, to, from) < 0) goto err;
508
509         generate_callid(&callid);
510         generate_fromtag(&fromtag, &callid);
511
512         if (new_dlg_uac(&callid, &fromtag, DEFAULT_CSEQ, from, to, &dialog) < 0) {
513                 LOG(L_ERR, "request(): Error while creating temporary dialog\n");
514                 goto err;
515         }
516
517         if (ruri) {
518                 dialog->rem_target.s = ruri->s;
519                 dialog->rem_target.len = ruri->len;
520                 /* hooks will be set from w_calculate_hooks */
521         }
522
523         if (next_hop) dialog->dst_uri = *next_hop;
524         w_calculate_hooks(dialog);
525
526         /* WARNING:
527          * to be clean it should be called 
528          *   set_dlg_target(dialog, ruri, next_hop);
529          * which sets both uris if given [but it duplicates them in shm!]
530          *
531          * but in this case the _ruri parameter in set_dlg_target
532          * must be optional (it is needed now) and following hacks
533          *   dialog->rem_target.s = 0;
534          *   dialog->dst_uri.s = 0;
535          * before freeing dialog here must be removed
536          */
537         uac_r->dialog = dialog;
538         res = t_uac(uac_r);
539         dialog->rem_target.s = 0;
540         dialog->dst_uri.s = 0;
541         free_dlg(dialog);
542         uac_r->dialog = 0;
543         return res;
544
545  err:
546         /* callback parameter must be freed outside of tm module
547         if (cp) shm_free(cp); */
548         return -1;
549 }