mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-27 06:31:54 +00:00
Parking: Add 'AnnounceChannel' argument to manager action 'Park'
(closes ASTERISK-23397) Reported by: Denis Review: https://reviewboard.asterisk.org/r/3446/ ........ Merged revisions 413196 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@413197 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
10
CHANGES
10
CHANGES
@@ -52,6 +52,15 @@ chan_sip
|
|||||||
calling information to communicate that the private information should
|
calling information to communicate that the private information should
|
||||||
not be relayed to untrusted parties.
|
not be relayed to untrusted parties.
|
||||||
|
|
||||||
|
res_parking
|
||||||
|
------------------
|
||||||
|
* Manager action 'Park' now takes an additional argument 'AnnounceChannel'
|
||||||
|
which can be used to announce the parked call's location to an arbitrary
|
||||||
|
channel in a bridge. If 'Channel' and 'TimeoutChannel' are now the two
|
||||||
|
parties in a one to one bridge, 'TimeoutChannel' is treated as having
|
||||||
|
parked 'Channel' like with the Park Call DTMF feature and will receive
|
||||||
|
announcements prior to being hung up.
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
--- Functionality changes from Asterisk 12.1.0 to Asterisk 12.2.0 ------------
|
--- Functionality changes from Asterisk 12.1.0 to Asterisk 12.2.0 ------------
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
@@ -1526,7 +1535,6 @@ sip_to_res_pjsip.py
|
|||||||
what the script provides will be needed.
|
what the script provides will be needed.
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
>>>>>>> .merge-right.r412746
|
|
||||||
--- Functionality changes from Asterisk 10 to Asterisk 11 --------------------
|
--- Functionality changes from Asterisk 10 to Asterisk 11 --------------------
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ struct parked_subscription_datastore {
|
|||||||
|
|
||||||
struct parked_subscription_data {
|
struct parked_subscription_data {
|
||||||
char *parkee_uuid;
|
char *parkee_uuid;
|
||||||
|
int hangup_after:1;
|
||||||
char parker_uuid[0];
|
char parker_uuid[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -114,7 +115,7 @@ static void parker_parked_call_message_response(struct ast_parked_call_payload *
|
|||||||
|
|
||||||
if (message->event_type == PARKED_CALL) {
|
if (message->event_type == PARKED_CALL) {
|
||||||
/* queue the saynum on the bridge channel and hangup */
|
/* queue the saynum on the bridge channel and hangup */
|
||||||
snprintf(saynum_buf, sizeof(saynum_buf), "%u %u", 1, message->parkingspace);
|
snprintf(saynum_buf, sizeof(saynum_buf), "%u %u", data->hangup_after, message->parkingspace);
|
||||||
ast_bridge_channel_queue_playfile(bridge_channel, say_parking_space, saynum_buf, NULL);
|
ast_bridge_channel_queue_playfile(bridge_channel, say_parking_space, saynum_buf, NULL);
|
||||||
wipe_subscription_datastore(bridge_channel->chan);
|
wipe_subscription_datastore(bridge_channel->chan);
|
||||||
}
|
}
|
||||||
@@ -138,7 +139,7 @@ static void parker_update_cb(void *data, struct stasis_subscription *sub, struct
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int create_parked_subscription(struct ast_channel *chan, const char *parkee_uuid)
|
int create_parked_subscription(struct ast_channel *chan, const char *parkee_uuid, int hangup_after)
|
||||||
{
|
{
|
||||||
struct ast_datastore *datastore;
|
struct ast_datastore *datastore;
|
||||||
struct parked_subscription_datastore *parked_datastore;
|
struct parked_subscription_datastore *parked_datastore;
|
||||||
@@ -166,6 +167,7 @@ static int create_parked_subscription(struct ast_channel *chan, const char *park
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
subscription_data->hangup_after = hangup_after;
|
||||||
subscription_data->parkee_uuid = subscription_data->parker_uuid + parker_uuid_size;
|
subscription_data->parkee_uuid = subscription_data->parker_uuid + parker_uuid_size;
|
||||||
strcpy(subscription_data->parkee_uuid, parkee_uuid);
|
strcpy(subscription_data->parkee_uuid, parkee_uuid);
|
||||||
strcpy(subscription_data->parker_uuid, parker_uuid);
|
strcpy(subscription_data->parker_uuid, parker_uuid);
|
||||||
@@ -218,7 +220,7 @@ static struct ast_channel *park_local_transfer(struct ast_channel *parker, const
|
|||||||
ast_channel_unlock(parkee);
|
ast_channel_unlock(parkee);
|
||||||
|
|
||||||
/* We need to have the parker subscribe to the new local channel before hand. */
|
/* We need to have the parker subscribe to the new local channel before hand. */
|
||||||
create_parked_subscription(parker, ast_channel_uniqueid(parkee_side_2));
|
create_parked_subscription(parker, ast_channel_uniqueid(parkee_side_2), 1);
|
||||||
|
|
||||||
ast_bridge_set_transfer_variables(parkee_side_2, ast_channel_name(parker), 0);
|
ast_bridge_set_transfer_variables(parkee_side_2, ast_channel_name(parker), 0);
|
||||||
|
|
||||||
@@ -325,7 +327,7 @@ static int parking_blind_transfer_park(struct ast_bridge_channel *bridge_channel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Subscribe to park messages with the other channel entering */
|
/* Subscribe to park messages with the other channel entering */
|
||||||
if (create_parked_subscription(bridge_channel->chan, ast_channel_uniqueid(other->chan))) {
|
if (create_parked_subscription(bridge_channel->chan, ast_channel_uniqueid(other->chan), 1)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,11 +74,21 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||||||
<para>Channel name to park.</para>
|
<para>Channel name to park.</para>
|
||||||
</parameter>
|
</parameter>
|
||||||
<parameter name="TimeoutChannel" required="false">
|
<parameter name="TimeoutChannel" required="false">
|
||||||
<para>Channel name to use when constructing the dial string that will be dialed if the parked channel times out.</para>
|
<para>Channel name to use when constructing the dial string that will be dialed if the parked channel
|
||||||
|
times out. If <literal>TimeoutChannel</literal> is in a two party bridge with
|
||||||
|
<literal>Channel</literal>, then <literal>TimeoutChannel</literal> will receive an announcement and be
|
||||||
|
treated as having parked <literal>Channel</literal> in the same manner as the Park Call DTMF feature.
|
||||||
|
</para>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="AnnounceChannel" required="false">
|
||||||
|
<para>If specified, then this channel will receive an announcement when <literal>Channel</literal>
|
||||||
|
is parked if <literal>AnnounceChannel</literal> is in a state where it can receive announcements
|
||||||
|
(AnnounceChannel must be bridged). <literal>AnnounceChannel</literal> has no bearing on the actual
|
||||||
|
state of the parked call.</para>
|
||||||
</parameter>
|
</parameter>
|
||||||
<parameter name="Timeout" required="false">
|
<parameter name="Timeout" required="false">
|
||||||
<para>Overrides the timeout of the parking lot for this park action. Specified in milliseconds, but will be converted to
|
<para>Overrides the timeout of the parking lot for this park action. Specified in milliseconds, but will be converted to
|
||||||
seconds. Use a value of 0 to nullify the timeout.
|
seconds. Use a value of 0 to disable the timeout.
|
||||||
</para>
|
</para>
|
||||||
</parameter>
|
</parameter>
|
||||||
<parameter name="Parkinglot" required="false">
|
<parameter name="Parkinglot" required="false">
|
||||||
@@ -420,17 +430,85 @@ static int manager_parking_lot_list(struct mansession *s, const struct message *
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void manager_park_unbridged(struct mansession *s, const struct message *m,
|
||||||
|
struct ast_channel *chan, const char *parkinglot, int timeout_override)
|
||||||
|
{
|
||||||
|
struct ast_bridge *parking_bridge = park_common_setup(chan,
|
||||||
|
chan, parkinglot, NULL, 0, 0, timeout_override, 1);
|
||||||
|
|
||||||
|
if (!parking_bridge) {
|
||||||
|
astman_send_error(s, m, "Park action failed\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ast_bridge_add_channel(parking_bridge, chan, NULL, 0, NULL)) {
|
||||||
|
astman_send_error(s, m, "Park action failed\n");
|
||||||
|
ao2_cleanup(parking_bridge);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
astman_send_ack(s, m, "Park successful\n");
|
||||||
|
ao2_cleanup(parking_bridge);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void manager_park_bridged(struct mansession *s, const struct message *m,
|
||||||
|
struct ast_channel *chan, struct ast_channel *parker_chan,
|
||||||
|
const char *parkinglot, int timeout_override)
|
||||||
|
{
|
||||||
|
struct ast_bridge_channel *bridge_channel;
|
||||||
|
char *app_data;
|
||||||
|
|
||||||
|
if (timeout_override != -1) {
|
||||||
|
if (ast_asprintf(&app_data, "%s,t(%d)", parkinglot, timeout_override) == -1) {
|
||||||
|
astman_send_error(s, m, "Park action failed\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (ast_asprintf(&app_data, "%s", parkinglot) == -1) {
|
||||||
|
astman_send_error(s, m, "Park action failed\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ast_channel_lock(parker_chan);
|
||||||
|
bridge_channel = ast_channel_get_bridge_channel(parker_chan);
|
||||||
|
ast_channel_unlock(parker_chan);
|
||||||
|
|
||||||
|
if (!bridge_channel) {
|
||||||
|
ast_free(app_data);
|
||||||
|
astman_send_error(s, m, "Park action failed\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Subscribe to park messages for the channel being parked */
|
||||||
|
if (create_parked_subscription(parker_chan, ast_channel_uniqueid(chan), 1)) {
|
||||||
|
ast_free(app_data);
|
||||||
|
astman_send_error(s, m, "Park action failed\n");
|
||||||
|
ao2_cleanup(bridge_channel);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ast_bridge_channel_write_park(bridge_channel, ast_channel_uniqueid(chan),
|
||||||
|
ast_channel_uniqueid(parker_chan), app_data);
|
||||||
|
|
||||||
|
ast_free(app_data);
|
||||||
|
|
||||||
|
astman_send_ack(s, m, "Park successful\n");
|
||||||
|
ao2_cleanup(bridge_channel);
|
||||||
|
}
|
||||||
|
|
||||||
static int manager_park(struct mansession *s, const struct message *m)
|
static int manager_park(struct mansession *s, const struct message *m)
|
||||||
{
|
{
|
||||||
const char *channel = astman_get_header(m, "Channel");
|
const char *channel = astman_get_header(m, "Channel");
|
||||||
const char *timeout_channel = S_OR(astman_get_header(m, "TimeoutChannel"), astman_get_header(m, "Channel2"));
|
const char *timeout_channel = S_OR(astman_get_header(m, "TimeoutChannel"), astman_get_header(m, "Channel2"));
|
||||||
|
const char *announce_channel = astman_get_header(m, "AnnounceChannel");
|
||||||
const char *timeout = astman_get_header(m, "Timeout");
|
const char *timeout = astman_get_header(m, "Timeout");
|
||||||
const char *parkinglot = astman_get_header(m, "Parkinglot");
|
const char *parkinglot = astman_get_header(m, "Parkinglot");
|
||||||
char buf[BUFSIZ];
|
char buf[BUFSIZ];
|
||||||
int timeout_override = -1;
|
int timeout_override = -1;
|
||||||
|
|
||||||
|
RAII_VAR(struct ast_channel *, parker_chan, NULL, ao2_cleanup);
|
||||||
RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup);
|
RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup);
|
||||||
RAII_VAR(struct ast_bridge *, parking_bridge, NULL, ao2_cleanup);
|
|
||||||
|
|
||||||
if (ast_strlen_zero(channel)) {
|
if (ast_strlen_zero(channel)) {
|
||||||
astman_send_error(s, m, "Channel not specified");
|
astman_send_error(s, m, "Channel not specified");
|
||||||
@@ -461,17 +539,37 @@ static int manager_park(struct mansession *s, const struct message *m)
|
|||||||
}
|
}
|
||||||
ast_channel_unlock(chan);
|
ast_channel_unlock(chan);
|
||||||
|
|
||||||
if (!(parking_bridge = park_common_setup(chan, chan, parkinglot, NULL, 0, 0, timeout_override, 0))) {
|
parker_chan = ast_channel_bridge_peer(chan);
|
||||||
astman_send_error(s, m, "Park action failed\n");
|
if (!parker_chan || strcmp(ast_channel_name(parker_chan), timeout_channel)) {
|
||||||
|
if (!ast_strlen_zero(announce_channel)) {
|
||||||
|
struct ast_channel *announce_chan = ast_channel_get_by_name(announce_channel);
|
||||||
|
if (!announce_channel) {
|
||||||
|
astman_send_error(s, m, "AnnounceChannel does not exist");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ast_bridge_add_channel(parking_bridge, chan, NULL, 0, NULL)) {
|
create_parked_subscription(announce_chan, ast_channel_uniqueid(chan), 0);
|
||||||
astman_send_error(s, m, "Park action failed\n");
|
ast_channel_cleanup(announce_chan);
|
||||||
|
}
|
||||||
|
|
||||||
|
manager_park_unbridged(s, m, chan, parkinglot, timeout_override);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
astman_send_ack(s, m, "Park successful\n");
|
if (!ast_strlen_zero(announce_channel) && strcmp(announce_channel, timeout_channel)) {
|
||||||
|
/* When using an announce_channel in bridge mode, only add the announce channel if it isn't
|
||||||
|
* the same as the timeout channel (which will play announcements anyway) */
|
||||||
|
struct ast_channel *announce_chan = ast_channel_get_by_name(announce_channel);
|
||||||
|
if (!announce_channel) {
|
||||||
|
astman_send_error(s, m, "AnnounceChannel does not exist");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
create_parked_subscription(announce_chan, ast_channel_uniqueid(chan), 0);
|
||||||
|
ast_channel_cleanup(announce_chan);
|
||||||
|
}
|
||||||
|
|
||||||
|
manager_park_bridged(s, m, chan, parker_chan, parkinglot, timeout_override);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -385,6 +385,19 @@ void publish_parked_call_failure(struct ast_channel *parkee);
|
|||||||
*/
|
*/
|
||||||
void publish_parked_call(struct parked_user *pu, enum ast_parked_call_event_type event_type);
|
void publish_parked_call(struct parked_user *pu, enum ast_parked_call_event_type event_type);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \since 12.3.0
|
||||||
|
* \brief Create a parking announcement subscription
|
||||||
|
*
|
||||||
|
* \param chan Channel that will receive the announcement
|
||||||
|
* \param parkee_uuid Unique ID of the channel being parked
|
||||||
|
* \param hangup_after if non-zero, have the channel hangup after hearing the announcement
|
||||||
|
*
|
||||||
|
* \retval 0 on success
|
||||||
|
* \retval -1 on failure
|
||||||
|
*/
|
||||||
|
int create_parked_subscription(struct ast_channel *chan, const char *parkee_uuid, int hangup_after);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \since 12.0.0
|
* \since 12.0.0
|
||||||
* \brief Setup a parked call on a parking bridge without needing to parse appdata
|
* \brief Setup a parked call on a parking bridge without needing to parse appdata
|
||||||
|
|||||||
Reference in New Issue
Block a user