diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c index ee033b5113..e55c488356 100644 --- a/channels/chan_pjsip.c +++ b/channels/chan_pjsip.c @@ -1510,6 +1510,7 @@ static int call(void *data) int res = ast_sip_session_create_invite(session, &tdata); if (res) { + ast_set_hangupsource(session->channel, ast_channel_name(session->channel), 0); ast_queue_hangup(session->channel); } else { update_initial_connected_line(session); @@ -1945,6 +1946,7 @@ static void chan_pjsip_session_end(struct ast_sip_session *session) chan_pjsip_remove_hold(ast_channel_uniqueid(session->channel)); + ast_set_hangupsource(session->channel, ast_channel_name(session->channel), 0); if (!ast_channel_hangupcause(session->channel) && session->inv_session) { int cause = hangup_sip2cause(session->inv_session->cause); @@ -2072,6 +2074,8 @@ static struct ast_sip_session_supplement pbx_start_supplement = { static void chan_pjsip_incoming_response(struct ast_sip_session *session, struct pjsip_rx_data *rdata) { struct pjsip_status_line status = rdata->msg_info.msg->line.status; + struct ast_control_pvt_cause_code *cause_code; + int data_size = sizeof(*cause_code); if (!session->channel) { return; @@ -2095,6 +2099,21 @@ static void chan_pjsip_incoming_response(struct ast_sip_session *session, struct default: break; } + + /* Build and send the tech-specific cause information */ + /* size of the string making up the cause code is "SIP " number + " " + reason length */ + data_size += 4 + 4 + pj_strlen(&status.reason); + cause_code = ast_alloca(data_size); + memset(cause_code, 0, data_size); + + ast_copy_string(cause_code->chan_name, ast_channel_name(session->channel), AST_CHANNEL_NAME); + + snprintf(cause_code->code, data_size - sizeof(*cause_code) + 1, "SIP %d %.*s", status.code, + (int) pj_strlen(&status.reason), pj_strbuf(&status.reason)); + + cause_code->ast_cause = hangup_sip2cause(status.code); + ast_queue_control_data(session->channel, AST_CONTROL_PVT_CAUSE_CODE, cause_code, data_size); + ast_channel_hangupcause_hash_set(session->channel, cause_code, data_size); } static int chan_pjsip_incoming_ack(struct ast_sip_session *session, struct pjsip_rx_data *rdata) diff --git a/main/cel.c b/main/cel.c index 57fb946a40..a3005af8b7 100644 --- a/main/cel.c +++ b/main/cel.c @@ -1270,6 +1270,35 @@ static void save_dialstatus(struct ast_multi_channel_blob *blob) } } +static int is_valid_dialstatus(struct ast_multi_channel_blob *blob) +{ + const char *dialstatus = get_blob_variable(blob, "dialstatus"); + int res = 0; + + if (ast_strlen_zero(dialstatus)) { + res = 0; + } else if (!strcasecmp(dialstatus, "CHANUNAVAIL")) { + res = 1; + } else if (!strcasecmp(dialstatus, "CONGESTION")) { + res = 1; + } else if (!strcasecmp(dialstatus, "NOANSWER")) { + res = 1; + } else if (!strcasecmp(dialstatus, "BUSY")) { + res = 1; + } else if (!strcasecmp(dialstatus, "ANSWER")) { + res = 1; + } else if (!strcasecmp(dialstatus, "CANCEL")) { + res = 1; + } else if (!strcasecmp(dialstatus, "DONTCALL")) { + res = 1; + } else if (!strcasecmp(dialstatus, "TORTURE")) { + res = 1; + } else if (!strcasecmp(dialstatus, "INVALIDARGS")) { + res = 1; + } + return res; +} + static void cel_dial_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message) { @@ -1298,11 +1327,9 @@ static void cel_dial_cb(void *data, struct stasis_subscription *sub, } } - if (ast_strlen_zero(get_blob_variable(blob, "dialstatus"))) { - return; + if (is_valid_dialstatus(blob)) { + save_dialstatus(blob); } - - save_dialstatus(blob); } static void cel_generic_cb( diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c index a721612a4e..3361220404 100644 --- a/res/res_pjsip_session.c +++ b/res/res_pjsip_session.c @@ -2134,6 +2134,7 @@ static void session_inv_on_media_update(pjsip_inv_session *inv, pj_status_t stat if ((status != PJ_SUCCESS) || (pjmedia_sdp_neg_get_active_local(inv->neg, &local) != PJ_SUCCESS) || (pjmedia_sdp_neg_get_active_remote(inv->neg, &remote) != PJ_SUCCESS)) { ast_channel_hangupcause_set(session->channel, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); + ast_set_hangupsource(session->channel, ast_channel_name(session->channel), 0); ast_queue_hangup(session->channel); return; } diff --git a/tests/test_cel.c b/tests/test_cel.c index 245a8831c3..ff0aaca24c 100644 --- a/tests/test_cel.c +++ b/tests/test_cel.c @@ -773,6 +773,40 @@ AST_TEST_DEFINE(test_cel_dial_unanswered) return AST_TEST_PASS; } +AST_TEST_DEFINE(test_cel_dial_unanswered_filter) +{ + RAII_VAR(struct ast_channel *, chan_caller, NULL, safe_channel_release); + RAII_VAR(struct ast_channel *, chan_callee, NULL, safe_channel_release); + struct ast_party_caller caller = ALICE_CALLERID; + + switch (cmd) { + case TEST_INIT: + info->name = __func__; + info->category = TEST_CATEGORY; + info->summary = "Test CEL for a dial that isn't answered"; + info->description = + "Test CEL records for a channel that\n" + "performs a dial operation that isn't answered\n"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + CREATE_ALICE_CHANNEL(chan_caller, &caller); + + EMULATE_DIAL(chan_caller, CHANNEL_TECH_NAME "/Bob"); + + START_DIALED(chan_caller, chan_callee); + + ast_channel_state_set(chan_caller, AST_STATE_RINGING); + ast_channel_publish_dial(chan_caller, chan_callee, NULL, "NOT A VALID DIAL STATUS"); + ast_channel_publish_dial(chan_caller, chan_callee, NULL, "NOANSWER"); + + HANGUP_CHANNEL(chan_caller, AST_CAUSE_NO_ANSWER, "NOANSWER"); + HANGUP_CHANNEL(chan_callee, AST_CAUSE_NO_ANSWER, ""); + + return AST_TEST_PASS; +} AST_TEST_DEFINE(test_cel_dial_busy) { @@ -2040,6 +2074,7 @@ static int unload_module(void) #endif AST_TEST_UNREGISTER(test_cel_dial_unanswered); + AST_TEST_UNREGISTER(test_cel_dial_unanswered_filter); AST_TEST_UNREGISTER(test_cel_dial_congestion); AST_TEST_UNREGISTER(test_cel_dial_busy); AST_TEST_UNREGISTER(test_cel_dial_unavailable); @@ -2114,6 +2149,7 @@ static int load_module(void) #endif AST_TEST_REGISTER(test_cel_dial_unanswered); + AST_TEST_REGISTER(test_cel_dial_unanswered_filter); AST_TEST_REGISTER(test_cel_dial_congestion); AST_TEST_REGISTER(test_cel_dial_busy); AST_TEST_REGISTER(test_cel_dial_unavailable);