Asterisk - The Open Source Telephony Project  21.4.1
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"

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

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.

References ast_async_goto(), ast_exists_extension(), ast_strdupa, parking_lot::cfg, parked_user::chan, parking_lot_cfg::comebackcontext, parking_lot_cfg::comebacktoorigin, flatten_dial_string(), and parked_user::parker_dial_string.

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 }
Main Channel structure associated with a channel.
const ast_string_field comebackcontext
Definition: res_parking.h:89
void flatten_dial_string(char *dialstring)
Flattens a dial string so that it can be written to/found from PBX extensions.
char * parker_dial_string
Definition: res_parking.h:109
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
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
unsigned int comebacktoorigin
Definition: res_parking.h:74
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
struct ast_channel * chan
Definition: res_parking.h:104
struct parking_lot_cfg * cfg
Definition: res_parking.h:96
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.

Referenced by comeback_goto().

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 }
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.

References ast_bridge_features_ds_get(), ast_bridge_features_ds_set(), parking_lot::cfg, parking_lot_cfg::parkedcallhangup, parking_lot_cfg::parkedcallrecording, parking_lot_cfg::parkedcallreparking, and parking_lot_cfg::parkedcalltransfers.

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 }
int parkedcallreparking
Definition: res_parking.h:77
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
struct ast_flags * ast_bridge_features_ds_get(struct ast_channel *chan)
Get DTMF feature flags from the channel.
Definition: bridge_basic.c:268
Structure used to handle boolean flags.
Definition: utils.h:199
int parkedcalltransfers
Definition: res_parking.h:76
int parkedcallrecording
Definition: res_parking.h:79
struct parking_lot_cfg * cfg
Definition: res_parking.h:96
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.

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

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_add_bridge_role(struct ast_channel *chan, const char *role_name)
Adds a bridge role to a channel.
Definition: bridge_roles.c:313
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
const ast_string_field mohclass
Definition: res_parking.h:89
struct parking_lot_cfg * cfg
Definition: res_parking.h:96
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.

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

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 * parking_bridge
Definition: res_parking.h:94
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
Structure that contains information about a bridge.
Definition: bridge.h:349
struct ast_bridge * bridge_parking_new(struct parking_lot *bridge_lot)
Create a new parking bridge.
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.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_ref, parking_lot::cfg, parking_lot::next_space, parking_lot::parked_users, parking_lot_cfg::parkfindnext, parked_user::parking_space, parking_lot_cfg::parking_start, and parking_lot_cfg::parking_stop.

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 
121  i = ao2_iterator_init(lot->parked_users, 0);
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 }
struct ao2_container * parked_users
Definition: res_parking.h:95
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
int next_space
Definition: res_parking.h:93
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
int parking_space
Definition: res_parking.h:107
unsigned int parkfindnext
Definition: res_parking.h:71
structure to hold users read from users.conf
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 ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
struct parking_lot_cfg * cfg
Definition: res_parking.h:96
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.

References ao2_callback, and parking_lot::parked_users.

Referenced by func_get_parkingslot_channel().

169 {
170  struct parked_user *user;
171 
172  if (target < 0) {
173  user = ao2_callback(lot->parked_users, 0, NULL, NULL);
174  } else {
175  user = ao2_callback(lot->parked_users, 0, retrieve_parked_user_targeted, &target);
176  }
177 
178  if (!user) {
179  return NULL;
180  }
181 
182  return user;
183 }
struct ao2_container * parked_users
Definition: res_parking.h:95
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
Definition: astobj2.h:1693
structure to hold users read from users.conf
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.

References ao2_callback, ao2_ref, ao2_unlink, parked_user::lot, PARK_ANSWERED, parking_lot::parked_users, parking_lot_remove_if_unused(), RAII_VAR, and parked_user::resolution.

186 {
187  RAII_VAR(struct parked_user *, user, NULL, ao2_cleanup);
188 
189  if (target < 0) {
190  user = ao2_callback(lot->parked_users, 0, NULL, NULL);
191  } else {
192  user = ao2_callback(lot->parked_users, 0, retrieve_parked_user_targeted, &target);
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. */
202  ao2_unlock(user);
203  return NULL;
204  }
205 
207  user->resolution = PARK_ANSWERED;
208  ao2_unlock(user);
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 }
struct ao2_container * parked_users
Definition: res_parking.h:95
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
Definition: astobj2.h:1693
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 ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578
structure to hold users read from users.conf
#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
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.

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

86 {
87  if (pu->lot) {
88  ao2_unlink(pu->lot->parked_users, pu);
90  return 0;
91  }
92 
93  return -1;
94 }
struct ao2_container * parked_users
Definition: res_parking.h:95
struct parking_lot * lot
Definition: res_parking.h:111
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 ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578