summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES28
-rw-r--r--UPGRADE.txt16
-rw-r--r--bridges/bridge_builtin_features.c3
-rw-r--r--include/asterisk/channel.h8
-rw-r--r--include/asterisk/parking.h8
-rw-r--r--main/bridging.c3
-rw-r--r--main/cel.c2
-rw-r--r--main/channel.c11
-rw-r--r--main/features.c40
-rw-r--r--main/parking.c12
-rw-r--r--res/parking/parking_applications.c110
-rw-r--r--res/parking/parking_bridge.c67
-rw-r--r--res/parking/parking_bridge_features.c45
-rw-r--r--res/parking/parking_controller.c36
-rw-r--r--res/parking/parking_manager.c54
-rw-r--r--res/parking/parking_ui.c6
-rw-r--r--res/parking/res_parking.h37
17 files changed, 247 insertions, 239 deletions
diff --git a/CHANGES b/CHANGES
index e6da22224..3223822ba 100644
--- a/CHANGES
+++ b/CHANGES
@@ -136,6 +136,10 @@ Core
feature on the bridge peer in a multi-party bridge will execute it on all
peers of the activating channel.
+ * A channel variable ATTENDEDTRANSFER is now set which indicates which channel
+ was responsible for an attended transfer in a similar fashion to
+ BLINDTRANSFER.
+
AMI (Asterisk Manager Interface)
------------------
* The SIPshowpeer action will now include a 'SubscribeContext' field for a peer
@@ -176,12 +180,24 @@ AMI (Asterisk Manager Interface)
* The AMI events 'ParkedCall', 'ParkedCallTimeOut', 'ParkedCallGiveUp', and
'UnParkedCall' have changed significantly in the new res_parking module.
- First, channel snapshot data is included for both the parker and the parkee
- in lieu of the "From" and "Channel" fields. They follow standard channel
- snapshot format but each field is suffixed with 'Parker' or 'Parkee'
- depending on which side it applies to. The 'Exten' field is replaced with
- 'ParkingSpace' since the registration of extensions as for parking spaces
- is no longer mandatory.
+
+ The 'Channel' and 'From' headers are gone. For the channel that was parked
+ or is coming out of parking, a 'Parkee' channel snapshot is issued and it
+ has a number of fields associated with it. The old 'Channel' header relayed
+ the same data as the new 'ParkeeChannel' header.
+
+ The 'From' field was ambiguous and changed meaning depending on the event.
+ for most of these, it was the name of the channel that parked the call
+ (the 'Parker'). There is no longer a header that provides this channel name,
+ however the 'ParkerDialString' will contain a dialstring to redial the
+ device that parked the call.
+
+ On UnParkedCall events, the 'From' header would instead represent the
+ channel responsible for retrieving the parkee. It receives a channel
+ snapshot labeled 'Retriever'. The 'from' field is is replaced with
+ 'RetrieverChannel'.
+
+ Lastly, the 'Exten' field has been replaced with 'ParkingSpace'.
* The AMI event 'Parkinglot' (response to 'Parkinglots' command) in a similar
fashion has changed the field names 'StartExten' and 'StopExten' to
diff --git a/UPGRADE.txt b/UPGRADE.txt
index 7a5261b94..bcb2de4db 100644
--- a/UPGRADE.txt
+++ b/UPGRADE.txt
@@ -75,6 +75,22 @@ AMI:
- Channels no longer swap Uniqueid's as a result of the masquerade.
- Instead of a shell game of renames, there's now a single rename, appending
<ZOMBIE> to the name of the original channel.
+ - The AMI events 'ParkedCall', 'ParkedCallTimeOut', 'ParkedCallGiveUp', and
+ 'UnParkedCall' have changed significantly in the new res_parking module.
+ - The 'Channel' and 'From' headers are gone. For the channel that was parked
+ or is coming out of parking, a 'Parkee' channel snapshot is issued and it
+ has a number of fields associated with it. The old 'Channel' header relayed
+ the same data as the new 'ParkeeChannel' header.
+ - The 'From' field was ambiguous and changed meaning depending on the event.
+ for most of these, it was the name of the channel that parked the call
+ (the 'Parker'). There is no longer a header that provides this channel name,
+ however the 'ParkerDialString' will contain a dialstring to redial the
+ device that parked the call.
+ - On UnParkedCall events, the 'From' header would instead represent the
+ channel responsible for retrieving the parkee. It receives a channel
+ snapshot labeled 'Retriever'. The 'from' field is is replaced with
+ 'RetrieverChannel'.
+ - Lastly, the 'Exten' field has been replaced with 'ParkingSpace'.
CEL:
- The Uniqueid field for a channel is now a stable identifier, and will not
diff --git a/bridges/bridge_builtin_features.c b/bridges/bridge_builtin_features.c
index b53e0db5c..f0c4c2437 100644
--- a/bridges/bridge_builtin_features.c
+++ b/bridges/bridge_builtin_features.c
@@ -140,6 +140,9 @@ static struct ast_channel *dial_transfer(struct ast_channel *caller, const char
/* Who is transferring the call. */
pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", ast_channel_name(caller));
+ /* To work as an analog to BLINDTRANSFER */
+ pbx_builtin_setvar_helper(chan, "ATTENDEDTRANSFER", ast_channel_name(caller));
+
/* Before we actually dial out let's inherit appropriate information. */
copy_caller_data(chan, caller);
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index d61494141..2e7468418 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -4375,5 +4375,13 @@ int ast_channel_forward_endpoint(struct ast_channel *chan, struct ast_endpoint *
*/
const char *ast_channel_oldest_linkedid(const char *a, const char *b);
+/*!
+ * \brief Removes the trailing identifiers from a channel name string
+ * \since 12.0.0
+ *
+ * \param channel_name string that you wish to turn into a dial string.
+ * This string will be edited in place.
+ */
+void ast_channel_name_to_dial_string(char *channel_name);
#endif /* _ASTERISK_CHANNEL_H */
diff --git a/include/asterisk/parking.h b/include/asterisk/parking.h
index c4019d9cb..dd8a67bf2 100644
--- a/include/asterisk/parking.h
+++ b/include/asterisk/parking.h
@@ -45,14 +45,14 @@ enum ast_parked_call_event_type {
*/
struct ast_parked_call_payload {
struct ast_channel_snapshot *parkee; /*!< Snapshot of the channel that is parked */
- struct ast_channel_snapshot *parker; /*!< Snapshot of the channel that parked the call */
- struct ast_channel_snapshot *retriever; /*!< Snapshot of the channel that retrieved the call */
+ struct ast_channel_snapshot *retriever; /*!< Snapshot of the channel that retrieved the call (may be NULL) */
enum ast_parked_call_event_type event_type; /*!< Reason for issuing the parked call message */
long unsigned int timeout; /*!< Time remaining before the call times out (seconds ) */
long unsigned int duration; /*!< How long the parkee has been parked (seconds) */
unsigned int parkingspace; /*!< Which Parking Space the parkee occupies */
AST_DECLARE_STRING_FIELDS(
AST_STRING_FIELD(parkinglot); /*!< Name of the parking lot used to park the parkee */
+ AST_STRING_FIELD(parker_dial_string); /*!< The device string used for call control on parking timeout */
);
};
@@ -64,7 +64,7 @@ struct ast_exten;
*
* \param event_type What kind of parked call event is happening
* \param parkee_snapshot channel snapshot of the parkee
- * \param parker_snapshot channel snapshot of the parker
+ * \param parker_dial_string dialstring used when the call times out
* \param retriever_snapshot channel snapshot of the retriever (NULL allowed)
* \param parkinglot name of the parking lot where the parked call is parked
* \param parkingspace what numerical parking space the parked call is parked in
@@ -75,7 +75,7 @@ struct ast_exten;
* \retval reference to a newly created parked call payload
*/
struct ast_parked_call_payload *ast_parked_call_payload_create(enum ast_parked_call_event_type event_type,
- struct ast_channel_snapshot *parkee_snapshot, struct ast_channel_snapshot *parker_snapshot,
+ struct ast_channel_snapshot *parkee_snapshot, const char *parker_dial_string,
struct ast_channel_snapshot *retriever_snapshot, const char *parkinglot,
unsigned int parkingspace, unsigned long int timeout, unsigned long int duration);
diff --git a/main/bridging.c b/main/bridging.c
index 110f5255b..348ce48e8 100644
--- a/main/bridging.c
+++ b/main/bridging.c
@@ -719,8 +719,9 @@ static int bridge_channel_push(struct ast_bridge_channel *bridge_channel)
bridge_channel_pull(swap);
}
- /* Clear any BLINDTRANSFER since the transfer has completed. */
+ /* Clear any BLINDTRANSFER and ATTENDEDTRANSFER since the transfer has completed. */
pbx_builtin_setvar_helper(bridge_channel->chan, "BLINDTRANSFER", NULL);
+ pbx_builtin_setvar_helper(bridge_channel->chan, "ATTENDEDTRANSFER", NULL);
bridge->reconfigured = 1;
return 0;
diff --git a/main/cel.c b/main/cel.c
index 30838f369..bc1182aa7 100644
--- a/main/cel.c
+++ b/main/cel.c
@@ -1333,7 +1333,7 @@ static void cel_parking_cb(
case PARKED_CALL:
report_event_snapshot(parked_payload->parkee, AST_CEL_PARK_START, NULL,
parked_payload->parkinglot,
- S_COR(parked_payload->parker, parked_payload->parker->name, NULL));
+ parked_payload->parker_dial_string);
break;
case PARKED_CALL_TIMEOUT:
report_event_snapshot(parked_payload->parkee, AST_CEL_PARK_END, NULL, "ParkedCallTimeOut", NULL);
diff --git a/main/channel.c b/main/channel.c
index 3bc5c0a75..ce11e50b7 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -6565,6 +6565,17 @@ const char *ast_channel_oldest_linkedid(const char *a, const char *b)
}
}
+void ast_channel_name_to_dial_string(char *channel_name)
+{
+ char *dash;
+
+ /* Truncate after the dash */
+ dash = strrchr(channel_name, '-');
+ if (dash) {
+ *dash = '\0';
+ }
+}
+
/*!
* \internal
* \brief Transfer COLP between target and transferee channels.
diff --git a/main/features.c b/main/features.c
index 577a17655..9128551d8 100644
--- a/main/features.c
+++ b/main/features.c
@@ -282,46 +282,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<para>Bridge together two channels already in the PBX.</para>
</description>
</manager>
- <managerEvent language="en_US" name="ParkedCallTimeOut">
- <managerEventInstance class="EVENT_FLAG_CALL">
- <synopsis>Raised when a parked call times out.</synopsis>
- <syntax>
- <parameter name="Exten">
- <para>The parking lot extension.</para>
- </parameter>
- <parameter name="Channel"/>
- <parameter name="Parkinglot">
- <para>The name of the parking lot.</para>
- </parameter>
- <parameter name="CallerIDNum"/>
- <parameter name="CallerIDName"/>
- <parameter name="ConnectedLineNum"/>
- <parameter name="ConnectedLineName"/>
- <parameter name="UniqueID"/>
- </syntax>
- <see-also>
- <ref type="managerEvent">ParkedCall</ref>
- </see-also>
- </managerEventInstance>
- </managerEvent>
- <managerEvent language="en_US" name="ParkedCallGiveUp">
- <managerEventInstance class="EVENT_FLAG_CALL">
- <synopsis>Raised when a parked call hangs up while in the parking lot.</synopsis>
- <syntax>
- <xi:include xpointer="xpointer(/docs/managerEvent[@name='ParkedCallTimeOut']/managerEventInstance/syntax/parameter[@name='Exten'])" />
- <parameter name="Channel"/>
- <xi:include xpointer="xpointer(/docs/managerEvent[@name='ParkedCallTimeOut']/managerEventInstance/syntax/parameter[@name='Parkinglot'])" />
- <parameter name="CallerIDNum"/>
- <parameter name="CallerIDName"/>
- <parameter name="ConnectedLineNum"/>
- <parameter name="ConnectedLineName"/>
- <parameter name="UniqueID"/>
- </syntax>
- <see-also>
- <ref type="managerEvent">ParkedCall</ref>
- </see-also>
- </managerEventInstance>
- </managerEvent>
<managerEvent language="en_US" name="Pickup">
<managerEventInstance class="EVENT_FLAG_CALL">
<synopsis>Raised when a call pickup occurs.</synopsis>
diff --git a/main/parking.c b/main/parking.c
index a3da860b7..02695cd01 100644
--- a/main/parking.c
+++ b/main/parking.c
@@ -79,13 +79,12 @@ static void parked_call_payload_destructor(void *obj)
struct ast_parked_call_payload *park_obj = obj;
ao2_cleanup(park_obj->parkee);
- ao2_cleanup(park_obj->parker);
ao2_cleanup(park_obj->retriever);
ast_string_field_free_memory(park_obj);
}
struct ast_parked_call_payload *ast_parked_call_payload_create(enum ast_parked_call_event_type event_type,
- struct ast_channel_snapshot *parkee_snapshot, struct ast_channel_snapshot *parker_snapshot,
+ struct ast_channel_snapshot *parkee_snapshot, const char *parker_dial_string,
struct ast_channel_snapshot *retriever_snapshot, const char *parkinglot,
unsigned int parkingspace, unsigned long int timeout,
unsigned long int duration)
@@ -106,11 +105,6 @@ struct ast_parked_call_payload *ast_parked_call_payload_create(enum ast_parked_c
ao2_ref(parkee_snapshot, +1);
payload->parkee = parkee_snapshot;
- if (parker_snapshot) {
- ao2_ref(parker_snapshot, +1);
- payload->parker = parker_snapshot;
- }
-
if (retriever_snapshot) {
ao2_ref(retriever_snapshot, +1);
payload->retriever = retriever_snapshot;
@@ -120,6 +114,10 @@ struct ast_parked_call_payload *ast_parked_call_payload_create(enum ast_parked_c
ast_string_field_set(payload, parkinglot, parkinglot);
}
+ if (parker_dial_string) {
+ ast_string_field_set(payload, parker_dial_string, parker_dial_string);
+ }
+
payload->parkingspace = parkingspace;
payload->timeout = timeout;
payload->duration = duration;
diff --git a/res/parking/parking_applications.c b/res/parking/parking_applications.c
index eceeaca18..f7e279766 100644
--- a/res/parking/parking_applications.c
+++ b/res/parking/parking_applications.c
@@ -284,14 +284,24 @@ static int park_app_parse_data(const char *data, int *disable_announce, int *use
return 0;
}
-static void park_common_datastore_destroy(void *data)
+void park_common_datastore_free(struct park_common_datastore *datastore)
{
- struct park_common_datastore *datastore = data;
+ if (!datastore) {
+ return;
+ }
+
ast_free(datastore->parker_uuid);
+ ast_free(datastore->parker_dial_string);
ast_free(datastore->comeback_override);
ast_free(datastore);
}
+static void park_common_datastore_destroy(void *data)
+{
+ struct park_common_datastore *datastore = data;
+ park_common_datastore_free(datastore);
+}
+
static const struct ast_datastore_info park_common_info = {
.type = "park entry data",
.destroy = park_common_datastore_destroy,
@@ -314,6 +324,9 @@ static int setup_park_common_datastore(struct ast_channel *parkee, const char *p
{
struct ast_datastore *datastore = NULL;
struct park_common_datastore *park_datastore;
+ const char *attended_transfer;
+ const char *blind_transfer;
+ char *parker_dial_string = NULL;
wipe_park_common_datastore(parkee);
@@ -326,7 +339,27 @@ static int setup_park_common_datastore(struct ast_channel *parkee, const char *p
return -1;
}
- park_datastore->parker_uuid = ast_strdup(parker_uuid);
+ if (parker_uuid) {
+ park_datastore->parker_uuid = ast_strdup(parker_uuid);
+ }
+
+ ast_channel_lock(parkee);
+
+ attended_transfer = pbx_builtin_getvar_helper(parkee, "ATTENDEDTRANSFER");
+ blind_transfer = pbx_builtin_getvar_helper(parkee, "BLINDTRANSFER");
+
+ if (attended_transfer || blind_transfer) {
+ parker_dial_string = ast_strdupa(S_OR(attended_transfer, blind_transfer));
+ }
+
+ ast_channel_unlock(parkee);
+
+ if (!ast_strlen_zero(parker_dial_string)) {
+ ast_channel_name_to_dial_string(parker_dial_string);
+ ast_verb(5, "Setting dial string to %s from %s value", parker_dial_string, attended_transfer ? "ATTENDEDTRANSFER" : "BLINDTRANSFER");
+ park_datastore->parker_dial_string = ast_strdup(parker_dial_string);
+ }
+
park_datastore->randomize = randomize;
park_datastore->time_limit = time_limit;
park_datastore->silence_announce = silence_announce;
@@ -344,16 +377,15 @@ static int setup_park_common_datastore(struct ast_channel *parkee, const char *p
return 0;
}
-void get_park_common_datastore_data(struct ast_channel *parkee, char **parker_uuid, char **comeback_override,
- int *randomize, int *time_limit, int *silence_announce)
+struct park_common_datastore *get_park_common_datastore_copy(struct ast_channel *parkee)
{
struct ast_datastore *datastore;
struct park_common_datastore *data;
+ struct park_common_datastore *data_copy;
- ast_channel_lock(parkee);
+ SCOPED_CHANNELLOCK(lock, parkee);
if (!(datastore = ast_channel_datastore_find(parkee, &park_common_info, NULL))) {
- ast_channel_unlock(parkee);
- return;
+ return NULL;
}
data = datastore->data;
@@ -363,16 +395,37 @@ void get_park_common_datastore_data(struct ast_channel *parkee, char **parker_uu
ast_assert(0);
}
- *parker_uuid = ast_strdup(data->parker_uuid);
- *randomize = data->randomize;
- *time_limit = data->time_limit;
- *silence_announce = data->silence_announce;
+ data_copy = ast_calloc(1, sizeof(*data_copy));
+ if (!data_copy) {
+ return NULL;
+ }
+
+ if (!(data_copy->parker_uuid = ast_strdup(data->parker_uuid))) {
+ park_common_datastore_free(data_copy);
+ return NULL;
+ }
+
+ data_copy->randomize = data->randomize;
+ data_copy->time_limit = data->time_limit;
+ data_copy->silence_announce = data->silence_announce;
if (data->comeback_override) {
- *comeback_override = ast_strdup(data->comeback_override);
+ data_copy->comeback_override = ast_strdup(data->comeback_override);
+ if (!data_copy->comeback_override) {
+ park_common_datastore_free(data_copy);
+ return NULL;
+ }
}
- ast_channel_unlock(parkee);
+ if (data->parker_dial_string) {
+ data_copy->parker_dial_string = ast_strdup(data->parker_dial_string);
+ if (!data_copy->parker_dial_string) {
+ park_common_datastore_free(data_copy);
+ return NULL;
+ }
+ }
+
+ return data_copy;
}
struct ast_bridge *park_common_setup(struct ast_channel *parkee, struct ast_channel *parker,
@@ -382,6 +435,10 @@ struct ast_bridge *park_common_setup(struct ast_channel *parkee, struct ast_chan
struct ast_bridge *parking_bridge;
RAII_VAR(struct parking_lot *, lot, NULL, ao2_cleanup);
+ if (!parker) {
+ parker = parkee;
+ }
+
/* If the name of the parking lot isn't specified in the arguments, find it based on the channel. */
if (ast_strlen_zero(lot_name)) {
ast_channel_lock(parker);
@@ -433,18 +490,6 @@ struct ast_bridge *park_application_setup(struct ast_channel *parkee, struct ast
}
-/* XXX BUGBUG - determining the parker when transferred to deep park priority
- * Currently all parking by the park application is treated as calls parking themselves.
- * However, it's possible for calls to be transferred here when the Park application is
- * set after the first priority of an extension. In that case, there used to be a variable
- * (BLINDTRANSFER) set indicating which channel placed that call here.
- *
- * If BLINDTRANSFER is set, this channel name will need to be referenced in Park events
- * generated by stasis. Ideally we would get a whole channel snapshot and use that for the
- * parker, but that would likely require applying the channel snapshot to a channel datastore
- * on all transfers. Alternatively just the name of the parking channel could be applied along
- * with an indication that it's dead.
- */
int park_app_exec(struct ast_channel *chan, const char *data)
{
RAII_VAR(struct ast_bridge *, parking_bridge, NULL, ao2_cleanup);
@@ -452,7 +497,7 @@ int park_app_exec(struct ast_channel *chan, const char *data)
struct ast_bridge_features chan_features;
int res;
int silence_announcements = 0;
- const char *blind_transfer;
+ const char *transferer;
/* Answer the channel if needed */
if (ast_channel_state(chan) != AST_STATE_UP) {
@@ -460,14 +505,15 @@ int park_app_exec(struct ast_channel *chan, const char *data)
}
ast_channel_lock(chan);
- if ((blind_transfer = pbx_builtin_getvar_helper(chan, "BLINDTRANSFER"))) {
- blind_transfer = ast_strdupa(blind_transfer);
+ if (!(transferer = pbx_builtin_getvar_helper(chan, "ATTENDEDTRANSFER"))) {
+ transferer = pbx_builtin_getvar_helper(chan, "BLINDTRANSFER");
}
+ transferer = ast_strdupa(S_OR(transferer, ""));
ast_channel_unlock(chan);
/* Handle the common parking setup stuff */
- if (!(parking_bridge = park_application_setup(chan, chan, data, &silence_announcements))) {
- if (!silence_announcements && !blind_transfer) {
+ if (!(parking_bridge = park_application_setup(chan, NULL, data, &silence_announcements))) {
+ if (!silence_announcements && !transferer) {
ast_stream_and_wait(chan, "pbx-parkingfailed", "");
}
return 0;
@@ -767,7 +813,7 @@ int park_and_announce_app_exec(struct ast_channel *chan, const char *data)
}
/* Handle the common parking setup stuff */
- if (!(parking_bridge = park_application_setup(chan, chan, data, &silence_announcements))) {
+ if (!(parking_bridge = park_application_setup(chan, NULL, data, &silence_announcements))) {
return 0;
}
diff --git a/res/parking/parking_bridge.c b/res/parking/parking_bridge.c
index 60d05ed59..d0566a898 100644
--- a/res/parking/parking_bridge.c
+++ b/res/parking/parking_bridge.c
@@ -66,8 +66,23 @@ static void destroy_parked_user(void *obj)
struct parked_user *pu = obj;
ao2_cleanup(pu->lot);
- ao2_cleanup(pu->parker);
ao2_cleanup(pu->retriever);
+ ast_free(pu->parker_dial_string);
+}
+
+/* Only call this on a parked user that hasn't had its parker_dial_string set already */
+static int parked_user_set_parker_dial_string(struct parked_user *pu, struct ast_channel *parker)
+{
+ char *dial_string = ast_strdupa(ast_channel_name(parker));
+
+ ast_channel_name_to_dial_string(dial_string);
+ pu->parker_dial_string = ast_strdup(dial_string);
+
+ if (!pu->parker_dial_string) {
+ return -1;
+ }
+
+ return 0;
}
/*!
@@ -78,6 +93,7 @@ static void destroy_parked_user(void *obj)
* \param lot The parking lot we are assigning the user to
* \param parkee The channel being parked
* \param parker The channel performing the park operation (may be the same channel)
+ * \param parker_dial_string Takes priority over parker for setting the parker dial string if included
* \param use_random_space if true, prioritize using a random parking space instead
* of ${PARKINGEXTEN} and/or automatic assignment from the parking lot
* \param time_limit If using a custom timeout, this should be supplied so that the
@@ -89,7 +105,7 @@ static void destroy_parked_user(void *obj)
*
* \note ao2_cleanup this reference when you are done using it or you'll cause leaks.
*/
-static struct parked_user *generate_parked_user(struct parking_lot *lot, struct ast_channel *chan, struct ast_channel *parker, int use_random_space, int time_limit)
+static struct parked_user *generate_parked_user(struct parking_lot *lot, struct ast_channel *chan, struct ast_channel *parker, const char *parker_dial_string, int use_random_space, int time_limit)
{
struct parked_user *new_parked_user;
int preferred_space = -1; /* Initialize to use parking lot defaults */
@@ -106,10 +122,6 @@ static struct parked_user *generate_parked_user(struct parking_lot *lot, struct
return NULL;
}
- ast_channel_lock(chan);
- ast_copy_string(new_parked_user->blindtransfer, S_OR(pbx_builtin_getvar_helper(chan, "BLINDTRANSFER"), ""), AST_CHANNEL_NAME);
- ast_channel_unlock(chan);
-
if (use_random_space) {
preferred_space = ast_random() % (lot->cfg->parking_stop - lot->cfg->parking_start + 1);
preferred_space += lot->cfg->parking_start;
@@ -150,8 +162,18 @@ static struct parked_user *generate_parked_user(struct parking_lot *lot, struct
new_parked_user->start = ast_tvnow();
new_parked_user->time_limit = (time_limit >= 0) ? time_limit : lot->cfg->parkingtime;
- new_parked_user->parker = ast_channel_snapshot_create(parker);
- if (!new_parked_user->parker) {
+
+ if (parker_dial_string) {
+ new_parked_user->parker_dial_string = ast_strdup(parker_dial_string);
+ } else {
+ if (parked_user_set_parker_dial_string(new_parked_user, parker)) {
+ ao2_ref(new_parked_user, -1);
+ ao2_unlock(lot);
+ return NULL;
+ }
+ }
+
+ if (!new_parked_user->parker_dial_string) {
ao2_ref(new_parked_user, -1);
ao2_unlock(lot);
return NULL;
@@ -183,13 +205,9 @@ static struct parked_user *generate_parked_user(struct parking_lot *lot, struct
static int bridge_parking_push(struct ast_bridge_parking *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
{
struct parked_user *pu;
- int randomize = 0;
- int time_limit = -1;
- int silence = 0;
const char *blind_transfer;
- RAII_VAR(struct ast_channel *, parker, NULL, ao2_cleanup);
- RAII_VAR(char *, parker_uuid, NULL, ast_free);
- RAII_VAR(char *, comeback_override, NULL, ast_free);
+ RAII_VAR(struct ast_channel *, parker, NULL, ao2_cleanup); /* XXX replace with ast_channel_cleanup when available */
+ RAII_VAR(struct park_common_datastore *, park_datastore, NULL, park_common_datastore_free);
ast_bridge_base_v_table.push(&self->base, bridge_channel, swap);
@@ -231,11 +249,14 @@ static int bridge_parking_push(struct ast_bridge_parking *self, struct ast_bridg
return 0;
}
- get_park_common_datastore_data(bridge_channel->chan, &parker_uuid, &comeback_override, &randomize, &time_limit, &silence);
- parker = ast_channel_get_by_name(parker_uuid);
+ if (!(park_datastore = get_park_common_datastore_copy(bridge_channel->chan))) {
+ /* There was either a failure to apply the datastore when performing park common setup or else we had alloc failures while cloning. Abort. */
+ return -1;
+ }
+ parker = ast_channel_get_by_name(park_datastore->parker_uuid);
/* If the parker and the parkee are the same channel pointer, then the channel entered using
- * the park application. It's possible the the blindtransfer channel is still alive (particularly
+ * the park application. It's possible that the channel that transferred it is still alive (particularly
* when a multichannel bridge is parked), so try to get the real parker if possible. */
ast_channel_lock(bridge_channel->chan);
blind_transfer = S_OR(pbx_builtin_getvar_helper(bridge_channel->chan, "BLINDTRANSFER"),
@@ -253,19 +274,17 @@ static int bridge_parking_push(struct ast_bridge_parking *self, struct ast_bridg
}
}
- if (!parker) {
- return -1;
- }
+ pu = generate_parked_user(self->lot, bridge_channel->chan, parker,
+ park_datastore->parker_dial_string, park_datastore->randomize, park_datastore->time_limit);
- pu = generate_parked_user(self->lot, bridge_channel->chan, parker, randomize, time_limit);
if (!pu) {
publish_parked_call_failure(bridge_channel->chan);
return -1;
}
/* If a comeback_override was provided, set it for the parked user's comeback string. */
- if (comeback_override) {
- strncpy(pu->comeback, comeback_override, sizeof(pu->comeback));
+ if (park_datastore->comeback_override) {
+ strncpy(pu->comeback, park_datastore->comeback_override, sizeof(pu->comeback));
pu->comeback[sizeof(pu->comeback) - 1] = '\0';
}
@@ -273,7 +292,7 @@ static int bridge_parking_push(struct ast_bridge_parking *self, struct ast_bridg
publish_parked_call(pu, PARKED_CALL);
/* If the parkee and the parker are the same and silence_announce isn't set, play the announcement to the parkee */
- if (!strcmp(blind_transfer, ast_channel_name(bridge_channel->chan)) && !silence) {
+ if (!strcmp(blind_transfer, ast_channel_name(bridge_channel->chan)) && !park_datastore->silence_announce) {
char saynum_buf[16];
snprintf(saynum_buf, sizeof(saynum_buf), "%u %u", 0, pu->parking_space);
ast_bridge_channel_queue_playfile(bridge_channel, say_parking_space, saynum_buf, NULL);
diff --git a/res/parking/parking_bridge_features.c b/res/parking/parking_bridge_features.c
index f0cf0ae44..aee4edbab 100644
--- a/res/parking/parking_bridge_features.c
+++ b/res/parking/parking_bridge_features.c
@@ -367,23 +367,6 @@ static void parking_duration_cb_destroyer(void *hook_pvt)
ao2_ref(user, -1);
}
-/*!
- * \brief Removes the identification information from a channel name string
- * \since 12.0
- *
- * \param channel name string that you wish to turn into a dial string. This will be edited in place.
- */
-static void channel_name_to_dial_string(char *peername)
-{
- char *dash;
-
- /* Truncate after the dash */
- dash = strrchr(peername, '-');
- if (dash) {
- *dash = '\0';
- }
-}
-
/*! \internal
* \brief Interval hook. Pulls a parked call from the parking bridge after the timeout is passed and sets the resolution to timeout.
*
@@ -396,8 +379,8 @@ static int parking_duration_callback(struct ast_bridge *bridge, struct ast_bridg
struct parked_user *user = hook_pvt;
struct ast_channel *chan = user->chan;
struct ast_context *park_dial_context;
- char *peername;
- char *peername_flat;
+ const char *dial_string;
+ char *dial_string_flat;
char parking_space[AST_MAX_EXTENSION];
char returnexten[AST_MAX_EXTENSION];
@@ -426,14 +409,12 @@ static int parking_duration_callback(struct ast_bridge *bridge, struct ast_bridg
pbx_builtin_setvar_helper(chan, "PARKINGSLOT", parking_space); /* Deprecated version of PARKING_SPACE */
pbx_builtin_setvar_helper(chan, "PARKEDLOT", user->lot->name);
- peername = ast_strdupa(S_OR(user->blindtransfer, user->parker->name));
- channel_name_to_dial_string(peername);
-
- peername_flat = ast_strdupa(user->parker->name);
- flatten_peername(peername_flat);
+ dial_string = user->parker_dial_string;
+ dial_string_flat = ast_strdupa(dial_string);
+ flatten_dial_string(dial_string_flat);
- pbx_builtin_setvar_helper(chan, "PARKER", peername);
- pbx_builtin_setvar_helper(chan, "PARKER_FLAT", peername_flat);
+ pbx_builtin_setvar_helper(chan, "PARKER", dial_string);
+ pbx_builtin_setvar_helper(chan, "PARKER_FLAT", dial_string_flat);
/* Dialplan generation for park-dial extensions */
@@ -462,26 +443,26 @@ static int parking_duration_callback(struct ast_bridge *bridge, struct ast_bridg
ast_assert(0);
}
- snprintf(returnexten, sizeof(returnexten), "%s,%u", peername,
+ snprintf(returnexten, sizeof(returnexten), "%s,%u", dial_string,
user->lot->cfg->comebackdialtime);
duplicate_returnexten = ast_strdup(returnexten);
if (!duplicate_returnexten) {
ast_log(LOG_ERROR, "Failed to create parking redial parker extension %s@%s - Dial(%s)\n",
- peername_flat, PARK_DIAL_CONTEXT, returnexten);
+ dial_string_flat, PARK_DIAL_CONTEXT, returnexten);
}
/* If an extension already exists here because we registered it for another parked call timing out, then we may overwrite it. */
- if ((existing_exten = pbx_find_extension(NULL, NULL, &pbx_finder, PARK_DIAL_CONTEXT, peername_flat, 1, NULL, NULL, E_MATCH)) &&
+ if ((existing_exten = pbx_find_extension(NULL, NULL, &pbx_finder, PARK_DIAL_CONTEXT, dial_string_flat, 1, NULL, NULL, E_MATCH)) &&
(strcmp(ast_get_extension_registrar(existing_exten), BASE_REGISTRAR))) {
ast_debug(3, "An extension for '%s@%s' was already registered by another registrar '%s'\n",
- peername_flat, PARK_DIAL_CONTEXT, ast_get_extension_registrar(existing_exten));
- } else if (ast_add_extension2_nolock(park_dial_context, 1, peername_flat, 1, NULL, NULL,
+ dial_string_flat, PARK_DIAL_CONTEXT, ast_get_extension_registrar(existing_exten));
+ } else if (ast_add_extension2_nolock(park_dial_context, 1, dial_string_flat, 1, NULL, NULL,
"Dial", duplicate_returnexten, ast_free_ptr, BASE_REGISTRAR)) {
ast_free(duplicate_returnexten);
ast_log(LOG_ERROR, "Failed to create parking redial parker extension %s@%s - Dial(%s)\n",
- peername_flat, PARK_DIAL_CONTEXT, returnexten);
+ dial_string_flat, PARK_DIAL_CONTEXT, returnexten);
}
if (ast_unlock_context(park_dial_context)) {
diff --git a/res/parking/parking_controller.c b/res/parking/parking_controller.c
index 2764f50d4..aa2baf5cc 100644
--- a/res/parking/parking_controller.c
+++ b/res/parking/parking_controller.c
@@ -220,22 +220,14 @@ void parked_call_retrieve_enable_features(struct ast_channel *chan, struct parki
return;
}
-void flatten_peername(char *peername)
+void flatten_dial_string(char *dialstring)
{
int i;
- char *dash;
- /* Truncate after the dash */
- dash = strrchr(peername, '-');
- if (dash) {
- *dash = '\0';
- }
-
- /* Replace slashes with underscores since slashes are reserved characters for extension matching */
- for (i = 0; peername[i]; i++) {
- if (peername[i] == '/') {
+ for (i = 0; dialstring[i]; i++) {
+ if (dialstring[i] == '/') {
/* The underscore is the flattest character of all. */
- peername[i] = '_';
+ dialstring[i] = '_';
}
}
}
@@ -243,39 +235,37 @@ void flatten_peername(char *peername)
int comeback_goto(struct parked_user *pu, struct parking_lot *lot)
{
struct ast_channel *chan = pu->chan;
- char *peername;
-
- peername = ast_strdupa(S_OR(pu->blindtransfer, pu->parker->name));
+ char *peername_flat = ast_strdupa(pu->parker_dial_string);
/* Flatten the peername so that it can be used for performing the timeout PBX operations */
- flatten_peername(peername);
+ flatten_dial_string(peername_flat);
if (lot->cfg->comebacktoorigin) {
- if (ast_exists_extension(chan, PARK_DIAL_CONTEXT, peername, 1, NULL)) {
- ast_async_goto(chan, PARK_DIAL_CONTEXT, peername, 1);
+ if (ast_exists_extension(chan, PARK_DIAL_CONTEXT, peername_flat, 1, NULL)) {
+ ast_async_goto(chan, PARK_DIAL_CONTEXT, peername_flat, 1);
return 0;
} else {
ast_log(LOG_ERROR, "Can not start %s at %s,%s,1 because extension does not exist. Terminating call.\n",
- ast_channel_name(chan), PARK_DIAL_CONTEXT, peername);
+ ast_channel_name(chan), PARK_DIAL_CONTEXT, peername_flat);
return -1;
}
}
- if (ast_exists_extension(chan, lot->cfg->comebackcontext, peername, 1, NULL)) {
- ast_async_goto(chan, lot->cfg->comebackcontext, peername, 1);
+ if (ast_exists_extension(chan, lot->cfg->comebackcontext, peername_flat, 1, NULL)) {
+ ast_async_goto(chan, lot->cfg->comebackcontext, peername_flat, 1);
return 0;
}
if (ast_exists_extension(chan, lot->cfg->comebackcontext, "s", 1, NULL)) {
ast_verb(2, "Could not start %s at %s,%s,1. Using 's@%s' instead.\n", ast_channel_name(chan),
- lot->cfg->comebackcontext, peername, lot->cfg->comebackcontext);
+ lot->cfg->comebackcontext, peername_flat, lot->cfg->comebackcontext);
ast_async_goto(chan, lot->cfg->comebackcontext, "s", 1);
return 0;
}
ast_verb(2, "Can not start %s at %s,%s,1 and exten 's@%s' does not exist. Using 's@default'\n",
ast_channel_name(chan),
- lot->cfg->comebackcontext, peername, lot->cfg->comebackcontext);
+ lot->cfg->comebackcontext, peername_flat, lot->cfg->comebackcontext);
ast_async_goto(chan, "default", "s", 1);
return 0;
diff --git a/res/parking/parking_manager.c b/res/parking/parking_manager.c
index 5a2b3f6fd..b26f90e35 100644
--- a/res/parking/parking_manager.c
+++ b/res/parking/parking_manager.c
@@ -134,43 +134,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
</parameter>
<parameter name="ParkeeUniqueid">
</parameter>
- <parameter name="ParkerChannel">
- </parameter>
- <parameter name="ParkerChannelState">
- <para>A numeric code for the channel's current state, related to ChannelStateDesc</para>
- </parameter>
- <parameter name="ParkerChannelStateDesc">
- <enumlist>
- <enum name="Down"/>
- <enum name="Rsrvd"/>
- <enum name="OffHook"/>
- <enum name="Dialing"/>
- <enum name="Ring"/>
- <enum name="Ringing"/>
- <enum name="Up"/>
- <enum name="Busy"/>
- <enum name="Dialing Offhook"/>
- <enum name="Pre-ring"/>
- <enum name="Unknown"/>
- </enumlist>
- </parameter>
- <parameter name="ParkerCallerIDNum">
- </parameter>
- <parameter name="ParkerCallerIDName">
- </parameter>
- <parameter name="ParkerConnectedLineNum">
- </parameter>
- <parameter name="ParkerConnectedLineName">
- </parameter>
- <parameter name="ParkerAccountCode">
- </parameter>
- <parameter name="ParkerContext">
- </parameter>
- <parameter name="ParkerExten">
- </parameter>
- <parameter name="ParkerPriority">
- </parameter>
- <parameter name="ParkerUniqueid">
+ <parameter name="ParkerDialString">
+ <para>Dial String that can be used to call back the parker on ParkingTimeout.</para>
</parameter>
<parameter name="Parkinglot">
<para>Name of the parking lot that the parkee is parked in</para>
@@ -276,10 +241,6 @@ static struct ast_parked_call_payload *parked_call_payload_from_parked_user(stru
struct timeval now = ast_tvnow();
const char *lot_name = pu->lot->name;
- if (!pu->parker) {
- return NULL;
- }
-
parkee_snapshot = ast_channel_snapshot_create(pu->chan);
if (!parkee_snapshot) {
@@ -289,7 +250,7 @@ static struct ast_parked_call_payload *parked_call_payload_from_parked_user(stru
timeout = pu->start.tv_sec + (long) pu->time_limit - now.tv_sec;
duration = now.tv_sec - pu->start.tv_sec;
- return ast_parked_call_payload_create(event_type, parkee_snapshot, pu->parker, pu->retriever, lot_name, pu->parking_space, timeout, duration);
+ return ast_parked_call_payload_create(event_type, parkee_snapshot, pu->parker_dial_string, pu->retriever, lot_name, pu->parking_space, timeout, duration);
}
@@ -298,7 +259,6 @@ static struct ast_str *manager_build_parked_call_string(const struct ast_parked_
{
struct ast_str *out = ast_str_create(1024);
RAII_VAR(struct ast_str *, parkee_string, NULL, ast_free);
- RAII_VAR(struct ast_str *, parker_string, NULL, ast_free);
RAII_VAR(struct ast_str *, retriever_string, NULL, ast_free);
if (!out) {
@@ -307,26 +267,22 @@ static struct ast_str *manager_build_parked_call_string(const struct ast_parked_
parkee_string = ast_manager_build_channel_state_string_prefix(payload->parkee, "Parkee");
- if (payload->parker) {
- parker_string = ast_manager_build_channel_state_string_prefix(payload->parker, "Parker");
- }
-
if (payload->retriever) {
retriever_string = ast_manager_build_channel_state_string_prefix(payload->retriever, "Retriever");
}
ast_str_set(&out, 0,
"%s" /* parkee channel state */
- "%s" /* parker channel state */
"%s" /* retriever channel state (when available) */
+ "ParkerDialString: %s\r\n"
"Parkinglot: %s\r\n"
"ParkingSpace: %u\r\n"
"ParkingTimeout: %lu\r\n"
"ParkingDuration: %lu\r\n",
ast_str_buffer(parkee_string),
- parker_string ? ast_str_buffer(parker_string) : "",
retriever_string ? ast_str_buffer(retriever_string) : "",
+ payload->parker_dial_string,
payload->parkinglot,
payload->parkingspace,
payload->timeout,
diff --git a/res/parking/parking_ui.c b/res/parking/parking_ui.c
index f3eeafa4c..2f54e8637 100644
--- a/res/parking/parking_ui.c
+++ b/res/parking/parking_ui.c
@@ -40,9 +40,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
static void display_parked_call(struct parked_user *user, int fd)
{
- ast_cli(fd, " Space: %d\n", user->parking_space);
- ast_cli(fd, " Channel: %s\n", ast_channel_name(user->chan));
- ast_cli(fd, " Parker: %s\n", user->parker ? user->parker->name : "<unknown>");
+ ast_cli(fd, " Space : %d\n", user->parking_space);
+ ast_cli(fd, " Channel : %s\n", ast_channel_name(user->chan));
+ ast_cli(fd, " Parker Dial String : %s\n", user->parker_dial_string);
ast_cli(fd, "\n");
}
diff --git a/res/parking/res_parking.h b/res/parking/res_parking.h
index 2955f87e1..b128ee335 100644
--- a/res/parking/res_parking.h
+++ b/res/parking/res_parking.h
@@ -100,12 +100,11 @@ struct parking_lot {
struct parked_user {
struct ast_channel *chan; /*!< Parked channel */
- struct ast_channel_snapshot *parker; /*!< Snapshot of the channel that parked the call at the time of parking */
struct ast_channel_snapshot *retriever; /*!< Snapshot of the channel that retrieves a parked call */
struct timeval start; /*!< When the call was parked */
int parking_space; /*!< Which parking space is used */
char comeback[AST_MAX_CONTEXT]; /*!< Where to go on parking timeout */
- char blindtransfer[AST_CHANNEL_NAME]; /*!< What the BLINDTRANSFER variable was at the time of entry */
+ char *parker_dial_string; /*!< dialstring to call back with comebacktoorigin. Used timeout extension generation and call control */
unsigned int time_limit; /*!< How long this specific channel may remain in the parking lot before timing out */
struct parking_lot *lot; /*!< Which parking lot the user is parked to */
enum park_call_resolution resolution; /*!< How did the parking session end? If the call is in a bridge, lock parked_user before checking/setting */
@@ -285,11 +284,11 @@ const char *find_channel_parking_lot_name(struct ast_channel *chan);
/*!
* \since 12.0.0
- * \brief Flattens a peer name so that it can be written to/found from PBX extensions
+ * \brief Flattens a dial string so that it can be written to/found from PBX extensions
*
- * \param peername unflattened peer name. This will be flattened in place, so expect it to change.
+ * \param peername unflattened dial string. This will be flattened in place.
*/
-void flatten_peername(char *peername);
+void flatten_dial_string(char *dialstring);
/*!
* \since 12.0.0
@@ -370,7 +369,7 @@ struct ast_bridge *park_common_setup(struct ast_channel *parkee, struct ast_chan
* channel.
*
* \param parkee The channel being preparred for parking
- * \param parker The channel initiating the park; may be the parkee as well
+ * \param parker The channel initiating the park; may be the parkee as well. May be NULL.
* \param app_data arguments supplied to the Park application. May be NULL.
* \param silence_announcements optional pointer to an integer where we want to store the silence option flag
* this value should be initialized to 0 prior to calling park_common_setup.
@@ -385,6 +384,7 @@ struct ast_bridge *park_application_setup(struct ast_channel *parkee, struct ast
struct park_common_datastore {
char *parker_uuid; /*!< Unique ID of the channel parking the call. */
+ char *parker_dial_string; /*!< Dial string that we would attempt to call when timing out when comebacktoorigin=yes */
char *comeback_override; /*!< Optional goto string for where to send the call after we are done */
int randomize; /*!< Pick a parking space to enter on at random */
int time_limit; /*!< time limit override. -1 values don't override, 0 for unlimited time, >0 for custom time limit in seconds */
@@ -393,19 +393,22 @@ struct park_common_datastore {
/*!
* \since 12.0.0
- * \brief Function that pulls data from the park common datastore on a channel in order to apply it to
- * the parked user struct upon bridging.
+ * \brief Get a copy of the park_common_datastore from a channel that is being parked
*
* \param parkee The channel entering parking with the datastore we are checking
- * \param parker_uuid pointer to a string pointer for placing the name of the channel that parked parkee
- * \param comeback_override pointer to a string pointer for placing the comeback_override option
- * \param randomize integer pointer to an integer for placing the randomize option
- * \param time_limit integer pointer to an integer for placing the time limit option
- * \param silence_announce pointer to an integer for placing the silence_announcements option
- */
-void get_park_common_datastore_data(struct ast_channel *parkee,
- char **parker_uuid, char **comeback_override,
- int *randomize, int *time_limit, int *silence_announce);
+ *
+ * \retval Pointer to a copy of the park common datastore for parkee if it could be cloned. This needs to be free'd with park_common_datastore free.
+ * \retval NULL if the park_common_datastore could not be copied off of the channel.
+ */
+struct park_common_datastore *get_park_common_datastore_copy(struct ast_channel *parkee);
+
+/*!
+ * \since 12.0.0
+ * \brief Free a park common datastore struct
+ *
+ * \param datastore The park_common_datastore being free'd. (NULL tolerant)
+ */
+void park_common_datastore_free(struct park_common_datastore *datastore);
/*!
* \since 12.0.0