Asterisk - The Open Source Telephony Project GIT-master-d856a3e
Functions | Variables
pickup.c File Reference

Routines implementing call pickup. More...

#include "asterisk.h"
#include "asterisk/pickup.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/app.h"
#include "asterisk/callerid.h"
#include "asterisk/causes.h"
#include "asterisk/stasis.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/features_config.h"
Include dependency graph for pickup.c:

Go to the source code of this file.

Functions

int ast_can_pickup (struct ast_channel *chan)
 Test if a channel can be picked up. More...
 
int ast_do_pickup (struct ast_channel *chan, struct ast_channel *target)
 Pickup a call target. More...
 
int ast_pickup_call (struct ast_channel *chan)
 Pickup a call. More...
 
struct ast_channelast_pickup_find_by_group (struct ast_channel *chan)
 Find a pickup channel target by group. More...
 
int ast_pickup_init (void)
 Initialize pickup. More...
 
static struct ast_manager_event_blobcall_pickup_to_ami (struct stasis_message *message)
 
static int find_channel_by_group (void *obj, void *arg, void *data, int flags)
 
static void pickup_shutdown (void)
 
static int send_call_pickup_stasis_message (struct ast_channel *picking_up, struct ast_channel_snapshot *chan, struct ast_channel_snapshot *target)
 
 STASIS_MESSAGE_TYPE_DEFN (ast_call_pickup_type,.to_ami=call_pickup_to_ami)
 

Variables

static const struct ast_datastore_info pickup_active
 

Detailed Description

Routines implementing call pickup.

Author
Matt Jordan mjord.nosp@m.an@d.nosp@m.igium.nosp@m..com

Definition in file pickup.c.

Function Documentation

◆ ast_can_pickup()

int ast_can_pickup ( struct ast_channel chan)

Test if a channel can be picked up.

Parameters
chanChannel to test if can be picked up.
Note
This function assumes that chan is locked.
Return values
TRUEif channel can be picked up.

Definition at line 77 of file pickup.c.

78{
82 /*
83 * Check the down state as well because some SIP devices do not
84 * give 180 ringing when they can just give 183 session progress
85 * instead. Issue 14005. (Some ISDN switches as well for that
86 * matter.)
87 */
90 return 1;
91 }
92 return 0;
93}
struct ast_channel * ast_channel_masq(const struct ast_channel *chan)
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
@ AST_FLAG_ZOMBIE
Definition: channel.h:1007
struct ast_pbx * ast_channel_pbx(const struct ast_channel *chan)
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:2418
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_RING
Definition: channelstate.h:40
@ AST_STATE_RINGING
Definition: channelstate.h:41
@ AST_STATE_DOWN
Definition: channelstate.h:36
static const struct ast_datastore_info pickup_active
Definition: pickup.c:73
#define NULL
Definition: resample.c:96
#define ast_test_flag(p, flag)
Definition: utils.h:63

References ast_channel_datastore_find(), ast_channel_flags(), ast_channel_masq(), ast_channel_pbx(), AST_FLAG_ZOMBIE, AST_STATE_DOWN, AST_STATE_RING, AST_STATE_RINGING, ast_test_flag, NULL, and pickup_active.

Referenced by ast_pickup_find_by_group(), find_by_mark(), find_by_name(), find_by_uniqueid(), find_channel_by_group(), and pickup_by_exten().

◆ ast_do_pickup()

int ast_do_pickup ( struct ast_channel chan,
struct ast_channel target 
)

Pickup a call target.

Parameters
chanchannel that initiated pickup.
targetchannel to be picked up.
Note
This function assumes that target is locked.
Return values
0on success.
-1on failure.

< A masquerade changes channel names.

< A masquerade changes channel names.

Definition at line 301 of file pickup.c.

