Asterisk - The Open Source Telephony Project GIT-master-2de1a68
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.

234{
235 return create_parked_subscription_full(chan, parkee_uuid, hangup_after, NULL);
236}
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 NULL
Definition: resample.c:96

References create_parked_subscription_full(), parked_subscription_data::hangup_after, NULL, and parked_subscription_data::parkee_uuid.

Referenced by manager_park(), and manager_park_bridged().

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

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_free(a)
Definition: astmm.h:180
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2385
#define ast_channel_lock(chan)
Definition: channel.h:2922
const char * ast_channel_uniqueid(const struct ast_channel *chan)
#define ast_channel_unlock(chan)
Definition: channel.h:2923
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:85
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
struct stasis_topic * ast_parking_topic(void)
accessor for the parking stasis topic
Definition: parking.c:67
struct stasis_message_type * ast_parked_call_type(void)
accessor for the parked call stasis message type
struct stasis_message_type * stasis_subscription_change_type(void)
Gets the message type for subscription change notices.
static void wipe_subscription_datastore(struct ast_channel *chan)
static const struct ast_datastore_info parked_subscription_info
static void parker_update_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
@ STASIS_SUBSCRIPTION_FILTER_SELECTIVE
Definition: stasis.h:297
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:1023
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:1077
#define stasis_subscribe_pool(topic, callback, data)
Definition: stasis.h:680
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
Structure for a data store object.
Definition: datastore.h:64
void * data
Definition: datastore.h:66
struct transfer_channel_data * transfer_data
struct stasis_subscription * parked_subscription

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_info, 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().

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

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

References ast_channel::bridge_channel, NULL, parking_park_call(), and SCOPED_MODULE_USE.

Referenced by load_parking_bridge_features().

◆ 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 731 of file parking_bridge_features.c.

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

References ao2_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(), buf, pbx_find_info::data, len(), LOG_ERROR, NULL, parking_lot_find_by_name(), parking_lot_inspect_parked_user(), and RAII_VAR.

◆ 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 800 of file parking_bridge_features.c.

801{
802 parking_provider.module = AST_MODULE_SELF;
803
805
807 return -1;
808 }
809
811 return -1;
812 }
813
814 return 0;
815}
@ AST_BRIDGE_BUILTIN_PARKCALL
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:3062
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_parking_bridge_feature_fn_table parking_provider
static int feature_park_call(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
static struct ast_custom_function getparkingslotchannel_function
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1558
struct ast_module * module
The module info for the module registering this parking provider.
Definition: parking.h:202

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

Referenced by load_module().

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

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}
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:4352
int ast_call(struct ast_channel *chan, const char *addr, int timeout)
Make a call.
Definition: channel.c:6460
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2541
@ AST_CHANNEL_REQUESTOR_REPLACEMENT
Definition: channel.h:1479
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:2929
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
int ast_channel_datastore_inherit(struct ast_channel *from, struct ast_channel *to)
Inherit datastores from a parent to a child.
Definition: channel.c:2368
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:6433
const char * ast_channel_parkinglot(const struct ast_channel *chan)
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:6770
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
#define AST_MAX_CONTEXT
Definition: channel.h:135
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:8292
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
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:6353
#define AST_MAX_EXTENSION
Definition: channel.h:134
struct ast_channel * ast_local_get_peer(struct ast_channel *ast)
Get the other local channel in the pair.
Definition: core_local.c:276
Main Channel structure associated with a channel.
char exten[AST_MAX_EXTENSION]
#define ast_assert(a)
Definition: utils.h:739

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(), voicemailpwcheck::context, create_parked_subscription_full(), ast_channel::exten, and NULL.

Referenced by parking_blind_transfer_park().

◆ parked_subscription_datastore_destroy()

static void parked_subscription_datastore_destroy ( void *  data)
static

Definition at line 76 of file parking_bridge_features.c.

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}
struct stasis_subscription * stasis_unsubscribe(struct stasis_subscription *subscription)
Cancel a subscription.
Definition: stasis.c:971

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

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

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 {
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}
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_bridge_channel * ast_channel_get_bridge_channel(struct ast_channel *chan)
Get a reference to the channel's bridge pointer.
Definition: channel.c:10581
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:2969
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454
@ PARKED_CALL
Definition: parking.h:47
@ PARKED_CALL_FAILED
Definition: parking.h:51
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...
Structure that contains information regarding a channel in a bridge.
const ast_string_field uniqueid
Structure representing a snapshot of channel state.
struct ast_channel_snapshot_base * base

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_datastore::data, parked_subscription_data::hangup_after, NULL, PARKED_CALL, PARKED_CALL_FAILED, parked_subscription_data::parker_uuid, RAII_VAR, say_parking_space(), parked_subscription_data::transfer_data, ast_channel_snapshot_base::uniqueid, and wipe_subscription_datastore().

