Merge 1d955e2760
into 555a541680
This commit is contained in:
commit
59d1ac26ea
|
@ -52,6 +52,7 @@
|
|||
<para>Parameter describing which type of information is requested. Types are:</para>
|
||||
<enumlist>
|
||||
<enum name="tech"><para>Technology-specific cause information</para></enum>
|
||||
<enum name="tech_extended"><para>Technology-specific extended list of cause information</para></enum>
|
||||
<enum name="ast"><para>Translated Asterisk cause code</para></enum>
|
||||
</enumlist>
|
||||
</parameter>
|
||||
|
@ -110,9 +111,10 @@ static int hangupcause_read(struct ast_channel *chan, const char *cmd, char *dat
|
|||
char *parms;
|
||||
struct ast_control_pvt_cause_code *cause_code;
|
||||
int res = 0;
|
||||
struct ast_str *causelist = ast_str_create(128);
|
||||
AST_DECLARE_APP_ARGS(args,
|
||||
AST_APP_ARG(channel); /*!< Channel name */
|
||||
AST_APP_ARG(type); /*!< Type of information requested (ast or tech) */
|
||||
AST_APP_ARG(type); /*!< Type of information requested (ast, tech or tech_extended) */
|
||||
);
|
||||
|
||||
/* Ensure that the buffer is empty */
|
||||
|
@ -131,6 +133,19 @@ static int hangupcause_read(struct ast_channel *chan, const char *cmd, char *dat
|
|||
}
|
||||
|
||||
ast_channel_lock(chan);
|
||||
if (!strcmp(args.type, "tech_extended") && causelist) {
|
||||
struct ao2_iterator *cause_codes;
|
||||
cause_codes = ast_channel_dialed_causes_find_multiple(chan, args.channel);
|
||||
while ((cause_code = ao2_iterator_next(cause_codes))) {
|
||||
if (!cause_code->cause_extended) {
|
||||
ao2_ref(cause_code, -1);
|
||||
continue;
|
||||
}
|
||||
ast_str_append(&causelist, 0, "%s%s", (ast_str_strlen(causelist) ? "," : ""), cause_code->code);
|
||||
ao2_ref(cause_code, -1);
|
||||
}
|
||||
ao2_iterator_destroy(cause_codes);
|
||||
}
|
||||
cause_code = ast_channel_dialed_causes_find(chan, args.channel);
|
||||
ast_channel_unlock(chan);
|
||||
|
||||
|
@ -143,6 +158,8 @@ static int hangupcause_read(struct ast_channel *chan, const char *cmd, char *dat
|
|||
ast_copy_string(buf, ast_cause2str(cause_code->ast_cause), len);
|
||||
} else if (!strcmp(args.type, "tech")) {
|
||||
ast_copy_string(buf, cause_code->code, len);
|
||||
} else if (!strcmp(args.type, "tech_extended")) {
|
||||
ast_copy_string(buf, ast_str_buffer(causelist), len);
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Information type not recognized (%s)\n", args.type);
|
||||
res = -1;
|
||||
|
|
|
@ -4368,6 +4368,24 @@ struct ast_str *ast_channel_dialed_causes_channels(const struct ast_channel *cha
|
|||
*/
|
||||
struct ast_control_pvt_cause_code *ast_channel_dialed_causes_find(const struct ast_channel *chan, const char *chan_name);
|
||||
|
||||
/*!
|
||||
* \since 22
|
||||
* \brief Retrieve a ref-counted cause code information structure iterator
|
||||
*
|
||||
* \details
|
||||
* This function makes use of datastore operations on the channel, so
|
||||
* it is important to lock the channel before calling this function.
|
||||
* This function increases the ref count of the returned object, so the
|
||||
* calling function must decrease the reference count when it is finished
|
||||
* with the object.
|
||||
*
|
||||
* \param chan The channel from which to retrieve information
|
||||
* \param chan_name The name of the channel about which to retrieve information
|
||||
* \retval NULL on search failure
|
||||
* \retval Pointer to a ao2_iterator object containing the desired information
|
||||
*/
|
||||
struct ao2_iterator *ast_channel_dialed_causes_find_multiple(const struct ast_channel *chan, const char *chan_name);
|
||||
|
||||
/*!
|
||||
* \since 11
|
||||
* \brief Add cause code information to the channel
|
||||
|
|
|
@ -413,6 +413,7 @@ enum ast_control_transfer {
|
|||
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 */
|
||||
unsigned int cause_extended:1; /*!< Indicates whether this cause code retrieved from supplimentary sources */
|
||||
int ast_cause; /*!< Asterisk cause code associated with this message */
|
||||
char code[1]; /*!< Tech-specific cause code information, beginning with the name of the tech */
|
||||
};
|
||||
|
|
|
@ -1252,7 +1252,9 @@ static int collect_names_cb(void *obj, void *arg, int flags)
|
|||
struct ast_control_pvt_cause_code *cause_code = obj;
|
||||
struct ast_str **str = arg;
|
||||
|
||||
ast_str_append(str, 0, "%s%s", (ast_str_strlen(*str) ? "," : ""), cause_code->chan_name);
|
||||
if (!cause_code->cause_extended) {
|
||||
ast_str_append(str, 0, "%s%s", (ast_str_strlen(*str) ? "," : ""), cause_code->chan_name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1272,7 +1274,23 @@ struct ast_str *ast_channel_dialed_causes_channels(const struct ast_channel *cha
|
|||
|
||||
struct ast_control_pvt_cause_code *ast_channel_dialed_causes_find(const struct ast_channel *chan, const char *chan_name)
|
||||
{
|
||||
return ao2_find(chan->dialed_causes, chan_name, OBJ_KEY);
|
||||
struct ao2_iterator *causes;
|
||||
struct ast_control_pvt_cause_code *cause_code;
|
||||
|
||||
causes = ao2_find(chan->dialed_causes, chan_name, OBJ_KEY | OBJ_MULTIPLE);
|
||||
while ((cause_code = ao2_iterator_next(causes))) {
|
||||
if (!cause_code->cause_extended) {
|
||||
ao2_iterator_destroy(causes);
|
||||
return cause_code;
|
||||
}
|
||||
}
|
||||
ao2_iterator_destroy(causes);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct ao2_iterator *ast_channel_dialed_causes_find_multiple(const struct ast_channel *chan, const char *chan_name)
|
||||
{
|
||||
return ao2_find(chan->dialed_causes, chan_name, OBJ_KEY | OBJ_MULTIPLE);
|
||||
}
|
||||
|
||||
int ast_channel_dialed_causes_add(const struct ast_channel *chan, const struct ast_control_pvt_cause_code *cause_code, int datalen)
|
||||
|
@ -1281,6 +1299,7 @@ int ast_channel_dialed_causes_add(const struct ast_channel *chan, const struct a
|
|||
ao2_find(chan->dialed_causes, cause_code->chan_name, OBJ_KEY | OBJ_UNLINK | OBJ_NODATA);
|
||||
ao2_cause_code = ao2_alloc(datalen, NULL);
|
||||
|
||||
|
||||
if (ao2_cause_code) {
|
||||
memcpy(ao2_cause_code, cause_code, datalen);
|
||||
ao2_link(chan->dialed_causes, ao2_cause_code);
|
||||
|
@ -1309,7 +1328,7 @@ static int pvt_cause_cmp_fn(void *obj, void *vstr, int flags)
|
|||
struct ast_control_pvt_cause_code *pc = obj;
|
||||
char *str = ast_tech_to_upper(ast_strdupa(vstr));
|
||||
char *pc_str = ast_tech_to_upper(ast_strdupa(pc->chan_name));
|
||||
return !strcmp(pc_str, str) ? CMP_MATCH | CMP_STOP : 0;
|
||||
return (!strcmp(pc_str, str)) ? CMP_MATCH | CMP_STOP : 0;
|
||||
}
|
||||
|
||||
#define DIALED_CAUSES_BUCKETS 37
|
||||
|
|
|
@ -46,9 +46,11 @@ static void rfc3326_use_reason_header(struct ast_sip_session *session, struct pj
|
|||
for (; header;
|
||||
header = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_reason, header->next)) {
|
||||
int cause_q850, cause_sip;
|
||||
struct ast_control_pvt_cause_code *cause_code;
|
||||
int data_size = sizeof(*cause_code);
|
||||
|
||||
ast_copy_pj_str(buf, &header->hvalue, sizeof(buf));
|
||||
cause = ast_skip_blanks(buf);
|
||||
|
||||
cause_q850 = !strncasecmp(cause, "Q.850", 5);
|
||||
cause_sip = !strncasecmp(cause, "SIP", 3);
|
||||
if ((cause_q850 || cause_sip) && (cause = strstr(cause, "cause="))) {
|
||||
|
@ -56,6 +58,22 @@ static void rfc3326_use_reason_header(struct ast_sip_session *session, struct pj
|
|||
if (sscanf(cause, "cause=%30d", code) != 1) {
|
||||
*code = 0;
|
||||
}
|
||||
|
||||
/* Build and send the tech-specific cause information */
|
||||
/* size of the string making up the cause code is "SIP " + reason length */
|
||||
data_size += 4 + strlen(cause) + 1;
|
||||
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, "SIP %s", cause);
|
||||
cause_code->cause_extended = 1;
|
||||
if (code_q850) {
|
||||
cause_code->ast_cause = *code & 0x7;
|
||||
} else if (code_sip) {
|
||||
cause_code->ast_cause = ast_sip_hangup_sip2cause(*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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue