Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Functions | Variables
parking_bridge.c File Reference

Parking Bridge Class. More...

#include "asterisk.h"
#include "res_parking.h"
#include "asterisk/astobj2.h"
#include "asterisk/logger.h"
#include "asterisk/say.h"
#include "asterisk/term.h"
#include "asterisk/features.h"
#include "asterisk/bridge_internal.h"
Include dependency graph for parking_bridge.c:

Go to the source code of this file.

Data Structures

struct  ast_bridge_parking
 

Functions

static struct ast_bridgeast_bridge_parking_init (struct ast_bridge_parking *self, struct parking_lot *bridge_lot)
 
static void bridge_parking_destroy (struct ast_bridge_parking *self)
 
static void bridge_parking_dissolving (struct ast_bridge_parking *self)
 
static void bridge_parking_get_merge_priority (struct ast_bridge_parking *self)
 
struct ast_bridgebridge_parking_new (struct parking_lot *bridge_lot)
 Create a new parking bridge. More...
 
static void bridge_parking_notify_masquerade (struct ast_bridge_parking *self, struct ast_bridge_channel *bridge_channel)
 
static void bridge_parking_pull (struct ast_bridge_parking *self, struct ast_bridge_channel *bridge_channel)
 
static int bridge_parking_push (struct ast_bridge_parking *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
 
static void destroy_parked_user (void *obj)
 
static struct parked_usergenerate_parked_user (struct parking_lot *lot, struct ast_channel *chan, const char *parker_channel_name, const char *parker_dial_string, int use_random_space, int time_limit)
 
static int parked_user_set_parker_dial_string (struct parked_user *pu, const char *parker_channel_name)
 

Variables

struct ast_bridge_methods ast_bridge_parking_v_table
 

Detailed Description

Parking Bridge Class.

Author
Jonathan Rose jrose[email protected]@dig[email protected]ium.c[email protected]om

Definition in file parking_bridge.c.

Function Documentation

◆ ast_bridge_parking_init()

static struct ast_bridge* ast_bridge_parking_init ( struct ast_bridge_parking self,
struct parking_lot bridge_lot 
)
static

Definition at line 438 of file parking_bridge.c.

References ao2_ref, and NULL.

Referenced by bridge_parking_new().

439 {
440  if (!self) {
441  return NULL;
442  }
443 
444  /* If no lot is defined for the bridge, then we aren't allowing the bridge to be initialized. */
445  if (!bridge_lot) {
446  ao2_ref(self, -1);
447  return NULL;
448  }
449 
450  /* It doesn't need to be a reference since the bridge only lives as long as the parking lot lives. */
451  self->lot = bridge_lot;
452 
453  return &self->base;
454 }
#define NULL
Definition: resample.c:96
#define ao2_ref(o, delta)
Definition: astobj2.h:464

◆ bridge_parking_destroy()

static void bridge_parking_destroy ( struct ast_bridge_parking self)
static

Definition at line 54 of file parking_bridge.c.

References ast_bridge_base_v_table, and ast_bridge_methods::destroy.

55 {
57 }
struct ast_bridge base
struct ast_bridge_methods ast_bridge_base_v_table
Bridge base class virtual method table.
Definition: bridge.c:949
ast_bridge_destructor_fn destroy
Definition: bridge.h:269

◆ bridge_parking_dissolving()

static void bridge_parking_dissolving ( struct ast_bridge_parking self)
static

Definition at line 59 of file parking_bridge.c.

References ast_bridge_base_v_table, ast_bridge_methods::dissolving, and NULL.

60 {
61  self->lot = NULL;
63 }
struct ast_bridge base
ast_bridge_dissolving_fn dissolving
Definition: bridge.h:271
#define NULL
Definition: resample.c:96
struct ast_bridge_methods ast_bridge_base_v_table
Bridge base class virtual method table.
Definition: bridge.c:949

◆ bridge_parking_get_merge_priority()

static void bridge_parking_get_merge_priority ( struct ast_bridge_parking self)
static

Definition at line 423 of file parking_bridge.c.

References ast_bridge_base_v_table, and ast_bridge_methods::get_merge_priority.

424 {
426 }
struct ast_bridge base
struct ast_bridge_methods ast_bridge_base_v_table
Bridge base class virtual method table.
Definition: bridge.c:949
ast_bridge_merge_priority_fn get_merge_priority
Definition: bridge.h:279

◆ 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
Newlycreated parking bridge

Definition at line 456 of file parking_bridge.c.

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(), bridge_alloc(), bridge_base_init(), bridge_register(), parking_lot::name, and NULL.

Referenced by parking_lot_get_bridge().

457 {
458  void *bridge;
459 
463  | AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM, "Parking", bridge_lot->name, NULL);
464  bridge = ast_bridge_parking_init(bridge, bridge_lot);
465  bridge = bridge_register(bridge);
466  return bridge;
467 }
struct ast_bridge * bridge_register(struct ast_bridge *bridge)
Register the new bridge with the system.
Definition: bridge.c:709
#define NULL
Definition: resample.c:96
static struct ast_bridge * ast_bridge_parking_init(struct ast_bridge_parking *self, struct parking_lot *bridge_lot)
struct ast_bridge * bridge_alloc(size_t size, const struct ast_bridge_methods *v_table)
Definition: bridge.c:724
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:760
const ast_string_field name
Definition: res_parking.h:100
struct ast_bridge_methods ast_bridge_parking_v_table

