23485901840ef0803543b31b109b644461205160
[sip-router] / modules_k / dialog / dlg_transfer.c
1 /**
2  * $Id$
3  *
4  * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com)
5  *
6  * This file is part of kamailio, a free SIP server.
7  *
8  * kamailio is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version
12  *
13  * kamailio is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include "../../dprint.h"
27 #include "../../ut.h"
28 #include "../../trim.h"
29 #include "../../mem/mem.h"
30 #include "../../mem/shm_mem.h"
31 #include "../../parser/parse_from.h"
32 #include "../../parser/msg_parser.h"
33
34 #include "../../modules/tm/tm_load.h"
35
36 #include "dlg_req_within.h"
37 #include "dlg_transfer.h"
38
39 #define DLG_HOLD_SDP "v=0\r\no=kamailio-bridge 0 0 IN IP4 0.0.0.0\r\ns=kamailio\r\nc=IN IP4 0.0.0.0\r\nt=0 0\r\nm=audio 9 RTP/AVP 8 0\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:0 PCMU/8000\r\n"
40 #define DLG_HOLD_SDP_LEN        (sizeof(DLG_HOLD_SDP)-1)
41
42 #define DLG_HOLD_CT_HDR "Contact: <sip:kamailio.org:5060>\r\nContent-Type: application/sdp\r\n"
43 #define DLG_HOLD_CT_HDR_LEN     (sizeof(DLG_HOLD_CT_HDR)-1)
44
45 extern str dlg_bridge_controller;
46
47 void dlg_transfer_ctx_free(dlg_transfer_ctx_t *dtc)
48 {
49         struct dlg_cell *dlg;
50
51         if(dtc==NULL)
52                 return;
53         if(dtc->from.s!=NULL)
54                 shm_free(dtc->from.s);
55         if(dtc->to.s!=NULL)
56                 shm_free(dtc->to.s);
57
58         dlg = dtc->dlg;
59         if(dlg!=NULL)
60         {
61                 if (dlg->tag[DLG_CALLER_LEG].s)
62                         shm_free(dlg->tag[DLG_CALLER_LEG].s);
63
64                 if (dlg->tag[DLG_CALLEE_LEG].s)
65                         shm_free(dlg->tag[DLG_CALLEE_LEG].s);
66
67                 if (dlg->cseq[DLG_CALLER_LEG].s)
68                         shm_free(dlg->cseq[DLG_CALLER_LEG].s);
69
70                 if (dlg->cseq[DLG_CALLEE_LEG].s)
71                         shm_free(dlg->cseq[DLG_CALLEE_LEG].s);
72
73                 shm_free(dlg);
74         }
75
76         shm_free(dtc);
77 }
78
79 void dlg_refer_tm_callback(struct cell *t, int type, struct tmcb_params *ps)
80 {
81         dlg_transfer_ctx_t *dtc = NULL;
82         dlg_t* dialog_info = NULL;
83         str met = {"BYE", 3};
84         int result;
85         struct dlg_cell *dlg;
86         uac_req_t uac_r;
87
88         if(ps->param==NULL || *ps->param==0)
89         {
90                 LM_DBG("message id not received\n");
91                 return;
92         }
93         dtc = *((dlg_transfer_ctx_t**)ps->param);
94         if(dtc==NULL)
95                 return;
96         LM_DBG("REFER completed with status %d\n", ps->code);
97
98         /* we send the BYE anyhow */
99         dlg = dtc->dlg;
100         if ((dialog_info = build_dlg_t(dlg, DLG_CALLEE_LEG)) == 0){
101                 LM_ERR("failed to create dlg_t\n");
102                 goto error;
103         }
104
105         memset(&uac_r, '\0', sizeof(uac_req_t));
106         set_uac_req(&uac_r, &met, NULL, NULL, dialog_info, 0, NULL, NULL);
107         result = d_tmb.t_request_within(&uac_r);
108
109         if(result < 0) {
110                 LM_ERR("failed to send the REFER request\n");
111                 /* todo: clean-up dtc */
112                 goto error;
113         }
114
115         free_tm_dlg(dialog_info);
116         dlg_transfer_ctx_free(dtc);
117
118         LM_DBG("BYE sent\n");
119         return;
120
121 error:
122         dlg_transfer_ctx_free(dtc);
123         if(dialog_info)
124                 free_tm_dlg(dialog_info);
125         return;
126
127 }
128
129 static int dlg_refer_callee(dlg_transfer_ctx_t *dtc)
130 {
131         /*verify direction*/
132         dlg_t* dialog_info = NULL;
133         str met = {"REFER", 5};
134         int result;
135         str hdrs;
136         struct dlg_cell *dlg;
137         uac_req_t uac_r;
138
139         dlg = dtc->dlg;
140
141         if ((dialog_info = build_dlg_t(dlg, DLG_CALLEE_LEG)) == 0){
142                 LM_ERR("failed to create dlg_t\n");
143                 goto error;
144         }
145
146         hdrs.len = 23 + 2*CRLF_LEN + dlg_bridge_controller.len
147                 + dtc->to.len;
148         LM_DBG("sending REFER [%d] <%.*s>\n", hdrs.len, dtc->to.len, dtc->to.s);
149         hdrs.s = (char*)pkg_malloc(hdrs.len*sizeof(char));
150         if(hdrs.s == NULL)
151                 goto error;
152         memcpy(hdrs.s, "Referred-By: ", 13);
153         memcpy(hdrs.s+13, dlg_bridge_controller.s, dlg_bridge_controller.len);
154         memcpy(hdrs.s+13+dlg_bridge_controller.len, CRLF, CRLF_LEN);
155         memcpy(hdrs.s+13+dlg_bridge_controller.len+CRLF_LEN, "Refer-To: ", 10);
156         memcpy(hdrs.s+23+dlg_bridge_controller.len+CRLF_LEN, dtc->to.s,
157                         dtc->to.len);
158         memcpy(hdrs.s+23+dlg_bridge_controller.len+CRLF_LEN+dtc->to.len,
159                         CRLF, CRLF_LEN);
160
161         memset(&uac_r, '\0', sizeof(uac_req_t));
162         set_uac_req(&uac_r, &met, &hdrs, NULL, dialog_info, 0,
163                                 dlg_refer_tm_callback, (void*)dtc);
164         result = d_tmb.t_request_within(&uac_r);
165
166         pkg_free(hdrs.s);
167         if(result < 0) {
168                 LM_ERR("failed to send the REFER request\n");
169                 /* todo: clean-up dtc */
170                 goto error;
171         }
172
173         free_tm_dlg(dialog_info);
174
175         LM_DBG("REFER sent\n");
176         return 0;
177
178 error:
179         if(dialog_info)
180                 free_tm_dlg(dialog_info);
181         return -1;
182 }
183
184
185 void dlg_bridge_tm_callback(struct cell *t, int type, struct tmcb_params *ps)
186 {
187         struct sip_msg *msg = NULL;
188         dlg_transfer_ctx_t *dtc = NULL;
189         struct dlg_cell *dlg = NULL;
190         str s;
191         str cseq;
192         str empty = {"", 0};
193
194         if(ps->param==NULL || *ps->param==0)
195         {
196                 LM_DBG("message id not received\n");
197                 return;
198         }
199         dtc = *((dlg_transfer_ctx_t**)ps->param);
200         if(dtc==NULL)
201                 return;
202         LM_DBG("completed with status %d\n", ps->code);
203         if(ps->code>=300)
204                 goto error;
205
206         /* 2xx - build dialog/send refer */
207         msg = ps->rpl;
208         if((msg->cseq==NULL || parse_headers(msg,HDR_CSEQ_F,0)<0)
209                         || msg->cseq==NULL || msg->cseq->parsed==NULL)
210         {
211                         LM_ERR("bad sip message or missing CSeq hdr :-/\n");
212                         goto error;
213         }
214         cseq = (get_cseq(msg))->number;
215
216         if((msg->to==NULL && parse_headers(msg, HDR_TO_F,0)<0) || msg->to==NULL)
217         {
218                 LM_ERR("bad request or missing TO hdr\n");
219                 goto error;
220         }
221         if(parse_from_header(msg))
222         {
223                 LM_ERR("bad request or missing FROM hdr\n");
224                 goto error;
225         }
226         if((msg->callid==NULL && parse_headers(msg,HDR_CALLID_F,0)<0)
227                         || msg->callid==NULL){
228                 LM_ERR("bad request or missing CALLID hdr\n");
229                 goto error;
230         }
231         s = msg->callid->body;
232         trim(&s);
233
234         /* some sanity checks */
235         if (s.len==0 || get_from(msg)->tag_value.len==0) {
236                 LM_ERR("invalid request -> callid (%d) or from TAG (%d) empty\n",
237                         s.len, get_from(msg)->tag_value.len);
238                 goto error;
239         }
240
241         dlg = build_new_dlg(&s /*callid*/, &(get_from(msg)->uri) /*from uri*/,
242                 &(get_to(msg)->uri) /*to uri*/,
243                 &(get_from(msg)->tag_value)/*from_tag*/ );
244         if (dlg==0) {
245                 LM_ERR("failed to create new dialog\n");
246                 goto error;
247         }
248         dtc->dlg = dlg;
249         if (dlg_set_leg_info(dlg, &(get_from(msg)->tag_value),
250                                 &empty, &dlg_bridge_controller, &cseq, DLG_CALLER_LEG)!=0) {
251                 LM_ERR("dlg_set_leg_info failed\n");
252                 goto error;
253         }
254
255         if (populate_leg_info(dlg, msg, t, DLG_CALLEE_LEG,
256                         &(get_to(msg)->tag_value)) !=0)
257         {
258                 LM_ERR("could not add further info to the dialog\n");
259                 shm_free(dlg);
260                 goto error;
261         }
262
263         if(dlg_refer_callee(dtc)!=0)
264                 goto error;
265         return;
266
267 error:
268         dlg_transfer_ctx_free(dtc);
269         return;
270 }
271
272
273 int dlg_bridge(str *from, str *to, str *op)
274 {
275         dlg_transfer_ctx_t *dtc;
276         int ret;
277         str s_method = {"INVITE", 6};
278         str s_body;
279         str s_hdrs;
280         uac_req_t uac_r;
281
282         dtc = (dlg_transfer_ctx_t*)shm_malloc(sizeof(dlg_transfer_ctx_t));
283         if(dtc==NULL)
284         {
285                 LM_ERR("no shm\n");
286                 return -1;
287         }
288         memset(dtc, 0, sizeof(dlg_transfer_ctx_t));
289         dtc->from.s = (char*)shm_malloc((from->len+1)*sizeof(char));
290         if(dtc->from.s==NULL)
291         {
292                 LM_ERR("no shm\n");
293                 shm_free(dtc);
294                 return -1;
295         }
296         dtc->to.s = (char*)shm_malloc((to->len+1)*sizeof(char));
297         if(dtc->to.s==NULL)
298         {
299                 LM_ERR("no shm\n");
300                 shm_free(dtc->from.s);
301                 shm_free(dtc);
302                 return -1;
303         }
304         memcpy(dtc->from.s, from->s, from->len);
305         dtc->from.len = from->len;
306         dtc->from.s[dtc->from.len] = '\0';
307         memcpy(dtc->to.s, to->s, to->len);
308         dtc->to.len = to->len;
309         dtc->to.s[dtc->to.len] = '\0';
310
311         LM_DBG("bridge <%.*s> to <%.*s>\n", dtc->from.len, dtc->from.s,
312                         dtc->to.len, dtc->to.s);
313         s_body.s   = DLG_HOLD_SDP;
314         s_body.len = DLG_HOLD_SDP_LEN;
315         s_hdrs.s   = DLG_HOLD_CT_HDR;
316         s_hdrs.len = DLG_HOLD_CT_HDR_LEN;
317
318         memset(&uac_r, '\0', sizeof(uac_req_t));
319         uac_r.method = &s_method;
320         uac_r.headers = &s_hdrs;
321         uac_r.body = &s_body;
322         uac_r.cb = dlg_bridge_tm_callback;
323         uac_r.cbp = (void*)(long)dtc;
324         ret = d_tmb.t_request(&uac_r, /* UAC Req */
325                                                   &dtc->from, /* Request-URI (To) */
326                                                   &dtc->from, /* To */
327                                                   &dlg_bridge_controller, /* From */
328                                                   (op != NULL && op->len>0)?op:NULL /* Outbound-URI */
329                 );
330
331         if(ret<0)
332         {
333                 dlg_transfer_ctx_free(dtc);
334                 return -1;
335         }
336         return 0;
337 }
338
339 int dlg_transfer(struct dlg_cell *dlg, str *to, int side)
340 {
341         dlg_transfer_ctx_t *dtc = NULL;
342         struct dlg_cell *ndlg = NULL;
343         str from;
344         str empty = {"", 0};
345
346         dtc = (dlg_transfer_ctx_t*)shm_malloc(sizeof(dlg_transfer_ctx_t));
347         if(dtc==NULL)
348         {
349                 LM_ERR("no shm\n");
350                 return -1;
351         }
352         if(side==DLG_CALLEE_LEG)
353         {
354                 from = dlg->from_uri;
355         } else {
356                 from = dlg->to_uri;
357         }
358         memset(dtc, 0, sizeof(dlg_transfer_ctx_t));
359         dtc->from.s = (char*)shm_malloc((from.len+1)*sizeof(char));
360         if(dtc->from.s==NULL)
361         {
362                 LM_ERR("no shm\n");
363                 shm_free(dtc);
364                 return -1;
365         }
366         dtc->to.s = (char*)shm_malloc((to->len+1)*sizeof(char));
367         if(dtc->to.s==NULL)
368         {
369                 LM_ERR("no shm\n");
370                 shm_free(dtc->from.s);
371                 shm_free(dtc);
372                 return -1;
373         }
374         memcpy(dtc->from.s, from.s, from.len);
375         dtc->from.len = from.len;
376         dtc->from.s[dtc->from.len] = '\0';
377         memcpy(dtc->to.s, to->s, to->len);
378         dtc->to.len = to->len;
379         dtc->to.s[dtc->to.len] = '\0';
380         
381         if(side==DLG_CALLER_LEG)
382                 ndlg = build_new_dlg(&dlg->callid /*callid*/,
383                                 &dlg->to_uri /*from uri*/, &dlg->from_uri /*to uri*/,
384                                 &dlg->tag[side]/*from_tag*/ );
385         else
386                 ndlg = build_new_dlg(&dlg->callid /*callid*/,
387                                 &dlg->from_uri /*from uri*/, &dlg->to_uri /*to uri*/,
388                                 &dlg->tag[side]/*from_tag*/ );
389         if (ndlg==0) {
390                 LM_ERR("failed to create new dialog\n");
391                 goto error;
392         }
393         dtc->dlg = ndlg;
394         if (dlg_set_leg_info(ndlg, &dlg->tag[side], &empty,
395                         &dlg->contact[side], &dlg->cseq[side], DLG_CALLER_LEG)!=0)
396         {
397                 LM_ERR("dlg_set_leg_info failed for caller\n");
398                 goto error;
399         }
400         if(side==DLG_CALLEE_LEG)
401                 side = DLG_CALLER_LEG;
402         else
403                 side = DLG_CALLEE_LEG;
404         if (dlg_set_leg_info(ndlg, &dlg->tag[side], &dlg->route_set[side],
405                         &dlg->contact[side], &dlg->cseq[side], DLG_CALLEE_LEG)!=0)
406         {
407                 LM_ERR("dlg_set_leg_info failed for caller\n");
408                 goto error;
409         }
410
411         if(dlg_refer_callee(dtc)!=0)
412                 goto error;
413         return 0;
414
415 error:
416         dlg_transfer_ctx_free(dtc);
417         return -1;
418 }
419