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
This commit is contained in:
Kinsey Moore
2012-05-14 19:44:27 +00:00
parent fef9a32fb4
commit b5a6de76fc
26 changed files with 101 additions and 23 deletions
+5
View File
@@ -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
+3
View File
@@ -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));
+3
View File
@@ -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;
+3
View File
@@ -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;
+1
View File
@@ -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;
+1
View File
@@ -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;
+2
View File
@@ -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;
}
+1
View File
@@ -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:
+3
View File
@@ -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);
+2
View File
@@ -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;
}
+2
View File
@@ -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);
+2
View File
@@ -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;
}
+1
View File
@@ -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;
+2
View File
@@ -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));
}
+19 -14
View File
@@ -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);
+2
View File
@@ -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;
+2
View File
@@ -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;
}
+3
View File
@@ -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;
-9
View File
@@ -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]
+3
View File
@@ -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) {
+7
View File
@@ -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)
+19
View File
@@ -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);
+3
View File
@@ -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);
+5
View File
@@ -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:
+1
View File
@@ -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;
+6
View File
@@ -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;