From: Jonathan Rose Date: Thu, 4 Jul 2013 18:46:56 +0000 (+0000) Subject: res_parking: Replace Parker snapshots with ParkerDialString X-Git-Tag: 13.0.0-beta1~1545 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=93ed5ef0ffdffc342ef2e0670b9cf51686027401;p=thirdparty%2Fasterisk.git res_parking: Replace Parker snapshots with ParkerDialString This process also involved a large amount of rework regarding how to redial the Parker when a channel leaves a parking lot due to timeout. An attended transfer channel variable has been added to attended transfers to extensions that will eventually park (but haven't at the time of transfer) as well. This resolves one of the two BUGBUG comments remaining in res_parking. (issues ASTERISK-21877) Reported by: Matt Jordan Review: https://reviewboard.asterisk.org/r/2638/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393704 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- diff --git a/CHANGES b/CHANGES index e6da22224e..3223822ba6 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 7a5261b94d..bcb2de4db1 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 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 b53e0db5c5..f0c4c24379 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 d61494141d..2e74684183 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 c4019d9cb6..dd8a67bf28 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 110f5255b1..348ce48e82 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 30838f369e..bc1182aa74 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 3bc5c0a75c..ce11e50b75 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 577a176550..9128551d88 100644 --- a/main/features.c +++ b/main/features.c @@ -282,46 +282,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") Bridge together two channels already in the PBX. - - - Raised when a parked call times out. - - - The parking lot extension. - - - - The name of the parking lot. - - - - - - - - - ParkedCall - - - - - - Raised when a parked call hangs up while in the parking lot. - - - - - - - - - - - - ParkedCall - - - Raised when a call pickup occurs. diff --git a/main/parking.c b/main/parking.c index a3da860b73..02695cd01c 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 eceeaca18a..f7e2797661 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 60d05ed59d..d0566a8984 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 f0cf0ae448..aee4edbab2 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 2764f50d4f..aa2baf5cce 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 5a2b3f6fdf..b26f90e359 100644 --- a/res/parking/parking_manager.c +++ b/res/parking/parking_manager.c @@ -134,43 +134,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") - - - - A numeric code for the channel's current state, related to ChannelStateDesc - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + Dial String that can be used to call back the parker on ParkingTimeout. Name of the parking lot that the parkee is parked in @@ -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 f3eeafa4c6..2f54e8637e 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 : ""); + 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 2955f87e1d..b128ee3358 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