// Return codes: // 2 - No limit // 1 - Limited // -1 - No credit // -2 - Locked // -3 - Duplicated callid // -4 - Call limit reached // -5 - Internal error (message parsing, communication, ...) static int CallControl(struct sip_msg *msg, char *str1, char *str2) { int result; struct dlg_cell *dlg; CallInfo *call; if (disable) return 2; if (msg->first_line.type!=SIP_REQUEST || msg->REQ_METHOD!=METHOD_INVITE || has_to_tag(msg)) { LM_WARN("call_control should only be called for the first INVITE\n"); return -5; } result = call_control_initialize(msg); if (result == 1) { // A call with a time limit that will be traced by callcontrol if (dlg_api.create_dlg(msg, 0) < 0) { LM_ERR("could not create new dialog\n"); call = get_call_info(msg, CAStop); if (!call) { LM_ERR("can't retrieve call info\n"); return -5; } call_control_stop(msg, call->callid); return -5; } dlg = dlg_api.get_dlg(); if (!dlg) { LM_CRIT("error getting dialog\n"); call = get_call_info(msg, CAStop); if (!call) { LM_ERR("can't retrieve call info\n"); return -5; } call_control_stop(msg, call->callid); return -5; } if (dlg_api.register_dlgcb(dlg, DLGCB_RESPONSE_FWDED, __dialog_replies, NULL, NULL) != 0) { LM_ERR("cannot register callback for dialog confirmation\n"); call_control_stop(msg, dlg->callid); return -5; } if (dlg_api.register_dlgcb(dlg, DLGCB_TERMINATED | DLGCB_FAILED | DLGCB_EXPIRED | DLGCB_DESTROY, __dialog_ended, (void*)CCActive, NULL) != 0) { LM_ERR("cannot register callback for dialog termination\n"); call_control_stop(msg, dlg->callid); return -5; } } return result; }
static void __dialog_ended(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params) { if ((int)(long)*_params->param == CCActive) { call_control_stop(_params->msg, dlg->callid); *_params->param = (void *)CCInactive; } }
static void __dialog_ended(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params) { if ((int)(long)*_params->param == CCActive) { struct sip_msg* msg = _params->rpl; if( !msg || msg == FAKED_REPLY) msg = _params->req; call_control_stop(msg, dlg->callid); *_params->param = NULL; } }
// Postprocess a request after the main script route is done. // // After all script processing is done, check if the dialog was actually // created to take care of call control. If the FL_USE_CALL_CONTROL flag // is still set, then the dialog creation callback was not called which // means that there was a failure relaying the message and we have to // tell the call control application to discard the call, otherwise it // would remain dangling until it expires. // static int postprocess_request(struct sip_msg *msg, unsigned int flags, void *_param) { CallInfo *call; if ((msg->msg_flags & FL_USE_CALL_CONTROL) == 0) return 1; // the FL_USE_CALL_CONTROL flag is still set => the dialog was not created LOG(L_WARN, "dialog to trace controlled call was not created. discarding callcontrol."); call = get_call_info(msg, CAStop); if (!call) { LOG(L_ERR, "can't retrieve call info\n"); return -1; } call_control_stop(msg, call->callid); return 1; }