◆ bridge_parking_notify_masquerade()

static void bridge_parking_notify_masquerade ( struct ast_bridge_parking self,
struct ast_bridge_channel bridge_channel 
)
static

Definition at line 418 of file parking_bridge.c.

References ast_bridge_base_v_table, and ast_bridge_methods::notify_masquerade.

419 {
420  ast_bridge_base_v_table.notify_masquerade(&self->base, bridge_channel);
421 }
struct ast_bridge base
struct ast_bridge_methods ast_bridge_base_v_table
Bridge base class virtual method table.
Definition: bridge.c:949
ast_bridge_notify_masquerade_fn notify_masquerade
Definition: bridge.h:277

◆ bridge_parking_pull()

static void bridge_parking_pull ( struct ast_bridge_parking self,
struct ast_bridge_channel bridge_channel 
)
static

Definition at line 342 of file parking_bridge.c.

References ao2_cleanup, ao2_lock, ao2_unlock, ast_bridge_base_v_table, ast_bridge_channel_queue_playfile(), AST_DEVICE_NOT_INUSE, AST_FEATURE_FLAG_BYCALLEE, ast_bridge_channel::bridge_pvt, ast_bridge_channel::chan, NULL, PARK_ABANDON, PARK_ANSWERED, PARK_FORCED, PARK_TIMEOUT, PARK_UNSET, PARKED_CALL_GIVEUP, parked_call_retrieve_enable_features(), PARKED_CALL_TIMEOUT, PARKED_CALL_UNPARKED, parking_notify_metermaids(), publish_parked_call(), ast_bridge_methods::pull, RAII_VAR, and unpark_parked_user().

