Asterisk - The Open Source Telephony Project GIT-master-d856a3e
parking_bridge.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2013, Digium, Inc.
5 *
6 * Jonathan Rose <jrose@digium.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19/*! \file
20 *
21 * \brief Parking Bridge Class
22 *
23 * \author Jonathan Rose <jrose@digium.com>
24 */
25
26#include "asterisk.h"
27#include "res_parking.h"
28#include "asterisk/astobj2.h"
29#include "asterisk/logger.h"
30#include "asterisk/say.h"
31#include "asterisk/term.h"
32#include "asterisk/features.h"
34
36{
38
39 /* private stuff for parking */
41};
42
43/*!
44 * \internal
45 * \brief ast_bridge parking class destructor
46 * \since 12.0.0
47 *
48 * \param self Bridge to operate upon.
49 *
50 * \note XXX Stub... and it might go unused.
51 */
53{
55}
56
58{
59 self->lot = NULL;
61}
62
63static void destroy_parked_user(void *obj)
64{
65 struct parked_user *pu = obj;
66
67 ao2_cleanup(pu->lot);
70}
71
72/* Only call this on a parked user that hasn't had its parker_dial_string set already */
73static int parked_user_set_parker_dial_string(struct parked_user *pu, const char *parker_channel_name)
74{
75 char *dial_string = ast_strdupa(parker_channel_name);
76
78 pu->parker_dial_string = ast_strdup(dial_string);
79
80 if (!pu->parker_dial_string) {
81 return -1;
82 }
83
84 return 0;
85}
86
87/*!
88 * \internal
89 * \since 12
90 * \brief Construct a parked_user struct assigned to the specified parking lot
91 *
92 * \param lot The parking lot we are assigning the user to
93 * \param chan The channel being parked
94 * \param parker_channel_name The name of the parker of this channel
95 * \param parker_dial_string Takes priority over parker for setting the parker dial string if included
96 * \param use_random_space if true, prioritize using a random parking space instead
97 * of ${PARKINGEXTEN} and/or automatic assignment from the parking lot
98 * \param time_limit If using a custom timeout, this should be supplied so that the
99 * parked_user struct can provide this information for manager events. If <0,
100 * use the parking lot limit instead.
101 *
102 * \retval NULL on failure
103 * \return reference to the parked user
104 *
105 * \note ao2_cleanup this reference when you are done using it or you'll cause leaks.
106 */
107static 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)
108{
109 struct parked_user *new_parked_user;
110 int preferred_space = -1; /* Initialize to use parking lot defaults */
111 int parking_space;
112 const char *parkingexten;
113
114 if (lot->mode == PARKINGLOT_DISABLED) {
115 ast_log(LOG_NOTICE, "Tried to park in a parking lot that is no longer able to be parked to.\n");
116 return NULL;
117 }
118
119 new_parked_user = ao2_alloc(sizeof(*new_parked_user), destroy_parked_user);
120 if (!new_parked_user) {
121 return NULL;
122 }
123
124 if (use_random_space) {
125 preferred_space = ast_random() % (lot->cfg->parking_stop - lot->cfg->parking_start + 1);
126 preferred_space += lot->cfg->parking_start;
127 } else {
129 if ((parkingexten = pbx_builtin_getvar_helper(chan, "PARKINGEXTEN"))) {
130 parkingexten = ast_strdupa(parkingexten);
131 }
133
134 if (!ast_strlen_zero(parkingexten)) {
135 if (sscanf(parkingexten, "%30d", &preferred_space) != 1 || preferred_space <= 0) {
136 ast_log(LOG_WARNING, "PARKINGEXTEN='%s' is not a valid parking space.\n", parkingexten);
137 ao2_ref(new_parked_user, -1);
138 return NULL;
139 }
140 }
141 }
142
143 /* 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. */
144 ao2_lock(lot);
145
146 parking_space = parking_lot_get_space(lot, preferred_space);
147 if (parking_space == -1) {
148 ast_log(LOG_NOTICE, "Failed to get parking space in lot '%s'. All full.\n", lot->name);
149 ao2_ref(new_parked_user, -1);
151 return NULL;
152 }
153
155 new_parked_user->chan = chan;
156 new_parked_user->parking_space = parking_space;
157
158 /* Have the parked user take a reference to the parking lot. This reference should be immutable and released at destruction */
159 new_parked_user->lot = lot;
160 ao2_ref(lot, +1);
161
162 new_parked_user->start = ast_tvnow();
163 new_parked_user->time_limit = (time_limit >= 0) ? time_limit : lot->cfg->parkingtime;
164
167 } else {
168 if (ast_strlen_zero(parker_channel_name) || parked_user_set_parker_dial_string(new_parked_user, parker_channel_name)) {
169 ao2_ref(new_parked_user, -1);
171 return NULL;
172 }
173 }
174
175 if (!new_parked_user->parker_dial_string) {
176 ao2_ref(new_parked_user, -1);
178 return NULL;
179 }
180
181 /* Insert into the parking lot's parked user list. We can unlock the lot now. */
182 ao2_link(lot->parked_users, new_parked_user);
184
185 return new_parked_user;
186}
187
188/* TODO CEL events for parking */
189
190/*!
191 * \internal
192 * \brief ast_bridge parking push method.
193 * \since 12.0.0
194 *
195 * \param self Bridge to operate upon
196 * \param bridge_channel Bridge channel to push
197 * \param swap Bridge channel to swap places with if not NULL
198 *
199 * \note On entry, self is already locked
200 *
201 * \retval 0 on success
202 * \retval -1 on failure
203 */
204static int bridge_parking_push(struct ast_bridge_parking *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
205{
206 struct parked_user *pu;
207 const char *blind_transfer;
208 struct ast_channel_snapshot *parker = NULL;
209 const char *parker_channel_name = NULL;
211
212 ast_bridge_base_v_table.push(&self->base, bridge_channel, swap);
213
214 ast_assert(self->lot != NULL);
215
216 /* Answer the channel if needed */
217 if (ast_channel_state(bridge_channel->chan) != AST_STATE_UP) {
218 ast_answer(bridge_channel->chan);
219 }
220
221 if (swap) {
222 int use_ringing = 0;
223
225 pu = swap->bridge_pvt;
226 if (!pu) {
227 /* This should be impossible since the only way a channel can enter in the first place
228 * is if it has a parked user associated with it */
229 publish_parked_call_failure(bridge_channel->chan);
231 return -1;
232 }
233
234 /* Give the swap channel's parked user reference to the incoming channel */
235 pu->chan = bridge_channel->chan;
236 bridge_channel->bridge_pvt = pu;
237 swap->bridge_pvt = NULL;
238
239 if (ast_bridge_channel_has_role(swap, "holding_participant")) {
240 const char *idle_mode = ast_bridge_channel_get_role_option(swap, "holding_participant", "idle_mode");
241
242 if (!ast_strlen_zero(idle_mode) && !strcmp(idle_mode, "ringing")) {
243 use_ringing = 1;
244 }
245 }
246
248
249 parking_set_duration(bridge_channel->features, pu);
250
251 if (parking_channel_set_roles(bridge_channel->chan, self->lot, use_ringing)) {
252 ast_log(LOG_WARNING, "Failed to apply holding bridge roles to %s while joining the parking lot.\n",
253 ast_channel_name(bridge_channel->chan));
254 }
255
257
258 return 0;
259 }
260
261 if (!(park_datastore = get_park_common_datastore_copy(bridge_channel->chan))) {
262 /* There was either a failure to apply the datastore when performing park common setup or else we had alloc failures while cloning. Abort. */
263 return -1;
264 }
265 parker = ast_channel_snapshot_get_latest(park_datastore->parker_uuid);
266
267 /* If the parker and the parkee are the same channel pointer, then the channel entered using
268 * the park application. It's possible that the channel that transferred it is still alive (particularly
269 * when a multichannel bridge is parked), so try to get the real parker if possible. */
270 ast_channel_lock(bridge_channel->chan);
271 blind_transfer = pbx_builtin_getvar_helper(bridge_channel->chan, "BLINDTRANSFER");
272 blind_transfer = ast_strdupa(S_OR(blind_transfer, ""));
273 ast_channel_unlock(bridge_channel->chan);
274 if (!parker || !strcmp(parker->base->name, ast_channel_name(bridge_channel->chan))) {
275 if (ast_strlen_zero(blind_transfer) && parker) {
276 /* If no BLINDTRANSFER exists but the parker does then use their channel name */
277 parker_channel_name = parker->base->name;
278 } else {
279 /* Even if there is no BLINDTRANSFER dialplan variable then blind_transfer will
280 * be an empty string.
281 */
282 parker_channel_name = blind_transfer;
283 }
284 } else {
285 parker_channel_name = parker->base->name;
286 }
287
288 pu = generate_parked_user(self->lot, bridge_channel->chan, parker_channel_name,
289 park_datastore->parker_dial_string, park_datastore->randomize, park_datastore->time_limit);
290 ao2_cleanup(parker);
291 if (!pu) {
292 publish_parked_call_failure(bridge_channel->chan);
293 return -1;
294 }
295
296 /* If a comeback_override was provided, set it for the parked user's comeback string. */
297 if (park_datastore->comeback_override) {
298 ast_copy_string(pu->comeback, park_datastore->comeback_override, sizeof(pu->comeback));
299 }
300
301 /* Generate ParkedCall Stasis Message */
303
304 /* If not a blind transfer and silence_announce isn't set, play the announcement to the parkee */
305 if (ast_strlen_zero(blind_transfer) && !park_datastore->silence_announce) {
306 char saynum_buf[16];
307
308 snprintf(saynum_buf, sizeof(saynum_buf), "%d %d", 0, pu->parking_space);
309 ast_bridge_channel_queue_playfile(bridge_channel, say_parking_space, saynum_buf, NULL);
310 }
311
312 /* Apply parking duration limits */
313 parking_set_duration(bridge_channel->features, pu);
314
315 /* Set this to the bridge pvt so that we don't have to refind the parked user associated with this bridge channel again. */
316 bridge_channel->bridge_pvt = pu;
317
318 ast_verb(3, "Parking '" COLORIZE_FMT "' in '" COLORIZE_FMT "' at space %d\n",
319 COLORIZE(COLOR_BRMAGENTA, 0, ast_channel_name(bridge_channel->chan)),
320 COLORIZE(COLOR_BRMAGENTA, 0, self->lot->name),
321 pu->parking_space);
322
324
325 return 0;
326}
327
328/*!
329 * \internal
330 * \brief ast_bridge parking pull method.
331 * \since 12.0.0
332 *
333 * \param self Bridge to operate upon.
334 * \param bridge_channel Bridge channel to pull.
335 *
336 * \note On entry, self is already locked.
337 */
338static void bridge_parking_pull(struct ast_bridge_parking *self, struct ast_bridge_channel *bridge_channel)
339{
340 RAII_VAR(struct parked_user *, pu, NULL, ao2_cleanup);
341
342 ast_bridge_base_v_table.pull(&self->base, bridge_channel);
343
344 /* Take over the bridge channel's pu reference. It will be released when we are done. */
345 pu = bridge_channel->bridge_pvt;
346 bridge_channel->bridge_pvt = NULL;
347
348 /* This should only happen if the exiting channel was swapped out */
349 if (!pu) {
350 return;
351 }
352
353 /* If we got here without the resolution being set, that's because the call was hung up for some reason without
354 * timing out or being picked up. There may be some forcible park removals later, but the resolution should be
355 * handled in those cases */
356 ao2_lock(pu);
357 if (pu->resolution == PARK_UNSET) {
358 pu->resolution = PARK_ABANDON;
359 }
360 ao2_unlock(pu);
361
362 /* Pull can still happen after the bridge starts dissolving, so make sure we still have a lot before trying to notify metermaids. */
363 if (self->lot) {
365 }
366
367 switch (pu->resolution) {
368 case PARK_UNSET:
369 /* This should be impossible now since the resolution is forcibly set to abandon if it was unset at this point. Resolution
370 isn't allowed to be changed when it isn't currently PARK_UNSET. */
371 break;
372 case PARK_ABANDON:
373 /* Since the call was abandoned without additional handling, we need to issue the give up event and unpark the user. */
376 break;
377 case PARK_FORCED:
378 /* PARK_FORCED is currently unused, but it is expected that it would be handled similar to PARK_ANSWERED.
379 * There is currently no event related to forced parked calls either */
380 break;
381 case PARK_ANSWERED:
382 /* If answered or forced, the channel should be pulled from the bridge as part of that process and unlinked from
383 * the parking lot afterwards. We do need to apply bridge features though and play the courtesy tone if set. */
386
387 if (pu->lot->cfg->parkedplay & AST_FEATURE_FLAG_BYCALLEE) {
388 ast_bridge_channel_queue_playfile(bridge_channel, NULL, pu->lot->cfg->courtesytone, NULL);
389 }
390 break;
391 case PARK_TIMEOUT:
392 /* Timeout is similar to abandon because it simply sets the bridge state to end and doesn't
393 * actually pull the channel. Because of that, unpark should happen in here. */
397 break;
398 }
399}
400
401/*!
402 * \internal
403 * \brief ast_bridge parking notify_masquerade method.
404 * \since 12.0.0
405 *
406 * \param self Bridge to operate upon.
407 * \param bridge_channel Bridge channel that was masqueraded.
408 *
409 * \note On entry, self is already locked.
410 * \note XXX Stub... and it will probably go unused.
411 */
412static void bridge_parking_notify_masquerade(struct ast_bridge_parking *self, struct ast_bridge_channel *bridge_channel)
413{
414 ast_bridge_base_v_table.notify_masquerade(&self->base, bridge_channel);
415}
416
418{
420}
421
423 .name = "parking",
430};
431
432static struct ast_bridge *ast_bridge_parking_init(struct ast_bridge_parking *self, struct parking_lot *bridge_lot)
433{
434 if (!self) {
435 return NULL;
436 }
437
438 /* If no lot is defined for the bridge, then we aren't allowing the bridge to be initialized. */
439 if (!bridge_lot) {
440 ao2_ref(self, -1);
441 return NULL;
442 }
443
444 /* It doesn't need to be a reference since the bridge only lives as long as the parking lot lives. */
445 self->lot = bridge_lot;
446
447 return &self->base;
448}
449
450struct ast_bridge *bridge_parking_new(struct parking_lot *bridge_lot)
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}
if(!yyg->yy_init)
Definition: ast_expr2f.c:854
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_log
Definition: astobj2.c:42
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
void(* ast_bridge_destructor_fn)(struct ast_bridge *self)
Destroy the bridge.
Definition: bridge.h:176
void(* ast_bridge_notify_masquerade_fn)(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel)
Notify the bridge that this channel was just masqueraded.
Definition: bridge.h:238
void(* ast_bridge_dissolving_fn)(struct ast_bridge *self)
The bridge is being dissolved.
Definition: bridge.h:189
struct ast_bridge_methods ast_bridge_base_v_table
Bridge base class virtual method table.
Definition: bridge.c:923
int(* ast_bridge_merge_priority_fn)(struct ast_bridge *self)
Get the merge priority of this bridge.
Definition: bridge.h:249
@ AST_BRIDGE_CAPABILITY_HOLDING
Definition: bridge.h:86
void(* ast_bridge_pull_channel_fn)(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel)
Pull this channel from the bridge.
Definition: bridge.h:224
int(* ast_bridge_push_channel_fn)(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
Push this channel into the bridge.
Definition: bridge.h:209
#define ast_bridge_channel_unlock(bridge_channel)
Unlock the bridge_channel.
#define ast_bridge_channel_lock(bridge_channel)
Lock the bridge_channel.
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_FLAG_SWAP_INHIBIT_FROM
@ AST_BRIDGE_FLAG_MERGE_INHIBIT_TO
@ AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM
Private Bridging API.
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
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:423
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:414
const char * ast_channel_name(const struct ast_channel *chan)
#define ast_channel_lock(chan)
Definition: channel.h:2968
void ast_channel_name_to_dial_string(char *channel_name)
Removes the trailing identifiers from a channel name string.
Definition: channel.c:6858
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2824
#define ast_channel_unlock(chan)
Definition: channel.h:2969
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_UP
Definition: channelstate.h:42
@ AST_DEVICE_INUSE
Definition: devicestate.h:55
@ AST_DEVICE_NOT_INUSE
Definition: devicestate.h:54
Call Parking and Pickup API Includes code and algorithms from the Zapata library.
@ AST_FEATURE_FLAG_BYCALLEE
Definition: features.h:37
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,...
Support for logging to various files, console and syslog Configuration in file logger....
#define ast_verb(level,...)
#define LOG_NOTICE
#define LOG_WARNING
@ PARKED_CALL
Definition: parking.h:47
@ PARKED_CALL_TIMEOUT
Definition: parking.h:48
@ PARKED_CALL_UNPARKED
Definition: parking.h:50
@ PARKED_CALL_GIVEUP
Definition: parking.h:49
@ PARKED_CALL_SWAP
Definition: parking.h:52
void park_common_datastore_free(struct park_common_datastore *datastore)
Free a park common datastore struct.
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_bridge * bridge_parking_new(struct parking_lot *bridge_lot)
Create a new parking bridge.
struct ast_bridge_methods ast_bridge_parking_v_table
static void bridge_parking_pull(struct ast_bridge_parking *self, struct ast_bridge_channel *bridge_channel)
static void bridge_parking_get_merge_priority(struct ast_bridge_parking *self)
static void bridge_parking_notify_masquerade(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 bridge_parking_dissolving(struct ast_bridge_parking *self)
static void destroy_parked_user(void *obj)
static void bridge_parking_destroy(struct ast_bridge_parking *self)
static struct ast_bridge * ast_bridge_parking_init(struct ast_bridge_parking *self, struct parking_lot *bridge_lot)
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 int parked_user_set_parker_dial_string(struct parked_user *pu, const char *parker_channel_name)
void parking_set_duration(struct ast_bridge_features *features, struct parked_user *user)
Setup timeout interval feature on an ast_bridge_features for parking.
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...
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.
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.
int parking_lot_get_space(struct parking_lot *lot, int target_override)
Get an available parking space within a parking lot.
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.
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.
void publish_parked_call_failure(struct ast_channel *parkee)
Publish a stasis parked call message for the channel indicating failure to park.
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Call Parking Resource Internal API.
@ 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
@ PARKINGLOT_DISABLED
Definition: res_parking.h:61
#define NULL
Definition: resample.c:96
Say numbers and dates (maybe words one day too)
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
Structure that contains information regarding a channel in a bridge.
void * bridge_pvt
Bridge class private channel data.
struct ast_bridge_features * features
struct ast_channel * chan
Bridge virtual methods table definition.
Definition: bridge.h:257
ast_bridge_dissolving_fn dissolving
Definition: bridge.h:263
ast_bridge_push_channel_fn push
Definition: bridge.h:265
const char * name
Definition: bridge.h:259
ast_bridge_notify_masquerade_fn notify_masquerade
Definition: bridge.h:269
ast_bridge_destructor_fn destroy
Definition: bridge.h:261
ast_bridge_merge_priority_fn get_merge_priority
Definition: bridge.h:271
ast_bridge_pull_channel_fn pull
Definition: bridge.h:267
struct ast_bridge base
struct parking_lot * lot
Structure that contains information about a bridge.
Definition: bridge.h:349
const ast_string_field name
Structure representing a snapshot of channel state.
struct ast_channel_snapshot_base * base
Main Channel structure associated with a channel.
char * parker_dial_string
Definition: res_parking.h:111
unsigned int time_limit
Definition: res_parking.h:112
int parking_space
Definition: res_parking.h:109
struct ast_channel * chan
Definition: res_parking.h:106
struct parking_lot * lot
Definition: res_parking.h:113
struct ast_channel_snapshot * retriever
Definition: res_parking.h:107
char comeback[AST_MAX_CONTEXT]
Definition: res_parking.h:110
struct timeval start
Definition: res_parking.h:108
unsigned int parkingtime
Definition: res_parking.h:69
const ast_string_field parking_con
Definition: res_parking.h:89
int next_space
Definition: res_parking.h:93
enum parking_lot_modes mode
Definition: res_parking.h:97
struct parking_lot_cfg * cfg
Definition: res_parking.h:96
const ast_string_field name
Definition: res_parking.h:102
struct ao2_container * parked_users
Definition: res_parking.h:95
Handy terminal functions for vt* terms.
#define COLORIZE(fg, bg, str)
Definition: term.h:72
#define COLORIZE_FMT
Shortcut macros for coloring a set of text.
Definition: term.h:71
#define COLOR_BRMAGENTA
Definition: term.h:61
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
#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
#define ast_assert(a)
Definition: utils.h:739
long int ast_random(void)
Definition: utils.c:2312