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

Parking Bridge DTMF and Interval features. More...

#include "asterisk.h"
#include "res_parking.h"
#include "asterisk/utils.h"
#include "asterisk/astobj2.h"
#include "asterisk/logger.h"
#include "asterisk/pbx.h"
#include "asterisk/app.h"
#include "asterisk/bridge.h"
#include "asterisk/bridge_internal.h"
#include "asterisk/bridge_channel.h"
#include "asterisk/bridge_features.h"
#include "asterisk/conversions.h"
#include "asterisk/features.h"
#include "asterisk/say.h"
#include "asterisk/datastore.h"
#include "asterisk/stasis.h"
#include "asterisk/module.h"
#include "asterisk/core_local.h"
#include "asterisk/causes.h"
Include dependency graph for parking_bridge_features.c:

Go to the source code of this file.

Data Structures

struct  parked_subscription_data
 
struct  parked_subscription_datastore
 

Functions

int create_parked_subscription (struct ast_channel *chan, const char *parkee_uuid, int hangup_after)
 Create a parking announcement subscription. More...
 
static int create_parked_subscription_full (struct ast_channel *chan, const char *parkee_uuid, int hangup_after, struct transfer_channel_data *parked_channel_data)
 
static int feature_park_call (struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 
static int func_get_parkingslot_channel (struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
 Dial plan function to get the parking lot channel of an occupied parking lot. More...
 
int load_parking_bridge_features (void)
 Register bridge features for parking. More...
 
static struct ast_channelpark_local_transfer (struct ast_channel *parker, const char *context, const char *exten, struct transfer_channel_data *parked_channel_data)
 
static void parked_subscription_datastore_destroy (void *data)
 
static void parker_parked_call_message_response (struct ast_parked_call_payload *message, struct parked_subscription_data *data, struct stasis_subscription *sub)
 
static void parker_update_cb (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 
static int parking_blind_transfer_park (struct ast_bridge_channel *bridge_channel, const char *context, const char *exten, transfer_channel_cb parked_channel_cb, struct transfer_channel_data *parked_channel_data)
 
static int parking_duration_callback (struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 
static int parking_is_exten_park (const char *context, const char *exten)
 
static int parking_park_bridge_channel (struct ast_bridge_channel *bridge_channel, const char *uuid_parkee, const char *uuid_parker, const char *app_data)
 
static int parking_park_call (struct ast_bridge_channel *parker, char *exten, size_t length)
 
void parking_set_duration (struct ast_bridge_features *features, struct parked_user *user)
 Setup timeout interval feature on an ast_bridge_features for parking. More...
 
static void parking_timeout_set_caller_features (struct ast_channel *chan, struct parking_lot_cfg *cfg)
 
void say_parking_space (struct ast_bridge_channel *bridge_channel, const char *payload)
 custom callback function for ast_bridge_channel_queue_playfile which plays a parking space and optionally hangs up the call afterwards based on the payload in playfile. More...
 
void unload_parking_bridge_features (void)
 Unregister features registered by load_parking_bridge_features. More...
 
static void wipe_subscription_datastore (struct ast_channel *chan)
 

Variables

static struct ast_custom_function getparkingslotchannel_function
 
static const struct ast_datastore_info parked_subscription_info
 
struct ast_parking_bridge_feature_fn_table parking_provider
 

Detailed Description

Parking Bridge DTMF and Interval features.

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

Definition in file parking_bridge_features.c.

Function Documentation

◆ create_parked_subscription()

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

Create a parking announcement subscription.

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

Definition at line 233 of file parking_bridge_features.c.

References create_parked_subscription_full(), and NULL.

Referenced by manager_park(), and manager_park_bridged().

234 {
235  return create_parked_subscription_full(chan, parkee_uuid, hangup_after, NULL);
236 }
#define NULL
Definition: resample.c:96
static int create_parked_subscription_full(struct ast_channel *chan, const char *parkee_uuid, int hangup_after, struct transfer_channel_data *parked_channel_data)

◆ create_parked_subscription_full()

static int create_parked_subscription_full ( struct ast_channel chan,
const char *  parkee_uuid,
int  hangup_after,
struct transfer_channel_data parked_channel_data 
)
static

Definition at line 174 of file parking_bridge_features.c.

References ao2_ref, ast_calloc, ast_channel_datastore_add(), ast_channel_lock, ast_channel_uniqueid(), ast_channel_unlock, ast_copy_string(), ast_datastore_alloc, ast_datastore_free(), ast_free, ast_parked_call_type(), ast_parking_topic(), ast_strdupa, ast_datastore::data, parked_subscription_data::hangup_after, NULL, parked_subscription_datastore::parked_subscription, parked_subscription_data::parkee_uuid, parker_update_cb(), parked_subscription_data::parker_uuid, stasis_subscribe_pool, stasis_subscription_accept_message_type(), stasis_subscription_change_type(), STASIS_SUBSCRIPTION_FILTER_SELECTIVE, stasis_subscription_set_filter(), parked_subscription_data::transfer_data, and wipe_subscription_datastore().

Referenced by create_parked_subscription(), park_local_transfer(), and parking_blind_transfer_park().

176 {
177  struct ast_datastore *datastore;
178  struct parked_subscription_datastore *parked_datastore;
179  struct parked_subscription_data *subscription_data;
180 
182  size_t parker_uuid_size;
183  size_t parkee_uuid_size;
184 
185  /* If there is already a subscription, get rid of it. */
187 
188  if (!(datastore = ast_datastore_alloc(&parked_subscription_info, NULL))) {
189  return -1;
190  }
191 
192  if (!(parked_datastore = ast_calloc(1, sizeof(*parked_datastore)))) {
193  ast_datastore_free(datastore);
194  return -1;
195  }
196 
197  parker_uuid_size = strlen(parker_uuid) + 1;
198  parkee_uuid_size = strlen(parkee_uuid) + 1;
199 
200  if (!(subscription_data = ast_calloc(1, sizeof(*subscription_data) + parker_uuid_size +
201  parkee_uuid_size))) {
202  ast_datastore_free(datastore);
203  ast_free(parked_datastore);
204  return -1;
205  }
206 
207  if (parked_channel_data) {
208  subscription_data->transfer_data = parked_channel_data;
209  ao2_ref(parked_channel_data, +1);
210  }
211 
212  subscription_data->hangup_after = hangup_after;
213  subscription_data->parkee_uuid = subscription_data->parker_uuid + parker_uuid_size;
214  ast_copy_string(subscription_data->parkee_uuid, parkee_uuid, parkee_uuid_size);
215  ast_copy_string(subscription_data->parker_uuid, parker_uuid, parker_uuid_size);
216 
217  if (!(parked_datastore->parked_subscription = stasis_subscribe_pool(ast_parking_topic(), parker_update_cb, subscription_data))) {
218  return -1;
219  }
223 
224  datastore->data = parked_datastore;
225 
226  ast_channel_lock(chan);
227  ast_channel_datastore_add(chan, datastore);
228  ast_channel_unlock(chan);
229 
230  return 0;
231 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
struct stasis_message_type * ast_parked_call_type(void)
accessor for the parked call stasis message type
int stasis_subscription_set_filter(struct stasis_subscription *subscription, enum stasis_subscription_message_filter filter)
Set the message type filtering level on a subscription.
Definition: stasis.c:1079
static const struct ast_datastore_info parked_subscription_info
static void parker_update_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Structure for a data store object.
Definition: datastore.h:68
#define NULL
Definition: resample.c:96
struct stasis_subscription * parked_subscription
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
struct transfer_channel_data * transfer_data
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
const char * ast_channel_uniqueid(const struct ast_channel *chan)
#define stasis_subscribe_pool(topic, callback, data)
Definition: stasis.h:682
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
static void wipe_subscription_datastore(struct ast_channel *chan)
void * data
Definition: datastore.h:70
struct stasis_topic * ast_parking_topic(void)
accessor for the parking stasis topic
Definition: parking.c:67
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
int stasis_subscription_accept_message_type(struct stasis_subscription *subscription, const struct stasis_message_type *type)
Indicate to a subscription that we are interested in a message type.
Definition: stasis.c:1025
struct stasis_message_type * stasis_subscription_change_type(void)
Gets the message type for subscription change notices.
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2390

◆ feature_park_call()

static int feature_park_call ( struct ast_bridge_channel bridge_channel,
void *  hook_pvt 
)
static

Definition at line 524 of file parking_bridge_features.c.

References NULL, parking_park_call(), and SCOPED_MODULE_USE.

Referenced by load_parking_bridge_features().

525 {
526  SCOPED_MODULE_USE(AST_MODULE_SELF);
527 
528  parking_park_call(bridge_channel, NULL, 0);
529  return 0;
530 }
#define NULL
Definition: resample.c:96
static int parking_park_call(struct ast_bridge_channel *parker, char *exten, size_t length)
#define SCOPED_MODULE_USE(module)
Definition: module.h:665

◆ func_get_parkingslot_channel()

static int func_get_parkingslot_channel ( struct ast_channel chan,
const char *  function,
char *  data,
char *  buf,
size_t  len 
)
static

Dial plan function to get the parking lot channel of an occupied parking lot.

Definition at line 733 of file parking_bridge_features.c.

References ao2_cleanup, args, AST_APP_ARG, ast_channel_name(), ast_copy_string(), AST_DECLARE_APP_ARGS, ast_log, AST_STANDARD_APP_ARGS, ast_str_to_uint(), ast_strlen_zero, LOG_ERROR, NULL, parking_lot_find_by_name(), parking_lot_inspect_parked_user(), and RAII_VAR.

734 {
735  RAII_VAR(struct parked_user *, pu, NULL, ao2_cleanup);
736  RAII_VAR(struct parking_lot *, lot, NULL, ao2_cleanup);
737  unsigned int space = 0;
738  const char *content = NULL;
739 
741  AST_APP_ARG(parking_space);
743  AST_APP_ARG(other);
744  );
745 
746  /* Parse the arguments. */
748 
749  if (args.argc < 2) {
750  /* Didn't receive enough arguments to do anything */
751  ast_log(LOG_ERROR, "Usage: %s(<parking_space>,<parking_lot>)\n",
752  function);
753  return -1;
754  }
755 
756  lot = parking_lot_find_by_name(args.parking_lot);
757  if (!lot) {
758  ast_log(LOG_ERROR, "Could not find parking lot: '%s'\n", args.parking_lot);
759  return -1;
760  }
761 
762  if (!ast_strlen_zero(args.parking_space)) {
763  if (ast_str_to_uint(args.parking_space, &space) != 0) {
764  ast_log(LOG_ERROR, "value '%s' for parking_space argument is invalid. Must be an integer greater than 0.\n",
765  args.parking_space);
766  return -1;
767  }
768  }
769 
770  pu = parking_lot_inspect_parked_user(lot, space);
771  if (!pu) {
772  return -1;
773  }
774 
775  content = ast_channel_name(pu->chan);
776  ast_copy_string(buf, content, len);
777 
778  return 0;
779 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
const char * args
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
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. ...
#define ast_log
Definition: astobj2.c:42
#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 LOG_ERROR
Definition: logger.h:285
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int ast_str_to_uint(const char *str, unsigned int *res)
Convert the given string to an unsigned integer.
Definition: conversions.c:56
#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
const char * ast_channel_name(const struct ast_channel *chan)
struct parking_lot * parking_lot_find_by_name(const char *lot_name)
Find a parking lot based on its name.
Definition: res_parking.c:601
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ load_parking_bridge_features()

int load_parking_bridge_features ( void  )

Register bridge features for parking.

Since
12.0.0
Return values
0on success
-1on failure

Definition at line 802 of file parking_bridge_features.c.

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

Referenced by load_module().

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

◆ park_local_transfer()

static struct ast_channel* park_local_transfer ( struct ast_channel parker,
const char *  context,
const char *  exten,
struct transfer_channel_data parked_channel_data 
)
static

Definition at line 244 of file parking_bridge_features.c.

References ast_assert, ast_bridge_set_transfer_variables(), ast_call(), ast_channel_caller(), ast_channel_connected(), ast_channel_datastore_inherit(), ast_channel_inherit_variables(), ast_channel_lock_both, ast_channel_name(), ast_channel_nativeformats(), ast_channel_parkinglot(), ast_channel_req_accountcodes(), AST_CHANNEL_REQUESTOR_REPLACEMENT, ast_channel_uniqueid(), ast_channel_unlock, ast_channel_unref, ast_connected_line_copy_from_caller(), ast_hangup(), ast_local_get_peer(), AST_MAX_CONTEXT, AST_MAX_EXTENSION, ast_request(), create_parked_subscription_full(), and NULL.

Referenced by parking_blind_transfer_park().

245 {
246  char destination[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 1];
247  struct ast_channel *parkee;
248  struct ast_channel *parkee_side_2;
249  int cause;
250 
251  /* Fill the variable with the extension and context we want to call */
252  snprintf(destination, sizeof(destination), "%s@%s", exten, context);
253 
254  /* Now we request that chan_local prepare to call the destination */
255  parkee = ast_request("Local", ast_channel_nativeformats(parker), NULL, parker, destination,
256  &cause);
257  if (!parkee) {
258  return NULL;
259  }
260 
261  /* Before we actually dial out let's inherit appropriate information. */
262  ast_channel_lock_both(parker, parkee);
264  ast_channel_parkinglot_set(parkee, ast_channel_parkinglot(parker));
266  ast_channel_inherit_variables(parker, parkee);
268  ast_channel_datastore_inherit(parker, parkee);
269  ast_channel_unlock(parker);
270 
271  parkee_side_2 = ast_local_get_peer(parkee);
272  ast_assert(parkee_side_2 != NULL);
273  ast_channel_unlock(parkee);
274 
275  /* We need to have the parker subscribe to the new local channel before hand. */
276  if (create_parked_subscription_full(parker, ast_channel_uniqueid(parkee_side_2), 1, parked_channel_data)) {
277  ast_channel_unref(parkee_side_2);
278  ast_hangup(parkee);
279  return NULL;
280  }
281 
282  ast_channel_unref(parkee_side_2);
283 
284  /* Since the above worked fine now we actually call it and return the channel */
285  if (ast_call(parkee, destination, 0)) {
286  ast_hangup(parkee);
287  return NULL;
288  }
289 
290  return parkee;
291 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
Main Channel structure associated with a channel.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
int ast_call(struct ast_channel *chan, const char *addr, int timeout)
Make a call.
Definition: channel.c:6553
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
struct ast_channel * ast_local_get_peer(struct ast_channel *ast)
Get the other local channel in the pair.
Definition: core_local.c:276
struct ast_channel * ast_request(const char *type, struct ast_format_cap *request_cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *addr, int *cause)
Requests a channel.
Definition: channel.c:6444
int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel *to)
Inherit datastores from a parent to a child.
Definition: channel.c:2373
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
#define AST_MAX_EXTENSION
Definition: channel.h:135
void ast_channel_req_accountcodes(struct ast_channel *chan, const struct ast_channel *requestor, enum ast_channel_requestor_relationship relationship)
Setup new channel accountcodes from the requestor channel after ast_request().
Definition: channel.c:6526
const char * ast_channel_uniqueid(const struct ast_channel *chan)
static int create_parked_subscription_full(struct ast_channel *chan, const char *parkee_uuid, int hangup_after, struct transfer_channel_data *parked_channel_data)
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define AST_MAX_CONTEXT
Definition: channel.h:136
void ast_channel_inherit_variables(const struct ast_channel *parent, struct ast_channel *child)
Inherits channel variable from parent to child channel.
Definition: channel.c:6866
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2548
void ast_bridge_set_transfer_variables(struct ast_channel *chan, const char *value, int is_attended)
Set the relevant transfer variables for a single channel.
Definition: bridge.c:4404
struct ast_format_cap * ast_channel_nativeformats(const struct ast_channel *chan)
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2952
void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest, const struct ast_party_caller *src)
Copy the caller information to the connected line information.
Definition: channel.c:8389
const char * ast_channel_name(const struct ast_channel *chan)
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
const char * ast_channel_parkinglot(const struct ast_channel *chan)

◆ parked_subscription_datastore_destroy()

static void parked_subscription_datastore_destroy ( void *  data)
static

Definition at line 76 of file parking_bridge_features.c.

References ast_free, NULL, parked_subscription_datastore::parked_subscription, and stasis_unsubscribe().

77 {
78  struct parked_subscription_datastore *subscription_datastore = data;
79 
80  stasis_unsubscribe(subscription_datastore->parked_subscription);
81  subscription_datastore->parked_subscription = NULL;
82 
83  ast_free(subscription_datastore);
84 }
#define NULL
Definition: resample.c:96
struct stasis_subscription * parked_subscription
struct stasis_subscription * stasis_unsubscribe(struct stasis_subscription *subscription)
Cancel a subscription.
Definition: stasis.c:973
#define ast_free(a)
Definition: astmm.h:182

◆ parker_parked_call_message_response()

static void parker_parked_call_message_response ( struct ast_parked_call_payload message,
struct parked_subscription_data data,
struct stasis_subscription sub 
)
static

Definition at line 105 of file parking_bridge_features.c.

References ao2_cleanup, ast_bridge_channel_queue_playfile(), ast_bridge_channel_queue_playfile_sync(), ast_channel_cleanup, ast_channel_get_bridge_channel(), ast_channel_get_by_name(), ast_channel_lock, ast_channel_unlock, ast_channel_snapshot::base, transfer_channel_data::completed, ast_parked_call_payload::event_type, parked_subscription_data::hangup_after, NULL, PARKED_CALL, PARKED_CALL_FAILED, ast_parked_call_payload::parkee, parked_subscription_data::parkee_uuid, parked_subscription_data::parker_uuid, ast_parked_call_payload::parkingspace, RAII_VAR, say_parking_space(), parked_subscription_data::transfer_data, ast_channel_snapshot_base::uniqueid, and wipe_subscription_datastore().

Referenced by parker_update_cb().

107 {
108  const char *parkee_to_act_on = data->parkee_uuid;
109  char saynum_buf[16];
110  struct ast_channel_snapshot *parkee_snapshot = message->parkee;
111  RAII_VAR(struct ast_channel *, parker, NULL, ast_channel_cleanup);
112  RAII_VAR(struct ast_bridge_channel *, bridge_channel, NULL, ao2_cleanup);
113 
114  if (strcmp(parkee_to_act_on, parkee_snapshot->base->uniqueid)) {
115  return;
116  }
117 
118  if (message->event_type != PARKED_CALL && message->event_type != PARKED_CALL_FAILED) {
119  /* We only care about these two event types */
120  return;
121  }
122 
123  parker = ast_channel_get_by_name(data->parker_uuid);
124  if (!parker) {
125  return;
126  }
127 
128  ast_channel_lock(parker);
129  bridge_channel = ast_channel_get_bridge_channel(parker);
130  ast_channel_unlock(parker);
131  if (!bridge_channel) {
132  return;
133  }
134 
135  /* This subscription callback will block for the duration of the announcement if
136  * parked_subscription_data is tracking a transfer_channel_data struct. */
137  if (message->event_type == PARKED_CALL) {
138  /* queue the saynum on the bridge channel and hangup */
139  snprintf(saynum_buf, sizeof(saynum_buf), "%d %u", data->hangup_after, message->parkingspace);
140  if (!data->transfer_data) {
141  ast_bridge_channel_queue_playfile(bridge_channel, say_parking_space, saynum_buf, NULL);
142  } else {
143  ast_bridge_channel_queue_playfile_sync(bridge_channel, say_parking_space, saynum_buf, NULL);
144  data->transfer_data->completed = 1;
145  }
147  } else if (message->event_type == PARKED_CALL_FAILED) {
148  if (!data->transfer_data) {
149  ast_bridge_channel_queue_playfile(bridge_channel, NULL, "pbx-parkingfailed", NULL);
150  } else {
151  ast_bridge_channel_queue_playfile_sync(bridge_channel, NULL, "pbx-parkingfailed", NULL);
152  data->transfer_data->completed = 1;
153  }
155  }
156 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
struct ast_channel_snapshot_base * base
Structure representing a snapshot of channel state.
const ast_string_field uniqueid
#define NULL
Definition: resample.c:96
enum ast_parked_call_event_type event_type
Definition: parking.h:62
struct ast_channel_snapshot * parkee
Definition: parking.h:60
#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
struct transfer_channel_data * transfer_data
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:2992
unsigned int parkingspace
Definition: parking.h:65
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
static void wipe_subscription_datastore(struct ast_channel *chan)
struct ast_bridge_channel * ast_channel_get_bridge_channel(struct ast_channel *chan)
Get a reference to the channel&#39;s bridge pointer.
Definition: channel.c:10783
Structure that contains information regarding a channel in a bridge.
#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.
int ast_bridge_channel_queue_playfile_sync(struct ast_bridge_channel *bridge_channel, ast_bridge_custom_play_fn custom_play, const char *playfile, const char *moh_class)
Synchronously queue a bridge action play file frame onto the bridge channel.
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454

◆ parker_update_cb()

static void parker_update_cb ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Definition at line 158 of file parking_bridge_features.c.

References ao2_cleanup, ast_free, ast_parked_call_type(), NULL, parker_parked_call_message_response(), stasis_message_data(), stasis_message_type(), stasis_subscription_final_message(), and parked_subscription_data::transfer_data.

Referenced by create_parked_subscription_full().

159 {
160  if (stasis_subscription_final_message(sub, message)) {
161  struct parked_subscription_data *ps_data = data;
162  ao2_cleanup(ps_data->transfer_data);
163  ps_data->transfer_data = NULL;
164  ast_free(data);
165  return;
166  }
167 
168  if (stasis_message_type(message) == ast_parked_call_type()) {
169  struct ast_parked_call_payload *parked_call_message = stasis_message_data(message);
170  parker_parked_call_message_response(parked_call_message, data, sub);
171  }
172 }
struct stasis_message_type * ast_parked_call_type(void)
accessor for the parked call stasis message type
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
A parked call message payload.
Definition: parking.h:59
#define NULL
Definition: resample.c:96
struct transfer_channel_data * transfer_data
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
static void parker_parked_call_message_response(struct ast_parked_call_payload *message, struct parked_subscription_data *data, struct stasis_subscription *sub)
int stasis_subscription_final_message(struct stasis_subscription *sub, struct stasis_message *msg)
Determine whether a message is the final message to be received on a subscription.
Definition: stasis.c:1176
#define ast_free(a)
Definition: astmm.h:182
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ parking_blind_transfer_park()

static int parking_blind_transfer_park ( struct ast_bridge_channel bridge_channel,
const char *  context,
const char *  exten,
transfer_channel_cb  parked_channel_cb,
struct transfer_channel_data parked_channel_data 
)
static

Definition at line 336 of file parking_bridge_features.c.

References ao2_cleanup, ao2_ref, ast_bridge_channel_lock_bridge(), ast_bridge_channel_peer(), ast_bridge_channel_write_park(), ast_bridge_impart(), AST_BRIDGE_IMPART_CHAN_INDEPENDENT, AST_BRIDGE_TRANSFER_MULTI_PARTY, AST_BRIDGE_TRANSFER_SINGLE_PARTY, ast_bridge_unlock, ast_channel_cleanup, ast_channel_ref, ast_channel_uniqueid(), ast_channel_unref, ast_get_extension_app_data(), ast_hangup(), ast_strlen_zero, ast_bridge_channel::bridge, ast_bridge_channel::chan, create_parked_subscription_full(), E_MATCH, ast_bridge_channel::in_bridge, NULL, ast_bridge::num_channels, park_local_transfer(), parking_is_exten_park(), pbx_find_extension(), RAII_VAR, and pbx_find_info::stacklen.

Referenced by parking_park_call().

339 {
340  RAII_VAR(struct ast_bridge_channel *, other, NULL, ao2_cleanup);
341  RAII_VAR(struct ast_channel *, other_chan, NULL, ast_channel_cleanup);
342 
343  struct ast_exten *e;
344  struct pbx_find_info find_info = { .stacklen = 0 };
345  int peer_count;
346 
348  return -1;
349  }
350 
351  if (!bridge_channel->in_bridge) {
352  return -1;
353  }
354 
356  return -1;
357  }
358 
359  ast_bridge_channel_lock_bridge(bridge_channel);
360  peer_count = bridge_channel->bridge->num_channels;
361  if (peer_count == 2) {
362  other = ast_bridge_channel_peer(bridge_channel);
363  ao2_ref(other, +1);
364  other_chan = other->chan;
365  ast_channel_ref(other_chan);
366  }
367  ast_bridge_unlock(bridge_channel->bridge);
368 
369  if (peer_count < 2) {
370  /* There is nothing to do if there is no one to park. */
371  return -1;
372  }
373 
374  /* With a multiparty bridge, we need to do a regular blind transfer. We link the
375  * existing bridge to the parking lot with a Local channel rather than
376  * transferring others. */
377  if (peer_count > 2) {
378  struct ast_channel *transfer_chan = NULL;
379 
380  transfer_chan = park_local_transfer(bridge_channel->chan, context, exten, parked_channel_data);
381  if (!transfer_chan) {
382  return -1;
383  }
384  ast_channel_ref(transfer_chan);
385 
386  if (parked_channel_cb) {
387  parked_channel_cb(transfer_chan, parked_channel_data, AST_BRIDGE_TRANSFER_MULTI_PARTY);
388  }
389 
390  if (ast_bridge_impart(bridge_channel->bridge, transfer_chan, NULL, NULL,
392  ast_hangup(transfer_chan);
393  ast_channel_unref(transfer_chan);
394  return -1;
395  }
396 
397  ast_channel_unref(transfer_chan);
398 
399  return 0;
400  }
401 
402  /* Subscribe to park messages with the other channel entering */
403  if (create_parked_subscription_full(bridge_channel->chan, ast_channel_uniqueid(other->chan), 1, parked_channel_data)) {
404  return -1;
405  }
406 
407  if (parked_channel_cb) {
408  parked_channel_cb(other_chan, parked_channel_data, AST_BRIDGE_TRANSFER_SINGLE_PARTY);
409  }
410 
411  e = pbx_find_extension(NULL, NULL, &find_info, context, exten, 1, NULL, NULL, E_MATCH);
412 
413  /* Write the park frame with the intended recipient and other data out to the bridge. */
414  ast_bridge_channel_write_park(bridge_channel,
415  ast_channel_uniqueid(other_chan),
416  ast_channel_uniqueid(bridge_channel->chan),
418 
419  return 0;
420 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
Main Channel structure associated with a channel.
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
struct ast_bridge_channel * ast_bridge_channel_peer(struct ast_bridge_channel *bridge_channel)
Get the peer bridge channel of a two party bridge.
int ast_bridge_channel_write_park(struct ast_bridge_channel *bridge_channel, const char *parkee_uuid, const char *parker_uuid, const char *app_data)
Have a bridge channel park a channel in the bridge.
void * ast_get_extension_app_data(struct ast_exten *e)
Definition: pbx.c:8601
#define NULL
Definition: resample.c:96
struct ast_bridge * bridge
Bridge this channel is participating in.
#define ast_strlen_zero(foo)
Definition: strings.h:52
int ast_bridge_impart(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features, enum ast_bridge_impart_flags flags) attribute_warn_unused_result
Impart a channel to a bridge (non-blocking)
Definition: bridge.c:1924
#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 ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:2992
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const char * ast_channel_uniqueid(const struct ast_channel *chan)
static int parking_is_exten_park(const char *context, const char *exten)
static int create_parked_subscription_full(struct ast_channel *chan, const char *parkee_uuid, int hangup_after, struct transfer_channel_data *parked_channel_data)
unsigned int in_bridge
#define ast_bridge_unlock(bridge)
Unlock the bridge.
Definition: bridge.h:493
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2548
int stacklen
Definition: extconf.h:238
struct ast_channel * chan
Structure that contains information regarding a channel in a bridge.
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2970
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void ast_bridge_channel_lock_bridge(struct ast_bridge_channel *bridge_channel)
Lock the bridge associated with the bridge channel.
static struct ast_channel * park_local_transfer(struct ast_channel *parker, const char *context, const char *exten, struct transfer_channel_data *parked_channel_data)
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
struct ast_exten * pbx_find_extension(struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
Definition: ael_main.c:152
unsigned int num_channels
Definition: bridge.h:381

◆ parking_duration_callback()

static int parking_duration_callback ( struct ast_bridge_channel bridge_channel,
void *  hook_pvt 
)
static

Definition at line 575 of file parking_bridge_features.c.

References ao2_lock, ao2_unlock, ast_add_extension2_nolock(), ast_assert, ast_async_parseable_goto(), ast_bridge_channel_leave_bridge(), AST_CAUSE_NORMAL_CLEARING, ast_channel_lock, ast_channel_stage_snapshot(), ast_channel_stage_snapshot_done(), ast_channel_unlock, ast_context_find_or_create(), ast_debug, ast_free_ptr(), ast_get_extension_registrar(), ast_log, AST_MAX_EXTENSION, ast_strdup, ast_strdupa, ast_strlen_zero, ast_unlock_context(), ast_unlock_contexts(), ast_wrlock_context(), ast_wrlock_contexts(), BASE_REGISTRAR, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, parking_lot::cfg, parked_user::chan, parked_user::comeback, comeback_goto(), parking_lot_cfg::comebackdialtime, E_MATCH, flatten_dial_string(), LOG_ERROR, parked_user::lot, parking_lot::name, NULL, PARK_DIAL_CONTEXT, PARK_TIMEOUT, PARK_UNSET, parked_user::parker_dial_string, parked_user::parking_space, parking_timeout_set_caller_features(), pbx_builtin_setvar_helper(), pbx_find_extension(), parked_user::resolution, and pbx_find_info::stacklen.

Referenced by parking_set_duration().

576 {
577  struct parked_user *user = hook_pvt;
578  struct ast_channel *chan = user->chan;
579  struct ast_context *park_dial_context;
580  const char *dial_string;
581  char *dial_string_flat;
582  char parking_space[AST_MAX_EXTENSION];
583 
584  char returnexten[AST_MAX_EXTENSION];
585  char *duplicate_returnexten;
586  struct ast_exten *existing_exten;
587  struct pbx_find_info pbx_finder = { .stacklen = 0 }; /* The rest is reset in pbx_find_extension */
588 
589 
590  /* We are still in the bridge, so it's possible for other stuff to mess with the parked call before we leave the bridge
591  to deal with this, lock the parked user, check and set resolution. */
592  ao2_lock(user);
593  if (user->resolution != PARK_UNSET) {
594  /* Abandon timeout since something else has resolved the parked user before we got to it. */
595  ao2_unlock(user);
596  return -1;
597  }
598  user->resolution = PARK_TIMEOUT;
599  ao2_unlock(user);
600 
603 
604  dial_string = user->parker_dial_string;
605  dial_string_flat = ast_strdupa(dial_string);
606  flatten_dial_string(dial_string_flat);
607 
608  /* Set parking timeout channel variables */
609  snprintf(parking_space, sizeof(parking_space), "%d", user->parking_space);
610  ast_channel_lock(chan);
612  pbx_builtin_setvar_helper(chan, "PARKING_SPACE", parking_space);
613  pbx_builtin_setvar_helper(chan, "PARKEDLOT", user->lot->name);
614  pbx_builtin_setvar_helper(chan, "PARKER", dial_string);
615  pbx_builtin_setvar_helper(chan, "PARKER_FLAT", dial_string_flat);
618  ast_channel_unlock(chan);
619 
620  /* Dialplan generation for park-dial extensions */
621 
622  if (ast_wrlock_contexts()) {
623  ast_log(LOG_ERROR, "Failed to lock the contexts list. Can't add the park-dial extension.\n");
624  return -1;
625  }
626 
627  if (!(park_dial_context = ast_context_find_or_create(NULL, NULL, PARK_DIAL_CONTEXT, BASE_REGISTRAR))) {
628  ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", PARK_DIAL_CONTEXT);
629  if (ast_unlock_contexts()) {
630  ast_assert(0);
631  }
632  goto abandon_extension_creation;
633  }
634 
635  if (ast_wrlock_context(park_dial_context)) {
636  ast_log(LOG_ERROR, "failed to obtain write lock on context '%s'\n", PARK_DIAL_CONTEXT);
637  if (ast_unlock_contexts()) {
638  ast_assert(0);
639  }
640  goto abandon_extension_creation;
641  }
642 
643  if (ast_unlock_contexts()) {
644  ast_assert(0);
645  }
646 
647  snprintf(returnexten, sizeof(returnexten), "%s,%u", dial_string,
648  user->lot->cfg->comebackdialtime);
649 
650  duplicate_returnexten = ast_strdup(returnexten);
651  if (!duplicate_returnexten) {
652  ast_log(LOG_ERROR, "Failed to create parking redial parker extension %s@%s - Dial(%s)\n",
653  dial_string_flat, PARK_DIAL_CONTEXT, returnexten);
654  }
655 
656  /* If an extension already exists here because we registered it for another parked call timing out, then we may overwrite it. */
657  if ((existing_exten = pbx_find_extension(NULL, NULL, &pbx_finder, PARK_DIAL_CONTEXT, dial_string_flat, 1, NULL, NULL, E_MATCH)) &&
658  (strcmp(ast_get_extension_registrar(existing_exten), BASE_REGISTRAR))) {
659  ast_debug(3, "An extension for '%s@%s' was already registered by another registrar '%s'\n",
660  dial_string_flat, PARK_DIAL_CONTEXT, ast_get_extension_registrar(existing_exten));
661  } else if (ast_add_extension2_nolock(park_dial_context, 1, dial_string_flat, 1, NULL, NULL,
662  "Dial", duplicate_returnexten, ast_free_ptr, BASE_REGISTRAR, NULL, 0)) {
663  ast_log(LOG_ERROR, "Failed to create parking redial parker extension %s@%s - Dial(%s)\n",
664  dial_string_flat, PARK_DIAL_CONTEXT, returnexten);
665  }
666 
667  if (ast_unlock_context(park_dial_context)) {
668  ast_assert(0);
669  }
670 
671 abandon_extension_creation:
672 
673  /* async_goto the proper PBX destination - this should happen when we come out of the bridge */
674  if (!ast_strlen_zero(user->comeback)) {
675  ast_async_parseable_goto(chan, user->comeback);
676  } else {
677  comeback_goto(user, user->lot);
678  }
679 
680  return -1;
681 }
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:8530
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
static void parking_timeout_set_caller_features(struct ast_channel *chan, struct parking_lot_cfg *cfg)
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
unsigned int comebackdialtime
Definition: res_parking.h:70
const char * ast_get_extension_registrar(struct ast_exten *e)
Definition: pbx.c:8571
#define BASE_REGISTRAR
Definition: res_parking.h:36
#define PARK_DIAL_CONTEXT
Definition: res_parking.h:37
#define ast_assert(a)
Definition: utils.h:695
int ast_wrlock_contexts(void)
Write locks the context list.
Definition: pbx.c:8502
#define ao2_unlock(a)
Definition: astobj2.h:730
void flatten_dial_string(char *dialstring)
Flattens a dial string so that it can be written to/found from PBX extensions.
#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
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1771
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
char * parker_dial_string
Definition: res_parking.h:109
#define AST_MAX_EXTENSION
Definition: channel.h:135
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:105
int parking_space
Definition: res_parking.h:107
#define ao2_lock(a)
Definition: astobj2.h:718
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
enum park_call_resolution resolution
Definition: res_parking.h:112
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
#define LOG_ERROR
Definition: logger.h:285
int comeback_goto(struct parked_user *pu, struct parking_lot *lot)
Set a channel&#39;s position in the PBX after timeout using the parking lot settings. ...
char comeback[80]
Definition: res_parking.h:108
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8512
int ast_wrlock_context(struct ast_context *con)
Write locks a given context.
Definition: pbx.c:8520
void ast_bridge_channel_leave_bridge(struct ast_bridge_channel *bridge_channel, enum bridge_channel_state new_state, int cause)
Set bridge channel state to leave bridge (if not leaving already).
#define ast_channel_unlock(chan)
Definition: channel.h:2946
int stacklen
Definition: extconf.h:238
const ast_string_field name
Definition: res_parking.h:100
structure to hold users read from users.conf
int ast_async_parseable_goto(struct ast_channel *chan, const char *goto_string)
Definition: pbx.c:8864
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
struct ast_context * ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
Register a new context or find an existing one.
Definition: pbx.c:6198
struct ast_exten * pbx_find_extension(struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
Definition: ael_main.c:152
ast_context: An extension context - must remain in sync with fake_context
Definition: pbx.c:284
struct ast_channel * chan
Definition: res_parking.h:104
int ast_add_extension2_nolock(struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar, const char *registrar_file, int registrar_line)
Same as ast_add_extension2, but assumes you have already locked context.
Definition: pbx.c:7308
struct parking_lot_cfg * cfg
Definition: res_parking.h:96

◆ parking_is_exten_park()

static int parking_is_exten_park ( const char *  context,
const char *  exten 
)
static

Definition at line 297 of file parking_bridge_features.c.

References ast_debug, ast_get_extension_app(), E_MATCH, NULL, PARK_APPLICATION, pbx_find_extension(), and pbx_find_info::stacklen.

Referenced by parking_blind_transfer_park().

298 {
299  struct ast_exten *exten_obj;
300  struct pbx_find_info info = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
301  const char *app_at_exten;
302 
303  ast_debug(4, "Checking if %s@%s is a parking exten\n", exten, context);
304  exten_obj = pbx_find_extension(NULL, NULL, &info, context, exten, 1, NULL, NULL, E_MATCH);
305  if (!exten_obj) {
306  return 0;
307  }
308 
309  app_at_exten = ast_get_extension_app(exten_obj);
310  if (!app_at_exten || strcasecmp(PARK_APPLICATION, app_at_exten)) {
311  return 0;
312  }
313 
314  return 1;
315 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
const char * ast_get_extension_app(struct ast_exten *e)
Definition: pbx.c:8596
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
def info(msg)
#define PARK_APPLICATION
The default parking application that Asterisk expects.
Definition: parking.h:35
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
struct ast_exten * pbx_find_extension(struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
Definition: ael_main.c:152

◆ parking_park_bridge_channel()

static int parking_park_bridge_channel ( struct ast_bridge_channel bridge_channel,
const char *  uuid_parkee,
const char *  uuid_parker,
const char *  app_data 
)
static

Definition at line 434 of file parking_bridge_features.c.

References ao2_cleanup, ao2_lock, ao2_ref, ao2_unlock, ast_bridge_move(), ast_bridge_set_transfer_variables(), ast_channel_get_by_name(), ast_channel_name(), ast_channel_uniqueid(), ast_log, ast_bridge_channel::bridge, ast_bridge_channel::chan, LOG_ERROR, LOG_NOTICE, NULL, park_application_setup(), publish_parked_call_failure(), and RAII_VAR.

435 {
436  RAII_VAR(struct ast_bridge *, parking_bridge, NULL, ao2_cleanup);
437  RAII_VAR(struct ast_bridge *, original_bridge, NULL, ao2_cleanup);
438  RAII_VAR(struct ast_channel *, parker, NULL, ao2_cleanup);
439 
440  if (strcmp(ast_channel_uniqueid(bridge_channel->chan), uuid_parkee)) {
441  /* We aren't the parkee, so ignore this action. */
442  return -1;
443  }
444 
445  parker = ast_channel_get_by_name(uuid_parker);
446 
447  if (!parker) {
448  ast_log(LOG_NOTICE, "Channel with uuid %s left before we could start parking the call. Parking canceled.\n", uuid_parker);
449  publish_parked_call_failure(bridge_channel->chan);
450  return -1;
451  }
452 
453  if (!(parking_bridge = park_application_setup(bridge_channel->chan, parker, app_data, NULL))) {
454  publish_parked_call_failure(bridge_channel->chan);
455  return -1;
456  }
457 
458  ast_bridge_set_transfer_variables(bridge_channel->chan, ast_channel_name(parker), 0);
459 
460  /* bridge_channel must be locked so we can get a reference to the bridge it is currently on */
461  ao2_lock(bridge_channel);
462 
463  original_bridge = bridge_channel->bridge;
464  if (!original_bridge) {
465  ao2_unlock(bridge_channel);
466  publish_parked_call_failure(bridge_channel->chan);
467  return -1;
468  }
469 
470  ao2_ref(original_bridge, +1); /* Cleaned by RAII_VAR */
471 
472  ao2_unlock(bridge_channel);
473 
474  if (ast_bridge_move(parking_bridge, original_bridge, bridge_channel->chan, NULL, 1)) {
475  ast_log(LOG_ERROR, "Failed to move %s into the parking bridge.\n",
476  ast_channel_name(bridge_channel->chan));
477  return -1;
478  }
479 
480  return 0;
481 }
Main Channel structure associated with a channel.
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
struct ast_bridge * bridge
Bridge this channel is participating in.
void publish_parked_call_failure(struct ast_channel *parkee)
Publish a stasis parked call message for the channel indicating failure to park.
#define ast_log
Definition: astobj2.c:42
struct ast_bridge * park_application_setup(struct ast_channel *parkee, struct ast_channel *parker, const char *app_data, int *silence_announcements)
Function to prepare a channel for parking by determining which parking bridge should be used...
#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_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
const char * ast_channel_uniqueid(const struct ast_channel *chan)
Structure that contains information about a bridge.
Definition: bridge.h:357
#define LOG_ERROR
Definition: logger.h:285
#define LOG_NOTICE
Definition: logger.h:263
void ast_bridge_set_transfer_variables(struct ast_channel *chan, const char *value, int is_attended)
Set the relevant transfer variables for a single channel.
Definition: bridge.c:4404
struct ast_channel * chan
int ast_bridge_move(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridge, struct ast_channel *chan, struct ast_channel *swap, int attempt_recovery)
Move a channel from one bridge to another.
Definition: bridge.c:2508
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
const char * ast_channel_name(const struct ast_channel *chan)
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454

◆ parking_park_call()

static int parking_park_call ( struct ast_bridge_channel parker,
char *  exten,
size_t  length 
)
static

Definition at line 499 of file parking_bridge_features.c.

References ao2_cleanup, ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_copy_string(), ast_log, AST_LOG_WARNING, ast_strdupa, ast_bridge_channel::chan, find_channel_parking_lot_name(), NULL, parking_blind_transfer_park(), parking_create_dynamic_lot(), parking_lot_find_by_name(), and RAII_VAR.

Referenced by feature_park_call().

500 {
501  RAII_VAR(struct parking_lot *, lot, NULL, ao2_cleanup);
502  const char *lot_name;
503 
504  ast_channel_lock(parker->chan);
505  lot_name = ast_strdupa(find_channel_parking_lot_name(parker->chan));
506  ast_channel_unlock(parker->chan);
507 
508  lot = parking_lot_find_by_name(lot_name);
509  if (!lot) {
510  lot = parking_create_dynamic_lot(lot_name, parker->chan);
511  }
512  if (!lot) {
513  ast_log(AST_LOG_WARNING, "Cannot Park %s: lot %s unknown\n",
514  ast_channel_name(parker->chan), lot_name);
515  return -1;
516  }
517 
518  if (exten) {
519  ast_copy_string(exten, lot->cfg->parkext, length);
520  }
521  return parking_blind_transfer_park(parker, lot->cfg->parking_con, lot->cfg->parkext, NULL, NULL);
522 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
struct parking_lot * parking_create_dynamic_lot(const char *name, struct ast_channel *chan)
Create a dynamic parking lot.
Definition: res_parking.c:1059
#define AST_LOG_WARNING
Definition: logger.h:279
#define NULL
Definition: resample.c:96
static int parking_blind_transfer_park(struct ast_bridge_channel *bridge_channel, const char *context, const char *exten, transfer_channel_cb parked_channel_cb, struct transfer_channel_data *parked_channel_data)
#define ast_log
Definition: astobj2.c:42
#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 ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define ast_channel_unlock(chan)
Definition: channel.h:2946
struct ast_channel * chan
#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
const char * ast_channel_name(const struct ast_channel *chan)
struct parking_lot * parking_lot_find_by_name(const char *lot_name)
Find a parking lot based on its name.
Definition: res_parking.c:601
const char * find_channel_parking_lot_name(struct ast_channel *chan)
Find parking lot name from channel.
Definition: res_parking.c:607

◆ parking_set_duration()

void parking_set_duration ( struct ast_bridge_features features,
struct parked_user user 
)

Setup timeout interval feature on an ast_bridge_features for parking.

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

Definition at line 705 of file parking_bridge_features.c.

References __ao2_cleanup(), ao2_ref, AST_BRIDGE_HOOK_REMOVE_ON_PULL, ast_bridge_interval_hook(), ast_log, ast_remaining_ms(), LOG_ERROR, parking_duration_callback(), parked_user::start, and parked_user::time_limit.

Referenced by bridge_parking_push().

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

◆ parking_timeout_set_caller_features()

static void parking_timeout_set_caller_features ( struct ast_channel chan,
struct parking_lot_cfg cfg 
)
static

Definition at line 542 of file parking_bridge_features.c.

References AST_FEATURE_FLAG_BYCALLER, parking_lot_cfg::parkedcallhangup, parking_lot_cfg::parkedcallrecording, parking_lot_cfg::parkedcallreparking, parking_lot_cfg::parkedcalltransfers, and pbx_builtin_setvar_helper().

Referenced by parking_duration_callback().

543 {
544  char features[5];
545  char *pos;
546 
547  /*
548  * We are setting the callee Dial flag values because in the
549  * timeout case, the caller is who is being called back.
550  */
551  pos = features;
553  *pos++ = 't';
554  }
556  *pos++ = 'k';
557  }
559  *pos++ = 'h';
560  }
562  *pos++ = 'x';
563  }
564  *pos = '\0';
565 
566  pbx_builtin_setvar_helper(chan, "BRIDGE_FEATURES", features);
567 }
int parkedcallreparking
Definition: res_parking.h:77
int parkedcalltransfers
Definition: res_parking.h:76
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
int parkedcallrecording
Definition: res_parking.h:79

◆ say_parking_space()

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

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

Since
12.0.0

Definition at line 683 of file parking_bridge_features.c.

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

Referenced by bridge_parking_push(), and parker_parked_call_message_response().

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

◆ unload_parking_bridge_features()

void unload_parking_bridge_features ( void  )

Unregister features registered by load_parking_bridge_features.

Since
12.0.0

Definition at line 795 of file parking_bridge_features.c.

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

Referenced by unload_module().

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

◆ wipe_subscription_datastore()

static void wipe_subscription_datastore ( struct ast_channel chan)
static

Definition at line 91 of file parking_bridge_features.c.

References ast_channel_datastore_find(), ast_channel_datastore_remove(), ast_channel_lock, ast_channel_unlock, ast_datastore_free(), and NULL.

Referenced by create_parked_subscription_full(), and parker_parked_call_message_response().

92 {
93  struct ast_datastore *datastore;
94 
95  ast_channel_lock(chan);
96 
98  if (datastore) {
99  ast_channel_datastore_remove(chan, datastore);
100  ast_datastore_free(datastore);
101  }
102  ast_channel_unlock(chan);
103 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
static const struct ast_datastore_info parked_subscription_info
Structure for a data store object.
Definition: datastore.h:68
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2404
#define NULL
Definition: resample.c:96
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
#define ast_channel_unlock(chan)
Definition: channel.h:2946
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2399

Variable Documentation

◆ getparkingslotchannel_function

struct ast_custom_function getparkingslotchannel_function
static
Initial value:
= {
.name = "PARK_GET_CHANNEL",
}
static int func_get_parkingslot_channel(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
Dial plan function to get the parking lot channel of an occupied parking lot.

Definition at line 781 of file parking_bridge_features.c.

◆ parked_subscription_info

const struct ast_datastore_info parked_subscription_info
static
Initial value:
= {
.type = "park subscription",
}
static void parked_subscription_datastore_destroy(void *data)

Definition at line 86 of file parking_bridge_features.c.

◆ parking_provider

struct ast_parking_bridge_feature_fn_table parking_provider