343 {
344  RAII_VAR(struct parked_user *, pu, NULL, ao2_cleanup);
345 
346  ast_bridge_base_v_table.pull(&self->base, bridge_channel);
347 
348  /* Take over the bridge channel's pu reference. It will be released when we are done. */
349  pu = bridge_channel->bridge_pvt;
350  bridge_channel->bridge_pvt = NULL;
351 
352  /* This should only happen if the exiting channel was swapped out */
353  if (!pu) {
354  return;
355  }
356 
357  /* If we got here without the resolution being set, that's because the call was hung up for some reason without
358  * timing out or being picked up. There may be some forcible park removals later, but the resolution should be
359  * handled in those cases */
360  ao2_lock(pu);
361  if (pu->resolution == PARK_UNSET) {
362  pu->resolution = PARK_ABANDON;
363  }
364  ao2_unlock(pu);
365 
366  /* Pull can still happen after the bridge starts dissolving, so make sure we still have a lot before trying to notify metermaids. */
367  if (self->lot) {
369  }
370 
371  switch (pu->resolution) {
372  case PARK_UNSET:
373  /* This should be impossible now since the resolution is forcibly set to abandon if it was unset at this point. Resolution
374  isn't allowed to be changed when it isn't currently PARK_UNSET. */
375  break;
376  case PARK_ABANDON:
377  /* Since the call was abandoned without additional handling, we need to issue the give up event and unpark the user. */
379  unpark_parked_user(pu);
380  break;
381  case PARK_FORCED:
382  /* PARK_FORCED is currently unused, but it is expected that it would be handled similar to PARK_ANSWERED.
383  * There is currently no event related to forced parked calls either */
384  break;
385  case PARK_ANSWERED:
386  /* If answered or forced, the channel should be pulled from the bridge as part of that process and unlinked from
387  * the parking lot afterwards. We do need to apply bridge features though and play the courtesy tone if set. */
390 
391  if (pu->lot->cfg->parkedplay & AST_FEATURE_FLAG_BYCALLEE) {
392  ast_bridge_channel_queue_playfile(bridge_channel, NULL, pu->lot->cfg->courtesytone, NULL);
393  }
394  break;
395  case PARK_TIMEOUT:
396  /* Timeout is similar to abandon because it simply sets the bridge state to end and doesn't
397  * actually pull the channel. Because of that, unpark should happen in here. */
400  unpark_parked_user(pu);
401  break;
402  }
403 }
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 afterw...
void parking_notify_metermaids(int exten, const char *context, enum ast_device_state state)
Notify metermaids that we've changed an extension.
struct ast_bridge base
struct parking_lot * lot
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.
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
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.
struct ast_bridge_methods ast_bridge_base_v_table
Bridge base class virtual method table.
Definition: bridge.c:949
const ast_string_field parking_con
Definition: res_parking.h:89
#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:911
#define ao2_lock(a)
Definition: astobj2.h:718
struct ast_channel * chan
void * bridge_pvt
Bridge class private channel data.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
int ast_bridge_channel_queue_playfile(struct ast_bridge_channel *bridge_channel, ast_bridge_custom_play_fn custom_play, const char *playfile, const char *moh_class)
Queue a bridge action play file frame onto the bridge channel.
ast_bridge_pull_channel_fn pull
Definition: bridge.h:275
struct parking_lot_cfg * cfg
Definition: res_parking.h:96

◆ bridge_parking_push()

static int bridge_parking_push ( struct ast_bridge_parking self,
struct ast_bridge_channel bridge_channel,
struct ast_bridge_channel swap 
)
static

Definition at line 206 of file parking_bridge.c.

References ao2_cleanup, ast_answer(), ast_assert, ast_bridge_base_v_table, ast_bridge_channel_get_role_option(), ast_bridge_channel_has_role(), ast_bridge_channel_lock, ast_bridge_channel_queue_playfile(), ast_bridge_channel_unlock, ast_channel_lock, ast_channel_name(), ast_channel_snapshot_get_latest(), ast_channel_unlock, ast_copy_string(), AST_DEVICE_INUSE, ast_log, AST_STATE_UP, ast_strdupa, ast_strlen_zero, ast_verb, ast_channel_snapshot::base, ast_bridge_channel::bridge_pvt, ast_bridge_channel::chan, parked_user::chan, COLOR_BRMAGENTA, COLORIZE, COLORIZE_FMT, parked_user::comeback, ast_bridge_channel::features, generate_parked_user(), get_park_common_datastore_copy(), LOG_WARNING, ast_channel_snapshot_base::name, NULL, park_common_datastore_free(), PARKED_CALL, PARKED_CALL_SWAP, parking_channel_set_roles(), parking_notify_metermaids(), parking_set_duration(), parked_user::parking_space, pbx_builtin_getvar_helper(), publish_parked_call(), publish_parked_call_failure(), ast_bridge_methods::push, RAII_VAR, S_OR, and say_parking_space().

