ims_dialog: small spelling fix in WARN log messages
[sip-router] / src / modules / ims_dialog / dlg_req_within.c
1 /*
2  * Copyright (C) 2007 Voice System SRL
3  *
4  * This file is part of Kamailio, a free SIP server.
5  *
6  * Kamailio is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version
10  *
11  * Kamailio is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include "../../core/dprint.h"
26 #include "../../core/ut.h"
27 #include "../../lib/srdb1/db.h"
28 #include "../../core/dprint.h"
29 #include "../../core/config.h"
30 #include "../../core/socket_info.h"
31 #include "../../modules/tm/dlg.h"
32 #include "../../modules/tm/tm_load.h"
33 #include "../../core/counters.h"
34 #include "../../core/locking.h"
35 #include "dlg_timer.h"
36 #include "dlg_hash.h"
37 #include "dlg_req_within.h"
38 #include "dlg_db_handler.h"
39 #include "dlg_ng_stats.h"
40
41 #define MAX_FWD_HDR        "Max-Forwards: " MAX_FWD CRLF
42 #define MAX_FWD_HDR_LEN    (sizeof(MAX_FWD_HDR) - 1)
43
44 extern str dlg_extra_hdrs;
45 extern int dlg_db_mode;
46 extern struct dialog_ng_counters_h dialog_ng_cnts_h;
47
48 int free_tm_dlg(dlg_t *td) {
49     if (td) {
50         if (td->route_set)
51             free_rr(&td->route_set);
52         pkg_free(td);
53     }
54     return 0;
55 }
56
57 dlg_t * build_dlg_t(struct dlg_cell * cell, int dir) {
58
59     dlg_t* td = NULL;
60     str cseq;
61     unsigned int loc_seq;
62     str route_set;
63     str contact;
64
65     struct dlg_cell_out *dlg_out = 0;
66     struct dlg_entry_out* dlg_entry_out = 0;
67
68     /* if trying to send by to callee we need to get the corresponding dlg_out cell */
69     lock_get(cell->dlg_out_entries_lock);
70     dlg_entry_out = &cell->dlg_entry_out;
71
72     dlg_out = dlg_entry_out->first;
73     //must be concurrent call - lets choose - TODO - ie. check if there is more
74
75     if (!dlg_out) {
76         LM_ERR("Trying to send BYE for dialog with no callee leg\n");
77         lock_release(cell->dlg_out_entries_lock);
78         return NULL;
79     }
80
81     td = (dlg_t*) pkg_malloc(sizeof (dlg_t));
82     if (!td) {
83
84         LM_ERR("out of pkg memory\n");
85         lock_release(cell->dlg_out_entries_lock);
86         return NULL;
87     }
88     memset(td, 0, sizeof (dlg_t));
89
90     if (dir == DLG_CALLER_LEG) {
91         cseq = cell->first_req_cseq;
92         route_set = cell->caller_route_set;
93         contact = cell->caller_contact;
94         td->rem_uri = cell->from_uri;
95         td->loc_uri = dlg_out->to_uri;
96         td->id.rem_tag = cell->from_tag;
97         td->id.loc_tag = dlg_out->to_tag;
98         td->send_sock = cell->caller_bind_addr;
99     } else {
100         cseq = dlg_out->callee_cseq;
101         route_set = dlg_out->callee_route_set;
102         contact = dlg_out->callee_contact;
103         td->rem_uri = dlg_out->to_uri;
104         td->loc_uri = cell->from_uri;
105         td->id.rem_tag = dlg_out->to_tag;
106         td->id.loc_tag = cell->from_tag;
107         td->send_sock = dlg_out->callee_bind_addr;
108     }
109
110     if (str2int(&cseq, &loc_seq) != 0) {
111         LM_ERR("invalid cseq\n");
112         goto error;
113     }
114
115     /*we don not increase here the cseq as this will be done by TM*/
116     td->loc_seq.value = loc_seq;
117     td->loc_seq.is_set = 1;
118
119     /*route set*/
120     if (route_set.s && route_set.len) {
121
122         if (parse_rr_body(route_set.s, route_set.len, &td->route_set) != 0) {
123             LM_ERR("failed to parse route set\n");
124             goto error;
125         }
126     }
127
128     if (contact.s == 0 || contact.len == 0) {
129
130         LM_ERR("no contact available\n");
131         goto error;
132     }
133
134     td->id.call_id = cell->callid;
135     td->rem_target = contact;
136     td->state = DLG_CONFIRMED;
137
138     lock_release(cell->dlg_out_entries_lock);
139     return td;
140
141 error:
142     lock_release(cell->dlg_out_entries_lock);
143     free_tm_dlg(td);
144     return NULL;
145 }
146
147 /*callback function to handle responses to the BYE request */
148 void bye_reply_cb(struct cell* t, int type, struct tmcb_params* ps) {
149
150     struct dlg_cell* dlg;
151     int event, old_state, new_state, unref, ret;
152     struct dlg_cell_out *dlg_out = 0;
153
154     if (ps->param == NULL || *ps->param == NULL) {
155         LM_ERR("invalid parameter\n");
156         return;
157     }
158
159     if (ps->code < 200) {
160         LM_DBG("receiving a provisional reply\n");
161         return;
162     }
163
164     LM_DBG("receiving a final reply %d\n", ps->code);
165
166     dlg = (struct dlg_cell *) (*(ps->param));
167     event = DLG_EVENT_REQBYE;
168
169     //get the corresponding dlg out structure for this REQ
170     struct dlg_entry_out *dlg_entry_out = &dlg->dlg_entry_out;
171     lock_get(dlg->dlg_out_entries_lock);
172     dlg_out = dlg_entry_out->first; //TODO check for concurrent call
173     if (!dlg_out)
174         return;
175
176     next_state_dlg(dlg, event, &old_state, &new_state, &unref, &dlg_out->to_tag);
177
178     lock_release(dlg->dlg_out_entries_lock);
179
180     if (new_state == DLG_STATE_DELETED && old_state != DLG_STATE_DELETED) {
181
182         LM_DBG("removing dialog with h_entry %u and h_id %u\n",
183                 dlg->h_entry, dlg->h_id);
184
185         /* remove from timer */
186         ret = remove_dialog_timer(&dlg->tl);
187         if (ret < 0) {
188             LM_CRIT("unable to unlink the timer on dlg %p [%u:%u] "
189                     "with clid '%.*s'\n",
190                     dlg, dlg->h_entry, dlg->h_id,
191                     dlg->callid.len, dlg->callid.s);
192         } else if (ret > 0) {
193             LM_WARN("inconsistent dlg timer data on dlg %p [%u:%u] "
194                     "with clid '%.*s'\n",
195                     dlg, dlg->h_entry, dlg->h_id,
196                     dlg->callid.len, dlg->callid.s);
197         } else {
198             unref++;
199         }
200         
201         counter_add(dialog_ng_cnts_h.active, -1);
202         
203         /* dialog terminated (BYE) */
204         run_dlg_callbacks(DLGCB_TERMINATED, dlg, ps->req, ps->rpl, DLG_DIR_NONE, 0);
205
206         /* derefering the dialog */
207         unref_dlg(dlg, unref);          /*removed the extra +1 on the unref that is usually added in the unref of next_state_dlg */
208     }
209
210     if (new_state == DLG_STATE_DELETED && old_state == DLG_STATE_DELETED) {
211         /* trash the dialog from DB and memory */
212         if (dlg_db_mode)
213                 remove_dialog_in_from_db(dlg);
214
215         /* force delete from mem */
216         unref_dlg(dlg, 1);
217     }
218
219 }
220
221 static inline int build_extra_hdr(struct dlg_cell * cell, str *extra_hdrs,
222         str *str_hdr) {
223     char *p;
224
225     str_hdr->len = MAX_FWD_HDR_LEN + dlg_extra_hdrs.len;
226     if (extra_hdrs && extra_hdrs->len > 0)
227         str_hdr->len += extra_hdrs->len;
228
229     str_hdr->s = (char*) pkg_malloc(str_hdr->len * sizeof (char));
230     if (!str_hdr->s) {
231         LM_ERR("out of pkg memory\n");
232         goto error;
233     }
234
235     memcpy(str_hdr->s, MAX_FWD_HDR, MAX_FWD_HDR_LEN);
236     p = str_hdr->s + MAX_FWD_HDR_LEN;
237     if (dlg_extra_hdrs.len) {
238         memcpy(p, dlg_extra_hdrs.s, dlg_extra_hdrs.len);
239         p += dlg_extra_hdrs.len;
240     }
241     if (extra_hdrs && extra_hdrs->len > 0)
242         memcpy(p, extra_hdrs->s, extra_hdrs->len);
243
244     return 0;
245
246 error:
247     return -1;
248 }
249
250 /* cell- pointer to a struct dlg_cell
251  * dir- direction: the request will be sent to:
252  *              DLG_CALLER_LEG (0): caller
253  *              DLG_CALLEE_LEG (1): callee
254  */
255 static inline int send_bye(struct dlg_cell * cell, int dir, str *hdrs) {
256     uac_req_t uac_r;
257     dlg_t* dialog_info;
258     str met = {"BYE", 3};
259     int result;
260     /* do not send BYE request for non-confirmed dialogs (not supported) */
261     if (cell->state != DLG_STATE_CONFIRMED) {
262         LM_ERR("terminating only 1 side of non-confirmed dialogs not supported by this function\n");
263         return -1;
264     }
265
266     /*verify direction*/
267     if ((dialog_info = build_dlg_t(cell, dir)) == 0) {
268         LM_ERR("failed to create dlg_t\n");
269         goto err;
270     }
271
272     LM_DBG("sending BYE to %s\n", (dir == DLG_CALLER_LEG) ? "caller" : "callee");
273
274     ref_dlg(cell, 1);
275
276     memset(&uac_r, '\0', sizeof (uac_req_t));
277     set_uac_req(&uac_r, &met, hdrs, NULL, dialog_info, TMCB_LOCAL_COMPLETED,
278             bye_reply_cb, (void*) cell);
279
280     result = d_tmb.t_request_within(&uac_r);
281
282     if (result < 0) {
283         LM_ERR("failed to send the BYE request\n");
284         goto err1;
285     }
286
287     free_tm_dlg(dialog_info);
288
289     LM_DBG("BYE sent to %s\n", (dir == 0) ? "caller" : "callee");
290     return 0;
291
292 err1:
293     unref_dlg(cell, 1);
294 err:
295     if (dialog_info)
296         free_tm_dlg(dialog_info);
297     return -1;
298 }
299
300 /*static void early_transaction_destroyed(struct cell* t, int type, struct tmcb_params *param) {
301     struct dlg_cell *dlg = (struct dlg_cell *) (*param->param);
302
303     if (!dlg)
304         return;
305
306     LM_DBG("Early transaction destroyed\n");
307 }*/
308
309 /* side =
310  * 0: caller
311  * 1: callee
312  * 2: all
313  */
314 int dlg_terminate(struct dlg_cell *dlg, struct sip_msg *msg, str *reason, int side, str *extra_hdrs) {
315
316     struct cell* t;
317     str default_reason = {"call failed", 11};
318     int cfg_cmd = 0;
319     str default_extra_headers = {0,0};
320
321     if (!dlg) {
322         LM_ERR("calling end_dialog with NULL pointer dlg\n");
323         return -1;
324     }
325
326     if (!extra_hdrs)
327         extra_hdrs = &default_extra_headers;
328
329
330     if (msg) {
331         //assume called from cfg command -> dlg_terminate, as opposed to internal API or mi interface
332         cfg_cmd = 1;
333     }
334
335     if (!reason || reason->len <= 0 || !reason->s) {
336         reason = &default_reason;
337     }
338
339     if (dlg->state != DLG_STATE_CONFIRMED) {
340         if (side != 2) {
341             LM_ERR("can't terminate only 1 side of an early dialog\n");
342             return -1;
343         }
344         if (dlg->transaction) {
345             LM_DBG("terminating early dialog with %d outbound forks on transaction %p\n",
346                     dlg->transaction->nr_of_outgoings, dlg->transaction);
347
348             t = dlg->transaction;
349
350             if (t && t!=(void*) -1  && t->uas.request) {
351                 if (t->method.len!=6 || t->method.s[0]!='I' || t->method.s[1]!='N' || t->method.s[2]!='V')
352                 {
353                         //well this is the transaction of a subsequent request within the dialog
354                         //and the dialog is not confirmed yet, so its a PRACK or an UPDATE
355                         //could also be an options, but the important thing is how am i going to get
356                         //the transaction of the invite, that is the one i have to cancel
357                         LM_WARN("this is not my transaction so where am i?\n");
358                         return 1; //TODO - need to check why we got in here once before? this crashed on t_reply as t seemed invalid
359                 }
360
361                 //TODO: here we are assuming none of the CALLEE's have sent a 200, in
362                 //which case we would have to send an ACK, BYE
363                 //so right now - we are sending 488 to caller and CANCEL's to all CALLEEs
364
365                 LM_DBG("tearing down dialog in EARLY state - no clients responded > 199\n");
366                 if (cfg_cmd) {
367                         d_tmb.t_reply(msg,488,reason->s);
368                         d_tmb.t_release(msg);
369                 } else {
370                         d_tmb.t_reply(t->uas.request,488,reason->s);
371                         d_tmb.t_release(t->uas.request);
372                 }
373             }
374         } else {
375             LM_WARN("can't terminate early dialog without a transaction\n");
376             return -1;
377         }
378     } else {
379         LM_DBG("terminating confirmed dialog\n");
380         if (side == DLG_CALLER_LEG /* 0 */ || side == DLG_CALLEE_LEG /* 1 */) {
381             if (dlg_bye(dlg, (extra_hdrs->len > 0) ? extra_hdrs : NULL, side) < 0)
382                 return -1;
383
384         } else {
385             if (dlg_bye_all(dlg, (extra_hdrs->len > 0) ? extra_hdrs : NULL) < 0)
386                 return -1;
387         }
388     }
389     return 1;
390 }
391
392 #ifdef MI_REMOVED
393 /*parameters from MI: callid, from tag, to tag*/
394 /* TODO: add reason parameter to mi interface */
395 struct mi_root * mi_terminate_dlg(struct mi_root *cmd_tree, void *param) {
396
397     struct mi_node* node;
398     struct dlg_cell * dlg = NULL;
399     str mi_extra_hdrs = {"Reason: mi_terminated\r\n", 23};
400     int status, msg_len;
401     char *msg;
402
403     str callid = {NULL, 0};
404     str ftag = {NULL, 0};
405     str ttag = {NULL, 0};
406     str reason = {"mi_terminated", 13};
407
408     if (d_table == NULL)
409         goto end;
410
411     node = cmd_tree->node.kids;
412
413     if (node == NULL || node->next == NULL  || node->next->next == NULL)
414         return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
415
416     if (!node->value.s || !node->value.len) {
417         goto error;
418     } else {
419         callid = node->value;
420     }
421     node = node->next;
422     if (!node->value.s || !node->value.len) {
423         goto error;
424     } else {
425         ftag = node->value;
426     }
427     node = node->next;
428     if (!node->value.s || !node->value.len) {
429         goto error;
430     } else {
431         ttag = node->value;
432     }
433
434     if (node->next) {
435         node = node->next;
436         if (node->value.len && node->value.s)
437             mi_extra_hdrs = node->value;
438     }
439
440     unsigned int dir = DLG_DIR_NONE;
441     LM_DBG("Looking for callid [%.*s]\n", callid.len, callid.s);
442     dlg = get_dlg(&callid, &ftag, &ttag, &dir); //increments ref count!
443
444     if (dlg) {
445         LM_DBG("Found dialog to terminate and it is in state [%i] [%.*s]\n", dlg->state, mi_extra_hdrs.len, mi_extra_hdrs.s);
446
447         if (dlg_terminate(dlg, 0, &reason/*reson*/, /* all sides of a dialog*/ 2, &mi_extra_hdrs) < 0) {
448             status = 500;
449             msg = MI_DLG_OPERATION_ERR;
450             msg_len = MI_DLG_OPERATION_ERR_LEN;
451         } else {
452             status = 200;
453             msg = MI_OK_S;
454             msg_len = MI_OK_LEN;
455         }
456         unref_dlg(dlg, 1);
457
458         return init_mi_tree(status, msg, msg_len);
459     }
460 end:
461     return init_mi_tree(404, MI_DIALOG_NOT_FOUND, MI_DIALOG_NOT_FOUND_LEN);
462
463 error:
464     return init_mi_tree(400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
465
466 }
467 #endif
468
469 int dlg_bye(struct dlg_cell *dlg, str *hdrs, int side) {
470     str all_hdrs = {0, 0};
471     int ret;
472
473     if (side == DLG_CALLER_LEG) {
474         if (dlg->dflags & DLG_FLAG_CALLERBYE)
475             return -1;
476         dlg->dflags |= DLG_FLAG_CALLERBYE;
477     } else {
478         if (dlg->dflags & DLG_FLAG_CALLEEBYE)
479             return -1;
480         dlg->dflags |= DLG_FLAG_CALLEEBYE;
481     }
482     if ((build_extra_hdr(dlg, hdrs, &all_hdrs)) != 0) {
483         LM_ERR("failed to build dlg headers\n");
484         return -1;
485     }
486     ret = send_bye(dlg, side, &all_hdrs);
487     pkg_free(all_hdrs.s);
488     return ret;
489 }
490
491 /* Wrapper for terminating dialog from API - from other modules */
492 int w_api_terminate_dlg(str *callid, str *ftag, str *ttag, str *hdrs, str* reason) {
493     struct dlg_cell *dlg;
494
495     unsigned int dir = DLG_DIR_NONE;
496     dlg = get_dlg(callid, ftag, ttag, &dir); //increments ref count!
497
498     if (!dlg) {
499         LM_ERR("Asked to tear down non existent dialog\n");
500         return -1;
501     }
502
503     unref_dlg(dlg, 1);
504
505     return dlg_terminate(dlg, NULL, reason, 2, hdrs);
506
507 }
508
509 int dlg_bye_all(struct dlg_cell *dlg, str *hdrs) {
510     str all_hdrs = {0, 0};
511     int ret;
512
513     if ((build_extra_hdr(dlg, hdrs, &all_hdrs)) != 0) {
514         LM_ERR("failed to build dlg headers\n");
515         return -1;
516     }
517
518     ret = send_bye(dlg, DLG_CALLER_LEG, &all_hdrs);
519     ret |= send_bye(dlg, DLG_CALLEE_LEG, &all_hdrs);
520
521     pkg_free(all_hdrs.s);
522     return ret;
523
524 }
525
526
527 /* Wrapper for terminating dialog from API - from other modules */
528 int w_api_lookup_terminate_dlg(unsigned int h_entry, unsigned int h_id, str *hdrs) {
529     struct dlg_cell *dlg;
530
531     dlg = lookup_dlg(h_entry, h_id); //increments ref count!
532
533     if (!dlg) {
534         LM_ERR("Asked to tear down non existent dialog\n");
535         return -1;
536     }
537
538     unref_dlg(dlg, 1);
539
540     return dlg_terminate(dlg, NULL, NULL/*reason*/, 2, hdrs);
541
542 }
543