Asterisk - The Open Source Telephony Project GIT-master-f36a736
Data Structures | Macros | Enumerations | Functions
res_parking.h File Reference

Call Parking Resource Internal API. More...

#include "asterisk/pbx.h"
#include "asterisk/bridge.h"
#include "asterisk/parking.h"
#include "asterisk/stasis_channels.h"
Include dependency graph for res_parking.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  park_common_datastore
 
struct  parked_user
 
struct  parking_lot
 
struct  parking_lot_cfg
 

Macros

#define BASE_REGISTRAR   "res_parking"
 
#define DEFAULT_PARKING_EXTEN   "700"
 
#define DEFAULT_PARKING_LOT   "default"
 
#define PARK_DIAL_CONTEXT   "park-dial"
 
#define PARKED_CALL_APPLICATION   "ParkedCall"
 

Enumerations

enum  park_call_resolution {
  PARK_UNSET = 0 , PARK_ABANDON , PARK_TIMEOUT , PARK_FORCED ,
  PARK_ANSWERED
}
 
enum  parked_call_feature_options {
  OPT_PARKEDPLAY = 0 , OPT_PARKEDTRANSFERS , OPT_PARKEDREPARKING , OPT_PARKEDHANGUP ,
  OPT_PARKEDRECORDING
}
 
enum  parking_lot_modes { PARKINGLOT_NORMAL = 0 , PARKINGLOT_DYNAMIC , PARKINGLOT_DISABLED }
 

Functions

struct ast_bridgebridge_parking_new (struct parking_lot *bridge_lot)
 Create a new parking bridge. More...
 
int comeback_goto (struct parked_user *pu, struct parking_lot *lot)
 Set a channel's position in the PBX after timeout using the parking lot settings. More...
 
int create_parked_subscription (struct ast_channel *chan, const char *parkee_uuid, int hangup_after)
 Create a parking announcement subscription. More...
 
const char * find_channel_parking_lot_name (struct ast_channel *chan)
 Find parking lot name from channel. More...
 
void flatten_dial_string (char *dialstring)
 Flattens a dial string so that it can be written to/found from PBX extensions. More...
 
struct park_common_datastoreget_park_common_datastore_copy (struct ast_channel *parkee)
 Get a copy of the park_common_datastore from a channel that is being parked. More...
 
struct ao2_containerget_parking_lot_container (void)
 Get a pointer to the parking lot container for purposes such as iteration. More...
 
int load_parking_applications (void)
 Register parking applications. More...
 
int load_parking_bridge_features (void)
 Register bridge features for parking. More...
 
int load_parking_devstate (void)
 Register Parking devstate handler. More...
 
int load_parking_manager (void)
 Register manager actions and setup subscriptions for stasis events. More...
 
int load_parking_tests (void)
 Register parking unit tests. More...
 
int load_parking_ui (void)
 Register CLI commands. More...
 
struct ast_bridgepark_application_setup (struct ast_channel *parkee, struct ast_channel *parker, const char *app_data, int *silence_announcements)
 Function to prepare a channel for parking by determining which parking bridge should be used, setting up a park common datastore so that the parking bridge will have access to necessary parking information when joining, and applying various bridge roles to the channel. More...
 
void park_common_datastore_free (struct park_common_datastore *datastore)
 Free a park common datastore struct. More...
 
struct ast_bridgepark_common_setup (struct ast_channel *parkee, struct ast_channel *parker, const char *lot_name, const char *comeback_override, int use_ringing, int randomize, int time_limit, int silence_announcements)
 Setup a parked call on a parking bridge without needing to parse appdata. More...
 
void parked_call_retrieve_enable_features (struct ast_channel *chan, struct parking_lot *lot, int recipient_mode)
 Apply features based on the parking lot feature options. More...
 
int parking_channel_set_roles (struct ast_channel *chan, struct parking_lot *lot, int force_ringing)
 Set necessary bridge roles on a channel that is about to enter a parking lot. More...
 
struct parking_lotparking_create_dynamic_lot (const char *name, struct ast_channel *chan)
 Create a dynamic parking lot. More...
 
int parking_dynamic_lots_enabled (void)
 Check global configuration to see if dynamic parking is enabled. More...
 
struct parking_lotparking_lot_build_or_update (struct parking_lot_cfg *cfg, int dynamic)
 If a parking lot exists in the parking lot list already, update its status to match the provided configuration and return a reference return a reference to it. Otherwise, create a parking lot struct based on a parking lot configuration and return a reference to the new one. More...
 
int parking_lot_cfg_create_extensions (struct parking_lot_cfg *lot_cfg)
 Add extensions for a parking lot configuration. More...
 
void parking_lot_cfg_remove_extensions (struct parking_lot_cfg *lot_cfg)
 Remove extensions belonging to a parking lot configuration. More...
 
struct parking_lotparking_lot_find_by_name (const char *lot_name)
 Find a parking lot based on its name. More...
 
struct ast_bridgeparking_lot_get_bridge (struct parking_lot *lot)
 Get a reference to a parking lot's bridge. If it doesn't exist, create it and get a reference. More...
 
int parking_lot_get_space (struct parking_lot *lot, int target_override)
 Get an available parking space within a parking lot. More...
 
struct parked_userparking_lot_inspect_parked_user (struct parking_lot *lot, int target)
 Determine if there is a parked user in a parking space and return it if there is. More...
 
int parking_lot_remove_if_unused (struct parking_lot *lot)
 Remove a parking lot from the usable lists if it is no longer involved in any calls and no configuration currently claims it. More...
 
struct parked_userparking_lot_retrieve_parked_user (struct parking_lot *lot, int target)
 Determine if there is a parked user in a parking space and pull it from the parking lot if there is. More...
 
void parking_notify_metermaids (int exten, const char *context, enum ast_device_state state)
 Notify metermaids that we've changed an extension. More...
 
void parking_set_duration (struct ast_bridge_features *features, struct parked_user *user)
 Setup timeout interval feature on an ast_bridge_features for parking. More...
 
void publish_parked_call (struct parked_user *pu, enum ast_parked_call_event_type event_type)
 Publish a stasis parked call message for a given parked user. More...
 
void publish_parked_call_failure (struct ast_channel *parkee)
 Publish a stasis parked call message for the channel indicating failure to park. More...
 
void say_parking_space (struct ast_bridge_channel *bridge_channel, const char *payload)
 custom callback function for ast_bridge_channel_queue_playfile which plays a parking space and optionally hangs up the call afterwards based on the payload in playfile. More...
 
void unload_parking_applications (void)
 Unregister parking applications. More...
 
void unload_parking_bridge_features (void)
 Unregister features registered by load_parking_bridge_features. More...
 
void unload_parking_devstate (void)
 Unregister Parking devstate handler. More...
 
void unload_parking_manager (void)
 Unregister manager actions and remove subscriptions for stasis events. More...
 
void unload_parking_tests (void)
 Unregister parking unit tests. More...
 
void unload_parking_ui (void)
 Unregister CLI commands. More...
 
int unpark_parked_user (struct parked_user *user)
 Pull a parked user out of its parking lot. Use this when you don't want to use the parked user afterwards. More...
 

Detailed Description

Call Parking Resource Internal API.

Author
Jonathan Rose jrose.nosp@m.@dig.nosp@m.ium.c.nosp@m.om

Definition in file res_parking.h.

Macro Definition Documentation

◆ BASE_REGISTRAR

#define BASE_REGISTRAR   "res_parking"

Definition at line 36 of file res_parking.h.

◆ DEFAULT_PARKING_EXTEN

#define DEFAULT_PARKING_EXTEN   "700"

Definition at line 35 of file res_parking.h.

◆ DEFAULT_PARKING_LOT

#define DEFAULT_PARKING_LOT   "default"

Definition at line 34 of file res_parking.h.

◆ PARK_DIAL_CONTEXT

#define PARK_DIAL_CONTEXT   "park-dial"

Definition at line 37 of file res_parking.h.

◆ PARKED_CALL_APPLICATION

#define PARKED_CALL_APPLICATION   "ParkedCall"

Definition at line 38 of file res_parking.h.

Enumeration Type Documentation

◆ park_call_resolution

Enumerator
PARK_UNSET 
PARK_ABANDON 

Nothing set a resolution. This should never be observed in practice.

PARK_TIMEOUT 

The channel for the parked call hung up

PARK_FORCED 

The parked call stayed parked until the parking lot timeout was reached and was removed

PARK_ANSWERED 

The parked call was forcibly terminated by an unusual means in Asterisk

Definition at line 40 of file res_parking.h.

40 {
41 PARK_UNSET = 0, /*! Nothing set a resolution. This should never be observed in practice. */
42 PARK_ABANDON, /*! The channel for the parked call hung up */
43 PARK_TIMEOUT, /*! The parked call stayed parked until the parking lot timeout was reached and was removed */
44 PARK_FORCED, /*! The parked call was forcibly terminated by an unusual means in Asterisk */
45 PARK_ANSWERED, /*! The parked call was retrieved successfully */
46};
@ PARK_ANSWERED
Definition: res_parking.h:45
@ PARK_TIMEOUT
Definition: res_parking.h:43
@ PARK_FORCED
Definition: res_parking.h:44
@ PARK_UNSET
Definition: res_parking.h:41
@ PARK_ABANDON
Definition: res_parking.h:42

◆ parked_call_feature_options

Enumerator
OPT_PARKEDPLAY 
OPT_PARKEDTRANSFERS 
OPT_PARKEDREPARKING 
OPT_PARKEDHANGUP 
OPT_PARKEDRECORDING 

Definition at line 48 of file res_parking.h.

48 {
54};
@ OPT_PARKEDREPARKING
Definition: res_parking.h:51
@ OPT_PARKEDTRANSFERS
Definition: res_parking.h:50
@ OPT_PARKEDPLAY
Definition: res_parking.h:49
@ OPT_PARKEDRECORDING
Definition: res_parking.h:53
@ OPT_PARKEDHANGUP
Definition: res_parking.h:52

◆ parking_lot_modes

Enumerator
PARKINGLOT_NORMAL 
PARKINGLOT_DYNAMIC 

The parking lot is configured normally and can accept new calls. Disable on reload if the config isn't replaced. valid transitions: PARKINGLOT_DISABLED

PARKINGLOT_DISABLED 

The parking lot is a dynamically created parking lot. It can be parked to at any time. Disabled on last parked call leaving. valid transitions: PARKINGLOT_DISABLED

Definition at line 56 of file res_parking.h.

56 {
57 PARKINGLOT_NORMAL = 0, /*! The parking lot is configured normally and can accept new calls. Disable on reload if the config isn't replaced.
58 * valid transitions: PARKINGLOT_DISABLED */
59 PARKINGLOT_DYNAMIC, /*! The parking lot is a dynamically created parking lot. It can be parked to at any time. Disabled on last parked call leaving.
60 * valid transitions: PARKINGLOT_DISABLED */
61 PARKINGLOT_DISABLED, /*! The parking lot is no longer linked to a parking lot in configuration. It can no longer be parked to.
62 * and it can not be parked to. This mode has no transitions. */
63};
@ PARKINGLOT_DISABLED
Definition: res_parking.h:61
@ PARKINGLOT_NORMAL
Definition: res_parking.h:57
@ PARKINGLOT_DYNAMIC
Definition: res_parking.h:59

Function Documentation

◆ bridge_parking_new()

struct ast_bridge * bridge_parking_new ( struct parking_lot bridge_lot)

Create a new parking bridge.

Since
12.0.0
Parameters
bridge_lotParking lot which the new bridge should be based on
Return values
NULLif the bridge can not be created
Returns
Newly created parking bridge

Definition at line 450 of file parking_bridge.c.

451{
452 void *bridge;
453
457 | AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM, "Parking", bridge_lot->name, NULL);
458 bridge = ast_bridge_parking_init(bridge, bridge_lot);
459 bridge = bridge_register(bridge);
460 return bridge;
461}
@ AST_BRIDGE_CAPABILITY_HOLDING
Definition: bridge.h:86
@ AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM
@ AST_BRIDGE_FLAG_MERGE_INHIBIT_TO
@ AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM
struct ast_bridge * bridge_register(struct ast_bridge *bridge)
Register the new bridge with the system.
Definition: bridge.c:691
struct ast_bridge * bridge_base_init(struct ast_bridge *self, uint32_t capabilities, unsigned int flags, const char *creator, const char *name, const char *id)
Initialize the base class of the bridge.
Definition: bridge.c:742
struct ast_bridge * bridge_alloc(size_t size, const struct ast_bridge_methods *v_table)
Definition: bridge.c:706
struct ast_bridge_methods ast_bridge_parking_v_table
static struct ast_bridge * ast_bridge_parking_init(struct ast_bridge_parking *self, struct parking_lot *bridge_lot)
#define NULL
Definition: resample.c:96
const ast_string_field name
Definition: res_parking.h:102

References AST_BRIDGE_CAPABILITY_HOLDING, AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM, AST_BRIDGE_FLAG_MERGE_INHIBIT_TO, AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM, ast_bridge_parking_init(), ast_bridge_parking_v_table, bridge_alloc(), bridge_base_init(), bridge_register(), parking_lot::name, and NULL.

Referenced by parking_lot_get_bridge().

◆ comeback_goto()

int comeback_goto ( struct parked_user pu,
struct parking_lot lot 
)

Set a channel's position in the PBX after timeout using the parking lot settings.

Since
12.0.0
Parameters
puParked user who is entering/reentering the PBX
lotParking lot the user was removed from.
Return values
0Position set successfully
-1Failed to set the position

Definition at line 263 of file parking_controller.c.

264{
265 struct ast_channel *chan = pu->chan;
266 char *peername_flat = ast_strdupa(pu->parker_dial_string);
267
268 /* Flatten the peername so that it can be used for performing the timeout PBX operations */
269 flatten_dial_string(peername_flat);
270
271 if (lot->cfg->comebacktoorigin) {
272 if (ast_exists_extension(chan, PARK_DIAL_CONTEXT, peername_flat, 1, NULL)) {
273 ast_async_goto(chan, PARK_DIAL_CONTEXT, peername_flat, 1);
274 return 0;
275 } else {
276 ast_log(LOG_ERROR, "Can not start %s at %s,%s,1 because extension does not exist. Terminating call.\n",
277 ast_channel_name(chan), PARK_DIAL_CONTEXT, peername_flat);
278 return -1;
279 }
280 }
281
282 if (ast_exists_extension(chan, lot->cfg->comebackcontext, peername_flat, 1, NULL)) {
283 ast_async_goto(chan, lot->cfg->comebackcontext, peername_flat, 1);
284 return 0;
285 }
286
287 if (ast_exists_extension(chan, lot->cfg->comebackcontext, "s", 1, NULL)) {
288 ast_verb(2, "Could not start %s at %s,%s,1. Using 's@%s' instead.\n", ast_channel_name(chan),
289 lot->cfg->comebackcontext, peername_flat, lot->cfg->comebackcontext);
290 ast_async_goto(chan, lot->cfg->comebackcontext, "s", 1);
291 return 0;
292 }
293
294 ast_verb(2, "Can not start %s at %s,%s,1 and exten 's@%s' does not exist. Using 's@default'\n",
295 ast_channel_name(chan),
296 lot->cfg->comebackcontext, peername_flat, lot->cfg->comebackcontext);
297 ast_async_goto(chan, "default", "s", 1);
298
299 return 0;
300}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_log
Definition: astobj2.c:42
const char * ast_channel_name(const struct ast_channel *chan)
#define LOG_ERROR
#define ast_verb(level,...)
void flatten_dial_string(char *dialstring)
Flattens a dial string so that it can be written to/found from PBX extensions.
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:4175
int ast_async_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Set the channel to next execute the specified dialplan location.
Definition: pbx.c:6969
#define PARK_DIAL_CONTEXT
Definition: res_parking.h:37
Main Channel structure associated with a channel.
char * parker_dial_string
Definition: res_parking.h:111
struct ast_channel * chan
Definition: res_parking.h:106
unsigned int comebacktoorigin
Definition: res_parking.h:74
const ast_string_field comebackcontext
Definition: res_parking.h:89
struct parking_lot_cfg * cfg
Definition: res_parking.h:96

References ast_async_goto(), ast_channel_name(), ast_exists_extension(), ast_log, ast_strdupa, ast_verb, parking_lot::cfg, parked_user::chan, parking_lot_cfg::comebackcontext, parking_lot_cfg::comebacktoorigin, flatten_dial_string(), LOG_ERROR, NULL, PARK_DIAL_CONTEXT, and parked_user::parker_dial_string.

Referenced by parking_duration_callback().

◆ create_parked_subscription()

int create_parked_subscription ( struct ast_channel chan,
const char *  parkee_uuid,
int  hangup_after 
)

Create a parking announcement subscription.

Since
12.3.0
Parameters
chanChannel that will receive the announcement
parkee_uuidUnique ID of the channel being parked
hangup_afterif non-zero, have the channel hangup after hearing the announcement
Return values
0on success
-1on failure

Definition at line 233 of file parking_bridge_features.c.

234{
235 return create_parked_subscription_full(chan, parkee_uuid, hangup_after, NULL);
236}
static int create_parked_subscription_full(struct ast_channel *chan, const char *parkee_uuid, int hangup_after, struct transfer_channel_data *parked_channel_data)

References create_parked_subscription_full(), parked_subscription_data::hangup_after, NULL, and parked_subscription_data::parkee_uuid.

Referenced by manager_park(), and manager_park_bridged().

◆ find_channel_parking_lot_name()

const char * find_channel_parking_lot_name ( struct ast_channel chan)

Find parking lot name from channel.

Since
12.0.0
Parameters
chanThe channel we want the parking lot name for
Returns
name of the parking lot to use for the channel.
Note
Always returns a parking lot name.
Channel needs to be locked while the returned string is in use.

Definition at line 608 of file res_parking.c.

609{
610 const char *name;
611
612 /* The channel variable overrides everything */
613 name = pbx_builtin_getvar_helper(chan, "PARKINGLOT");
614 if (ast_strlen_zero(name)) {
615 /* Try the channel's parking lot. */
617 if (ast_strlen_zero(name)) {
618 /* Fall back to the default parking lot. */
620 }
621 }
622
623 return name;
624}
const char * ast_channel_parkinglot(const struct ast_channel *chan)
static const char name[]
Definition: format_mp3.c:68
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
#define DEFAULT_PARKING_LOT
Definition: res_parking.h:34
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65

References ast_channel_parkinglot(), ast_strlen_zero(), DEFAULT_PARKING_LOT, name, and pbx_builtin_getvar_helper().

Referenced by park_common_setup2(), parked_call_app_exec(), and parking_park_call().

◆ flatten_dial_string()

void flatten_dial_string ( char *  dialstring)

Flattens a dial string so that it can be written to/found from PBX extensions.

Since
12.0.0
Parameters
dialstringunflattened dial string. This will be flattened in place.

Definition at line 251 of file parking_controller.c.

252{
253 int i;
254
255 for (i = 0; dialstring[i]; i++) {
256 if (dialstring[i] == '/') {
257 /* The underscore is the flattest character of all. */
258 dialstring[i] = '_';
259 }
260 }
261}

Referenced by comeback_goto(), and parking_duration_callback().

◆ get_park_common_datastore_copy()

struct park_common_datastore * get_park_common_datastore_copy ( struct ast_channel parkee)

Get a copy of the park_common_datastore from a channel that is being parked.

Since
12.0.0
Parameters
parkeeThe channel entering parking with the datastore we are checking
Returns
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.
Return values
NULLif the park_common_datastore could not be copied off of the channel.

Definition at line 441 of file parking_applications.c.

442{
443 struct ast_datastore *datastore;
444 struct park_common_datastore *data;
445 struct park_common_datastore *data_copy;
446
447 SCOPED_CHANNELLOCK(lock, parkee);
448
449 if (!(datastore = ast_channel_datastore_find(parkee, &park_common_info, NULL))) {
450 return NULL;
451 }
452
453 data = datastore->data;
454
455 /* This data should always be populated if this datastore was appended to the channel */
456 ast_assert(data != NULL);
457
458 data_copy = ast_calloc(1, sizeof(*data_copy));
459 if (!data_copy) {
460 return NULL;
461 }
462
463 data_copy->parker_uuid = ast_strdup(data->parker_uuid);
464 if (!data_copy->parker_uuid) {
466 return NULL;
467 }
468
469 data_copy->randomize = data->randomize;
470 data_copy->time_limit = data->time_limit;
471 data_copy->silence_announce = data->silence_announce;
472
473 if (data->comeback_override) {
475 if (!data_copy->comeback_override) {
477 return NULL;
478 }
479 }
480
481 if (data->parker_dial_string) {
483 if (!data_copy->parker_dial_string) {
485 return NULL;
486 }
487 }
488
489 return data_copy;
490}
ast_mutex_t lock
Definition: app_sla.c:331
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2418
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition: lock.h:619
void park_common_datastore_free(struct park_common_datastore *datastore)
Free a park common datastore struct.
static const struct ast_datastore_info park_common_info
Structure for a data store object.
Definition: datastore.h:64
void * data
Definition: datastore.h:66
#define ast_assert(a)
Definition: utils.h:739

References ast_assert, ast_calloc, ast_channel_datastore_find(), ast_strdup, park_common_datastore::comeback_override, ast_datastore::data, lock, NULL, park_common_datastore_free(), park_common_info, park_common_datastore::parker_dial_string, park_common_datastore::parker_uuid, park_common_datastore::randomize, SCOPED_CHANNELLOCK, park_common_datastore::silence_announce, and park_common_datastore::time_limit.

Referenced by bridge_parking_push().

◆ get_parking_lot_container()

struct ao2_container * get_parking_lot_container ( void  )

Get a pointer to the parking lot container for purposes such as iteration.

Since
12.0.0
Returns
pointer to the parking lot container.

Definition at line 597 of file res_parking.c.

598{
600}
static struct ao2_container * parking_lot_container
Definition: res_parking.c:266

References parking_lot_container.

Referenced by cli_display_parking_lot_list(), complete_parking_lot(), manager_parking_lot_list(), manager_parking_status_all_lots(), and metermaidstate().

◆ load_parking_applications()

int load_parking_applications ( void  )

Register parking applications.

Since
12.0.0
Return values
0if successful
-1on failure

Definition at line 1008 of file parking_applications.c.

1009{
1011 return -1;
1012 }
1013
1015 return -1;
1016 }
1017
1019 return -1;
1020 }
1021
1022 return 0;
1023}
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:640
#define PARK_APPLICATION
The default parking application that Asterisk expects.
Definition: parking.h:35
static int park_app_exec(struct ast_channel *chan, const char *data)
static int park_and_announce_app_exec(struct ast_channel *chan, const char *data)
static int parked_call_app_exec(struct ast_channel *chan, const char *data)
#define PARK_AND_ANNOUNCE_APPLICATION
#define PARKED_CALL_APPLICATION
Definition: res_parking.h:38

References ast_register_application_xml, park_and_announce_app_exec(), PARK_AND_ANNOUNCE_APPLICATION, park_app_exec(), PARK_APPLICATION, parked_call_app_exec(), and PARKED_CALL_APPLICATION.

Referenced by load_module().

◆ load_parking_bridge_features()

int load_parking_bridge_features ( void  )

Register bridge features for parking.

Since
12.0.0
Return values
0on success
-1on failure

Definition at line 800 of file parking_bridge_features.c.

801{
802 parking_provider.module = AST_MODULE_SELF;
803
805
807 return -1;
808 }
809
811 return -1;
812 }
813
814 return 0;
815}
@ AST_BRIDGE_BUILTIN_PARKCALL
int ast_bridge_features_register(enum ast_bridge_builtin_feature feature, ast_bridge_hook_callback callback, const char *dtmf)
Register a handler for a built in feature.
Definition: bridge.c:3062
int ast_parking_register_bridge_features(struct ast_parking_bridge_feature_fn_table *fn_table)
Register a parking provider.
Definition: parking.c:196
struct ast_parking_bridge_feature_fn_table parking_provider
static int feature_park_call(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
static struct ast_custom_function getparkingslotchannel_function
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1558
struct ast_module * module
The module info for the module registering this parking provider.
Definition: parking.h:202

References AST_BRIDGE_BUILTIN_PARKCALL, ast_bridge_features_register(), ast_custom_function_register, ast_parking_register_bridge_features(), feature_park_call(), getparkingslotchannel_function, ast_parking_bridge_feature_fn_table::module, NULL, and parking_provider.

Referenced by load_module().

◆ load_parking_devstate()

int load_parking_devstate ( void  )

Register Parking devstate handler.

Since
12.0.0

Definition at line 121 of file parking_devicestate.c.

122{
124}
int ast_devstate_prov_add(const char *label, ast_devstate_prov_cb_type callback)
Add device state provider.
Definition: devicestate.c:391
static enum ast_device_state metermaidstate(const char *data)

References ast_devstate_prov_add(), and metermaidstate().

Referenced by load_module().

◆ load_parking_manager()

int load_parking_manager ( void  )

Register manager actions and setup subscriptions for stasis events.

Since
12.0.0

Definition at line 704 of file parking_manager.c.

705{
706 int res;
707
712 return res ? -1 : 0;
713}
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:191
#define EVENT_FLAG_CALL
Definition: manager.h:76
static int manager_park(struct mansession *s, const struct message *m)
static void parking_manager_enable_stasis(void)
static int manager_parking_status(struct mansession *s, const struct message *m)
static int manager_parking_lot_list(struct mansession *s, const struct message *m)

References ast_manager_register_xml, EVENT_FLAG_CALL, manager_park(), manager_parking_lot_list(), manager_parking_status(), and parking_manager_enable_stasis().

Referenced by load_module().

◆ load_parking_tests()

int load_parking_tests ( void  )

Register parking unit tests.

Since
12.0.0
Return values
0on success
nonzeroon failure

Definition at line 851 of file parking_tests.c.

852{
853 int res = 0;
854
855/* NOOP without test framework */
856#if defined(TEST_FRAMEWORK)
857 res |= AST_TEST_REGISTER(create_lot);
858 res |= AST_TEST_REGISTER(park_call);
859 res |= AST_TEST_REGISTER(retrieve_call);
860 res |= AST_TEST_REGISTER(park_extensions);
861 res |= AST_TEST_REGISTER(extension_conflicts);
862 res |= AST_TEST_REGISTER(dynamic_parking_variables);
863#endif
864
865 return res;
866}
#define AST_TEST_REGISTER(cb)
Definition: test.h:127

References AST_TEST_REGISTER.

Referenced by load_module().

◆ load_parking_ui()

int load_parking_ui ( void  )

Register CLI commands.

Since
12.0.0
Return values
0if successful
-1on failure

Definition at line 198 of file parking_ui.c.

199{
201}
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static struct ast_cli_entry cli_parking_lot[]
Definition: parking_ui.c:194
#define ARRAY_LEN(a)
Definition: utils.h:666

References ARRAY_LEN, ast_cli_register_multiple, and cli_parking_lot.

Referenced by load_module().

◆ park_application_setup()

struct ast_bridge * park_application_setup ( struct ast_channel parkee,
struct ast_channel parker,
const char *  app_data,
int *  silence_announcements 
)

Function to prepare a channel for parking by determining which parking bridge should be used, setting up a park common datastore so that the parking bridge will have access to necessary parking information when joining, and applying various bridge roles to the channel.

Since
12.0.0
Parameters
parkeeThe channel being prepared for parking
parkerThe channel initiating the park; may be the parkee as well. May be NULL.
app_dataarguments supplied to the Park application. May be NULL.
silence_announcementsoptional 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.
Returns
reference to a parking bridge if successful
Return values
NULLon failure
Note
ao2_cleanup this reference when you are done using it or you'll cause leaks.

Definition at line 545 of file parking_applications.c.

547{
548 int use_ringing = 0;
549 int randomize = 0;
550 int time_limit = -1;
551
552 RAII_VAR(char *, comeback_override, NULL, ast_free);
553 RAII_VAR(char *, lot_name_app_arg, NULL, ast_free);
554 RAII_VAR(char *, musicclass, NULL, ast_free);
555
556 if (app_data) {
557 park_app_parse_data(app_data, silence_announcements, &use_ringing, &randomize, &time_limit, &comeback_override, &lot_name_app_arg, &musicclass);
558 }
559
560 return park_common_setup2(parkee, parker, lot_name_app_arg, comeback_override, musicclass, use_ringing,
561 randomize, time_limit, silence_announcements ? *silence_announcements : 0);
562
563}
#define ast_free(a)
Definition: astmm.h:180
static int park_app_parse_data(const char *data, int *disable_announce, int *use_ringing, int *randomize, int *time_limit, char **comeback_override, char **lot_name, char **musicclass)
static struct ast_bridge * park_common_setup2(struct ast_channel *parkee, struct ast_channel *parker, const char *lot_name, const char *comeback_override, const char *musicclass, int use_ringing, int randomize, int time_limit, int silence_announcements)
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941

References ast_free, NULL, park_app_parse_data(), park_common_setup2(), and RAII_VAR.

Referenced by park_and_announce_app_exec(), park_app_exec(), and parking_park_bridge_channel().

◆ park_common_datastore_free()

void park_common_datastore_free ( struct park_common_datastore datastore)

Free a park common datastore struct.

Since
12.0.0
Parameters
datastoreThe park_common_datastore being free'd. (NULL tolerant)

Definition at line 335 of file parking_applications.c.

336{
337 if (!datastore) {
338 return;
339 }
340
341 ast_free(datastore->parker_uuid);
342 ast_free(datastore->parker_dial_string);
343 ast_free(datastore->comeback_override);
344 ast_free(datastore);
345}

References ast_free, park_common_datastore::comeback_override, park_common_datastore::parker_dial_string, and park_common_datastore::parker_uuid.

Referenced by bridge_parking_push(), get_park_common_datastore_copy(), and park_common_datastore_destroy().

◆ park_common_setup()

struct ast_bridge * park_common_setup ( struct ast_channel parkee,
struct ast_channel parker,
const char *  lot_name,
const char *  comeback_override,
int  use_ringing,
int  randomize,
int  time_limit,
int  silence_announcements 
)

Setup a parked call on a parking bridge without needing to parse appdata.

Since
12.0.0

Definition at line 538 of file parking_applications.c.

541{
542 return park_common_setup2(parkee, parker, lot_name, comeback_override, NULL, use_ringing, randomize, time_limit, silence_announcements);
543}

References NULL, and park_common_setup2().

Referenced by manager_park_unbridged().

◆ parked_call_retrieve_enable_features()

void parked_call_retrieve_enable_features ( struct ast_channel chan,
struct parking_lot lot,
int  recipient_mode 
)

Apply features based on the parking lot feature options.

Since
12.0.0
Parameters
chanWhich channel's feature set is being modified
lotparking lot which establishes the features used
recipient_modeAST_FEATURE_FLAG_BYCALLER if the user is the retriever AST_FEATURE_FLAG_BYCALLEE if the user is the parkee

Definition at line 217 of file parking_controller.c.

218{
219 /* Enabling features here should be additive to features that are already on the channel. */
220 struct ast_flags feature_flags = { 0 };
221 struct ast_flags *existing_features;
222
223 ast_channel_lock(chan);
224 existing_features = ast_bridge_features_ds_get(chan);
225 if (existing_features) {
226 feature_flags = *existing_features;
227 }
228
229 if (lot->cfg->parkedcalltransfers & recipient_mode) {
230 ast_set_flag(&feature_flags, AST_FEATURE_REDIRECT);
231 }
232
233 if (lot->cfg->parkedcallreparking & recipient_mode) {
234 ast_set_flag(&feature_flags, AST_FEATURE_PARKCALL);
235 }
236
237 if (lot->cfg->parkedcallhangup & recipient_mode) {
238 ast_set_flag(&feature_flags, AST_FEATURE_DISCONNECT);
239 }
240
241 if (lot->cfg->parkedcallrecording & recipient_mode) {
242 ast_set_flag(&feature_flags, AST_FEATURE_AUTOMIXMON);
243 }
244
245 ast_bridge_features_ds_set(chan, &feature_flags);
246 ast_channel_unlock(chan);
247
248 return;
249}
struct ast_flags * ast_bridge_features_ds_get(struct ast_channel *chan)
Get DTMF feature flags from the channel.
Definition: bridge_basic.c:268
int ast_bridge_features_ds_set(struct ast_channel *chan, struct ast_flags *flags)
Set basic bridge DTMF feature flags datastore on the channel.
Definition: bridge_basic.c:258
#define ast_channel_lock(chan)
Definition: channel.h:2968
@ AST_FEATURE_AUTOMIXMON
Definition: channel.h:1089
@ AST_FEATURE_REDIRECT
Definition: channel.h:1084
@ AST_FEATURE_PARKCALL
Definition: channel.h:1088
@ AST_FEATURE_DISCONNECT
Definition: channel.h:1085
#define ast_channel_unlock(chan)
Definition: channel.h:2969
Structure used to handle boolean flags.
Definition: utils.h:199
int parkedcalltransfers
Definition: res_parking.h:76
int parkedcallreparking
Definition: res_parking.h:77
int parkedcallrecording
Definition: res_parking.h:79
#define ast_set_flag(p, flag)
Definition: utils.h:70

References ast_bridge_features_ds_get(), ast_bridge_features_ds_set(), ast_channel_lock, ast_channel_unlock, AST_FEATURE_AUTOMIXMON, AST_FEATURE_DISCONNECT, AST_FEATURE_PARKCALL, AST_FEATURE_REDIRECT, ast_set_flag, parking_lot::cfg, parking_lot_cfg::parkedcallhangup, parking_lot_cfg::parkedcallrecording, parking_lot_cfg::parkedcallreparking, and parking_lot_cfg::parkedcalltransfers.

Referenced by bridge_parking_pull(), and parked_call_app_exec().

◆ parking_channel_set_roles()

int parking_channel_set_roles ( struct ast_channel chan,
struct parking_lot lot,
int  force_ringing 
)

Set necessary bridge roles on a channel that is about to enter a parking lot.

Since
12.0.0
Parameters
chanEntering channel
lotThe parking lot the channel will be entering
force_ringingUse ringing instead of music on hold
Return values
0on success
non-zeroon failure

Definition at line 57 of file parking_controller.c.

58{
59 if (ast_channel_add_bridge_role(chan, "holding_participant")) {
60 return -1;
61 }
62
63 if (force_ringing) {
64 if (ast_channel_set_bridge_role_option(chan, "holding_participant", "idle_mode", "ringing")) {
65 return -1;
66 }
67 } else {
68 if (ast_channel_set_bridge_role_option(chan, "holding_participant", "idle_mode", "musiconhold")) {
69 return -1;
70 }
71 if (!ast_strlen_zero(lot->cfg->mohclass)) {
72 if (ast_channel_set_bridge_role_option(chan, "holding_participant", "moh_class", lot->cfg->mohclass)) {
73 return -1;
74 }
75 }
76 }
77
78 return 0;
79}
int ast_channel_set_bridge_role_option(struct ast_channel *channel, const char *role_name, const char *option, const char *value)
Set a role option on a channel.
Definition: bridge_roles.c:375
int ast_channel_add_bridge_role(struct ast_channel *chan, const char *role_name)
Adds a bridge role to a channel.
Definition: bridge_roles.c:313
const ast_string_field mohclass
Definition: res_parking.h:89

References ast_channel_add_bridge_role(), ast_channel_set_bridge_role_option(), ast_strlen_zero(), parking_lot::cfg, and parking_lot_cfg::mohclass.

Referenced by bridge_parking_push(), and park_common_setup2().

◆ parking_create_dynamic_lot()

struct parking_lot * parking_create_dynamic_lot ( const char *  name,
struct ast_channel chan 
)

Create a dynamic parking lot.

Since
12.0.0
Parameters
nameDynamic parking lot name to create
chanChannel parkee to get dynamic parking lot parameters from
Returns
dynamically created parking lot on success
Return values
NULLon error
Note
This should be called only after verifying that the named parking lot doesn't already exist in a non-dynamic way.

Definition at line 1060 of file res_parking.c.

1060 {
1061 return create_dynamic_lot_full(name, chan, 0);
1062}
static struct parking_lot * create_dynamic_lot_full(const char *name, struct ast_channel *chan, int forced)
Definition: res_parking.c:971

References create_dynamic_lot_full(), and name.

Referenced by park_common_setup2(), and parking_park_call().

◆ parking_dynamic_lots_enabled()

int parking_dynamic_lots_enabled ( void  )

Check global configuration to see if dynamic parking is enabled.

Since
12.0.0
Return values
1if dynamic parking is enabled
0if dynamic parking is disabled

Definition at line 929 of file res_parking.c.

930{
932
933 if (!cfg) {
934 return 0;
935 }
936
937 return cfg->global->parkeddynamic;
938}
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
Definition: astobj2.h:918
static struct console_pvt globals

References ao2_cleanup, ao2_global_obj_ref, globals, and RAII_VAR.

Referenced by cli_display_parking_global(), and create_dynamic_lot_full().

◆ parking_lot_build_or_update()

struct parking_lot * parking_lot_build_or_update ( struct parking_lot_cfg cfg,
int  dynamic 
)

If a parking lot exists in the parking lot list already, update its status to match the provided configuration and return a reference return a reference to it. Otherwise, create a parking lot struct based on a parking lot configuration and return a reference to the new one.

Since
12.0.0
Parameters
cfgThe configuration being used as a reference to build the parking lot from.
dynamicnon-zero if creating a dynamic parking lot with this. Don't replace existing parking lots. Ever.
Returns
A reference to the new parking lot
Return values
NULLif it was not found and could not be allocated
Note
The parking lot will need to be unreffed if it ever falls out of scope
The parking lot will automatically be added to the parking lot container if needed as part of this process

Definition at line 869 of file res_parking.c.

870{
871 struct parking_lot *lot;
872 struct parking_lot_cfg *replaced_cfg = NULL;
873 int found = 0;
874
875 /* Start by trying to find it. If that works we can skip the rest. */
876 lot = named_item_find(parking_lot_container, lot_cfg->name);
877 if (!lot) {
878 lot = alloc_new_parking_lot(lot_cfg);
879
880 /* If we still don't have a lot, we failed to alloc one. */
881 if (!lot) {
882 return NULL;
883 }
884 } else {
885 found = 1;
886
887 if (dynamic) {
888 ast_log(LOG_ERROR, "Tried to create dynamic parking lot with name '%s' but a lot with that name already exists.\n", lot_cfg->name);
889 ao2_cleanup(lot);
890 return NULL;
891 }
892 }
893
894 /* Set the configuration reference. Unref the one currently in the lot if it's there. */
895 if (lot->cfg) {
896 replaced_cfg = lot->cfg;
897 }
898
899 ao2_ref(lot_cfg, +1);
900 lot->cfg = lot_cfg;
901
902 ao2_cleanup(replaced_cfg);
903
904 /* Set the operating mode to normal since the parking lot has a configuration. */
905 lot->disable_mark = 0;
906 lot->mode = dynamic ? PARKINGLOT_DYNAMIC : PARKINGLOT_NORMAL;
907
908 if (!found) {
909 /* Link after configuration is set since a lot without configuration will cause all kinds of trouble. */
911 };
912
913 return lot;
914}
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
static struct parking_lot * alloc_new_parking_lot(struct parking_lot_cfg *lot_cfg)
Definition: res_parking.c:638
static void * named_item_find(struct ao2_container *container, const char *name)
find an item in a container by its name
Definition: res_parking.c:497
enum parking_lot_modes mode
Definition: res_parking.h:97
int disable_mark
Definition: res_parking.h:98

References alloc_new_parking_lot(), ao2_cleanup, ao2_link, ao2_ref, ast_log, parking_lot::cfg, parking_lot::disable_mark, LOG_ERROR, parking_lot::mode, parking_lot_cfg::name, named_item_find(), NULL, parking_lot_container, PARKINGLOT_DYNAMIC, and PARKINGLOT_NORMAL.

Referenced by create_dynamic_lot_full(), and generate_or_link_lots_to_configs().

◆ parking_lot_cfg_create_extensions()

int parking_lot_cfg_create_extensions ( struct parking_lot_cfg lot_cfg)

Add extensions for a parking lot configuration.

Since
12.0.0
Parameters
lot_cfgparking lot configuration to generate extensions for
Return values
0on success
non-zeroon failure

Definition at line 759 of file res_parking.c.

760{
761 int parkingspace;
762 struct ast_exten *existing_exten;
763 struct ast_context *lot_context;
764 struct pbx_find_info find_info = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
765 const char *parkext_registrar_pointer; /* Used for park extension */
766 const char *parkedcall_registrar_pointer; /* Used for parkedcall extensions/hints */
767
768 if (ast_strlen_zero(lot_cfg->parkext)) {
769 return 0;
770 }
771
772 ast_string_field_build(lot_cfg, registrar, "%s/%s", BASE_REGISTRAR, lot_cfg->name);
773 parkedcall_registrar_pointer = lot_cfg->registrar;
774
775 if (lot_cfg->parkext_exclusive) {
776 parkext_registrar_pointer = lot_cfg->registrar;
777 } else {
778 parkext_registrar_pointer = BASE_REGISTRAR;
779 }
780
781 /* We need the contexts list locked to safely be able to both read and lock the specific context within */
783
784 if (!(lot_context = ast_context_find_or_create(NULL, NULL, lot_cfg->parking_con, parkext_registrar_pointer))) {
785 ast_log(LOG_ERROR, "Parking lot '%s' -- Needs a context '%s' which does not exist and Asterisk was unable to create\n",
786 lot_cfg->name, lot_cfg->parking_con);
788 return -1;
789 }
790
791 /* Once we know what context we will be modifying, we need to write lock it because we will be reading extensions
792 * and we don't want something else to destroy them while we are looking at them.
793 */
794 ast_wrlock_context(lot_context);
795
797
798 /* Handle generation/confirmation for the Park extension */
799 if ((existing_exten = pbx_find_extension(NULL, NULL, &find_info, lot_cfg->parking_con, lot_cfg->parkext, 1, NULL, NULL, E_MATCH))) {
800 if (lot_cfg->parkext_exclusive || !extension_is_compatible(lot_cfg, PARK_APPLICATION, existing_exten)) {
801 ast_unlock_context(lot_context);
802 return -1;
803 }
804 } else if (parking_add_extension(lot_context, 0, lot_cfg->parkext, 1, PARK_APPLICATION,
805 lot_cfg->parkext_exclusive ? lot_cfg->name : "", parkext_registrar_pointer)) {
806 ast_log(LOG_ERROR, "Parking lot '%s' -- Failed to add %s extension '%s@%s' to the PBX.\n",
807 lot_cfg->name, PARK_APPLICATION, lot_cfg->parkext, lot_cfg->parking_con);
808 ast_unlock_context(lot_context);
809 return -1;
810 }
811
812 /* Handle generation/confirmation for the ParkedCall extensions and hints */
813 for (parkingspace = lot_cfg->parking_start; parkingspace <= lot_cfg->parking_stop; parkingspace++) {
814 char space[AST_MAX_EXTENSION];
815 RAII_VAR(struct ast_str *, arguments_string, NULL, ast_free);
816 find_info.stacklen = 0; /* reset for pbx_find_exten */
817
818 snprintf(space, sizeof(space), "%d", parkingspace);
819
820 /* Unlike the Park extensions, ParkedCall extensions and their hints may never be shared for any reason. */
821 if ((existing_exten = pbx_find_extension(NULL, NULL, &find_info, lot_cfg->parking_con, space, 1, NULL, NULL, E_MATCH))) {
822 ast_unlock_context(lot_context);
823 return -1;
824 }
825
826 arguments_string = ast_str_create(32);
827 if (!arguments_string) {
828 ast_unlock_context(lot_context);
829 return -1;
830 }
831
832 ast_str_set(&arguments_string, 0, "%s,%s", lot_cfg->name, space);
833 if (parking_add_extension(lot_context, 0, space, 1, PARKED_CALL_APPLICATION,
834 ast_str_buffer(arguments_string), parkedcall_registrar_pointer)) {
835 ast_log(LOG_ERROR, "Parking lot '%s' -- Failed to add %s extension '%s@%s' to the PBX.\n",
836 lot_cfg->name, PARKED_CALL_APPLICATION, space, lot_cfg->parking_con);
837 ast_unlock_context(lot_context);
838 return -1;
839 }
840
841 find_info.stacklen = 0; /* reset for pbx_find_exten */
842
843 if (lot_cfg->parkaddhints) {
844 char hint_device[AST_MAX_EXTENSION];
845
846 snprintf(hint_device, sizeof(hint_device), "park:%s@%s", space, lot_cfg->parking_con);
847
848 if ((existing_exten = pbx_find_extension(NULL, NULL, &find_info, lot_cfg->parking_con, space, PRIORITY_HINT, NULL, NULL, E_MATCH))) {
849 ast_log(LOG_ERROR, "Parking lot '%s' -- Needs to add a hint '%s' at '%s@%s' but one already exists owned by %s\n",
850 lot_cfg->name, hint_device, space, lot_cfg->parking_con, ast_get_extension_registrar(existing_exten));
851 ast_unlock_context(lot_context);
852 return -1;
853 }
854
855 if (parking_add_extension(lot_context, 0, space, PRIORITY_HINT, hint_device, "", parkedcall_registrar_pointer)) {
856 ast_log(LOG_ERROR, "Parking lot '%s' -- Failed to add hint '%s@%s' to the PBX.\n",
857 lot_cfg->name, space, lot_cfg->parking_con);
858 ast_unlock_context(lot_context);
859 return -1;
860 }
861 }
862 }
863
864 ast_unlock_context(lot_context);
865
866 return 0;
867}
#define AST_MAX_EXTENSION
Definition: channel.h:134
@ E_MATCH
Definition: extconf.h:217
int ast_wrlock_contexts(void)
Write locks the context list.
Definition: pbx.c:8463
int ast_wrlock_context(struct ast_context *con)
Write locks a given context.
Definition: pbx.c:8481
struct ast_context * ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
Register a new context or find an existing one.
Definition: pbx.c:6149
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:8491
#define PRIORITY_HINT
Definition: pbx.h:54
struct ast_exten * pbx_find_extension(struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
Definition: ael_main.c:152
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8473
const char * ast_get_extension_registrar(struct ast_exten *e)
Definition: pbx.c:8532
static char * registrar
Definition: pbx_ael.c:78
static int parking_add_extension(struct ast_context *context, int replace, const char *extension, int priority, const char *application, const char *data, const char *registrar)
Definition: res_parking.c:714
static int extension_is_compatible(struct parking_lot_cfg *lot_cfg, const char *app_type, struct ast_exten *extension)
Definition: res_parking.c:731
#define BASE_REGISTRAR
Definition: res_parking.h:36
#define ast_string_field_build(x, field, fmt, args...)
Set a field to a complex (built) value.
Definition: stringfields.h:555
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
ast_context: An extension context
Definition: pbx.c:284
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own link...
Definition: pbx.c:237
Support for dynamic strings.
Definition: strings.h:623
unsigned int parkext_exclusive
Definition: res_parking.h:72
const ast_string_field registrar
Definition: res_parking.h:89
const ast_string_field parkext
Definition: res_parking.h:89
unsigned int parkaddhints
Definition: res_parking.h:73
const ast_string_field name
Definition: res_parking.h:89
const ast_string_field parking_con
Definition: res_parking.h:89
int stacklen
Definition: extconf.h:237

References ast_context_find_or_create(), ast_free, ast_get_extension_registrar(), ast_log, AST_MAX_EXTENSION, ast_str_buffer(), ast_str_create, ast_str_set(), ast_string_field_build, ast_strlen_zero(), ast_unlock_context(), ast_unlock_contexts(), ast_wrlock_context(), ast_wrlock_contexts(), BASE_REGISTRAR, E_MATCH, extension_is_compatible(), LOG_ERROR, parking_lot_cfg::name, NULL, PARK_APPLICATION, parking_lot_cfg::parkaddhints, PARKED_CALL_APPLICATION, parking_lot_cfg::parkext, parking_lot_cfg::parkext_exclusive, parking_add_extension(), parking_lot_cfg::parking_con, parking_lot_cfg::parking_start, pbx_find_extension(), PRIORITY_HINT, RAII_VAR, registrar, parking_lot_cfg::registrar, and pbx_find_info::stacklen.

Referenced by configure_parking_extensions(), and create_dynamic_lot_full().

◆ parking_lot_cfg_remove_extensions()

void parking_lot_cfg_remove_extensions ( struct parking_lot_cfg lot_cfg)

Remove extensions belonging to a parking lot configuration.

Since
12.0.0
Parameters
lot_cfgparking lot configuratin to remove extensions from
Note
This will not remove extensions registered non-exclusively even if those extensions were registered by lot_cfg. Those are only purged on a res_parking module reload.

Definition at line 664 of file res_parking.c.

665{
666 if (!ast_strlen_zero(lot_cfg->registrar)) {
667 /* Although the function is called ast_context_destroy, the use of this funtion is
668 * intended only to remove extensions, hints, etc registered by the parking lot's registrar.
669 * It won't actually destroy the context unless that context is empty afterwards and it is
670 * unreferenced.
671 */
673 }
674
675 /* If we come back for a second pass, someone else has this registrar now. */
676 ast_string_field_set(lot_cfg, registrar, "");
677}
void ast_context_destroy(struct ast_context *con, const char *registrar)
Destroy a context (matches the specified context or ANY context if NULL)
Definition: pbx.c:8221
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521

References ast_context_destroy(), ast_string_field_set, ast_strlen_zero(), NULL, registrar, and parking_lot_cfg::registrar.

Referenced by parking_lot_cfg_destructor(), remove_all_configured_parking_lot_extensions(), and remove_pending_parking_lot_extensions().

◆ parking_lot_find_by_name()

struct parking_lot * parking_lot_find_by_name ( const char *  lot_name)

Find a parking lot based on its name.

Since
12.0.0
Parameters
lot_nameName of the parking lot sought
Returns
The parking lot if found
Return values
NULLif no parking lot with the name specified exists
Note
ao2_cleanup this reference when you are done using it or you'll cause leaks.

Definition at line 602 of file res_parking.c.

603{
604 struct parking_lot *lot = named_item_find(parking_lot_container, lot_name);
605 return lot;
606}

References named_item_find(), and parking_lot_container.

Referenced by cli_display_parking_lot(), create_dynamic_lot_full(), func_get_parkingslot_channel(), manager_parking_status_single_lot(), park_common_setup2(), parked_call_app_exec(), and parking_park_call().

◆ parking_lot_get_bridge()

struct ast_bridge * parking_lot_get_bridge ( struct parking_lot lot)

Get a reference to a parking lot's bridge. If it doesn't exist, create it and get a reference.

Since
12.0.0
Parameters
lotWhich parking lot we need the bridge from. This parking lot must be locked before calling this function.
Returns
A reference to the ast_bridge associated with the parking lot
Return values
NULLif it didn't already have a bridge and one couldn't be created
Note
This bridge will need to be unreffed if it ever falls out of scope.

Definition at line 36 of file parking_controller.c.

37{
38 struct ast_bridge *lot_bridge;
39
40 if (lot->parking_bridge) {
41 ao2_ref(lot->parking_bridge, +1);
42 return lot->parking_bridge;
43 }
44
45 lot_bridge = bridge_parking_new(lot);
46 if (!lot_bridge) {
47 return NULL;
48 }
49
50 /* The parking lot needs a reference to the bridge as well. */
51 lot->parking_bridge = lot_bridge;
52 ao2_ref(lot->parking_bridge, +1);
53
54 return lot_bridge;
55}
struct ast_bridge * bridge_parking_new(struct parking_lot *bridge_lot)
Create a new parking bridge.
Structure that contains information about a bridge.
Definition: bridge.h:349
struct ast_bridge * parking_bridge
Definition: res_parking.h:94

References ao2_ref, bridge_parking_new(), NULL, and parking_lot::parking_bridge.

Referenced by park_common_setup2().

◆ parking_lot_get_space()

int parking_lot_get_space ( struct parking_lot lot,
int  target_override 
)

Get an available parking space within a parking lot.

Since
12.0.0
Parameters
lotWhich parking lot we are getting a space from
target_overrideIf there is a specific slot we want, provide it here and we'll start from that position
Return values
-1if No slot can be found
Returns
integer value of parking space selected
Note
lot should be locked before this is called and unlocked only after a parked_user with the space returned has been added to the parking lot.

Definition at line 96 of file parking_controller.c.

97{
98 int original_target;
99 int current_target;
100 struct ao2_iterator i;
101 struct parked_user *user;
102 int wrap;
103
104 if (lot->cfg->parkfindnext) {
105 /* Use next_space if the lot already has next_space set; otherwise use lot start. */
106 original_target = lot->next_space ? lot->next_space : lot->cfg->parking_start;
107 } else {
108 original_target = lot->cfg->parking_start;
109 }
110
111 if (target_override >= lot->cfg->parking_start && target_override <= lot->cfg->parking_stop) {
112 original_target = target_override;
113 } else if (target_override > -1) {
114 ast_log(LOG_WARNING, "Preferred parking spot %d is out of bounds (%d-%d)\n", target_override, lot->cfg->parking_start, lot->cfg->parking_stop);
115 }
116
117 current_target = original_target;
118
119 wrap = lot->cfg->parking_start;
120
122 while ((user = ao2_iterator_next(&i))) {
123 /* Increment the wrap on each pass until we find an empty space */
124 if (wrap == user->parking_space) {
125 wrap += 1;
126 }
127
128 if (user->parking_space < current_target) {
129 /* It's lower than the anticipated target, so we haven't reached the target yet. */
130 ao2_ref(user, -1);
131 continue;
132 }
133
134 if (user->parking_space > current_target) {
135 /* The current target is usable because all items below have been read and the next target is higher than the one we want. */
136 ao2_ref(user, -1);
137 break;
138 }
139
140 /* We found one already parked here. */
141 current_target += 1;
142 ao2_ref(user, -1);
143 }
145
146 if (current_target <= lot->cfg->parking_stop) {
147 return current_target;
148 }
149
150 if (wrap <= lot->cfg->parking_stop) {
151 return wrap;
152 }
153
154 return -1;
155}
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define LOG_WARNING
static char user[512]
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
struct parking_lot * lot
Definition: res_parking.h:113
unsigned int parkfindnext
Definition: res_parking.h:71
int next_space
Definition: res_parking.h:93
struct ao2_container * parked_users
Definition: res_parking.h:95
structure to hold users read from users.conf

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_log, parking_lot::cfg, LOG_WARNING, parked_user::lot, parking_lot::next_space, parking_lot::parked_users, parking_lot_cfg::parkfindnext, parking_lot_cfg::parking_start, parking_lot_cfg::parking_stop, and user.

Referenced by generate_parked_user().

◆ parking_lot_inspect_parked_user()

struct parked_user * parking_lot_inspect_parked_user ( struct parking_lot lot,
int  target 
)

Determine if there is a parked user in a parking space and return it if there is.

Parameters
lotParking lot being pulled from
targetIf < 0 search for the first occupied space in the parking lot If >= 0 Only pull from the indicated target
Return values
NULLif no parked user could be pulled from the requested parking lot at the requested parking space
Returns
reference to the requested parked user

Definition at line 168 of file parking_controller.c.

169{
170 struct parked_user *user;
171
172 if (target < 0) {
174 } else {
176 }
177
178 if (!user) {
179 return NULL;
180 }
181
182 return user;
183}
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition: astobj2.h:1693
static int retrieve_parked_user_targeted(void *obj, void *arg, int flags)

References ao2_callback, parked_user::lot, NULL, parking_lot::parked_users, retrieve_parked_user_targeted(), and user.

Referenced by func_get_parkingslot_channel().

◆ parking_lot_remove_if_unused()

int parking_lot_remove_if_unused ( struct parking_lot lot)

Remove a parking lot from the usable lists if it is no longer involved in any calls and no configuration currently claims it.

Since
12.0.0
Parameters
lotWhich parking lot is being checked for elimination
Return values
0if the parking lot was removed
-1if the parking lot wasn't removed.
Note
This should generally be called when something is happening that could cause a parking lot to die such as a call being unparked or a parking lot no longer existing in configurations.

Definition at line 400 of file res_parking.c.

401{
402 if (lot->mode != PARKINGLOT_DISABLED) {
403 return -1;
404 }
405
408 return 0;
409 }
410
411 return -1;
412}
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578

References ao2_container_count(), ao2_unlink, parking_lot::mode, parking_lot::parked_users, parking_lot_container, and PARKINGLOT_DISABLED.

Referenced by parking_lot_disable(), parking_lot_retrieve_parked_user(), and unpark_parked_user().

◆ parking_lot_retrieve_parked_user()

struct parked_user * parking_lot_retrieve_parked_user ( struct parking_lot lot,
int  target 
)

Determine if there is a parked user in a parking space and pull it from the parking lot if there is.

Since
12.0.0
Parameters
lotParking lot being pulled from
targetIf < 0 search for the first occupied space in the parking lot If >= 0 Only pull from the indicated target
Return values
NULLif no parked user could be pulled from the requested parking lot at the requested parking space
Returns
reference to the requested parked user
Note
The parked user will be removed from parking lot as part of this process
Remove this reference with ao2_cleanup once it falls out of scope.

Definition at line 185 of file parking_controller.c.

186{
188
189 if (target < 0) {
191 } else {
193 }
194
195 if (!user) {
196 return NULL;
197 }
198
199 ao2_lock(user);
200 if (user->resolution != PARK_UNSET) {
201 /* Abandon. Something else has resolved the parked user before we got to it. */
203 return NULL;
204 }
205
207 user->resolution = PARK_ANSWERED;
209
211
212 /* Bump the ref count by 1 since the RAII_VAR will eat the reference otherwise */
213 ao2_ref(user, +1);
214 return user;
215}
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
int parking_lot_remove_if_unused(struct parking_lot *lot)
Remove a parking lot from the usable lists if it is no longer involved in any calls and no configurat...
Definition: res_parking.c:400

References ao2_callback, ao2_cleanup, ao2_lock, ao2_ref, ao2_unlink, ao2_unlock, parked_user::lot, NULL, PARK_ANSWERED, PARK_UNSET, parking_lot::parked_users, parking_lot_remove_if_unused(), RAII_VAR, retrieve_parked_user_targeted(), and user.

Referenced by parked_call_app_exec().

◆ parking_notify_metermaids()

void parking_notify_metermaids ( int  exten,
const char *  context,
enum ast_device_state  state 
)

Notify metermaids that we've changed an extension.

Since
12.0.0
Parameters
extenExtension of the call parked/unparked
contextContext of the call parked/unparked
statenew device state

Definition at line 108 of file parking_devicestate.c.

109{
110 ast_debug(4, "Notification of state change to metermaids %d@%s\n to state '%s'\n",
112
114}
@ AST_DEVSTATE_CACHABLE
Definition: devicestate.h:70
int ast_devstate_changed(enum ast_device_state state, enum ast_devstate_cache cachable, const char *fmt,...)
Tells Asterisk the State for Device is changed.
Definition: devicestate.c:510
const char * ast_devstate2str(enum ast_device_state devstate) attribute_pure
Convert device state to text string for output.
Definition: devicestate.c:237
#define ast_debug(level,...)
Log a DEBUG message.

References ast_debug, ast_devstate2str(), AST_DEVSTATE_CACHABLE, ast_devstate_changed(), voicemailpwcheck::context, and parking_lot_extension_inuse_search::exten.

Referenced by bridge_parking_pull(), and bridge_parking_push().

◆ parking_set_duration()

void parking_set_duration ( struct ast_bridge_features features,
struct parked_user user 
)

Setup timeout interval feature on an ast_bridge_features for parking.

Since
12.0.0
Parameters
featuresThe ast_bridge_features we are establishing the interval hook on
userThe parked_user receiving the timeout duration limits

Definition at line 703 of file parking_bridge_features.c.

704{
705 unsigned int time_limit;
706
707 time_limit = user->time_limit * 1000;
708
709 if (!time_limit) {
710 /* There is no duration limit that we need to apply. */
711 return;
712 }
713
714 /* If the time limit has already been passed, set a really low time limit so we can kick them out immediately. */
715 time_limit = ast_remaining_ms(user->start, time_limit);
716 if (time_limit <= 0) {
717 time_limit = 1;
718 }
719
720 /* The interval hook is going to need a reference to the parked_user */
721 ao2_ref(user, +1);
722
723 if (ast_bridge_interval_hook(features, 0, time_limit,
725 ast_log(LOG_ERROR, "Failed to apply duration limit to the parked call.\n");
726 ao2_ref(user, -1);
727 }
728}
void __ao2_cleanup(void *obj)
Definition: astobj2.c:677
int ast_bridge_interval_hook(struct ast_bridge_features *features, enum ast_bridge_hook_timer_option flags, unsigned int interval, ast_bridge_hook_callback callback, void *hook_pvt, ast_bridge_hook_pvt_destructor destructor, enum ast_bridge_hook_remove_flags remove_flags)
Attach an interval hook to a bridge features structure.
Definition: bridge.c:3319
@ AST_BRIDGE_HOOK_REMOVE_ON_PULL
static int parking_duration_callback(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: utils.c:2281

References __ao2_cleanup(), ao2_ref, AST_BRIDGE_HOOK_REMOVE_ON_PULL, ast_bridge_interval_hook(), ast_log, ast_remaining_ms(), LOG_ERROR, and parking_duration_callback().

Referenced by bridge_parking_push().

◆ publish_parked_call()

void publish_parked_call ( struct parked_user pu,
enum ast_parked_call_event_type  event_type 
)

Publish a stasis parked call message for a given parked user.

Since
12.0.0
Parameters
pupointer to a parked_user that we are generating the message for
event_typeWhat parked call event type is provoking this message

Definition at line 627 of file parking_manager.c.

628{
630 RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
631
632 if (!ast_parked_call_type()) {
633 return;
634 }
635
636 payload = parked_call_payload_from_parked_user(pu, event_type);
637 if (!payload) {
638 return;
639 }
640
642 if (!msg) {
643 return;
644 }
645
647}
struct stasis_topic * ast_parking_topic(void)
accessor for the parking stasis topic
Definition: parking.c:67
struct stasis_message_type * ast_parked_call_type(void)
accessor for the parked call stasis message type
static struct ast_parked_call_payload * parked_call_payload_from_parked_user(struct parked_user *pu, enum ast_parked_call_event_type event_type)
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition: stasis.c:1512
A parked call message payload.
Definition: parking.h:59

References ao2_cleanup, ast_parked_call_type(), ast_parking_topic(), NULL, parked_call_payload_from_parked_user(), RAII_VAR, stasis_message_create(), and stasis_publish().

Referenced by bridge_parking_pull(), and bridge_parking_push().

◆ publish_parked_call_failure()

void publish_parked_call_failure ( struct ast_channel parkee)

Publish a stasis parked call message for the channel indicating failure to park.

Since
12.0.0
Parameters
parkeechannel belonging to the failed parkee

Definition at line 605 of file parking_manager.c.

606{
608 RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
609
610 if (!ast_parked_call_type()) {
611 return;
612 }
613
614 payload = parked_call_payload_from_failure(parkee);
615 if (!payload) {
616 return;
617 }
618
620 if (!msg) {
621 return;
622 }
623
625}
static struct ast_parked_call_payload * parked_call_payload_from_failure(struct ast_channel *chan)

References ao2_cleanup, ast_parked_call_type(), ast_parking_topic(), NULL, parked_call_payload_from_failure(), RAII_VAR, stasis_message_create(), and stasis_publish().

Referenced by bridge_parking_push(), park_app_exec(), and parking_park_bridge_channel().

◆ say_parking_space()

void say_parking_space ( struct ast_bridge_channel bridge_channel,
const char *  payload 
)

custom callback function for ast_bridge_channel_queue_playfile which plays a parking space and optionally hangs up the call afterwards based on the payload in playfile.

Since
12.0.0

Definition at line 681 of file parking_bridge_features.c.

682{
683 unsigned int numeric_value;
684 unsigned int hangup_after;
685
686 if (sscanf(payload, "%u %u", &hangup_after, &numeric_value) != 2) {
687 /* If say_parking_space is called with a non-numeric string, we have a problem. */
688 ast_assert(0);
689 ast_bridge_channel_leave_bridge(bridge_channel,
691 return;
692 }
693
694 ast_say_digits(bridge_channel->chan, numeric_value, "",
695 ast_channel_language(bridge_channel->chan));
696
697 if (hangup_after) {
698 ast_bridge_channel_leave_bridge(bridge_channel,
700 }
701}
@ BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE
void ast_bridge_channel_leave_bridge(struct ast_bridge_channel *bridge_channel, enum bridge_channel_state new_state, int cause)
Set bridge channel state to leave bridge (if not leaving already).
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:106
const char * ast_channel_language(const struct ast_channel *chan)
int ast_say_digits(struct ast_channel *chan, int num, const char *ints, const char *lang)
says digits
Definition: channel.c:8275
struct ast_channel * chan

References ast_assert, ast_bridge_channel_leave_bridge(), AST_CAUSE_NORMAL_CLEARING, ast_channel_language(), ast_say_digits(), BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, and ast_bridge_channel::chan.

Referenced by bridge_parking_push(), and parker_parked_call_message_response().

◆ unload_parking_applications()

void unload_parking_applications ( void  )

Unregister parking applications.

Since
12.0.0

Definition at line 1025 of file parking_applications.c.

1026{
1030}
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392

References ast_unregister_application(), PARK_AND_ANNOUNCE_APPLICATION, PARK_APPLICATION, and PARKED_CALL_APPLICATION.

Referenced by unload_module().

◆ unload_parking_bridge_features()

void unload_parking_bridge_features ( void  )

Unregister features registered by load_parking_bridge_features.

Since
12.0.0

Definition at line 793 of file parking_bridge_features.c.

794{
798}
int ast_bridge_features_unregister(enum ast_bridge_builtin_feature feature)
Unregister a handler for a built in feature.
Definition: bridge.c:3078
int ast_parking_unregister_bridge_features(const char *module_name)
Unregister the current parking provider.
Definition: parking.c:223
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
const char * module_name
The name of the module that provides this parking functionality.
Definition: parking.h:139

References AST_BRIDGE_BUILTIN_PARKCALL, ast_bridge_features_unregister(), ast_custom_function_unregister(), ast_parking_unregister_bridge_features(), getparkingslotchannel_function, ast_parking_bridge_feature_fn_table::module_name, and parking_provider.

Referenced by unload_module().

◆ unload_parking_devstate()

void unload_parking_devstate ( void  )

Unregister Parking devstate handler.

Since
12.0.0

Definition at line 116 of file parking_devicestate.c.

117{
118 ast_devstate_prov_del("Park");
119}
int ast_devstate_prov_del(const char *label)
Remove device state provider.
Definition: devicestate.c:418

References ast_devstate_prov_del().

Referenced by unload_module().

◆ unload_parking_manager()

void unload_parking_manager ( void  )

Unregister manager actions and remove subscriptions for stasis events.

Since
12.0.0

Definition at line 720 of file parking_manager.c.

721{
722 ast_manager_unregister("Parkinglots");
723 ast_manager_unregister("ParkedCalls");
726}
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7608
static void parking_manager_disable_stasis(void)

References ast_manager_unregister(), and parking_manager_disable_stasis().

Referenced by unload_module().

◆ unload_parking_tests()

void unload_parking_tests ( void  )

Unregister parking unit tests.

Since
12.0.0

Definition at line 838 of file parking_tests.c.

839{
840/* NOOP without test framework */
841#if defined(TEST_FRAMEWORK)
842 AST_TEST_UNREGISTER(create_lot);
843 AST_TEST_UNREGISTER(park_call);
844 AST_TEST_UNREGISTER(retrieve_call);
845 AST_TEST_UNREGISTER(park_extensions);
846 AST_TEST_UNREGISTER(extension_conflicts);
847 AST_TEST_UNREGISTER(dynamic_parking_variables);
848#endif
849}
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128

References AST_TEST_UNREGISTER.

Referenced by unload_module().

◆ unload_parking_ui()

void unload_parking_ui ( void  )

Unregister CLI commands.

Since
12.0.0

Definition at line 203 of file parking_ui.c.

204{
206}
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30

References ARRAY_LEN, ast_cli_unregister_multiple(), and cli_parking_lot.

Referenced by unload_module().

◆ unpark_parked_user()

int unpark_parked_user ( struct parked_user user)

Pull a parked user out of its parking lot. Use this when you don't want to use the parked user afterwards.

Since
12.0.0
Parameters
userThe parked user being pulled.
Return values
0on success
-1if the user didn't have its parking lot set

Definition at line 85 of file parking_controller.c.

86{
87 if (pu->lot) {
88 ao2_unlink(pu->lot->parked_users, pu);
90 return 0;
91 }
92
93 return -1;
94}

References ao2_unlink, parked_user::lot, parking_lot::parked_users, and parking_lot_remove_if_unused().

Referenced by bridge_parking_pull().