207 {
208  struct parked_user *pu;
209  const char *blind_transfer;
210  struct ast_channel_snapshot *parker = NULL;
211  const char *parker_channel_name = NULL;
213 
214  ast_bridge_base_v_table.push(&self->base, bridge_channel, swap);
215 
216  ast_assert(self->lot != NULL);
217 
218  /* Answer the channel if needed */
219  if (ast_channel_state(bridge_channel->chan) != AST_STATE_UP) {
220  ast_answer(bridge_channel->chan);
221  }
222 
223  if (swap) {
224  int use_ringing = 0;
225 
227  pu = swap->bridge_pvt;
228  if (!pu) {
229  /* This should be impossible since the only way a channel can enter in the first place
230  * is if it has a parked user associated with it */
231  publish_parked_call_failure(bridge_channel->chan);
233  return -1;
234  }
235 
236  /* Give the swap channel's parked user reference to the incoming channel */
237  pu->chan = bridge_channel->chan;
238  bridge_channel->bridge_pvt = pu;
239  swap->bridge_pvt = NULL;
240 
241  if (ast_bridge_channel_has_role(swap, "holding_participant")) {
242  const char *idle_mode = ast_bridge_channel_get_role_option(swap, "holding_participant", "idle_mode");
243 
244  if (!ast_strlen_zero(idle_mode) && !strcmp(idle_mode, "ringing")) {
245  use_ringing = 1;
246  }
247  }
248 
250 
251  parking_set_duration(bridge_channel->features, pu);
252 
253  if (parking_channel_set_roles(bridge_channel->chan, self->lot, use_ringing)) {
254  ast_log(LOG_WARNING, "Failed to apply holding bridge roles to %s while joining the parking lot.\n",
255  ast_channel_name(bridge_channel->chan));
256  }
257 
259 
260  return 0;
261  }
262 
263  if (!(park_datastore = get_park_common_datastore_copy(bridge_channel->chan))) {
264  /* There was either a failure to apply the datastore when performing park common setup or else we had alloc failures while cloning. Abort. */
265  return -1;
266  }
267  parker = ast_channel_snapshot_get_latest(park_datastore->parker_uuid);
268 
269  /* If the parker and the parkee are the same channel pointer, then the channel entered using
270  * the park application. It's possible that the channel that transferred it is still alive (particularly
271  * when a multichannel bridge is parked), so try to get the real parker if possible. */
272  ast_channel_lock(bridge_channel->chan);
273  blind_transfer = pbx_builtin_getvar_helper(bridge_channel->chan, "BLINDTRANSFER");
274  blind_transfer = ast_strdupa(S_OR(blind_transfer, ""));
275  ast_channel_unlock(bridge_channel->chan);
276  if (!parker || !strcmp(parker->base->name, ast_channel_name(bridge_channel->chan))) {
277  if (ast_strlen_zero(blind_transfer) && parker) {
278  /* If no BLINDTRANSFER exists but the parker does then use their channel name */
279  parker_channel_name = parker->base->name;
280  } else {
281  /* Even if there is no BLINDTRANSFER dialplan variable then blind_transfer will
282  * be an empty string.
283  */
284  parker_channel_name = blind_transfer;
285  }
286  } else {
287  parker_channel_name = parker->base->name;
288  }
289 
290  pu = generate_parked_user(self->lot, bridge_channel->chan, parker_channel_name,
291  park_datastore->parker_dial_string, park_datastore->randomize, park_datastore->time_limit);
292  ao2_cleanup(parker);
293  if (!pu) {
294  publish_parked_call_failure(bridge_channel->chan);
295  return -1;
296  }
297 
298  /* If a comeback_override was provided, set it for the parked user's comeback string. */
299  if (park_datastore->comeback_override) {
300  ast_copy_string(pu->comeback, park_datastore->comeback_override, sizeof(pu->comeback));
301  }
302 
303  /* Generate ParkedCall Stasis Message */
305 
306  /* If not a blind transfer and silence_announce isn't set, play the announcement to the parkee */
307  if (ast_strlen_zero(blind_transfer) && !park_datastore->silence_announce) {
308  char saynum_buf[16];
309 
310  snprintf(saynum_buf, sizeof(saynum_buf), "%d %d", 0, pu->parking_space);
311  ast_bridge_channel_queue_playfile(bridge_channel, say_parking_space, saynum_buf, NULL);
312  }
313 
314  /* Apply parking duration limits */
315  parking_set_duration(bridge_channel->features, pu);
316 
317  /* Set this to the bridge pvt so that we don't have to refind the parked user associated with this bridge channel again. */
318  bridge_channel->bridge_pvt = pu;
319 
320  ast_verb(3, "Parking '" COLORIZE_FMT "' in '" COLORIZE_FMT "' at space %d\n",
321  COLORIZE(COLOR_BRMAGENTA, 0, ast_channel_name(bridge_channel->chan)),
322  COLORIZE(COLOR_BRMAGENTA, 0, self->lot->name),
323  pu->parking_space);
324 
326 
327  return 0;
328 }
int ast_bridge_channel_has_role(struct ast_bridge_channel *bridge_channel, const char *role_name)
Check to see if a bridge channel inherited a specific role from its channel.
Definition: bridge_roles.c:418
#define ast_channel_lock(chan)
Definition: channel.h:2945
struct ast_channel_snapshot_base * base
struct ast_bridge_features * features
void park_common_datastore_free(struct park_common_datastore *datastore)
Free a park common datastore struct.
void parking_notify_metermaids(int exten, const char *context, enum ast_device_state state)
Notify metermaids that we've changed an extension.
#define LOG_WARNING
Definition: logger.h:274
struct ast_bridge base
Structure representing a snapshot of channel state.
struct parking_lot * lot
ast_channel_state
ast_channel states
Definition: channelstate.h:35
#define ast_assert(a)
Definition: utils.h:695
void parking_set_duration(struct ast_bridge_features *features, struct parked_user *user)
Setup timeout interval feature on an ast_bridge_features for parking.
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:463
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.
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 COLORIZE(fg, bg, str)
Definition: term.h:68
#define ast_strlen_zero(foo)
Definition: strings.h:52
void publish_parked_call_failure(struct ast_channel *parkee)
Publish a stasis parked call message for the channel indicating failure to park.
struct ast_bridge_methods ast_bridge_base_v_table
Bridge base class virtual method table.
Definition: bridge.c:949
#define ast_log
Definition: astobj2.c:42
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.
#define ast_bridge_channel_lock(bridge_channel)
Lock the bridge_channel.
const ast_string_field parking_con
Definition: res_parking.h:89
#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:911
int parking_space
Definition: res_parking.h:107
#define COLORIZE_FMT
Shortcut macros for coloring a set of text.
Definition: term.h:67
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define COLOR_BRMAGENTA
Definition: term.h:58
#define ast_bridge_channel_unlock(bridge_channel)
Unlock the bridge_channel.
char comeback[80]
Definition: res_parking.h:108
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 option...
#define ast_channel_unlock(chan)
Definition: channel.h:2946
const ast_string_field name
Definition: res_parking.h:100
struct ast_channel * chan
void * bridge_pvt
Bridge class private channel data.
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.
struct ast_channel_snapshot * ast_channel_snapshot_get_latest(const char *uniqueid)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object...
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
const char * ast_channel_name(const struct ast_channel *chan)
int ast_bridge_channel_queue_playfile(struct ast_bridge_channel *bridge_channel, ast_bridge_custom_play_fn custom_play, const char *playfile, const char *moh_class)
Queue a bridge action play file frame onto the bridge channel.
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2814
ast_bridge_push_channel_fn push
Definition: bridge.h:273
const char * ast_bridge_channel_get_role_option(struct ast_bridge_channel *bridge_channel, const char *role_name, const char *option)
Retrieve the value of a requested role option from a bridge channel.
Definition: bridge_roles.c:427
struct ast_channel * chan
Definition: res_parking.h:104
static struct parked_user * generate_parked_user(struct parking_lot *lot, struct ast_channel *chan, const char *parker_channel_name, const char *parker_dial_string, int use_random_space, int time_limit)
const ast_string_field name
struct parking_lot_cfg * cfg
Definition: res_parking.h:96