Referenced by parker_update_cb().

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

159{
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
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}
static void parker_parked_call_message_response(struct ast_parked_call_payload *message, struct parked_subscription_data *data, struct stasis_subscription *sub)
struct stasis_forward * sub
Definition: res_corosync.c:240
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
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:1174
A parked call message payload.
Definition: parking.h:59

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(), sub, and parked_subscription_data::transfer_data.

Referenced by create_parked_subscription_full().

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

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
347 if (ast_strlen_zero(context) || ast_strlen_zero(exten)) {
348 return -1;
349 }
350
351 if (!bridge_channel->in_bridge) {
352 return -1;
353 }
354
355 if (!parking_is_exten_park(context, exten)) {
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. */
415 ast_channel_uniqueid(other_chan),
418
419 return 0;
420}
#define ast_bridge_unlock(bridge)
Unlock the bridge.
Definition: bridge.h:481
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:1878
@ AST_BRIDGE_TRANSFER_SINGLE_PARTY
Definition: bridge.h:1111
@ AST_BRIDGE_TRANSFER_MULTI_PARTY
Definition: bridge.h:1113
@ AST_BRIDGE_IMPART_CHAN_INDEPENDENT
Definition: bridge.h:590
void ast_bridge_channel_lock_bridge(struct ast_bridge_channel *bridge_channel)
Lock the bridge associated with the bridge channel.
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.
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2947
@ E_MATCH
Definition: extconf.h:217
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 int parking_is_exten_park(const char *context, const char *exten)
void * ast_get_extension_app_data(struct ast_exten *e)
Definition: pbx.c:8562
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
struct ast_bridge * bridge
Bridge this channel is participating in.
struct ast_channel * chan
unsigned int in_bridge
unsigned int num_channels
Definition: bridge.h:373
struct ast_bridge_channel * bridge_channel
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own link...
Definition: pbx.c:237
int stacklen
Definition: extconf.h:237

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_channel::bridge_channel, ast_bridge_channel::chan, voicemailpwcheck::context, create_parked_subscription_full(), E_MATCH, ast_channel::exten, 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().

◆ parking_duration_callback()

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

Definition at line 573 of file parking_bridge_features.c.

