00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <stdio.h>
00024 #include <string.h>
00025 #include <stdlib.h>
00026 #include "../../dprint.h"
00027 #include "../../ut.h"
00028 #include "../../trim.h"
00029 #include "../../mem/mem.h"
00030 #include "../../mem/shm_mem.h"
00031 #include "../../parser/parse_from.h"
00032 #include "../../parser/msg_parser.h"
00033
00034 #include "../tm/tm_load.h"
00035
00036 #include "dlg_req_within.h"
00037 #include "dlg_transfer.h"
00038
00039 #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"
00040 #define DLG_HOLD_SDP_LEN (sizeof(DLG_HOLD_SDP)-1)
00041
00042 #define DLG_HOLD_CT_HDR "Contact: <sip:kamailio.org:5060>\r\nContent-Type: application/sdp\r\n"
00043 #define DLG_HOLD_CT_HDR_LEN (sizeof(DLG_HOLD_CT_HDR)-1)
00044
00045 extern str dlg_bridge_controller;
00046
00047 void dlg_transfer_ctx_free(dlg_transfer_ctx_t *dtc)
00048 {
00049 struct dlg_cell *dlg;
00050
00051 if(dtc==NULL)
00052 return;
00053 if(dtc->from.s!=NULL)
00054 shm_free(dtc->from.s);
00055 if(dtc->to.s!=NULL)
00056 shm_free(dtc->to.s);
00057
00058 dlg = dtc->dlg;
00059 if(dlg!=NULL)
00060 {
00061 if (dlg->tag[DLG_CALLER_LEG].s)
00062 shm_free(dlg->tag[DLG_CALLER_LEG].s);
00063
00064 if (dlg->tag[DLG_CALLEE_LEG].s)
00065 shm_free(dlg->tag[DLG_CALLEE_LEG].s);
00066
00067 if (dlg->cseq[DLG_CALLER_LEG].s)
00068 shm_free(dlg->cseq[DLG_CALLER_LEG].s);
00069
00070 if (dlg->cseq[DLG_CALLEE_LEG].s)
00071 shm_free(dlg->cseq[DLG_CALLEE_LEG].s);
00072
00073 shm_free(dlg);
00074 }
00075
00076 shm_free(dtc);
00077 }
00078
00079 void dlg_refer_tm_callback(struct cell *t, int type, struct tmcb_params *ps)
00080 {
00081 dlg_transfer_ctx_t *dtc = NULL;
00082 dlg_t* dialog_info = NULL;
00083 str met = {"BYE", 3};
00084 int result;
00085 struct dlg_cell *dlg;
00086
00087 if(ps->param==NULL || *ps->param==0)
00088 {
00089 LM_DBG("message id not received\n");
00090 return;
00091 }
00092 dtc = *((dlg_transfer_ctx_t**)ps->param);
00093 if(dtc==NULL)
00094 return;
00095 LM_DBG("REFER completed with status %d\n", ps->code);
00096
00097
00098 dlg = dtc->dlg;
00099 if ((dialog_info = build_dlg_t(dlg, DLG_CALLEE_LEG)) == 0){
00100 LM_ERR("failed to create dlg_t\n");
00101 goto error;
00102 }
00103
00104 result = d_tmb.t_request_within
00105 (&met,
00106 0,
00107 NULL,
00108 dialog_info,
00109 0,
00110 0);
00111
00112 if(result < 0) {
00113 LM_ERR("failed to send the REFER request\n");
00114
00115 goto error;
00116 }
00117
00118 free_tm_dlg(dialog_info);
00119 dlg_transfer_ctx_free(dtc);
00120
00121 LM_DBG("BYE sent\n");
00122 return;
00123
00124 error:
00125 dlg_transfer_ctx_free(dtc);
00126 if(dialog_info)
00127 free_tm_dlg(dialog_info);
00128 return;
00129
00130 }
00131
00132 static int dlg_refer_callee(dlg_transfer_ctx_t *dtc)
00133 {
00134
00135 dlg_t* dialog_info = NULL;
00136 str met = {"REFER", 5};
00137 int result;
00138 str hdrs;
00139 struct dlg_cell *dlg;
00140
00141 dlg = dtc->dlg;
00142
00143 if ((dialog_info = build_dlg_t(dlg, DLG_CALLEE_LEG)) == 0){
00144 LM_ERR("failed to create dlg_t\n");
00145 goto error;
00146 }
00147
00148 hdrs.len = 23 + 2*CRLF_LEN + dlg_bridge_controller.len
00149 + dtc->to.len;
00150 LM_DBG("sending REFER [%d] <%.*s>\n", hdrs.len, dtc->to.len, dtc->to.s);
00151 hdrs.s = (char*)pkg_malloc(hdrs.len*sizeof(char));
00152 if(hdrs.s == NULL)
00153 goto error;
00154 memcpy(hdrs.s, "Referred-By: ", 13);
00155 memcpy(hdrs.s+13, dlg_bridge_controller.s, dlg_bridge_controller.len);
00156 memcpy(hdrs.s+13+dlg_bridge_controller.len, CRLF, CRLF_LEN);
00157 memcpy(hdrs.s+13+dlg_bridge_controller.len+CRLF_LEN, "Refer-To: ", 10);
00158 memcpy(hdrs.s+23+dlg_bridge_controller.len+CRLF_LEN, dtc->to.s,
00159 dtc->to.len);
00160 memcpy(hdrs.s+23+dlg_bridge_controller.len+CRLF_LEN+dtc->to.len,
00161 CRLF, CRLF_LEN);
00162
00163 result = d_tmb.t_request_within
00164 (&met,
00165 &hdrs,
00166 NULL,
00167 dialog_info,
00168 dlg_refer_tm_callback,
00169 (void*)dtc);
00170
00171 pkg_free(hdrs.s);
00172 if(result < 0) {
00173 LM_ERR("failed to send the REFER request\n");
00174
00175 goto error;
00176 }
00177
00178 free_tm_dlg(dialog_info);
00179
00180 LM_DBG("REFER sent\n");
00181 return 0;
00182
00183 error:
00184 if(dialog_info)
00185 free_tm_dlg(dialog_info);
00186 return -1;
00187 }
00188
00189
00190 void dlg_bridge_tm_callback(struct cell *t, int type, struct tmcb_params *ps)
00191 {
00192 struct sip_msg *msg = NULL;
00193 dlg_transfer_ctx_t *dtc = NULL;
00194 struct dlg_cell *dlg = NULL;
00195 str s;
00196 str cseq;
00197 str empty = {"", 0};
00198
00199 if(ps->param==NULL || *ps->param==0)
00200 {
00201 LM_DBG("message id not received\n");
00202 return;
00203 }
00204 dtc = *((dlg_transfer_ctx_t**)ps->param);
00205 if(dtc==NULL)
00206 return;
00207 LM_DBG("completed with status %d\n", ps->code);
00208 if(ps->code>=300)
00209 goto error;
00210
00211
00212 msg = ps->rpl;
00213 if((msg->cseq==NULL || parse_headers(msg,HDR_CSEQ_F,0)<0)
00214 || msg->cseq==NULL || msg->cseq->parsed==NULL)
00215 {
00216 LM_ERR("bad sip message or missing CSeq hdr :-/\n");
00217 goto error;
00218 }
00219 cseq = (get_cseq(msg))->number;
00220
00221 if((msg->to==NULL && parse_headers(msg, HDR_TO_F,0)<0) || msg->to==NULL)
00222 {
00223 LM_ERR("bad request or missing TO hdr\n");
00224 goto error;
00225 }
00226 if(parse_from_header(msg))
00227 {
00228 LM_ERR("bad request or missing FROM hdr\n");
00229 goto error;
00230 }
00231 if((msg->callid==NULL && parse_headers(msg,HDR_CALLID_F,0)<0)
00232 || msg->callid==NULL){
00233 LM_ERR("bad request or missing CALLID hdr\n");
00234 goto error;
00235 }
00236 s = msg->callid->body;
00237 trim(&s);
00238
00239
00240 if (s.len==0 || get_from(msg)->tag_value.len==0) {
00241 LM_ERR("invalid request -> callid (%d) or from TAG (%d) empty\n",
00242 s.len, get_from(msg)->tag_value.len);
00243 goto error;
00244 }
00245
00246 dlg = build_new_dlg(&s , &(get_from(msg)->uri) ,
00247 &(get_to(msg)->uri) ,
00248 &(get_from(msg)->tag_value) );
00249 if (dlg==0) {
00250 LM_ERR("failed to create new dialog\n");
00251 goto error;
00252 }
00253 dtc->dlg = dlg;
00254 if (dlg_set_leg_info(dlg, &(get_from(msg)->tag_value),
00255 &empty, &dlg_bridge_controller, &cseq, DLG_CALLER_LEG)!=0) {
00256 LM_ERR("dlg_set_leg_info failed\n");
00257 goto error;
00258 }
00259
00260 if (populate_leg_info(dlg, msg, t, DLG_CALLEE_LEG,
00261 &(get_to(msg)->tag_value)) !=0)
00262 {
00263 LM_ERR("could not add further info to the dialog\n");
00264 shm_free(dlg);
00265 goto error;
00266 }
00267
00268 if(dlg_refer_callee(dtc)!=0)
00269 goto error;
00270 return;
00271
00272 error:
00273 dlg_transfer_ctx_free(dtc);
00274 return;
00275 }
00276
00277
00278 int dlg_bridge(str *from, str *to, str *op)
00279 {
00280 dlg_transfer_ctx_t *dtc;
00281 int ret;
00282 str s_method = {"INVITE", 6};
00283 str s_body;
00284 str s_hdrs;
00285
00286 dtc = (dlg_transfer_ctx_t*)shm_malloc(sizeof(dlg_transfer_ctx_t));
00287 if(dtc==NULL)
00288 {
00289 LM_ERR("no shm\n");
00290 return -1;
00291 }
00292 memset(dtc, 0, sizeof(dlg_transfer_ctx_t));
00293 dtc->from.s = (char*)shm_malloc((from->len+1)*sizeof(char));
00294 if(dtc->from.s==NULL)
00295 {
00296 LM_ERR("no shm\n");
00297 shm_free(dtc);
00298 return -1;
00299 }
00300 dtc->to.s = (char*)shm_malloc((to->len+1)*sizeof(char));
00301 if(dtc->to.s==NULL)
00302 {
00303 LM_ERR("no shm\n");
00304 shm_free(dtc->from.s);
00305 shm_free(dtc);
00306 return -1;
00307 }
00308 memcpy(dtc->from.s, from->s, from->len);
00309 dtc->from.len = from->len;
00310 dtc->from.s[dtc->from.len] = '\0';
00311 memcpy(dtc->to.s, to->s, to->len);
00312 dtc->to.len = to->len;
00313 dtc->to.s[dtc->to.len] = '\0';
00314
00315 LM_DBG("bridge <%.*s> to <%.*s>\n", dtc->from.len, dtc->from.s,
00316 dtc->to.len, dtc->to.s);
00317 s_body.s = DLG_HOLD_SDP;
00318 s_body.len = DLG_HOLD_SDP_LEN;
00319 s_hdrs.s = DLG_HOLD_CT_HDR;
00320 s_hdrs.len = DLG_HOLD_CT_HDR_LEN;
00321
00322 ret = d_tmb.t_request(&s_method,
00323 &dtc->from,
00324 &dtc->from,
00325 &dlg_bridge_controller,
00326 &s_hdrs,
00327 &s_body,
00328 (op!=NULL && op->len>0)?op:NULL,
00329 dlg_bridge_tm_callback,
00330 (void*)(long)dtc
00331 );
00332
00333 if(ret<0)
00334 {
00335 dlg_transfer_ctx_free(dtc);
00336 return -1;
00337 }
00338 return 0;
00339 }
00340
00341 int dlg_transfer(struct dlg_cell *dlg, str *to, int side)
00342 {
00343 dlg_transfer_ctx_t *dtc = NULL;
00344 struct dlg_cell *ndlg = NULL;
00345 str from;
00346 str empty = {"", 0};
00347
00348 dtc = (dlg_transfer_ctx_t*)shm_malloc(sizeof(dlg_transfer_ctx_t));
00349 if(dtc==NULL)
00350 {
00351 LM_ERR("no shm\n");
00352 return -1;
00353 }
00354 if(side==DLG_CALLEE_LEG)
00355 {
00356 from = dlg->from_uri;
00357 } else {
00358 from = dlg->to_uri;
00359 }
00360 memset(dtc, 0, sizeof(dlg_transfer_ctx_t));
00361 dtc->from.s = (char*)shm_malloc((from.len+1)*sizeof(char));
00362 if(dtc->from.s==NULL)
00363 {
00364 LM_ERR("no shm\n");
00365 shm_free(dtc);
00366 return -1;
00367 }
00368 dtc->to.s = (char*)shm_malloc((to->len+1)*sizeof(char));
00369 if(dtc->to.s==NULL)
00370 {
00371 LM_ERR("no shm\n");
00372 shm_free(dtc->from.s);
00373 shm_free(dtc);
00374 return -1;
00375 }
00376 memcpy(dtc->from.s, from.s, from.len);
00377 dtc->from.len = from.len;
00378 dtc->from.s[dtc->from.len] = '\0';
00379 memcpy(dtc->to.s, to->s, to->len);
00380 dtc->to.len = to->len;
00381 dtc->to.s[dtc->to.len] = '\0';
00382
00383 if(side==DLG_CALLER_LEG)
00384 ndlg = build_new_dlg(&dlg->callid ,
00385 &dlg->to_uri , &dlg->from_uri ,
00386 &dlg->tag[side] );
00387 else
00388 ndlg = build_new_dlg(&dlg->callid ,
00389 &dlg->from_uri , &dlg->to_uri ,
00390 &dlg->tag[side] );
00391 if (ndlg==0) {
00392 LM_ERR("failed to create new dialog\n");
00393 goto error;
00394 }
00395 dtc->dlg = ndlg;
00396 if (dlg_set_leg_info(ndlg, &dlg->tag[side], &empty,
00397 &dlg->contact[side], &dlg->cseq[side], DLG_CALLER_LEG)!=0)
00398 {
00399 LM_ERR("dlg_set_leg_info failed for caller\n");
00400 goto error;
00401 }
00402 if(side==DLG_CALLEE_LEG)
00403 side = DLG_CALLER_LEG;
00404 else
00405 side = DLG_CALLEE_LEG;
00406 if (dlg_set_leg_info(ndlg, &dlg->tag[side], &dlg->route_set[side],
00407 &dlg->contact[side], &dlg->cseq[side], DLG_CALLEE_LEG)!=0)
00408 {
00409 LM_ERR("dlg_set_leg_info failed for caller\n");
00410 goto error;
00411 }
00412
00413 if(dlg_refer_callee(dtc)!=0)
00414 goto error;
00415 return 0;
00416
00417 error:
00418 dlg_transfer_ctx_free(dtc);
00419 return -1;
00420 }
00421