302{
303 struct ast_party_connected_line connected_caller;
304 struct ast_datastore *ds_pickup;
305 const char *chan_name;/*!< A masquerade changes channel names. */
306 const char *target_name;/*!< A masquerade changes channel names. */
307 int res = -1;
308
309 RAII_VAR(struct ast_channel_snapshot *, chan_snapshot, NULL, ao2_cleanup);
310 RAII_VAR(struct ast_channel_snapshot *, target_snapshot, NULL, ao2_cleanup);
311
312 target_name = ast_strdupa(ast_channel_name(target));
313 ast_debug(1, "Call pickup on '%s' by '%s'\n", target_name, ast_channel_name(chan));
314
315 /* Mark the target to block any call pickup race. */
317 if (!ds_pickup) {
319 "Unable to create channel datastore on '%s' for call pickup\n", target_name);
320 return -1;
321 }
322 ast_channel_datastore_add(target, ds_pickup);
323
324 ast_party_connected_line_init(&connected_caller);
325 ast_party_connected_line_copy(&connected_caller, ast_channel_connected(target));
326 ast_channel_unlock(target);/* The pickup race is avoided so we do not need the lock anymore. */
327 /* Reset any earlier private connected id representation */
328 ast_party_id_reset(&connected_caller.priv);
329
330 connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
331 if (ast_channel_connected_line_sub(NULL, chan, &connected_caller, 0)) {
332 ast_channel_update_connected_line(chan, &connected_caller, NULL);
333 }
334 ast_party_connected_line_free(&connected_caller);
335
336 ast_channel_lock(chan);
337 chan_name = ast_strdupa(ast_channel_name(chan));
339 ast_channel_unlock(chan);
340 connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
341
342 if (ast_answer(chan)) {
343 ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan_name);
344 goto pickup_failed;
345 }
346
348 ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan_name);
349 goto pickup_failed;
350 }
351
352 ast_channel_queue_connected_line_update(chan, &connected_caller, NULL);
353
354 /* setting the HANGUPCAUSE so the ringing channel knows this call was not a missed call */
356
357 ast_channel_lock(chan);
358 chan_snapshot = ast_channel_snapshot_create(chan);
359 ast_channel_unlock(chan);
360 if (!chan_snapshot) {
361 goto pickup_failed;
362 }
363
364 target_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(target));
365 if (!target_snapshot) {
366 goto pickup_failed;
367 }
368
369 if (ast_channel_move(target, chan)) {
370 ast_log(LOG_WARNING, "Unable to complete call pickup of '%s' with '%s'\n",
371 chan_name, target_name);
372 goto pickup_failed;
373 }
374
375 /* target points to the channel that did the pickup at this point, so use that channel's topic instead of chan */
376 send_call_pickup_stasis_message(target, chan_snapshot, target_snapshot);
377
378 res = 0;
379
380pickup_failed:
381 ast_channel_lock(target);
382 if (!ast_channel_datastore_remove(target, ds_pickup)) {
383 ast_datastore_free(ds_pickup);
384 }
385 ast_party_connected_line_free(&connected_caller);
386
387 return res;
388}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_log
Definition: astobj2.c:42
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
@ AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER
Definition: callerid.h:554
#define AST_CAUSE_ANSWERED_ELSEWHERE
Definition: causes.h:114
const char * ast_channel_name(const struct ast_channel *chan)
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2404
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2413
int ast_channel_connected_line_sub(struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const void *connected_info, int frame)
Run a connected line interception subroutine and update a channel's connected line information.
Definition: channel.c:10360
void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
Destroy the connected line information contents.
Definition: channel.c:2091
#define ast_channel_lock(chan)
Definition: channel.h:2968
void ast_party_connected_line_copy(struct ast_party_connected_line *dest, const struct ast_party_connected_line *src)
Copy the source connected line information to the destination connected line.
Definition: channel.c:2050
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition: channel.c:1250
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
const char * ast_channel_uniqueid(const struct ast_channel *chan)
void ast_channel_update_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Indicate that the connected line information has changed.
Definition: channel.c:9115
int ast_channel_move(struct ast_channel *dest, struct ast_channel *source)
Move a channel from its current location to a new location.
Definition: channel.c:10688
void ast_party_id_reset(struct ast_party_id *id)
Destroy and initialize the given party id structure.
Definition: channel.c:1915
void ast_party_connected_line_init(struct ast_party_connected_line *init)
Initialize the given connected line structure.
Definition: channel.c:2041
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:8315
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
void ast_channel_queue_connected_line_update(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Queue a connected line update frame on a channel.
Definition: channel.c:9128
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2824
#define ast_channel_unlock(chan)
Definition: channel.h:2969
#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 ast_channel_snapshot * ast_channel_snapshot_get_latest(const char *uniqueid)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object,...
struct ast_channel_snapshot * ast_channel_snapshot_create(struct ast_channel *chan)
Generate a snapshot of the channel state. This is an ao2 object, so ao2_cleanup() to deallocate.
@ AST_CONTROL_ANSWER
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_WARNING
static int send_call_pickup_stasis_message(struct ast_channel *picking_up, struct ast_channel_snapshot *chan, struct ast_channel_snapshot *target)
Definition: pickup.c:277
Structure representing a snapshot of channel state.
Structure for a data store object.
Definition: datastore.h:64
Connected Line/Party information.
Definition: channel.h:458
#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, ast_answer(), AST_CAUSE_ANSWERED_ELSEWHERE, ast_channel_caller(), ast_channel_connected(), ast_channel_connected_line_sub(), ast_channel_datastore_add(), ast_channel_datastore_remove(), ast_channel_hangupcause_set(), ast_channel_lock, ast_channel_move(), ast_channel_name(), ast_channel_queue_connected_line_update(), ast_channel_snapshot_create(), ast_channel_snapshot_get_latest(), ast_channel_uniqueid(), ast_channel_unlock, ast_channel_update_connected_line(), ast_connected_line_copy_from_caller(), AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, AST_CONTROL_ANSWER, ast_datastore_alloc, ast_datastore_free(), ast_debug, ast_log, ast_party_connected_line_copy(), ast_party_connected_line_free(), ast_party_connected_line_init(), ast_party_id_reset(), ast_queue_control(), ast_strdupa, LOG_WARNING, NULL, pickup_active, ast_party_connected_line::priv, RAII_VAR, send_call_pickup_stasis_message(), and ast_party_connected_line::source.

Referenced by ast_pickup_call(), AST_TEST_DEFINE(), pickup_by_channel(), pickup_by_exten(), pickup_by_group(), pickup_by_mark(), and pickup_by_part().

◆ ast_pickup_call()

int ast_pickup_call ( struct ast_channel chan)

Pickup a call.

Walk list of channels, checking it is not itself, channel is pbx one, check that the callgroup for both channels are the same and the channel is ringing. Answer calling channel, flag channel as answered on queue, masq channels together.

< Potential pickup target

Definition at line 199 of file pickup.c.

200{
201 struct ast_channel *target;/*!< Potential pickup target */
202 int res = -1;
203 RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
204 const char *pickup_sound;
205 const char *fail_sound;
206
207 ast_debug(1, "Pickup attempt by %s\n", ast_channel_name(chan));
208 ast_channel_lock(chan);
209 pickup_cfg = ast_get_chan_features_pickup_config(chan);
210 if (!pickup_cfg) {
211 ast_log(LOG_ERROR, "Unable to retrieve pickup configuration. Unable to play pickup sounds\n");
212 }
213 pickup_sound = ast_strdupa(pickup_cfg ? pickup_cfg->pickupsound : "");
214 fail_sound = ast_strdupa(pickup_cfg ? pickup_cfg->pickupfailsound : "");
215 ast_channel_unlock(chan);
216
217 /* The found channel is already locked. */
218 target = ast_pickup_find_by_group(chan);
219 if (target) {
220 ast_log(LOG_NOTICE, "Pickup %s attempt by %s\n", ast_channel_name(target), ast_channel_name(chan));
221
222 res = ast_do_pickup(chan, target);
223 ast_channel_unlock(target);
224 if (!res) {
225 if (!ast_strlen_zero(pickup_sound)) {
226 pbx_builtin_setvar_helper(target, "BRIDGE_PLAY_SOUND", pickup_sound);
227 }
228 } else {
229 ast_log(LOG_WARNING, "Pickup %s failed by %s\n", ast_channel_name(target), ast_channel_name(chan));
230 }
231 target = ast_channel_unref(target);
232 }
233
234 if (res < 0) {
235 ast_debug(1, "No call pickup possible... for %s\n", ast_channel_name(chan));
236 if (!ast_strlen_zero(fail_sound)) {
237 ast_answer(chan);
238 ast_stream_and_wait(chan, fail_sound, "");
239 }
240 }
241
242 return res;
243}
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3004
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
Definition: file.c:1878
struct ast_features_pickup_config * ast_get_chan_features_pickup_config(struct ast_channel *chan)
Get the pickup configuration options for a channel.
#define LOG_ERROR
#define LOG_NOTICE
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_do_pickup(struct ast_channel *chan, struct ast_channel *target)
Pickup a call target.
Definition: pickup.c:301
struct ast_channel * ast_pickup_find_by_group(struct ast_channel *chan)
Find a pickup channel target by group.
Definition: pickup.c:133
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
Main Channel structure associated with a channel.
Configuration relating to call pickup.

References ao2_cleanup, ast_answer(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_channel_unref, ast_debug, ast_do_pickup(), ast_get_chan_features_pickup_config(), ast_log, ast_pickup_find_by_group(), ast_strdupa, ast_stream_and_wait(), ast_strlen_zero(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, NULL, pbx_builtin_setvar_helper(), and RAII_VAR.

Referenced by __analog_ss_thread(), analog_ss_thread(), call_pickup_incoming_request(), and handle_call_outgoing().

◆ ast_pickup_find_by_group()

struct ast_channel * ast_pickup_find_by_group ( struct ast_channel chan)

Find a pickup channel target by group.

Parameters
chanchannel that initiated pickup.
Returns
target on success. The returned channel is locked and reffed.
Return values
NULLon error.

< Candidate channels found to pickup.

< Potential pickup target

< Potential new older target

Definition at line 133 of file pickup.c.

134{
135 struct ao2_container *candidates;/*!< Candidate channels found to pickup. */
136 struct ast_channel *target;/*!< Potential pickup target */
137
139 if (!candidates) {
140 return NULL;
141 }
142
143 /* Find all candidate targets by group. */
144 ast_channel_callback(find_channel_by_group, chan, candidates, 0);
145
146 /* Find the oldest pickup target candidate */
147 target = NULL;
148 for (;;) {
149 struct ast_channel *candidate;/*!< Potential new older target */
150 struct ao2_iterator iter;
151
152 iter = ao2_iterator_init(candidates, 0);
153 while ((candidate = ao2_iterator_next(&iter))) {
154 if (!target) {
155 /* First target. */
156 target = candidate;
157 continue;
158 }
159 if (ast_tvcmp(ast_channel_creationtime(candidate), ast_channel_creationtime(target)) < 0) {
160 /* We have a new target. */
161 ast_channel_unref(target);
162 target = candidate;
163 continue;
164 }
165 ast_channel_unref(candidate);
166 }
168 if (!target) {
169 /* No candidates found. */
170 break;
171 }
172
173 /* The found channel must be locked and ref'd. */
174 ast_channel_lock(target);
175
176 /* Recheck pickup ability */
177 if (ast_can_pickup(target)) {
178 /* This is the channel to pickup. */
179 break;
180 }
181
182 /* Someone else picked it up or the call went away. */
183 ast_channel_unlock(target);
184 ao2_unlink(candidates, target);
185 target = ast_channel_unref(target);
186 }
187 ao2_ref(candidates, -1);
188
189 return target;
190}
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
Definition: astobj2.h:1327
struct ast_channel * ast_channel_callback(ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags)
Call a function with every active channel.
Definition: channel.c:1297
struct timeval ast_channel_creationtime(struct ast_channel *chan)
static int find_channel_by_group(void *obj, void *arg, void *data, int flags)
Definition: pickup.c:95
int ast_can_pickup(struct ast_channel *chan)
Test if a channel can be picked up.
Definition: pickup.c:77
Generic container type.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
int ast_tvcmp(struct timeval _a, struct timeval _b)
Compress two struct timeval instances returning -1, 0, 1 if the first arg is smaller,...
Definition: time.h:137

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_container_alloc_list, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ao2_unlink, ast_can_pickup(), ast_channel_callback(), ast_channel_creationtime(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, ast_tvcmp(), find_channel_by_group(), and NULL.

Referenced by ast_pickup_call(), and pickup_by_group().

◆ ast_pickup_init()

int ast_pickup_init ( void  )

Initialize pickup.

Return values
0on success
non-zeroon failure

Definition at line 399 of file pickup.c.

400{
403
404 return 0;
405}
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
static void pickup_shutdown(void)
Definition: pickup.c:394
struct stasis_message_type * ast_call_pickup_type(void)
accessor for call pickup message type
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition: stasis.h:1493

References ast_call_pickup_type(), ast_register_cleanup(), pickup_shutdown(), and STASIS_MESSAGE_TYPE_INIT.

Referenced by asterisk_daemon().

◆ call_pickup_to_ami()

static struct ast_manager_event_blob * call_pickup_to_ami ( struct stasis_message message)
static

Definition at line 245 of file pickup.c.

246{
248 struct ast_channel_snapshot *chan;
249 struct ast_channel_snapshot *target;
250 struct ast_manager_event_blob *res;
251
252 RAII_VAR(struct ast_str *, channel_str, NULL, ast_free);
253 RAII_VAR(struct ast_str *, target_str, NULL, ast_free);
254
257
258 ast_assert(chan != NULL && target != NULL);
259
260 if (!(channel_str = ast_manager_build_channel_state_string(chan))) {
261 return NULL;
262 }
263
264 if (!(target_str = ast_manager_build_channel_state_string_prefix(target, "Target"))) {
265 return NULL;
266 }
267
269 "%s"
270 "%s",
271 ast_str_buffer(channel_str),
272 ast_str_buffer(target_str));
273
274 return res;
275}
#define ast_free(a)
Definition: astmm.h:180
struct ast_channel_snapshot * ast_multi_channel_blob_get_channel(struct ast_multi_channel_blob *obj, const char *role)
Retrieve a channel snapshot associated with a specific role from a ast_multi_channel_blob.
struct ast_str * ast_manager_build_channel_state_string(const struct ast_channel_snapshot *snapshot)
Generate the AMI message body from a channel snapshot.
struct ast_manager_event_blob * ast_manager_event_blob_create(int event_flags, const char *manager_event, const char *extra_fields_fmt,...)
Construct a ast_manager_event_blob.
Definition: manager.c:10029
#define EVENT_FLAG_CALL
Definition: manager.h:76
struct ast_str * ast_manager_build_channel_state_string_prefix(const struct ast_channel_snapshot *snapshot, const char *prefix)
Generate the AMI message body from a channel snapshot.
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
Struct containing info for an AMI event to send out.
Definition: manager.h:502
A multi channel blob data structure for multi_channel_blob stasis messages.
Support for dynamic strings.
Definition: strings.h:623
const char * contents
#define ast_assert(a)
Definition: utils.h:739

References ast_assert, ast_free, ast_manager_build_channel_state_string(), ast_manager_build_channel_state_string_prefix(), ast_manager_event_blob_create(), ast_multi_channel_blob_get_channel(), ast_str_buffer(), contents, EVENT_FLAG_CALL, NULL, RAII_VAR, and stasis_message_data().

◆ find_channel_by_group()

static int find_channel_by_group ( void *  obj,
void *  arg,
void *  data,
int  flags 
)
static

< Potential pickup target

< Channel wanting to pickup call

< Candidate channels found.

Definition at line 95 of file pickup.c.

96{
97 struct ast_channel *target = obj; /*!< Potential pickup target */
98 struct ast_channel *chan = arg; /*!< Channel wanting to pickup call */
99
100 if (chan == target) {
101 return 0;
102 }
103
104 ast_channel_lock(target);
105 if (ast_can_pickup(target)) {
106 /* Lock both channels. */
107 while (ast_channel_trylock(chan)) {
108 ast_channel_unlock(target);
109 sched_yield();
110 ast_channel_lock(target);
111 }
112
113 /*
114 * Both callgroup and namedcallgroup pickup variants are
115 * matched independently. Checking for named group match is
116 * done last since it's a more expensive operation.
117 */
121 struct ao2_container *candidates = data;/*!< Candidate channels found. */
122
123 /* This is a candidate to pickup */
124 ao2_link(candidates, target);
125 }
126 ast_channel_unlock(chan);
127 }
128 ast_channel_unlock(target);
129
130 return 0;
131}
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
struct ast_namedgroups * ast_channel_named_pickupgroups(const struct ast_channel *chan)
struct ast_namedgroups * ast_channel_named_callgroups(const struct ast_channel *chan)
ast_group_t ast_channel_pickupgroup(const struct ast_channel *chan)
int ast_namedgroups_intersect(struct ast_namedgroups *a, struct ast_namedgroups *b)
Return TRUE if group a and b contain at least one common groupname.
Definition: channel.c:8112
#define ast_channel_trylock(chan)
Definition: channel.h:2970
ast_group_t ast_channel_callgroup(const struct ast_channel *chan)

References ao2_link, ast_can_pickup(), ast_channel_callgroup(), ast_channel_lock, ast_channel_named_callgroups(), ast_channel_named_pickupgroups(), ast_channel_pickupgroup(), ast_channel_trylock, ast_channel_unlock, and ast_namedgroups_intersect().

Referenced by ast_pickup_find_by_group().

◆ pickup_shutdown()

static void pickup_shutdown ( void  )
static

Definition at line 394 of file pickup.c.

395{
397}
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1515

References ast_call_pickup_type(), and STASIS_MESSAGE_TYPE_CLEANUP.

Referenced by ast_pickup_init().

◆ send_call_pickup_stasis_message()

static int send_call_pickup_stasis_message ( struct ast_channel picking_up,
struct ast_channel_snapshot chan,
struct ast_channel_snapshot target 
)
static

Definition at line 277 of file pickup.c.

278{
279 RAII_VAR(struct ast_multi_channel_blob *, pickup_payload, NULL, ao2_cleanup);
280 RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
281
282 if (!ast_call_pickup_type()) {
283 return -1;
284 }
285
286 if (!(pickup_payload = ast_multi_channel_blob_create(ast_json_null()))) {
287 return -1;
288 }
289
290 ast_multi_channel_blob_add_channel(pickup_payload, "channel", chan);
291 ast_multi_channel_blob_add_channel(pickup_payload, "target", target);
292
293 if (!(msg = stasis_message_create(ast_call_pickup_type(), pickup_payload))) {
294 return -1;
295 }
296
297 stasis_publish(ast_channel_topic(picking_up), msg);
298 return 0;
299}
struct stasis_topic * ast_channel_topic(struct ast_channel *chan)
A topic which publishes the events for a particular channel.
struct ast_multi_channel_blob * ast_multi_channel_blob_create(struct ast_json *blob)
Create a ast_multi_channel_blob suitable for a stasis_message.
void ast_multi_channel_blob_add_channel(struct ast_multi_channel_blob *obj, const char *role, struct ast_channel_snapshot *snapshot)
Add a ast_channel_snapshot to a ast_multi_channel_blob object.
struct ast_json * ast_json_null(void)
Get the JSON null value.
Definition: json.c:248
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition: stasis.c:1512

References ao2_cleanup, ast_call_pickup_type(), ast_channel_topic(), ast_json_null(), ast_multi_channel_blob_add_channel(), ast_multi_channel_blob_create(), NULL, RAII_VAR, stasis_message_create(), and stasis_publish().

Referenced by ast_do_pickup().

◆ STASIS_MESSAGE_TYPE_DEFN()

STASIS_MESSAGE_TYPE_DEFN ( ast_call_pickup_type  ,
to_ami = call_pickup_to_ami 
)

Variable Documentation

◆ pickup_active

const struct ast_datastore_info pickup_active
static
Initial value:
= {
.type = "pickup-active",
}

The presence of this datastore on the channel indicates that someone is attemting to pickup or has picked up the channel. The purpose is to prevent a race between two channels attempting to pickup the same channel.

Definition at line 73 of file pickup.c.

Referenced by ast_can_pickup(), and ast_do_pickup().