574{
575 struct parked_user *user = hook_pvt;
576 struct ast_channel *chan = user->chan;
577 struct ast_context *park_dial_context;
578 const char *dial_string;
579 char *dial_string_flat;
580 char parking_space[AST_MAX_EXTENSION];
581
582 char returnexten[AST_MAX_EXTENSION];
583 char *duplicate_returnexten;
584 struct ast_exten *existing_exten;
585 struct pbx_find_info pbx_finder = { .stacklen = 0 }; /* The rest is reset in pbx_find_extension */
586
587
588 /* We are still in the bridge, so it's possible for other stuff to mess with the parked call before we leave the bridge
589 to deal with this, lock the parked user, check and set resolution. */
590 ao2_lock(user);
591 if (user->resolution != PARK_UNSET) {
592 /* Abandon timeout since something else has resolved the parked user before we got to it. */
594 return -1;
595 }
596 user->resolution = PARK_TIMEOUT;
598
601
602 dial_string = user->parker_dial_string;
603 dial_string_flat = ast_strdupa(dial_string);
604 flatten_dial_string(dial_string_flat);
605
606 /* Set parking timeout channel variables */
607 snprintf(parking_space, sizeof(parking_space), "%d", user->parking_space);
608 ast_channel_lock(chan);
610 pbx_builtin_setvar_helper(chan, "PARKING_SPACE", parking_space);
611 pbx_builtin_setvar_helper(chan, "PARKEDLOT", user->lot->name);
612 pbx_builtin_setvar_helper(chan, "PARKER", dial_string);
613 pbx_builtin_setvar_helper(chan, "PARKER_FLAT", dial_string_flat);
616 ast_channel_unlock(chan);
617
618 /* Dialplan generation for park-dial extensions */
619
620 if (ast_wrlock_contexts()) {
621 ast_log(LOG_ERROR, "Failed to lock the contexts list. Can't add the park-dial extension.\n");
622 return -1;
623 }
624
626 ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", PARK_DIAL_CONTEXT);
627 if (ast_unlock_contexts()) {
628 ast_assert(0);
629 }
630 goto abandon_extension_creation;
631 }
632
633 if (ast_wrlock_context(park_dial_context)) {
634 ast_log(LOG_ERROR, "failed to obtain write lock on context '%s'\n", PARK_DIAL_CONTEXT);
635 if (ast_unlock_contexts()) {
636 ast_assert(0);
637 }
638 goto abandon_extension_creation;
639 }
640
641 if (ast_unlock_contexts()) {
642 ast_assert(0);
643 }
644
645 snprintf(returnexten, sizeof(returnexten), "%s,%u", dial_string,
646 user->lot->cfg->comebackdialtime);
647
648 duplicate_returnexten = ast_strdup(returnexten);
649 if (!duplicate_returnexten) {
650 ast_log(LOG_ERROR, "Failed to create parking redial parker extension %s@%s - Dial(%s)\n",
651 dial_string_flat, PARK_DIAL_CONTEXT, returnexten);
652 }
653
654 /* If an extension already exists here because we registered it for another parked call timing out, then we may overwrite it. */
655 if ((existing_exten = pbx_find_extension(NULL, NULL, &pbx_finder, PARK_DIAL_CONTEXT, dial_string_flat, 1, NULL, NULL, E_MATCH)) &&
656 (strcmp(ast_get_extension_registrar(existing_exten), BASE_REGISTRAR))) {
657 ast_debug(3, "An extension for '%s@%s' was already registered by another registrar '%s'\n",
658 dial_string_flat, PARK_DIAL_CONTEXT, ast_get_extension_registrar(existing_exten));
659 } else if (ast_add_extension2_nolock(park_dial_context, 1, dial_string_flat, 1, NULL, NULL,
660 "Dial", duplicate_returnexten, ast_free_ptr, BASE_REGISTRAR, NULL, 0)) {
661 ast_log(LOG_ERROR, "Failed to create parking redial parker extension %s@%s - Dial(%s)\n",
662 dial_string_flat, PARK_DIAL_CONTEXT, returnexten);
663 }
664
665 if (ast_unlock_context(park_dial_context)) {
666 ast_assert(0);
667 }
668
669abandon_extension_creation:
670
671 /* async_goto the proper PBX destination - this should happen when we come out of the bridge */
672 if (!ast_strlen_zero(user->comeback)) {
673 ast_async_parseable_goto(chan, user->comeback);
674 } else {
675 comeback_goto(user, user->lot);
676 }
677
678 return -1;
679}
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1739
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
@ BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE
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_CAUSE_NORMAL_CLEARING
Definition: causes.h:106
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
#define ast_debug(level,...)
Log a DEBUG message.
static void parking_timeout_set_caller_features(struct ast_channel *chan, struct parking_lot_cfg *cfg)
void flatten_dial_string(char *dialstring)
Flattens a dial string so that it can be written to/found from PBX extensions.
int comeback_goto(struct parked_user *pu, struct parking_lot *lot)
Set a channel's position in the PBX after timeout using the parking lot settings.
int ast_wrlock_contexts(void)
Write locks the context list.
Definition: pbx.c:8463
int ast_wrlock_context(struct ast_context *con)
Write locks a given context.
Definition: pbx.c:8481
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:6149
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 ast_unlock_context(struct ast_context *con)
Definition: pbx.c:8491
int ast_async_parseable_goto(struct ast_channel *chan, const char *goto_string)
Definition: pbx.c:8871
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:7266
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8473
const char * ast_get_extension_registrar(struct ast_exten *e)
Definition: pbx.c:8532
@ PARK_TIMEOUT
Definition: res_parking.h:43
@ PARK_UNSET
Definition: res_parking.h:41
#define BASE_REGISTRAR
Definition: res_parking.h:36
#define PARK_DIAL_CONTEXT
Definition: res_parking.h:37
ast_context: An extension context
Definition: pbx.c:284
structure to hold users read from users.conf

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, comeback_goto(), E_MATCH, flatten_dial_string(), LOG_ERROR, NULL, PARK_DIAL_CONTEXT, PARK_TIMEOUT, PARK_UNSET, parking_timeout_set_caller_features(), pbx_builtin_setvar_helper(), pbx_find_extension(), and pbx_find_info::stacklen.

Referenced by parking_set_duration().

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

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}
def info(msg)
#define PARK_APPLICATION
The default parking application that Asterisk expects.
Definition: parking.h:35
const char * ast_get_extension_app(struct ast_exten *e)
Definition: pbx.c:8557

References ast_debug, ast_get_extension_app(), voicemailpwcheck::context, E_MATCH, sip_to_pjsip::info(), NULL, PARK_APPLICATION, and pbx_find_extension().

