summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES7
-rw-r--r--channels/chan_misdn.c4
-rw-r--r--channels/chan_sip.c138
-rw-r--r--channels/sig_pri.c8
-rw-r--r--funcs/func_callerid.c27
-rw-r--r--include/asterisk/callerid.h6
-rw-r--r--include/asterisk/channel.h89
-rw-r--r--main/callerid.c9
-rw-r--r--main/channel.c166
9 files changed, 383 insertions, 71 deletions
diff --git a/CHANGES b/CHANGES
index da591e78a..e2fea7bc8 100644
--- a/CHANGES
+++ b/CHANGES
@@ -30,6 +30,13 @@ Queue
Reports 'InUse' for no logged in agents or no free agents.
Reports 'Idle' when an agent is free.
+Core
+------------------
+ * Redirecting reasons can now be set to arbitrary strings. This means
+ that the REDIRECTING dialplan function can be used to set the redirecting
+ reason to any string. It also allows for custom strings to be read as the
+ redirecting reason from SIP Diversion headers.
+
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 10 to Asterisk 11 --------------------
------------------------------------------------------------------------------
diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c
index 3578bc54e..2f644a86e 100644
--- a/channels/chan_misdn.c
+++ b/channels/chan_misdn.c
@@ -6383,7 +6383,7 @@ static void misdn_copy_redirecting_from_ast(struct misdn_bchannel *bc, struct as
bc->redirecting.to.number_plan = NUMPLAN_UNKNOWN;
}
- bc->redirecting.reason = ast_to_misdn_reason(ast_channel_redirecting(ast)->reason);
+ bc->redirecting.reason = ast_to_misdn_reason(ast_channel_redirecting(ast)->reason.code);
bc->redirecting.count = ast_channel_redirecting(ast)->count;
}
@@ -6427,7 +6427,7 @@ static void misdn_copy_redirecting_to_ast(struct ast_channel *ast, const struct
| misdn_to_ast_screen(redirect->to.screening);
redirecting.to.tag = tag;
- redirecting.reason = misdn_to_ast_reason(redirect->reason);
+ redirecting.reason.code = misdn_to_ast_reason(redirect->reason);
redirecting.count = redirect->count;
ast_channel_set_redirecting(ast, &redirecting, &update_redirecting);
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index e41ccc125..615f576fe 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -1576,7 +1576,7 @@ static int parse_ok_contact(struct sip_pvt *pvt, struct sip_request *req);
static int set_address_from_contact(struct sip_pvt *pvt);
static void check_via(struct sip_pvt *p, struct sip_request *req);
static int get_rpid(struct sip_pvt *p, struct sip_request *oreq);
-static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq, char **name, char **number, int *reason);
+static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq, char **name, char **number, int *reason, char **reason_str);
static enum sip_get_dest_result get_destination(struct sip_pvt *p, struct sip_request *oreq, int *cc_recall_core_id);
static int transmit_state_notify(struct sip_pvt *p, struct state_notify_data *data, int full, int timeout);
static void update_connectedline(struct sip_pvt *p, const void *data, size_t datalen);
@@ -2379,8 +2379,35 @@ static enum AST_REDIRECTING_REASON sip_reason_str_to_code(const char *text)
return ast;
}
-static const char *sip_reason_code_to_str(enum AST_REDIRECTING_REASON code)
+static const char *sip_reason_code_to_str(struct ast_party_redirecting_reason *reason, int *table_lookup)
{
+ int code = reason->code;
+
+ /* If there's a specific string set, then we just
+ * use it.
+ */
+ if (!ast_strlen_zero(reason->str)) {
+ /* If we care about whether this can be found in
+ * the table, then we need to check about that.
+ */
+ if (table_lookup) {
+ /* If the string is literally "unknown" then don't bother with the lookup
+ * because it can lead to a false negative.
+ */
+ if (!strcasecmp(reason->str, "unknown") ||
+ sip_reason_str_to_code(reason->str) != AST_REDIRECTING_REASON_UNKNOWN) {
+ *table_lookup = TRUE;
+ } else {
+ *table_lookup = FALSE;
+ }
+ }
+ return reason->str;
+ }
+
+ if (table_lookup) {
+ *table_lookup = TRUE;
+ }
+
if (code >= 0 && code < ARRAY_LEN(sip_reason_table)) {
return sip_reason_table[code].text;
}
@@ -13528,7 +13555,9 @@ static void add_diversion(struct sip_request *req, struct sip_pvt *pvt)
{
struct ast_party_id diverting_from;
const char *reason;
+ int found_in_table;
char header_text[256];
+ char encoded_number[SIPBUFSIZE/2];
/* We skip this entirely if the configuration doesn't allow diversion headers */
if (!sip_cfg.send_diversion) {
@@ -13545,17 +13574,37 @@ static void add_diversion(struct sip_request *req, struct sip_pvt *pvt)
return;
}
- reason = sip_reason_code_to_str(ast_channel_redirecting(pvt->owner)->reason);
+ if (sip_cfg.pedanticsipchecking) {
+ ast_uri_encode(diverting_from.number.str, encoded_number, sizeof(encoded_number), ast_uri_sip_user);
+ } else {
+ ast_copy_string(encoded_number, diverting_from.number.str, sizeof(encoded_number));
+ }
+
+ reason = sip_reason_code_to_str(&ast_channel_redirecting(pvt->owner)->reason, &found_in_table);
/* We at least have a number to place in the Diversion header, which is enough */
if (!diverting_from.name.valid
|| ast_strlen_zero(diverting_from.name.str)) {
- snprintf(header_text, sizeof(header_text), "<sip:%s@%s>;reason=%s", diverting_from.number.str,
- ast_sockaddr_stringify_host_remote(&pvt->ourip), reason);
+ snprintf(header_text, sizeof(header_text), "<sip:%s@%s>;reason=%s%s%s",
+ encoded_number,
+ ast_sockaddr_stringify_host_remote(&pvt->ourip),
+ found_in_table ? "" : "\"",
+ reason,
+ found_in_table ? "" : "\"");
} else {
- snprintf(header_text, sizeof(header_text), "\"%s\" <sip:%s@%s>;reason=%s",
- diverting_from.name.str, diverting_from.number.str,
- ast_sockaddr_stringify_host_remote(&pvt->ourip), reason);
+ char escaped_name[SIPBUFSIZE/2];
+ if (sip_cfg.pedanticsipchecking) {
+ ast_escape_quoted(diverting_from.name.str, escaped_name, sizeof(escaped_name));
+ } else {
+ ast_copy_string(escaped_name, diverting_from.name.str, sizeof(escaped_name));
+ }
+ snprintf(header_text, sizeof(header_text), "\"%s\" <sip:%s@%s>;reason=%s%s%s",
+ escaped_name,
+ encoded_number,
+ ast_sockaddr_stringify_host_remote(&pvt->ourip),
+ found_in_table ? "" : "\"",
+ reason,
+ found_in_table ? "" : "\"");
}
add_header(req, "Diversion", header_text);
@@ -16839,8 +16888,19 @@ static int get_rpid(struct sip_pvt *p, struct sip_request *oreq)
return 1;
}
-/*! \brief Get referring dnis */
-static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq, char **name, char **number, int *reason)
+/*! \brief Get referring dnis
+ *
+ * \param p dialog information
+ * \param oreq The request to retrieve RDNIS from
+ * \param[out] name The name of the party redirecting the call.
+ * \param[out] number The number of the party redirecting the call.
+ * \param[out] reason_code The numerical code corresponding to the reason for the redirection.
+ * \param[out] reason_str A string describing the reason for redirection. Will never be zero-length
+ *
+ * \retval -1 Could not retrieve RDNIS information
+ * \retval 0 RDNIS successfully retrieved
+ */
+static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq, char **name, char **number, int *reason_code, char **reason_str)
{
char tmp[256], *exten, *rexten, *rdomain, *rname = NULL;
char *params, *reason_param = NULL;
@@ -16897,9 +16957,9 @@ static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq, char **name, c
if (p->owner)
pbx_builtin_setvar_helper(p->owner, "__SIPRDNISDOMAIN", rdomain);
- if (sip_debug_test_pvt(p))
+ if (sip_debug_test_pvt(p)) {
ast_verbose("RDNIS for this call is %s (reason %s)\n", exten, S_OR(reason_param, ""));
-
+ }
/*ast_string_field_set(p, rdnis, rexten);*/
if (*tmp == '\"') {
@@ -16919,8 +16979,14 @@ static int get_rdnis(struct sip_pvt *p, struct sip_request *oreq, char **name, c
*name = ast_strdup(rname);
}
- if (reason && !ast_strlen_zero(reason_param)) {
- *reason = sip_reason_str_to_code(reason_param);
+ if (!ast_strlen_zero(reason_param)) {
+ if (reason_code) {
+ *reason_code = sip_reason_str_to_code(reason_param);
+ }
+
+ if (reason_str) {
+ *reason_str = ast_strdup(reason_param);
+ }
}
return 0;
@@ -21622,11 +21688,12 @@ static void change_redirecting_information(struct sip_pvt *p, struct sip_request
char *redirecting_from_number = NULL;
char *redirecting_to_name = NULL;
char *redirecting_to_number = NULL;
+ char *reason_str = NULL;
int reason = AST_REDIRECTING_REASON_UNCONDITIONAL;
int is_response = req->method == SIP_RESPONSE;
int res = 0;
- res = get_rdnis(p, req, &redirecting_from_name, &redirecting_from_number, &reason);
+ res = get_rdnis(p, req, &redirecting_from_name, &redirecting_from_number, &reason, &reason_str);
if (res == -1) {
if (is_response) {
get_name_and_number(sip_get_header(req, "TO"), &redirecting_from_name, &redirecting_from_number);
@@ -21679,7 +21746,12 @@ static void change_redirecting_information(struct sip_pvt *p, struct sip_request
ast_free(redirecting->to.name.str);
redirecting->to.name.str = redirecting_to_name;
}
- redirecting->reason = reason;
+ redirecting->reason.code = reason;
+ if (reason_str) {
+ ast_debug(3, "Got redirecting reason %s\n", reason_str);
+ ast_free(redirecting->reason.str);
+ redirecting->reason.str = reason_str;
+ }
}
/*! \brief Parse 302 Moved temporalily response
@@ -22450,6 +22522,28 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest
}
break;
+ case 480: /* Temporarily unavailable. */
+ /* RFC 3261 encourages setting the reason phrase to something indicative
+ * of why the endpoint is not available. We will make this readable via the
+ * redirecting reason.
+ */
+ xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE);
+ append_history(p, "TempUnavailable", "Endpoint is temporarily unavailable.");
+ if (p->owner && !req->ignore) {
+ struct ast_party_redirecting redirecting;
+ struct ast_set_party_redirecting update_redirecting;
+ ast_party_redirecting_set_init(&redirecting, ast_channel_redirecting(p->owner));
+ memset(&update_redirecting, 0, sizeof(update_redirecting));
+
+ redirecting.reason.code = sip_reason_str_to_code(rest);
+ redirecting.reason.str = ast_strdup(rest);
+
+ ast_channel_queue_redirecting_update(p->owner, &redirecting, &update_redirecting);
+ ast_party_redirecting_free(&redirecting);
+
+ ast_queue_control(p->owner, AST_CONTROL_BUSY);
+ }
+ break;
case 487: /* Cancelled transaction */
/* We have sent CANCEL on an outbound INVITE
This transaction is already scheduled to be killed by sip_hangup().
@@ -23320,7 +23414,16 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
handle_response_invite(p, resp, rest, req, seqno);
}
break;
-
+ case 480:
+ if (sipmethod == SIP_INVITE) {
+ handle_response_invite(p, resp, rest, req, seqno);
+ } else if (sipmethod == SIP_SUBSCRIBE) {
+ handle_response_subscribe(p, resp, rest, req, seqno);
+ } else if (owner) {
+ /* No specific handler. Default to congestion */
+ ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
+ }
+ break;
case 481: /* Call leg does not exist */
if (sipmethod == SIP_INVITE) {
handle_response_invite(p, resp, rest, req, seqno);
@@ -23409,7 +23512,6 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
}
break;
case 482: /* Loop Detected */
- case 480: /* Temporarily Unavailable */
case 404: /* Not Found */
case 410: /* Gone */
case 400: /* Bad Request */
diff --git a/channels/sig_pri.c b/channels/sig_pri.c
index bf73ced37..93a77efd7 100644
--- a/channels/sig_pri.c
+++ b/channels/sig_pri.c
@@ -916,8 +916,8 @@ static void sig_pri_redirecting_update(struct sig_pri_chan *pvt, struct ast_chan
sig_pri_party_id_from_ast(&pri_redirecting.to, &redirecting_to);
sig_pri_party_id_from_ast(&pri_redirecting.orig_called, &redirecting_orig);
pri_redirecting.count = ast_redirecting->count;
- pri_redirecting.orig_reason = ast_to_pri_reason(ast_redirecting->orig_reason);
- pri_redirecting.reason = ast_to_pri_reason(ast_redirecting->reason);
+ pri_redirecting.orig_reason = ast_to_pri_reason(ast_redirecting->orig_reason.code);
+ pri_redirecting.reason = ast_to_pri_reason(ast_redirecting->reason.code);
pri_redirecting_update(pvt->pri->pri, pvt->call, &pri_redirecting);
}
@@ -2177,8 +2177,8 @@ static void sig_pri_redirecting_convert(struct ast_party_redirecting *ast_redire
sig_pri_party_id_convert(&ast_redirecting->from, &pri_redirecting->from, pri);
sig_pri_party_id_convert(&ast_redirecting->to, &pri_redirecting->to, pri);
ast_redirecting->count = pri_redirecting->count;
- ast_redirecting->reason = pri_to_ast_reason(pri_redirecting->reason);
- ast_redirecting->orig_reason = pri_to_ast_reason(pri_redirecting->orig_reason);
+ ast_redirecting->reason.code = pri_to_ast_reason(pri_redirecting->reason);
+ ast_redirecting->orig_reason.code = pri_to_ast_reason(pri_redirecting->orig_reason);
}
/*!
diff --git a/funcs/func_callerid.c b/funcs/func_callerid.c
index 789575399..30026af3d 100644
--- a/funcs/func_callerid.c
+++ b/funcs/func_callerid.c
@@ -1493,7 +1493,7 @@ static int redirecting_read(struct ast_channel *chan, const char *cmd, char *dat
if (!strcasecmp("orig", member.argv[0])) {
if (member.argc == 2 && !strcasecmp("reason", member.argv[1])) {
ast_copy_string(buf,
- ast_redirecting_reason_name(ast_redirecting->orig_reason), len);
+ ast_redirecting_reason_name(&ast_redirecting->orig_reason), len);
} else {
status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
&ast_redirecting->orig);
@@ -1537,7 +1537,7 @@ static int redirecting_read(struct ast_channel *chan, const char *cmd, char *dat
ast_named_caller_presentation(
ast_party_id_presentation(&ast_redirecting->from)), len);
} else if (member.argc == 1 && !strcasecmp("reason", member.argv[0])) {
- ast_copy_string(buf, ast_redirecting_reason_name(ast_redirecting->reason), len);
+ ast_copy_string(buf, ast_redirecting_reason_name(&ast_redirecting->reason), len);
} else if (member.argc == 1 && !strcasecmp("count", member.argv[0])) {
snprintf(buf, len, "%d", ast_redirecting->count);
} else if (1 < member.argc && !strcasecmp("priv", member.argv[0])) {
@@ -1659,10 +1659,16 @@ static int redirecting_write(struct ast_channel *chan, const char *cmd, char *da
}
if (reason < 0) {
- ast_log(LOG_ERROR,
- "Unknown redirecting orig reason '%s', value unchanged\n", val);
+ /* The argument passed into the function does not correspond to a pre-defined
+ * reason, so we can just set the reason string to what was given and set the
+ * code to be unknown
+ */
+ redirecting.orig_reason.code = AST_REDIRECTING_REASON_UNKNOWN;
+ redirecting.orig_reason.str = val;
+ set_it(chan, &redirecting, NULL);
} else {
- redirecting.orig_reason = reason;
+ redirecting.orig_reason.code = reason;
+ redirecting.orig_reason.str = "";
set_it(chan, &redirecting, NULL);
}
} else {
@@ -1742,9 +1748,16 @@ static int redirecting_write(struct ast_channel *chan, const char *cmd, char *da
}
if (reason < 0) {
- ast_log(LOG_ERROR, "Unknown redirecting reason '%s', value unchanged\n", val);
+ /* The argument passed into the function does not correspond to a pre-defined
+ * reason, so we can just set the reason string to what was given and set the
+ * code to be unknown
+ */
+ redirecting.reason.code = AST_REDIRECTING_REASON_UNKNOWN;
+ redirecting.reason.str = val;
+ set_it(chan, &redirecting, NULL);
} else {
- redirecting.reason = reason;
+ redirecting.reason.code = reason;
+ redirecting.reason.str = "";
set_it(chan, &redirecting, NULL);
}
} else if (member.argc == 1 && !strcasecmp("count", member.argv[0])) {
diff --git a/include/asterisk/callerid.h b/include/asterisk/callerid.h
index 7c4905e13..4f32dbf66 100644
--- a/include/asterisk/callerid.h
+++ b/include/asterisk/callerid.h
@@ -424,15 +424,17 @@ int ast_redirecting_reason_parse(const char *data);
*/
const char *ast_redirecting_reason_describe(int data);
+struct ast_party_redirecting_reason;
+
/*!
* \since 1.8
* \brief Convert redirecting reason value to text code
*
- * \param data Q931_REDIRECTING_REASON from callerid.h
+ * \param data ast_party_redirecting_reason structure from channel.h
*
* \return string for config file
*/
-const char *ast_redirecting_reason_name(int data);
+const char *ast_redirecting_reason_name(const struct ast_party_redirecting_reason *data);
/*!
* \brief Connected line update source code
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index b60c8ad00..fed032a3d 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -450,6 +450,21 @@ struct ast_set_party_connected_line {
};
/*!
+ * \brief Redirecting reason information
+ */
+struct ast_party_redirecting_reason {
+ /*! \brief a string value for the redirecting reason
+ *
+ * Useful for cases where an endpoint has specified a redirecting reason
+ * that does not correspond to an enum AST_REDIRECTING_REASON
+ */
+ char *str;
+
+ /*! \brief enum AST_REDIRECTING_REASON value for redirection */
+ int code;
+};
+
+/*!
* \since 1.8
* \brief Redirecting Line information.
* RDNIS (Redirecting Directory Number Information Service)
@@ -477,14 +492,14 @@ struct ast_party_redirecting {
/*! \brief Call is redirecting to a new party (Sent to the caller) - private representation */
struct ast_party_id priv_to;
- /*! \brief Number of times the call was redirected */
- int count;
+ /*! \brief Reason for the redirection */
+ struct ast_party_redirecting_reason reason;
- /*! \brief enum AST_REDIRECTING_REASON value for redirection */
- int reason;
+ /*! \brief Reason for the redirection by the original party */
+ struct ast_party_redirecting_reason orig_reason;
- /*! \brief enum AST_REDIRECTING_REASON value for redirection by original party */
- int orig_reason;
+ /*! \brief Number of times the call was redirected */
+ int count;
};
/*!
@@ -3229,6 +3244,68 @@ void ast_party_connected_line_collect_caller(struct ast_party_connected_line *co
void ast_party_connected_line_free(struct ast_party_connected_line *doomed);
/*!
+ * \brief Initialize the given redirecting reason structure
+ *
+ * \param init Redirecting reason structure to initialize
+ *
+ * \return Nothing
+ */
+void ast_party_redirecting_reason_init(struct ast_party_redirecting_reason *init);
+
+/*!
+ * \brief Copy the source redirecting reason information to the destination redirecting reason.
+ *
+ * \param dest Destination redirecting reason
+ * \param src Source redirecting reason
+ *
+ * \return Nothing
+ */
+void ast_party_redirecting_reason_copy(struct ast_party_redirecting_reason *dest,
+ const struct ast_party_redirecting_reason *src);
+
+/*!
+ * \brief Initialize the given redirecting reason structure using the given guide
+ * for a set update operation.
+ *
+ * \details
+ * The initialization is needed to allow a set operation to know if a
+ * value needs to be updated. Simple integers need the guide's original
+ * value in case the set operation is not trying to set a new value.
+ * String values are simply set to NULL pointers if they are not going
+ * to be updated.
+ *
+ * \param init Redirecting reason structure to initialize.
+ * \param guide Source redirecting reason to use as a guide in initializing.
+ *
+ * \return Nothing
+ */
+void ast_party_redirecting_reason_set_init(struct ast_party_redirecting_reason *init,
+ const struct ast_party_redirecting_reason *guide);
+
+/*!
+ * \brief Set the redirecting reason information based on another redirecting reason source
+ *
+ * This is similar to ast_party_redirecting_reason_copy, except that NULL values for
+ * strings in the src parameter indicate not to update the corresponding dest values.
+ *
+ * \param dest The redirecting reason one wishes to update
+ * \param src The new redirecting reason values to update the dest
+ *
+ * \return Nothing
+ */
+void ast_party_redirecting_reason_set(struct ast_party_redirecting_reason *dest,
+ const struct ast_party_redirecting_reason *src);
+
+/*!
+ * \brief Destroy the redirecting reason contents
+ *
+ * \param doomed The redirecting reason to destroy.
+ *
+ * \return Nothing
+ */
+void ast_party_redirecting_reason_free(struct ast_party_redirecting_reason *doomed);
+
+/*!
* \brief Initialize the given redirecting structure.
* \since 1.8
*
diff --git a/main/callerid.c b/main/callerid.c
index d9f74180a..db5e795ff 100644
--- a/main/callerid.c
+++ b/main/callerid.c
@@ -1237,12 +1237,17 @@ const char *ast_redirecting_reason_describe(int data)
return "not-known";
}
-const char *ast_redirecting_reason_name(int data)
+const char *ast_redirecting_reason_name(const struct ast_party_redirecting_reason *data)
{
int index;
+ if (!ast_strlen_zero(data->str)) {
+ /* Use this string if it has been set. Otherwise, use the table. */
+ return data->str;
+ }
+
for (index = 0; index < ARRAY_LEN(redirecting_reason_types); ++index) {
- if (redirecting_reason_types[index].value == data) {
+ if (redirecting_reason_types[index].value == data->code) {
return redirecting_reason_types[index].name;
}
}
diff --git a/main/channel.c b/main/channel.c
index dbc4703b5..751cbdd52 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -2235,6 +2235,49 @@ void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
ast_party_id_free(&doomed->priv);
}
+void ast_party_redirecting_reason_init(struct ast_party_redirecting_reason *init)
+{
+ init->str = NULL;
+ init->code = AST_REDIRECTING_REASON_UNKNOWN;
+}
+
+void ast_party_redirecting_reason_copy(struct ast_party_redirecting_reason *dest, const struct ast_party_redirecting_reason *src)
+{
+ if (dest == src) {
+ return;
+ }
+
+ ast_free(dest->str);
+ dest->str = ast_strdup(src->str);
+ dest->code = src->code;
+}
+
+void ast_party_redirecting_reason_set_init(struct ast_party_redirecting_reason *init, const struct ast_party_redirecting_reason *guide)
+{
+ init->str = NULL;
+ init->code = guide->code;
+}
+
+void ast_party_redirecting_reason_set(struct ast_party_redirecting_reason *dest, const struct ast_party_redirecting_reason *src)
+{
+ if (dest == src) {
+ return;
+ }
+
+ if (src->str && src->str != dest->str) {
+ ast_free(dest->str);
+ dest->str = ast_strdup(src->str);
+ }
+
+ dest->code = src->code;
+}
+
+void ast_party_redirecting_reason_free(struct ast_party_redirecting_reason *doomed)
+{
+ ast_free(doomed->str);
+}
+
+
void ast_party_redirecting_init(struct ast_party_redirecting *init)
{
ast_party_id_init(&init->orig);
@@ -2243,9 +2286,9 @@ void ast_party_redirecting_init(struct ast_party_redirecting *init)
ast_party_id_init(&init->priv_orig);
ast_party_id_init(&init->priv_from);
ast_party_id_init(&init->priv_to);
+ ast_party_redirecting_reason_init(&init->reason);
+ ast_party_redirecting_reason_init(&init->orig_reason);
init->count = 0;
- init->reason = AST_REDIRECTING_REASON_UNKNOWN;
- init->orig_reason = AST_REDIRECTING_REASON_UNKNOWN;
}
void ast_party_redirecting_copy(struct ast_party_redirecting *dest, const struct ast_party_redirecting *src)
@@ -2261,9 +2304,9 @@ void ast_party_redirecting_copy(struct ast_party_redirecting *dest, const struct
ast_party_id_copy(&dest->priv_orig, &src->priv_orig);
ast_party_id_copy(&dest->priv_from, &src->priv_from);
ast_party_id_copy(&dest->priv_to, &src->priv_to);
+ ast_party_redirecting_reason_copy(&dest->reason, &src->reason);
+ ast_party_redirecting_reason_copy(&dest->orig_reason, &src->orig_reason);
dest->count = src->count;
- dest->reason = src->reason;
- dest->orig_reason = src->orig_reason;
}
void ast_party_redirecting_set_init(struct ast_party_redirecting *init, const struct ast_party_redirecting *guide)
@@ -2274,9 +2317,9 @@ void ast_party_redirecting_set_init(struct ast_party_redirecting *init, const st
ast_party_id_set_init(&init->priv_orig, &guide->priv_orig);
ast_party_id_set_init(&init->priv_from, &guide->priv_from);
ast_party_id_set_init(&init->priv_to, &guide->priv_to);
+ ast_party_redirecting_reason_set_init(&init->reason, &guide->reason);
+ ast_party_redirecting_reason_set_init(&init->orig_reason, &guide->orig_reason);
init->count = guide->count;
- init->reason = guide->reason;
- init->orig_reason = guide->orig_reason;
}
void ast_party_redirecting_set(struct ast_party_redirecting *dest, const struct ast_party_redirecting *src, const struct ast_set_party_redirecting *update)
@@ -2287,9 +2330,9 @@ void ast_party_redirecting_set(struct ast_party_redirecting *dest, const struct
ast_party_id_set(&dest->priv_orig, &src->priv_orig, update ? &update->priv_orig : NULL);
ast_party_id_set(&dest->priv_from, &src->priv_from, update ? &update->priv_from : NULL);
ast_party_id_set(&dest->priv_to, &src->priv_to, update ? &update->priv_to : NULL);
+ ast_party_redirecting_reason_set(&dest->reason, &src->reason);
+ ast_party_redirecting_reason_set(&dest->orig_reason, &src->orig_reason);
dest->count = src->count;
- dest->reason = src->reason;
- dest->orig_reason = src->orig_reason;
}
void ast_party_redirecting_free(struct ast_party_redirecting *doomed)
@@ -2300,6 +2343,8 @@ void ast_party_redirecting_free(struct ast_party_redirecting *doomed)
ast_party_id_free(&doomed->priv_orig);
ast_party_id_free(&doomed->priv_from);
ast_party_id_free(&doomed->priv_to);
+ ast_party_redirecting_reason_free(&doomed->reason);
+ ast_party_redirecting_reason_free(&doomed->orig_reason);
}
/*! \brief Free a channel structure */
@@ -9616,7 +9661,7 @@ enum {
AST_REDIRECTING_TO_NAME,
AST_REDIRECTING_TO_NUMBER_PLAN,
AST_REDIRECTING_TO_ID_PRESENTATION,/* Combined number and name presentation. */
- AST_REDIRECTING_REASON,
+ AST_REDIRECTING_REASON_CODE,
AST_REDIRECTING_COUNT,
AST_REDIRECTING_FROM_SUBADDRESS,
AST_REDIRECTING_FROM_SUBADDRESS_TYPE,
@@ -9656,7 +9701,7 @@ enum {
AST_REDIRECTING_ORIG_SUBADDRESS_ODD_EVEN,
AST_REDIRECTING_ORIG_SUBADDRESS_VALID,
AST_REDIRECTING_ORIG_TAG,
- AST_REDIRECTING_ORIG_REASON,
+ AST_REDIRECTING_ORIG_REASON_CODE,
AST_REDIRECTING_PRIV_TO_NUMBER,
AST_REDIRECTING_PRIV_TO_NUMBER_PLAN,
AST_REDIRECTING_PRIV_TO_NUMBER_VALID,
@@ -9696,8 +9741,48 @@ enum {
AST_REDIRECTING_PRIV_ORIG_SUBADDRESS_ODD_EVEN,
AST_REDIRECTING_PRIV_ORIG_SUBADDRESS_VALID,
AST_REDIRECTING_PRIV_ORIG_TAG,
+ AST_REDIRECTING_REASON_STR,
+ AST_REDIRECTING_ORIG_REASON_STR,
};
+struct ast_party_redirecting_reason_ies {
+ int code;
+ int str;
+};
+
+static int redirecting_reason_build_data(unsigned char *data, size_t datalen,
+ const struct ast_party_redirecting_reason *reason, const char *label,
+ const struct ast_party_redirecting_reason_ies *ies)
+{
+ size_t length;
+ size_t pos = 0;
+ int32_t value;
+
+ if (datalen < pos + (sizeof(data[0]) * 2) + sizeof(value)) {
+ ast_log(LOG_WARNING, "No space left for %s code\n", label);
+ return -1;
+ }
+ data[pos++] = ies->code;
+ data[pos++] = sizeof(value);
+ value = htonl(reason->code);
+ memcpy(data + pos, &value, sizeof(value));
+ pos += sizeof(value);
+
+ if (reason->str) {
+ length = strlen(reason->str);
+ if (datalen < pos + sizeof(data[0] * 2) + length) {
+ ast_log(LOG_WARNING, "No space left for %s string\n", label);
+ return -1;
+ }
+ data[pos++] = ies->str;
+ data[pos++] = length;
+ memcpy(data + pos, reason->str, length);
+ pos += length;
+ }
+
+ return pos;
+}
+
int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update)
{
int32_t value;
@@ -9818,6 +9903,15 @@ int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct
.tag = AST_REDIRECTING_PRIV_TO_TAG,
.combined_presentation = 0,/* Not sent. */
};
+ static const struct ast_party_redirecting_reason_ies reason_ies = {
+ .code = AST_REDIRECTING_REASON_CODE,
+ .str = AST_REDIRECTING_REASON_STR,
+ };
+
+ static const struct ast_party_redirecting_reason_ies orig_reason_ies = {
+ .code = AST_REDIRECTING_ORIG_REASON_CODE,
+ .str = AST_REDIRECTING_ORIG_REASON_STR,
+ };
/* Redirecting frame version */
if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
@@ -9871,26 +9965,20 @@ int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct
pos += res;
/* Redirecting reason */
- if (datalen < pos + (sizeof(data[0]) * 2) + sizeof(value)) {
- ast_log(LOG_WARNING, "No space left for redirecting reason\n");
+ res = redirecting_reason_build_data(data + pos, datalen - pos, &redirecting->reason,
+ "redirecting-reason", &reason_ies);
+ if (res < 0) {
return -1;
}
- data[pos++] = AST_REDIRECTING_REASON;
- data[pos++] = sizeof(value);
- value = htonl(redirecting->reason);
- memcpy(data + pos, &value, sizeof(value));
- pos += sizeof(value);
+ pos += res;
/* Redirecting original reason */
- if (datalen < pos + (sizeof(data[0]) * 2) + sizeof(value)) {
- ast_log(LOG_WARNING, "No space left for redirecting original reason\n");
+ res = redirecting_reason_build_data(data + pos, datalen - pos, &redirecting->orig_reason,
+ "redirecting-orig-reason", &orig_reason_ies);
+ if (res < 0) {
return -1;
}
- data[pos++] = AST_REDIRECTING_ORIG_REASON;
- data[pos++] = sizeof(value);
- value = htonl(redirecting->orig_reason);
- memcpy(data + pos, &value, sizeof(value));
- pos += sizeof(value);
+ pos += res;
/* Redirecting count */
if (datalen < pos + (sizeof(data[0]) * 2) + sizeof(value)) {
@@ -10614,25 +10702,43 @@ int ast_redirecting_parse_data(const unsigned char *data, size_t datalen, struct
redirecting->priv_to.tag[ie_len] = 0;
}
break;
-/* Redirecting reason */
- case AST_REDIRECTING_REASON:
+/* Redirecting reason code */
+ case AST_REDIRECTING_REASON_CODE:
if (ie_len != sizeof(value)) {
ast_log(LOG_WARNING, "Invalid redirecting reason (%u)\n",
(unsigned) ie_len);
break;
}
memcpy(&value, data + pos, sizeof(value));
- redirecting->reason = ntohl(value);
+ redirecting->reason.code = ntohl(value);
break;
-/* Redirecting orig-reason */
- case AST_REDIRECTING_ORIG_REASON:
+/* Redirecting reason string */
+ case AST_REDIRECTING_REASON_STR:
+ ast_free(redirecting->reason.str);
+ redirecting->reason.str = ast_malloc(ie_len + 1);
+ if (redirecting->reason.str) {
+ memcpy(redirecting->reason.str, data + pos, ie_len);
+ redirecting->reason.str[ie_len] = 0;
+ }
+ break;
+/* Redirecting orig-reason code */
+ case AST_REDIRECTING_ORIG_REASON_CODE:
if (ie_len != sizeof(value)) {
ast_log(LOG_WARNING, "Invalid redirecting original reason (%u)\n",
(unsigned) ie_len);
break;
}
memcpy(&value, data + pos, sizeof(value));
- redirecting->orig_reason = ntohl(value);
+ redirecting->orig_reason.code = ntohl(value);
+ break;
+/* Redirecting orig-reason string */
+ case AST_REDIRECTING_ORIG_REASON_STR:
+ ast_free(redirecting->orig_reason.str);
+ redirecting->orig_reason.str = ast_malloc(ie_len + 1);
+ if (redirecting->orig_reason.str) {
+ memcpy(redirecting->orig_reason.str, data + pos, ie_len);
+ redirecting->orig_reason.str[ie_len] = 0;
+ }
break;
/* Redirecting count */
case AST_REDIRECTING_COUNT: