Asterisk - The Open Source Telephony Project GIT-master-a358458
Data Structures | Functions
parking_controller.c File Reference

Parking Entry, Exit, and other assorted controls. More...

#include "asterisk.h"
#include "asterisk/logger.h"
#include "res_parking.h"
#include "asterisk/astobj2.h"
#include "asterisk/utils.h"
#include "asterisk/manager.h"
#include "asterisk/test.h"
#include "asterisk/features.h"
#include "asterisk/bridge_basic.h"
Include dependency graph for parking_controller.c:

Go to the source code of this file.

Data Structures

struct  parking_limits_pvt
 

Functions

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...
 
void flatten_dial_string (char *dialstring)
 Flattens a dial string so that it can be written to/found from PBX extensions. 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 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...
 
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...
 
static int retrieve_parked_user_targeted (void *obj, void *arg, int flags)
 
int unpark_parked_user (struct parked_user *pu)
 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

Parking Entry, Exit, and other assorted controls.

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

Definition in file parking_controller.c.

Function Documentation

◆ 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
#define NULL
Definition: resample.c:96
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().

◆ 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().

◆ 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:2922
@ AST_FEATURE_AUTOMIXMON
Definition: channel.h:1069
@ AST_FEATURE_REDIRECT
Definition: channel.h:1064
@ AST_FEATURE_PARKCALL
Definition: channel.h:1068
@ AST_FEATURE_DISCONNECT
Definition: channel.h:1065
#define ast_channel_unlock(chan)
Definition: channel.h:2923
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
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
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_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}
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
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_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_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
@ PARK_ANSWERED
Definition: res_parking.h:45
@ PARK_UNSET
Definition: res_parking.h:41
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
#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 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().

◆ retrieve_parked_user_targeted()

static int retrieve_parked_user_targeted ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 157 of file parking_controller.c.

158{
159 int *target = arg;
160 struct parked_user *user = obj;
161 if (user->parking_space == *target) {
162 return CMP_MATCH;
163 }
164
165 return 0;
166}
@ CMP_MATCH
Definition: astobj2.h:1027

References CMP_MATCH.

Referenced by parking_lot_inspect_parked_user(), and parking_lot_retrieve_parked_user().

◆ 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().