◆ destroy_parked_user()

static void destroy_parked_user ( void *  obj)
static

Definition at line 65 of file parking_bridge.c.

References ao2_cleanup, ast_free, parked_user::lot, parked_user::parker_dial_string, and parked_user::retriever.

Referenced by generate_parked_user().

66 {
67  struct parked_user *pu = obj;
68 
69  ao2_cleanup(pu->lot);
72 }
struct parking_lot * lot
Definition: res_parking.h:111
char * parker_dial_string
Definition: res_parking.h:109
#define ast_free(a)
Definition: astmm.h:182
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_channel_snapshot * retriever
Definition: res_parking.h:105

◆ generate_parked_user()

static struct parked_user* generate_parked_user ( struct parking_lot lot,
struct ast_channel chan,
const char *  parker_channel_name,
const char *  parker_dial_string,
int  use_random_space,
int  time_limit 
)
static

Definition at line 109 of file parking_bridge.c.

References ao2_alloc, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_channel_lock, ast_channel_unlock, ast_log, ast_random(), ast_strdup, ast_strdupa, ast_strlen_zero, ast_tvnow(), parking_lot::cfg, parked_user::chan, destroy_parked_user(), if(), LOG_NOTICE, LOG_WARNING, parked_user::lot, parking_lot::mode, parking_lot::name, parking_lot::next_space, NULL, parked_user_set_parker_dial_string(), parking_lot::parked_users, parked_user::parker_dial_string, parking_lot_get_space(), parked_user::parking_space, parking_lot_cfg::parking_start, parking_lot_cfg::parking_stop, PARKINGLOT_DISABLED, parking_lot_cfg::parkingtime, pbx_builtin_getvar_helper(), parked_user::start, and parked_user::time_limit.

