From b5a6de76fc71e3f604761885dd844975a11893ee Mon Sep 17 00:00:00 2001 From: Kinsey Moore <kmoore@digium.com> Date: Mon, 14 May 2012 19:44:27 +0000 Subject: [PATCH] Commit framework for HANGUPCAUSE (replacement for SIP_CAUSE) This is the starting point for the Asterisk 11: Who Hung Up work and provides a framework which will allow channel drivers to report the types of hangup cause information available in SIP_CAUSE without incurring the overhead of the MASTER_CHANNEL dialplan function. The initial implementation only includes cause generation for chan_sip and does not include cause code translation utilities. This change deprecates SIP_CAUSE and replaces its method of reporting cause codes with the new framework. This change also deprecates the 'storesipcause' option in sip.conf. Review: https://reviewboard.asterisk.org/r/1822/ (Closes issue SWP-4221) git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@366408 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- UPGRADE.txt | 5 +++++ apps/app_dial.c | 3 +++ apps/app_followme.c | 3 +++ apps/app_queue.c | 3 +++ channels/chan_alsa.c | 1 + channels/chan_console.c | 1 + channels/chan_gtalk.c | 2 ++ channels/chan_h323.c | 1 + channels/chan_iax2.c | 3 +++ channels/chan_jingle.c | 2 ++ channels/chan_mgcp.c | 2 ++ channels/chan_misdn.c | 2 ++ channels/chan_oss.c | 1 + channels/chan_phone.c | 2 ++ channels/chan_sip.c | 33 +++++++++++++++++++-------------- channels/chan_skinny.c | 2 ++ channels/chan_unistim.c | 2 ++ channels/chan_vpb.cc | 3 +++ configs/sip.conf.sample | 9 --------- funcs/func_frame_trace.c | 3 +++ include/asterisk/frame.h | 7 +++++++ main/channel.c | 19 +++++++++++++++++++ main/dial.c | 3 +++ main/features.c | 5 +++++ main/file.c | 1 + main/rtp_engine.c | 6 ++++++ 26 files changed, 101 insertions(+), 23 deletions(-) diff --git a/UPGRADE.txt b/UPGRADE.txt index e5bbb6ae17..fcdb803bed 100644 --- a/UPGRADE.txt +++ b/UPGRADE.txt @@ -91,6 +91,11 @@ SIP - A new manager event, "SessionTimeout" has been added and is triggered when a call is terminated due to RTP stream inactivity or SIP session timer expiration. + - SIP_CAUSE is now deprecated. It has been modified to use the same + mechanism as HANGUPCAUSE. Behavior should not change, but performance + should be vastly improved. The HANGUPCAUSE hash should now be used instead + of SIP_CAUSE. Because of this, the storesipcause option in sip.conf is also + deprecated. chan_unistim - Due to massive update in chan_unistim phone keys functions and on-screen diff --git a/apps/app_dial.c b/apps/app_dial.c index a5eb036750..e6d9c54485 100644 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -1427,6 +1427,9 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, cc_frame_received = 1; } break; + case AST_CONTROL_PVT_CAUSE_CODE: + ast_indicate_data(in, AST_CONTROL_PVT_CAUSE_CODE, f->data.ptr, f->datalen); + break; case -1: if (single && !caller_entertained) { ast_verb(3, "%s stopped sounds\n", ast_channel_name(c)); diff --git a/apps/app_followme.c b/apps/app_followme.c index 8b894d6d24..bbbde5fabf 100644 --- a/apps/app_followme.c +++ b/apps/app_followme.c @@ -877,6 +877,9 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us * the caller. */ break; + case AST_CONTROL_PVT_CAUSE_CODE: + ast_indicate_data(caller, f->subclass.integer, f->data.ptr, f->datalen); + break; case -1: ast_verb(3, "%s stopped sounds\n", ast_channel_name(winner)); break; diff --git a/apps/app_queue.c b/apps/app_queue.c index 7db08193ca..151f03cd4b 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -4050,6 +4050,9 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte } } break; + case AST_CONTROL_PVT_CAUSE_CODE: + ast_indicate_data(in, AST_CONTROL_PVT_CAUSE_CODE, f->data.ptr, f->datalen); + break; default: ast_debug(1, "Dunno what to do with control type %d\n", f->subclass.integer); break; diff --git a/channels/chan_alsa.c b/channels/chan_alsa.c index 5079fb6ba2..e535a3adc4 100644 --- a/channels/chan_alsa.c +++ b/channels/chan_alsa.c @@ -534,6 +534,7 @@ static int alsa_indicate(struct ast_channel *chan, int cond, const void *data, s case AST_CONTROL_CONGESTION: case AST_CONTROL_RINGING: case AST_CONTROL_INCOMPLETE: + case AST_CONTROL_PVT_CAUSE_CODE: case -1: res = -1; /* Ask for inband indications */ break; diff --git a/channels/chan_console.c b/channels/chan_console.c index 2856bae06a..dce9f01bbc 100644 --- a/channels/chan_console.c +++ b/channels/chan_console.c @@ -603,6 +603,7 @@ static int console_indicate(struct ast_channel *chan, int cond, const void *data case AST_CONTROL_CONGESTION: case AST_CONTROL_RINGING: case AST_CONTROL_INCOMPLETE: + case AST_CONTROL_PVT_CAUSE_CODE: case -1: res = -1; /* Ask for inband indications */ break; diff --git a/channels/chan_gtalk.c b/channels/chan_gtalk.c index 20f2589c30..8fd20c8300 100644 --- a/channels/chan_gtalk.c +++ b/channels/chan_gtalk.c @@ -1726,6 +1726,8 @@ static int gtalk_indicate(struct ast_channel *ast, int condition, const void *da break; default: ast_debug(3, "Don't know how to indicate condition '%d'\n", condition); + /* fallthrough */ + case AST_CONTROL_PVT_CAUSE_CODE: res = -1; } diff --git a/channels/chan_h323.c b/channels/chan_h323.c index 2dc0bdc57c..9fae0390c4 100644 --- a/channels/chan_h323.c +++ b/channels/chan_h323.c @@ -941,6 +941,7 @@ static int oh323_indicate(struct ast_channel *c, int condition, const void *data res = 0; break; case AST_CONTROL_PROCEEDING: + case AST_CONTROL_PVT_CAUSE_CODE: case -1: break; default: diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index e3912175b4..0d9af6979c 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -5669,6 +5669,9 @@ static int iax2_indicate(struct ast_channel *c, int condition, const void *data, if (!ast_test_flag64(pvt, IAX_SENDCONNECTEDLINE)) goto done; break; + case AST_CONTROL_PVT_CAUSE_CODE: + res = -1; + break; } res = send_command(pvt, AST_FRAME_CONTROL, condition, 0, data, datalen, -1); diff --git a/channels/chan_jingle.c b/channels/chan_jingle.c index 48cc550032..4f4af23fc6 100644 --- a/channels/chan_jingle.c +++ b/channels/chan_jingle.c @@ -1332,6 +1332,8 @@ static int jingle_indicate(struct ast_channel *ast, int condition, const void *d break; default: ast_log(LOG_NOTICE, "Don't know how to indicate condition '%d'\n", condition); + /* fallthrough */ + case AST_CONTROL_PVT_CAUSE_CODE: res = -1; } diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c index 6bec05cae7..c3a5c58f43 100644 --- a/channels/chan_mgcp.c +++ b/channels/chan_mgcp.c @@ -1483,6 +1483,8 @@ static int mgcp_indicate(struct ast_channel *ast, int ind, const void *data, siz break; default: ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind); + /* fallthrough */ + case AST_CONTROL_PVT_CAUSE_CODE: res = -1; } ast_mutex_unlock(&sub->lock); diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c index 0f1715b7a0..e236882327 100644 --- a/channels/chan_misdn.c +++ b/channels/chan_misdn.c @@ -7037,6 +7037,8 @@ static int misdn_indication(struct ast_channel *ast, int cond, const void *data, break; default: chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n", cond, p->bc->pid); + /* fallthrough */ + case AST_CONTROL_PVT_CAUSE_CODE: return -1; } diff --git a/channels/chan_oss.c b/channels/chan_oss.c index ca26e7922e..8cd20296db 100644 --- a/channels/chan_oss.c +++ b/channels/chan_oss.c @@ -758,6 +758,7 @@ static int oss_indicate(struct ast_channel *c, int cond, const void *data, size_ case AST_CONTROL_BUSY: case AST_CONTROL_CONGESTION: case AST_CONTROL_RINGING: + case AST_CONTROL_PVT_CAUSE_CODE: case -1: res = -1; break; diff --git a/channels/chan_phone.c b/channels/chan_phone.c index a781b232a9..0f050f6c9e 100644 --- a/channels/chan_phone.c +++ b/channels/chan_phone.c @@ -222,6 +222,8 @@ static int phone_indicate(struct ast_channel *chan, int condition, const void *d case AST_CONTROL_SRCUPDATE: res = 0; break; + case AST_CONTROL_PVT_CAUSE_CODE: + break; default: ast_log(LOG_WARNING, "Condition %d is not supported on channel %s\n", condition, ast_channel_name(chan)); } diff --git a/channels/chan_sip.c b/channels/chan_sip.c index f6fb2af7ca..0cf12acd07 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -7093,6 +7093,7 @@ static int sip_indicate(struct ast_channel *ast, int condition, const void *data break; case AST_CONTROL_UPDATE_RTP_PEER: /* Absorb this since it is handled by the bridge */ break; + case AST_CONTROL_PVT_CAUSE_CODE: /* these should be handled by the code in channel.c */ case -1: res = -1; break; @@ -26113,28 +26114,29 @@ static int handle_incoming(struct sip_pvt *p, struct sip_request *req, struct as ast_debug(1, "Ignoring out of order response %u (expecting %u)\n", seqno, p->ocseq); return -1; } else { - char causevar[256], causeval[256]; - if ((respid == 200) || ((respid >= 300) && (respid <= 399))) { extract_uri(p, req); } - handle_response(p, respid, e + len, req, seqno); + if (p->owner) { + struct ast_control_pvt_cause_code *cause_code; + int data_size = sizeof(*cause_code); + /* size of the string making up the cause code is "SIP " + cause length */ + data_size += 4 + strlen(REQ_OFFSET_TO_STR(req, rlPart2)); + cause_code = alloca(data_size); - if (global_store_sip_cause && p->owner) { - struct ast_channel *owner = p->owner; + ast_copy_string(cause_code->chan_name, ast_channel_name(p->owner), AST_CHANNEL_NAME); - snprintf(causevar, sizeof(causevar), "MASTER_CHANNEL(HASH(SIP_CAUSE,%s))", ast_channel_name(owner)); - snprintf(causeval, sizeof(causeval), "SIP %s", REQ_OFFSET_TO_STR(req, rlPart2)); + snprintf(cause_code->code, data_size - sizeof(*cause_code) + 1, "SIP %s", REQ_OFFSET_TO_STR(req, rlPart2)); - ast_channel_ref(owner); - sip_pvt_unlock(p); - ast_channel_unlock(owner); - *nounlock = 1; - pbx_builtin_setvar_helper(owner, causevar, causeval); - ast_channel_unref(owner); - sip_pvt_lock(p); + if (global_store_sip_cause) { + cause_code->emulate_sip_cause = 1; + } + + ast_queue_control_data(p->owner, AST_CONTROL_PVT_CAUSE_CODE, cause_code, data_size); } + + handle_response(p, respid, e + len, req, seqno); } return 0; } @@ -29882,6 +29884,9 @@ static int reload_config(enum channelreloadreason reason) } } else if (!strcasecmp(v->name, "storesipcause")) { global_store_sip_cause = ast_true(v->value); + if (global_store_sip_cause) { + ast_log(LOG_WARNING, "Usage of SIP_CAUSE is deprecated. Please use HANGUPCAUSE instead.\n"); + } } else if (!strcasecmp(v->name, "qualifygap")) { if (sscanf(v->value, "%30d", &global_qualify_gap) != 1) { ast_log(LOG_WARNING, "Invalid qualifygap '%s' at line %d of %s\n", v->value, v->lineno, config); diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c index 169ce4ac7a..cace12ee99 100644 --- a/channels/chan_skinny.c +++ b/channels/chan_skinny.c @@ -4828,6 +4828,8 @@ static int skinny_indicate(struct ast_channel *ast, int ind, const void *data, s break; default: ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind); + /* fallthrough */ + case AST_CONTROL_PVT_CAUSE_CODE: return -1; /* Tell asterisk to provide inband signalling */ } return 0; diff --git a/channels/chan_unistim.c b/channels/chan_unistim.c index 084df9f5d0..434aa0cb73 100644 --- a/channels/chan_unistim.c +++ b/channels/chan_unistim.c @@ -5224,6 +5224,8 @@ static int unistim_indicate(struct ast_channel *ast, int ind, const void *data, break; default: ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind); + /* fallthrough */ + case AST_CONTROL_PVT_CAUSE_CODE: return -1; } diff --git a/channels/chan_vpb.cc b/channels/chan_vpb.cc index e54cebda00..378c44773d 100644 --- a/channels/chan_vpb.cc +++ b/channels/chan_vpb.cc @@ -1714,6 +1714,9 @@ static int vpb_indicate(struct ast_channel *ast, int condition, const void *data case AST_CONTROL_UNHOLD: ast_moh_stop(ast); break; + case AST_CONTROL_PVT_CAUSE_CODE: + res = -1; + break; default: res = 0; break; diff --git a/configs/sip.conf.sample b/configs/sip.conf.sample index e8c67db539..0705ad0528 100644 --- a/configs/sip.conf.sample +++ b/configs/sip.conf.sample @@ -1084,15 +1084,6 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ; jblog = no ; Enables jitterbuffer frame logging. Defaults to "no". -;----------------------------- SIP_CAUSE reporting --------------------------------- -; storesipcause = no ; This option causes chan_sip to set the - ; HASH(SIP_CAUSE,<channel name>) channel variable - ; to the value of the last sip response. - ; WARNING: enabling this option carries a - ; significant performance burden. It should only - ; be used in low call volume situations. This - ; option defaults to "no". - ;----------------------------------------------------------------------------------- [authentication] diff --git a/funcs/func_frame_trace.c b/funcs/func_frame_trace.c index feb004c309..8e12aafb35 100644 --- a/funcs/func_frame_trace.c +++ b/funcs/func_frame_trace.c @@ -324,6 +324,9 @@ static void print_frame(struct ast_frame *frame) case AST_CONTROL_UPDATE_RTP_PEER: ast_verbose("SubClass: UPDATE_RTP_PEER\n"); break; + case AST_CONTROL_PVT_CAUSE_CODE: + ast_verbose("SubClass: PVT_CAUSE_CODE\n"); + break; } if (frame->subclass.integer == -1) { diff --git a/include/asterisk/frame.h b/include/asterisk/frame.h index 4e013534db..2c1d43cdf5 100644 --- a/include/asterisk/frame.h +++ b/include/asterisk/frame.h @@ -266,6 +266,7 @@ enum ast_control_frame_type { AST_CONTROL_INCOMPLETE = 30, /*!< Indication that the extension dialed is incomplete */ AST_CONTROL_MCID = 31, /*!< Indicate that the caller is being malicious. */ AST_CONTROL_UPDATE_RTP_PEER = 32, /*!< Interrupt the bridge and have it update the peer */ + AST_CONTROL_PVT_CAUSE_CODE = 33, /*!< Contains an update to the protocol-specific cause-code stored for branching dials */ }; enum ast_frame_read_action { @@ -324,6 +325,12 @@ enum ast_control_transfer { AST_TRANSFER_FAILED, /*!< Transfer request on the channel failed */ }; +struct ast_control_pvt_cause_code { + char chan_name[AST_CHANNEL_NAME]; /*!< Name of the channel that originated the cause information */ + unsigned int emulate_sip_cause:1; /*!< Indicates whether this should be used to emulate SIP_CAUSE support */ + char code[1]; /*!< Tech-specific cause code information, beginning with the name of the tech */ +}; + #define AST_SMOOTHER_FLAG_G729 (1 << 0) #define AST_SMOOTHER_FLAG_BE (1 << 1) diff --git a/main/channel.c b/main/channel.c index dfb31e1f3b..e46aa3a793 100644 --- a/main/channel.c +++ b/main/channel.c @@ -3444,6 +3444,7 @@ int ast_waitfordigit_full(struct ast_channel *c, int ms, int audiofd, int cmdfd) ast_frfree(f); ast_clear_flag(ast_channel_flags(c), AST_FLAG_END_DTMF_ONLY); return -1; + case AST_CONTROL_PVT_CAUSE_CODE: case AST_CONTROL_RINGING: case AST_CONTROL_ANSWER: case AST_CONTROL_SRCUPDATE: @@ -4171,6 +4172,7 @@ static int attribute_const is_visible_indication(enum ast_control_frame_type con case AST_CONTROL_END_OF_Q: case AST_CONTROL_MCID: case AST_CONTROL_UPDATE_RTP_PEER: + case AST_CONTROL_PVT_CAUSE_CODE: break; case AST_CONTROL_INCOMPLETE: @@ -4334,6 +4336,21 @@ int ast_indicate_data(struct ast_channel *chan, int _condition, case AST_CONTROL_CONGESTION: ts = ast_get_indication_tone(ast_channel_zone(chan), "congestion"); break; + case AST_CONTROL_PVT_CAUSE_CODE: + { + char causevar[256]; + const struct ast_control_pvt_cause_code *cause_code = data; + + snprintf(causevar, sizeof(causevar), "HASH(HANGUPCAUSE,%s)", cause_code->chan_name); + ast_func_write(chan, causevar, cause_code->code); + if (cause_code->emulate_sip_cause) { + snprintf(causevar, sizeof(causevar), "HASH(SIP_CAUSE,%s)", cause_code->chan_name); + ast_func_write(chan, causevar, cause_code->code); + } + + res = 0; + break; + } case AST_CONTROL_PROGRESS: case AST_CONTROL_PROCEEDING: case AST_CONTROL_VIDUPDATE: @@ -5481,6 +5498,7 @@ struct ast_channel *__ast_request_and_dial(const char *type, struct ast_format_c break; /* Ignore these */ + case AST_CONTROL_PVT_CAUSE_CODE: case AST_CONTROL_PROGRESS: case AST_CONTROL_PROCEEDING: case AST_CONTROL_HOLD: @@ -7172,6 +7190,7 @@ static enum ast_bridge_result ast_generic_bridge(struct ast_channel *c0, struct int bridge_exit = 0; switch (f->subclass.integer) { + case AST_CONTROL_PVT_CAUSE_CODE: case AST_CONTROL_AOC: case AST_CONTROL_MCID: ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen); diff --git a/main/dial.c b/main/dial.c index 251eab9ba8..39b837b2ad 100644 --- a/main/dial.c +++ b/main/dial.c @@ -467,6 +467,9 @@ static void handle_frame(struct ast_dial *dial, struct ast_dial_channel *channel case AST_CONTROL_OFFHOOK: case AST_CONTROL_FLASH: break; + case AST_CONTROL_PVT_CAUSE_CODE: + ast_indicate_data(chan, AST_CONTROL_PVT_CAUSE_CODE, fr->data.ptr, fr->datalen); + break; case -1: /* Prod the channel */ ast_indicate(chan, -1); diff --git a/main/features.c b/main/features.c index cbf7c1f42e..433c1a6470 100644 --- a/main/features.c +++ b/main/features.c @@ -3943,6 +3943,10 @@ static struct ast_channel *feature_request_and_dial(struct ast_channel *caller, ast_frfree(f); ready=1; break; + } else if (f->subclass.integer == AST_CONTROL_PVT_CAUSE_CODE) { + ast_indicate_data(caller, AST_CONTROL_PVT_CAUSE_CODE, f->data.ptr, f->datalen); + ast_frfree(f); + break; } else if (f->subclass.integer == AST_CONTROL_CONNECTED_LINE) { if (caller_hungup) { struct ast_party_connected_line connected; @@ -4463,6 +4467,7 @@ int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer, struct a ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen); } break; + case AST_CONTROL_PVT_CAUSE_CODE: case AST_CONTROL_AOC: case AST_CONTROL_HOLD: case AST_CONTROL_UNHOLD: diff --git a/main/file.c b/main/file.c index c4db7b6398..52f5af58db 100644 --- a/main/file.c +++ b/main/file.c @@ -1356,6 +1356,7 @@ static int waitstream_core(struct ast_channel *c, const char *breakon, case AST_CONTROL_REDIRECTING: case AST_CONTROL_AOC: case AST_CONTROL_UPDATE_RTP_PEER: + case AST_CONTROL_PVT_CAUSE_CODE: case -1: /* Unimportant */ break; diff --git a/main/rtp_engine.c b/main/rtp_engine.c index 681029ffbb..522ed0db12 100644 --- a/main/rtp_engine.c +++ b/main/rtp_engine.c @@ -928,6 +928,9 @@ static enum ast_bridge_result local_bridge_loop(struct ast_channel *c0, struct a ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen); } ast_frfree(fr); + } else if (fr->subclass.integer == AST_CONTROL_PVT_CAUSE_CODE) { + ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen); + ast_frfree(fr); } else { *fo = fr; *rc = who; @@ -1219,6 +1222,9 @@ static enum ast_bridge_result remote_bridge_loop(struct ast_channel *c0, ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen); } ast_frfree(fr); + } else if (fr->subclass.integer == AST_CONTROL_PVT_CAUSE_CODE) { + ast_indicate_data(other, fr->subclass.integer, fr->data.ptr, fr->datalen); + ast_frfree(fr); } else { *fo = fr; *rc = who; -- GitLab