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
changes/97/197/1
Jonathan Rose 11 years ago
parent 120ac66df9
commit 57372e61d2

@ -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;
}
create_parked_subscription(announce_chan, ast_channel_uniqueid(chan), 0);
ast_channel_cleanup(announce_chan);
}
manager_park_unbridged(s, m, chan, parkinglot, timeout_override);
return 0; return 0;
} }
if (ast_bridge_add_channel(parking_bridge, chan, NULL, 0, NULL)) { if (!ast_strlen_zero(announce_channel) && strcmp(announce_channel, timeout_channel)) {
astman_send_error(s, m, "Park action failed\n"); /* When using an announce_channel in bridge mode, only add the announce channel if it isn't
return 0; * 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);
} }
astman_send_ack(s, m, "Park successful\n"); 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

Loading…
Cancel
Save