Asterisk - The Open Source Telephony Project GIT-master-754dea3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
pickup.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 1999 - 2013, Digium, Inc.
5 * Copyright (C) 2012, Russell Bryant
6 *
7 * Matt Jordan <mjordan@digium.com>
8 *
9 * See http://www.asterisk.org for more information about
10 * the Asterisk project. Please do not directly contact
11 * any of the maintainers of this project for assistance;
12 * the project provides a web site, mailing lists and IRC
13 * channels for your use.
14 *
15 * This program is free software, distributed under the terms of
16 * the GNU General Public License Version 2. See the LICENSE file
17 * at the top of the source tree.
18 */
19
20/*! \file
21 *
22 * \brief Routines implementing call pickup
23 *
24 * \author Matt Jordan <mjordan@digium.com>
25 */
26
27/*!
28 * \li Call pickup uses the configuration file \ref features.conf
29 * \addtogroup configuration_file Configuration Files
30 */
31
32/*** MODULEINFO
33 <support_level>core</support_level>
34 ***/
35
36/*** DOCUMENTATION
37 <managerEvent language="en_US" name="Pickup">
38 <managerEventInstance class="EVENT_FLAG_CALL">
39 <since>
40 <version>12.0.0</version>
41 </since>
42 <synopsis>Raised when a call pickup occurs.</synopsis>
43 <syntax>
44 <channel_snapshot/>
45 <channel_snapshot prefix="Target"/>
46 </syntax>
47 </managerEventInstance>
48 </managerEvent>
49 ***/
50
51#include "asterisk.h"
52
53#include "asterisk/pickup.h"
54#include "asterisk/channel.h"
55#include "asterisk/pbx.h"
56#include "asterisk/app.h"
57#include "asterisk/callerid.h"
58#include "asterisk/causes.h"
59#include "asterisk/stasis.h"
62
64
68
69
70/*!
71 * The presence of this datastore on the channel indicates that
72 * someone is attempting to pickup or has picked up the channel.
73 * The purpose is to prevent a race between two channels
74 * attempting to pickup the same channel.
75 */
76static const struct ast_datastore_info pickup_active = {
77 .type = "pickup-active",
78};
79
80int ast_can_pickup(struct ast_channel *chan)
81{
85 /*
86 * Check the down state as well because some SIP devices do not
87 * give 180 ringing when they can just give 183 session progress
88 * instead. Issue 14005. (Some ISDN switches as well for that
89 * matter.)
90 */
93 return 1;
94 }
95 return 0;
96}
97
98static int find_channel_by_group(void *obj, void *arg, void *data, int flags)
99{
100 struct ast_channel *target = obj; /*!< Potential pickup target */
101 struct ast_channel *chan = arg; /*!< Channel wanting to pickup call */
102
103 if (chan == target) {
104 return 0;
105 }
106
107 ast_channel_lock(target);
108 if (ast_can_pickup(target)) {
109 /* Lock both channels. */
110 while (ast_channel_trylock(chan)) {
111 ast_channel_unlock(target);
112 sched_yield();
113 ast_channel_lock(target);
114 }
115
116 /*
117 * Both callgroup and namedcallgroup pickup variants are
118 * matched independently. Checking for named group match is
119 * done last since it's a more expensive operation.
120 */
124 struct ao2_container *candidates = data;/*!< Candidate channels found. */
125
126 /* This is a candidate to pickup */
127 ao2_link(candidates, target);
128 }
129 ast_channel_unlock(chan);
130 }
131 ast_channel_unlock(target);
132
133 return 0;
134}
135
137{
138 struct ao2_container *candidates;/*!< Candidate channels found to pickup. */
139 struct ast_channel *target;/*!< Potential pickup target */
140
142 if (!candidates) {
143 return NULL;
144 }
145
146 /* Find all candidate targets by group. */
147 ast_channel_callback(find_channel_by_group, chan, candidates, 0);
148
149 /* Find the oldest pickup target candidate */
150 target = NULL;
151 for (;;) {
152 struct ast_channel *candidate;/*!< Potential new older target */
153 struct ao2_iterator iter;
154
155 iter = ao2_iterator_init(candidates, 0);
156 while ((candidate = ao2_iterator_next(&iter))) {
157 if (!target) {
158 /* First target. */
159 target = candidate;
160 continue;
161 }
162 if (ast_tvcmp(ast_channel_creationtime(candidate), ast_channel_creationtime(target)) < 0) {
163 /* We have a new target. */
164 ast_channel_unref(target);
165 target = candidate;
166 continue;
167 }
168 ast_channel_unref(candidate);
169 }
171 if (!target) {
172 /* No candidates found. */
173 break;
174 }
175
176 /* The found channel must be locked and ref'd. */
177 ast_channel_lock(target);
178
179 /* Recheck pickup ability */
180 if (ast_can_pickup(target)) {
181 /* This is the channel to pickup. */
182 break;
183 }
184
185 /* Someone else picked it up or the call went away. */
186 ast_channel_unlock(target);
187 ao2_unlink(candidates, target);
188 target = ast_channel_unref(target);
189 }
190 ao2_ref(candidates, -1);
191
192 return target;
193}
194
195/*!
196 * \brief Pickup a call
197 *
198 * Walk list of channels, checking it is not itself, channel is pbx one,
199 * check that the callgroup for both channels are the same and the channel is ringing.
200 * Answer calling channel, flag channel as answered on queue, masq channels together.
201 */
203{
204 struct ast_channel *target;/*!< Potential pickup target */
205 int res = -1;
206 RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
207 const char *pickup_sound;
208 const char *fail_sound;
209
210 ast_debug(1, "Pickup attempt by %s\n", ast_channel_name(chan));
211 ast_channel_lock(chan);
212 pickup_cfg = ast_get_chan_features_pickup_config(chan);
213 if (!pickup_cfg) {
214 ast_log(LOG_ERROR, "Unable to retrieve pickup configuration. Unable to play pickup sounds\n");
215 }
216 pickup_sound = ast_strdupa(pickup_cfg ? pickup_cfg->pickupsound : "");
217 fail_sound = ast_strdupa(pickup_cfg ? pickup_cfg->pickupfailsound : "");
218 ast_channel_unlock(chan);
219
220 /* The found channel is already locked. */
221 target = ast_pickup_find_by_group(chan);
222 if (target) {
223 ast_log(LOG_NOTICE, "Pickup %s attempt by %s\n", ast_channel_name(target), ast_channel_name(chan));
224
225 res = ast_do_pickup(chan, target);
226 ast_channel_unlock(target);
227 if (!res) {
228 if (!ast_strlen_zero(pickup_sound)) {
229 pbx_builtin_setvar_helper(target, "BRIDGE_PLAY_SOUND", pickup_sound);
230 }
231 } else {
232 ast_log(LOG_WARNING, "Pickup %s failed by %s\n", ast_channel_name(target), ast_channel_name(chan));
233 }
234 target = ast_channel_unref(target);
235 }
236
237 if (res < 0) {
238 ast_debug(1, "No call pickup possible... for %s\n", ast_channel_name(chan));
239 if (!ast_strlen_zero(fail_sound)) {
240 ast_answer(chan);
241 ast_stream_and_wait(chan, fail_sound, "");
242 }
243 }
244
245 return res;
246}
247
249{
251 struct ast_channel_snapshot *chan;
252 struct ast_channel_snapshot *target;
253 struct ast_manager_event_blob *res;
254
255 RAII_VAR(struct ast_str *, channel_str, NULL, ast_free);
256 RAII_VAR(struct ast_str *, target_str, NULL, ast_free);
257
260
261 ast_assert(chan != NULL && target != NULL);
262
263 if (!(channel_str = ast_manager_build_channel_state_string(chan))) {
264 return NULL;
265 }
266
267 if (!(target_str = ast_manager_build_channel_state_string_prefix(target, "Target"))) {
268 return NULL;
269 }
270
272 "%s"
273 "%s",
274 ast_str_buffer(channel_str),
275 ast_str_buffer(target_str));
276
277 return res;
278}
279
280static int send_call_pickup_stasis_message(struct ast_channel *picking_up, struct ast_channel_snapshot *chan, struct ast_channel_snapshot *target)
281{
282 RAII_VAR(struct ast_multi_channel_blob *, pickup_payload, NULL, ao2_cleanup);
283 RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
284
285 if (!ast_call_pickup_type()) {
286 return -1;
287 }
288
289 if (!(pickup_payload = ast_multi_channel_blob_create(ast_json_null()))) {
290 return -1;
291 }
292
293 ast_multi_channel_blob_add_channel(pickup_payload, "channel", chan);
294 ast_multi_channel_blob_add_channel(pickup_payload, "target", target);
295
296 if (!(msg = stasis_message_create(ast_call_pickup_type(), pickup_payload))) {
297 return -1;
298 }
299
300 stasis_publish(ast_channel_topic(picking_up), msg);
301 return 0;
302}
303
304int ast_do_pickup(struct ast_channel *chan, struct ast_channel *target)
305{
306 struct ast_party_connected_line connected_caller;
307 struct ast_datastore *ds_pickup;
308 const char *chan_name;/*!< A masquerade changes channel names. */
309 const char *target_name;/*!< A masquerade changes channel names. */
310 int res = -1;
311
312 RAII_VAR(struct ast_channel_snapshot *, chan_snapshot, NULL, ao2_cleanup);
313 RAII_VAR(struct ast_channel_snapshot *, target_snapshot, NULL, ao2_cleanup);
314
315 target_name = ast_strdupa(ast_channel_name(target));
316 ast_debug(1, "Call pickup on '%s' by '%s'\n", target_name, ast_channel_name(chan));
317
318 /* Mark the target to block any call pickup race. */
320 if (!ds_pickup) {
322 "Unable to create channel datastore on '%s' for call pickup\n", target_name);
323 return -1;
324 }
325 ast_channel_datastore_add(target, ds_pickup);
326
327 ast_party_connected_line_init(&connected_caller);
328 ast_party_connected_line_copy(&connected_caller, ast_channel_connected(target));
329 ast_channel_unlock(target);/* The pickup race is avoided so we do not need the lock anymore. */
330 /* Reset any earlier private connected id representation */
331 ast_party_id_reset(&connected_caller.priv);
332
334 if (ast_channel_connected_line_sub(NULL, chan, &connected_caller, 0)) {
335 ast_channel_update_connected_line(chan, &connected_caller, NULL);
336 }
337 ast_party_connected_line_free(&connected_caller);
338
339 ast_channel_lock(chan);
340 chan_name = ast_strdupa(ast_channel_name(chan));
342 ast_channel_unlock(chan);
344
345 if (ast_answer(chan)) {
346 ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan_name);
347 goto pickup_failed;
348 }
349
351 ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan_name);
352 goto pickup_failed;
353 }
354
355 ast_channel_queue_connected_line_update(chan, &connected_caller, NULL);
356
357 /* setting the HANGUPCAUSE so the ringing channel knows this call was not a missed call */
359
360 ast_channel_lock(chan);
361 chan_snapshot = ast_channel_snapshot_create(chan);
362 ast_channel_unlock(chan);
363 if (!chan_snapshot) {
364 goto pickup_failed;
365 }
366
367 target_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(target));
368 if (!target_snapshot) {
369 goto pickup_failed;
370 }
371
372 if (ast_channel_move(target, chan)) {
373 ast_log(LOG_WARNING, "Unable to complete call pickup of '%s' with '%s'\n",
374 chan_name, target_name);
375 goto pickup_failed;
376 }
377
378 /* target points to the channel that did the pickup at this point, so use that channel's topic instead of chan */
379 send_call_pickup_stasis_message(target, chan_snapshot, target_snapshot);
380
381 res = 0;
382
383pickup_failed:
384 ast_channel_lock(target);
385 if (!ast_channel_datastore_remove(target, ds_pickup)) {
386 ast_datastore_free(ds_pickup);
387 }
388 ast_party_connected_line_free(&connected_caller);
389
390 return res;
391}
392
393/*!
394 * \internal
395 * \brief Clean up resources on Asterisk shutdown
396 */
397static void pickup_shutdown(void)
398{
400}
401
403{
406
407 return 0;
408}
Asterisk main include file. File version handling, generic pbx functions.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
#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_log
Definition: astobj2.c:42
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#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
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
@ AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER
Definition: callerid.h:554
Internal Asterisk hangup causes.
#define AST_CAUSE_ANSWERED_ELSEWHERE
Definition: causes.h:114
General Asterisk PBX channel definitions.
const char * ast_channel_name(const struct ast_channel *chan)
struct ast_channel * ast_channel_masq(const struct ast_channel *chan)
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:1305
struct ast_namedgroups * ast_channel_named_pickupgroups(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:2414
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2423
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:10364
void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
Destroy the connected line information contents.
Definition: channel.c:2099
struct stasis_topic * ast_channel_topic(struct ast_channel *chan)
A topic which publishes the events for a particular channel.
#define ast_channel_lock(chan)
Definition: channel.h:2970
struct ast_namedgroups * ast_channel_named_callgroups(const struct ast_channel *chan)
ast_group_t ast_channel_pickupgroup(const struct ast_channel *chan)
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:2058
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition: channel.c:1258
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
struct ast_party_connected_line * ast_channel_connected(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:8116
const char * ast_channel_uniqueid(const struct ast_channel *chan)
#define ast_channel_trylock(chan)
Definition: channel.h:2972
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:9119
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:10692
struct timeval ast_channel_creationtime(struct ast_channel *chan)
void ast_party_id_reset(struct ast_party_id *id)
Destroy and initialize the given party id structure.
Definition: channel.c:1923
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3006
@ AST_FLAG_ZOMBIE
Definition: channel.h:1007
ast_group_t ast_channel_callgroup(const struct ast_channel *chan)
void ast_party_connected_line_init(struct ast_party_connected_line *init)
Initialize the given connected line structure.
Definition: channel.c:2049
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:8319
struct ast_pbx * ast_channel_pbx(const struct ast_channel *chan)
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:9132
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2834
#define ast_channel_unlock(chan)
Definition: channel.h:2971
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:2428
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
#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
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:1886
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.
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_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.
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.
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
struct ast_features_pickup_config * ast_get_chan_features_pickup_config(struct ast_channel *chan)
Get the pickup configuration options for a channel.
@ AST_CONTROL_ANSWER
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define LOG_NOTICE
#define LOG_WARNING
struct ast_json * ast_json_null(void)
Get the JSON null value.
Definition: json.c:248
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:10237
#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.
Core PBX routines and definitions.
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.
STASIS_MESSAGE_TYPE_DEFN(ast_call_pickup_type,.to_ami=call_pickup_to_ami)
static int find_channel_by_group(void *obj, void *arg, void *data, int flags)
Definition: pickup.c:98
static const struct ast_datastore_info pickup_active
Definition: pickup.c:76
int ast_pickup_call(struct ast_channel *chan)
Pickup a call.
Definition: pickup.c:202
int ast_pickup_init(void)
Initialize pickup.
Definition: pickup.c:402
static void pickup_shutdown(void)
Definition: pickup.c:397
int ast_can_pickup(struct ast_channel *chan)
Test if a channel can be picked up.
Definition: pickup.c:80
int ast_do_pickup(struct ast_channel *chan, struct ast_channel *target)
Pickup a call target.
Definition: pickup.c:304
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:280
struct ast_channel * ast_pickup_find_by_group(struct ast_channel *chan)
Find a pickup channel target by group.
Definition: pickup.c:136
static struct ast_manager_event_blob * call_pickup_to_ami(struct stasis_message *message)
Definition: pickup.c:248
Call Pickup API.
struct stasis_message_type * ast_call_pickup_type(void)
accessor for call pickup message type
static void to_ami(struct ast_sip_subscription *sub, struct ast_str **buf)
#define NULL
Definition: resample.c:96
Stasis Message Bus API. See Stasis Message Bus API for detailed documentation.
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1515
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition: stasis.h:1493
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
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:1538
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
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
Structure representing a snapshot of channel state.
Main Channel structure associated with a channel.
Structure for a data store type.
Definition: datastore.h:31
const char * type
Definition: datastore.h:32
Structure for a data store object.
Definition: datastore.h:64
Configuration relating to call pickup.
Struct containing info for an AMI event to send out.
Definition: manager.h:503
A multi channel blob data structure for multi_channel_blob stasis messages.
Connected Line/Party information.
Definition: channel.h:458
int source
Information about the source of an update.
Definition: channel.h:484
struct ast_party_id priv
Private connected party ID.
Definition: channel.h:470
Support for dynamic strings.
Definition: strings.h:623
const char * contents
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
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
#define ast_assert(a)
Definition: utils.h:739