Referenced by bridge_parking_push().

110 {
111  struct parked_user *new_parked_user;
112  int preferred_space = -1; /* Initialize to use parking lot defaults */
113  int parking_space;
114  const char *parkingexten;
115 
116  if (lot->mode == PARKINGLOT_DISABLED) {
117  ast_log(LOG_NOTICE, "Tried to park in a parking lot that is no longer able to be parked to.\n");
118  return NULL;
119  }
120 
121  new_parked_user = ao2_alloc(sizeof(*new_parked_user), destroy_parked_user);
122  if (!new_parked_user) {
123  return NULL;
124  }
125 
126  if (use_random_space) {
127  preferred_space = ast_random() % (lot->cfg->parking_stop - lot->cfg->parking_start + 1);
128  preferred_space += lot->cfg->parking_start;
129  } else {
130  ast_channel_lock(chan);
131  if ((parkingexten = pbx_builtin_getvar_helper(chan, "PARKINGEXTEN"))) {
132  parkingexten = ast_strdupa(parkingexten);
133  }
134  ast_channel_unlock(chan);
135 
136  if (!ast_strlen_zero(parkingexten)) {
137  if (sscanf(parkingexten, "%30d", &preferred_space) != 1 || preferred_space <= 0) {
138  ast_log(LOG_WARNING, "PARKINGEXTEN='%s' is not a valid parking space.\n", parkingexten);
139  ao2_ref(new_parked_user, -1);
140  return NULL;
141  }
142  }
143  }
144 
145  /* We need to keep the lot locked between parking_lot_get_space and actually placing it in the lot. Or until we decide not to. */
146  ao2_lock(lot);
147 
148  parking_space = parking_lot_get_space(lot, preferred_space);
149  if (parking_space == -1) {
150  ast_log(LOG_NOTICE, "Failed to get parking space in lot '%s'. All full.\n", lot->name);
151  ao2_ref(new_parked_user, -1);
152  ao2_unlock(lot);
153  return NULL;
154  }
155 
156  lot->next_space = ((parking_space + 1) - lot->cfg->parking_start) % (lot->cfg->parking_stop - lot->cfg->parking_start + 1) + lot->cfg->parking_start;
157  new_parked_user->chan = chan;
158  new_parked_user->parking_space = parking_space;
159 
160  /* Have the parked user take a reference to the parking lot. This reference should be immutable and released at destruction */
161  new_parked_user->lot = lot;
162  ao2_ref(lot, +1);
163 
164  new_parked_user->start = ast_tvnow();
165  new_parked_user->time_limit = (time_limit >= 0) ? time_limit : lot->cfg->parkingtime;
166 
169  } else {
170  if (ast_strlen_zero(parker_channel_name) || parked_user_set_parker_dial_string(new_parked_user, parker_channel_name)) {
171  ao2_ref(new_parked_user, -1);
172  ao2_unlock(lot);
173  return NULL;
174  }
175  }
176 
177  if (!new_parked_user->parker_dial_string) {
178  ao2_ref(new_parked_user, -1);
179  ao2_unlock(lot);
180  return NULL;
181  }
182 
183  /* Insert into the parking lot's parked user list. We can unlock the lot now. */
184  ao2_link(lot->parked_users, new_parked_user);
185  ao2_unlock(lot);
186 
187  return new_parked_user;
188 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
int parking_lot_get_space(struct parking_lot *lot, int target_override)
Get an available parking space within a parking lot.
#define LOG_WARNING
Definition: logger.h:274
struct ao2_container * parked_users
Definition: res_parking.h:95
unsigned int parkingtime
Definition: res_parking.h:69
unsigned int time_limit
Definition: res_parking.h:110
if(!yyg->yy_init)
Definition: ast_expr2f.c:868
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
struct parking_lot * lot
Definition: res_parking.h:111
struct timeval start
Definition: res_parking.h:106
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 ast_strlen_zero(foo)
Definition: strings.h:52
int next_space
Definition: res_parking.h:93
#define ast_log
Definition: astobj2.c:42
char * parker_dial_string
Definition: res_parking.h:109
int parking_space
Definition: res_parking.h:107
#define ao2_ref(o, delta)
Definition: astobj2.h:464
long int ast_random(void)
Definition: main/utils.c:2064
#define ao2_lock(a)
Definition: astobj2.h:718
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static int parked_user_set_parker_dial_string(struct parked_user *pu, const char *parker_channel_name)
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
#define LOG_NOTICE
Definition: logger.h:263
#define ast_channel_unlock(chan)
Definition: channel.h:2946
const ast_string_field name
Definition: res_parking.h:100
enum parking_lot_modes mode
Definition: res_parking.h:97
static void destroy_parked_user(void *obj)
struct ast_channel * chan
Definition: res_parking.h:104
struct parking_lot_cfg * cfg
Definition: res_parking.h:96
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ parked_user_set_parker_dial_string()

static int parked_user_set_parker_dial_string ( struct parked_user pu,
const char *  parker_channel_name 
)
static

Definition at line 75 of file parking_bridge.c.

References ast_channel_name_to_dial_string(), ast_strdup, ast_strdupa, and parked_user::parker_dial_string.

Referenced by generate_parked_user().

76 {
77  char *dial_string = ast_strdupa(parker_channel_name);
78 
80  pu->parker_dial_string = ast_strdup(dial_string);
81 
82  if (!pu->parker_dial_string) {
83  return -1;
84  }
85 
86  return 0;
87 }
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
char * parker_dial_string
Definition: res_parking.h:109
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
void ast_channel_name_to_dial_string(char *channel_name)
Removes the trailing identifiers from a channel name string.
Definition: channel.c:6934

Variable Documentation

◆ ast_bridge_parking_v_table

struct ast_bridge_methods ast_bridge_parking_v_table

Definition at line 428 of file parking_bridge.c.