/* send keep-alive * dlg - pointer to a struct dlg_cell * dir - direction: the request will be sent to: * DLG_CALLER_LEG (0): caller * DLG_CALLEE_LEG (1): callee */ int dlg_send_ka(dlg_cell_t *dlg, int dir, str *hdrs) { uac_req_t uac_r; dlg_t* di; str met = {"OPTIONS", 7}; int result; dlg_iuid_t *iuid = NULL; /* do not send KA request for non-confirmed dialogs (not supported) */ if (dlg->state != DLG_STATE_CONFIRMED) { LM_DBG("skipping non-confirmed dialogs\n"); return 0; } /* build tm dlg by direction */ if ((di = build_dlg_t(dlg, dir)) == 0){ LM_ERR("failed to create dlg_t\n"); goto err; } /* tm increases cseq value, decrease it no to make it invalid * - dialog is ended on timeout (408) or C/L does not exist (481) */ if(di->loc_seq.value>1) di->loc_seq.value -= 2; else di->loc_seq.value -= 1; LM_DBG("sending BYE to %s\n", (dir==DLG_CALLER_LEG)?"caller":"callee"); iuid = dlg_get_iuid_shm_clone(dlg); if(iuid==NULL) { LM_ERR("failed to create dialog unique id clone\n"); goto err; } memset(&uac_r,'\0', sizeof(uac_req_t)); set_uac_req(&uac_r, &met, hdrs, NULL, di, TMCB_LOCAL_COMPLETED, dlg_ka_cb, (void*)iuid); result = d_tmb.t_request_within(&uac_r); if(result < 0){ LM_ERR("failed to send the BYE request\n"); goto err; } free_tm_dlg(di); LM_DBG("keep-alive sent to %s\n", (dir==0)?"caller":"callee"); return 0; err: if(di) free_tm_dlg(di); return -1; }
/* cell- pointer to a struct dlg_cell * leg - a dialog leg to be BYE'ed : * = 0: caller leg * > 0: callee legs */ static inline int send_leg_bye(struct dlg_cell *cell, int dst_leg, int src_leg, str *extra_hdrs) { context_p old_ctx; context_p *new_ctx; dlg_t* dialog_info; str met = {"BYE", 3}; int result; if ((dialog_info = build_dlg_t(cell, dst_leg, src_leg)) == 0){ LM_ERR("failed to create dlg_t\n"); goto err; } LM_DBG("sending BYE to %s (%d)\n", (dst_leg==DLG_CALLER_LEG)?"caller":"callee", dst_leg); /* set new processing context */ if (push_new_processing_context( cell, &old_ctx, &new_ctx, NULL)!=0) goto err; ctx_lastdstleg_set(dst_leg); ref_dlg(cell, 1); result = d_tmb.t_request_within (&met, /* method*/ extra_hdrs, /* extra headers*/ NULL, /* body*/ dialog_info, /* dialog structure*/ bye_reply_cb, /* callback function*/ (void*)cell, /* callback parameter*/ NULL); /* release function*/ /* reset the processing contect */ if (current_processing_ctx == NULL) *new_ctx = NULL; else context_destroy(CONTEXT_GLOBAL, *new_ctx); current_processing_ctx = old_ctx; if(result < 0){ LM_ERR("failed to send the BYE request\n"); goto err1; } free_tm_dlg(dialog_info); LM_DBG("BYE sent to %s\n", (dst_leg==DLG_CALLER_LEG)?"caller":"callee"); return 0; err1: unref_dlg(cell, 1); err: return -1; }
static int dlg_refer_callee(dlg_transfer_ctx_t *dtc) { /*verify direction*/ dlg_t* dialog_info = NULL; str met = {"REFER", 5}; int result; str hdrs; struct dlg_cell *dlg; uac_req_t uac_r; dlg = dtc->dlg; if ((dialog_info = build_dlg_t(dlg, DLG_CALLEE_LEG)) == 0){ LM_ERR("failed to create dlg_t\n"); goto error; } hdrs.len = 23 + 2*CRLF_LEN + dlg_bridge_controller.len + dtc->to.len + dlg_bridge_ref_hdrs.len; LM_DBG("sending REFER [%d] <%.*s>\n", hdrs.len, dtc->to.len, dtc->to.s); hdrs.s = (char*)pkg_malloc(hdrs.len*sizeof(char)); if(hdrs.s == NULL) goto error; memcpy(hdrs.s, "Referred-By: ", 13); memcpy(hdrs.s+13, dlg_bridge_controller.s, dlg_bridge_controller.len); memcpy(hdrs.s+13+dlg_bridge_controller.len, CRLF, CRLF_LEN); memcpy(hdrs.s+13+dlg_bridge_controller.len+CRLF_LEN, "Refer-To: ", 10); memcpy(hdrs.s+23+dlg_bridge_controller.len+CRLF_LEN, dtc->to.s, dtc->to.len); memcpy(hdrs.s+23+dlg_bridge_controller.len+CRLF_LEN+dtc->to.len, CRLF, CRLF_LEN); memcpy(hdrs.s+23+dlg_bridge_controller.len+CRLF_LEN+dtc->to.len+CRLF_LEN, dlg_bridge_ref_hdrs.s, dlg_bridge_ref_hdrs.len); set_uac_req(&uac_r, &met, &hdrs, NULL, dialog_info, TMCB_LOCAL_COMPLETED, dlg_refer_tm_callback, (void*)dtc); result = d_tmb.t_request_within(&uac_r); pkg_free(hdrs.s); if(result < 0) { LM_ERR("failed to send the REFER request\n"); /* todo: clean-up dtc */ goto error; } free_tm_dlg(dialog_info); LM_DBG("REFER sent\n"); return 0; error: if(dialog_info) free_tm_dlg(dialog_info); return -1; }
void dlg_refer_tm_callback(struct cell *t, int type, struct tmcb_params *ps) { dlg_transfer_ctx_t *dtc = NULL; dlg_t* dialog_info = NULL; str met = {"BYE", 3}; int result; struct dlg_cell *dlg; uac_req_t uac_r; if(ps->param==NULL || *ps->param==0) { LM_DBG("message id not received\n"); return; } dtc = *((dlg_transfer_ctx_t**)ps->param); if(dtc==NULL) return; LM_DBG("REFER completed with status %d\n", ps->code); /* we send the BYE anyhow */ dlg = dtc->dlg; if ((dialog_info = build_dlg_t(dlg, DLG_CALLEE_LEG)) == 0){ LM_ERR("failed to create dlg_t\n"); goto error; } /* after REFER, the CSeq must be increased */ dialog_info->loc_seq.value++; set_uac_req(&uac_r, &met, NULL, NULL, dialog_info, 0, NULL, NULL); result = d_tmb.t_request_within(&uac_r); if(result < 0) { LM_ERR("failed to send the REFER request\n"); /* todo: clean-up dtc */ goto error; } free_tm_dlg(dialog_info); dlg_transfer_ctx_free(dtc); LM_DBG("BYE sent\n"); return; error: dlg_transfer_ctx_free(dtc); if(dialog_info) free_tm_dlg(dialog_info); return; }
/* cell- pointer to a struct dlg_cell * dir- direction: the request will be sent to: * DLG_CALLER_LEG (0): caller * DLG_CALLEE_LEG (1): callee */ static inline int send_bye(struct dlg_cell * cell, int dir, str *hdrs) { uac_req_t uac_r; dlg_t* dialog_info; str met = {"BYE", 3}; int result; dlg_iuid_t *iuid = NULL; /* do not send BYE request for non-confirmed dialogs (not supported) */ if (cell->state != DLG_STATE_CONFIRMED_NA && cell->state != DLG_STATE_CONFIRMED) { LM_ERR("terminating non-confirmed dialogs not supported\n"); return -1; } /*verify direction*/ if ((dialog_info = build_dlg_t(cell, dir)) == 0){ LM_ERR("failed to create dlg_t\n"); goto err; } LM_DBG("sending BYE to %s\n", (dir==DLG_CALLER_LEG)?"caller":"callee"); iuid = dlg_get_iuid_shm_clone(cell); if(iuid==NULL) { LM_ERR("failed to create dialog unique id clone\n"); goto err; } memset(&uac_r,'\0', sizeof(uac_req_t)); set_uac_req(&uac_r, &met, hdrs, NULL, dialog_info, TMCB_LOCAL_COMPLETED, bye_reply_cb, (void*)iuid); result = d_tmb.t_request_within(&uac_r); if(result < 0){ LM_ERR("failed to send the BYE request\n"); goto err; } free_tm_dlg(dialog_info); LM_DBG("BYE sent to %s\n", (dir==0)?"caller":"callee"); return 0; err: if(dialog_info) free_tm_dlg(dialog_info); return -1; }
/* cell- pointer to a struct dlg_cell * leg - a dialog leg to be BYE'ed : * = 0: caller leg * > 0: callee legs */ static inline int send_leg_bye(struct dlg_cell *cell, int dst_leg, int src_leg, str *extra_hdrs) { dlg_t* dialog_info; struct dlg_cell *old_cell; str met = {"BYE", 3}; int result; if ((dialog_info = build_dlg_t(cell, dst_leg, src_leg)) == 0){ LM_ERR("failed to create dlg_t\n"); goto err; } LM_DBG("sending BYE to %s (%d)\n", (dst_leg==DLG_CALLER_LEG)?"caller":"callee", dst_leg); ref_dlg(cell, 1); old_cell = current_dlg_pointer; current_dlg_pointer = cell; result = d_tmb.t_request_within (&met, /* method*/ extra_hdrs, /* extra headers*/ NULL, /* body*/ dialog_info, /* dialog structure*/ bye_reply_cb, /* callback function*/ (void*)cell, /* callback parameter*/ NULL); /* release function*/ current_dlg_pointer = old_cell; if(result < 0){ LM_ERR("failed to send the BYE request\n"); goto err1; } free_tm_dlg(dialog_info); LM_DBG("BYE sent to %s\n", (dst_leg==DLG_CALLER_LEG)?"caller":"callee"); return 0; err1: unref_dlg(cell, 1); err: return -1; }