Referenced by parking_blind_transfer_park().

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

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}
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:2460
#define LOG_NOTICE
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,...
void publish_parked_call_failure(struct ast_channel *parkee)
Publish a stasis parked call message for the channel indicating failure to park.
Structure that contains information about a bridge.
Definition: bridge.h:349

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_channel::bridge_channel, ast_bridge_channel::chan, LOG_ERROR, LOG_NOTICE, NULL, park_application_setup(), publish_parked_call_failure(), and RAII_VAR.

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

500{
501 RAII_VAR(struct parking_lot *, lot, NULL, ao2_cleanup);
502 const char *lot_name;
503
504 ast_channel_lock(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_LOG_WARNING
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)
struct parking_lot * parking_create_dynamic_lot(const char *name, struct ast_channel *chan)
Create a dynamic parking lot.
Definition: res_parking.c:1060
const char * find_channel_parking_lot_name(struct ast_channel *chan)
Find parking lot name from channel.
Definition: res_parking.c:608

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, ast_channel::exten, 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().

◆ 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 703 of file parking_bridge_features.c.

704{
705 unsigned int time_limit;
706
707 time_limit = user->time_limit * 1000;
708
709 if (!time_limit) {
710 /* There is no duration limit that we need to apply. */
711 return;
712 }
713
714 /* If the time limit has already been passed, set a really low time limit so we can kick them out immediately. */
715 time_limit = ast_remaining_ms(user->start, time_limit);
716 if (time_limit <= 0) {
717 time_limit = 1;
718 }
719
720 /* The interval hook is going to need a reference to the parked_user */
721 ao2_ref(user, +1);
722
723 if (ast_bridge_interval_hook(features, 0, time_limit,
725 ast_log(LOG_ERROR, "Failed to apply duration limit to the parked call.\n");
726 ao2_ref(user, -1);
727 }
728}
void __ao2_cleanup(void *obj)
Definition: astobj2.c:677
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:3319
@ AST_BRIDGE_HOOK_REMOVE_ON_PULL
static int parking_duration_callback(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: utils.c:2281

References __ao2_cleanup(), ao2_ref, AST_BRIDGE_HOOK_REMOVE_ON_PULL, ast_bridge_interval_hook(), ast_log, ast_remaining_ms(), LOG_ERROR, and parking_duration_callback().

Referenced by bridge_parking_push().

◆ 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 540 of file parking_bridge_features.c.

541{
542 char features[5];
543 char *pos;
544
545 /*
546 * We are setting the callee Dial flag values because in the
547 * timeout case, the caller is who is being called back.
548 */
549 pos = features;
551 *pos++ = 't';
552 }
554 *pos++ = 'k';
555 }
557 *pos++ = 'h';
558 }
560 *pos++ = 'x';
561 }
562 *pos = '\0';
563
564 pbx_builtin_setvar_helper(chan, "BRIDGE_FEATURES", features);
565}
@ AST_FEATURE_FLAG_BYCALLER
Definition: features.h:38
int parkedcalltransfers
Definition: res_parking.h:76
int parkedcallreparking
Definition: res_parking.h:77
int parkedcallrecording
Definition: res_parking.h:79

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

◆ 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 681 of file parking_bridge_features.c.

682{
683 unsigned int numeric_value;
684 unsigned int hangup_after;
685
686 if (sscanf(payload, "%u %u", &hangup_after, &numeric_value) != 2) {
687 /* If say_parking_space is called with a non-numeric string, we have a problem. */
688 ast_assert(0);
689 ast_bridge_channel_leave_bridge(bridge_channel,
691 return;
692 }
693
694 ast_say_digits(bridge_channel->chan, numeric_value, "",
695 ast_channel_language(bridge_channel->chan));
696
697 if (hangup_after) {
698 ast_bridge_channel_leave_bridge(bridge_channel,
700 }
701}
const char * ast_channel_language(const struct ast_channel *chan)
int ast_say_digits(struct ast_channel *chan, int num, const char *ints, const char *lang)
says digits
Definition: channel.c:8252

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

◆ 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 793 of file parking_bridge_features.c.

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

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

Referenced by unload_module().

◆ wipe_subscription_datastore()

static void wipe_subscription_datastore ( struct ast_channel chan)
static

Definition at line 91 of file parking_bridge_features.c.

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}
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2394
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:2399

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

Referenced by create_parked_subscription_full(), and parker_parked_call_message_response().

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 779 of file parking_bridge_features.c.

Referenced by load_parking_bridge_features(), and unload_parking_bridge_features().

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

Referenced by create_parked_subscription_full(), and wipe_subscription_datastore().

◆ parking_provider

struct ast_parking_bridge_feature_fn_table parking_provider