Asterisk - The Open Source Telephony Project GIT-master-7e7a603
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 <synopsis>Raised when a call pickup occurs.</synopsis>
40 <syntax>
41 <channel_snapshot/>
42 <channel_snapshot prefix="Target"/>
43 </syntax>
44 </managerEventInstance>
45 </managerEvent>
46 ***/
47
48#include "asterisk.h"
49
50#include "asterisk/pickup.h"
51#include "asterisk/channel.h"
52#include "asterisk/pbx.h"
53#include "asterisk/app.h"
54#include "asterisk/callerid.h"
55#include "asterisk/causes.h"
56#include "asterisk/stasis.h"
59
61
65
66
67/*!
68 * The presence of this datastore on the channel indicates that
69 * someone is attemting to pickup or has picked up the channel.
70 * The purpose is to prevent a race between two channels
71 * attempting to pickup the same channel.
72 */
73static const struct ast_datastore_info pickup_active = {
74 .type = "pickup-active",
75};
76
77int ast_can_pickup(struct ast_channel *chan)
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}
94
95static int find_channel_by_group(void *obj, void *arg, void *data, int flags)
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}
132
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}
191
192/*!
193 * \brief Pickup a call
194 *
195 * Walk list of channels, checking it is not itself, channel is pbx one,
196 * check that the callgroup for both channels are the same and the channel is ringing.
197 * Answer calling channel, flag channel as answered on queue, masq channels together.
198 */
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}
244
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}
276
277static int send_call_pickup_stasis_message(struct ast_channel *picking_up, struct ast_channel_snapshot *chan, struct ast_channel_snapshot *target)
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}
300
301int ast_do_pickup(struct ast_channel *chan, struct ast_channel *target)
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
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);
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}
389
390/*!
391 * \internal
392 * \brief Clean up resources on Asterisk shutdown
393 */
394static void pickup_shutdown(void)
395{
397}
398
400{
403
404 return 0;
405}
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:1278
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:2385
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2394
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:10338
void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
Destroy the connected line information contents.
Definition: channel.c:2072
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:2922
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:2031
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition: channel.c:1231
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:8090
const char * ast_channel_uniqueid(const struct ast_channel *chan)
#define ast_channel_trylock(chan)
Definition: channel.h:2924
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:9093
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:10666
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:1896
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
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:2022
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:8293
@ AST_FLAG_ZOMBIE
Definition: channel.h:987
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:9106
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2805
#define ast_channel_unlock(chan)
Definition: channel.h:2923
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
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:1878
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:10548
#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:95
static const struct ast_datastore_info pickup_active
Definition: pickup.c:73
int ast_pickup_call(struct ast_channel *chan)
Pickup a call.
Definition: pickup.c:199
int ast_pickup_init(void)
Initialize pickup.
Definition: pickup.c:399
static void pickup_shutdown(void)
Definition: pickup.c:394
int ast_can_pickup(struct ast_channel *chan)
Test if a channel can be picked up.
Definition: pickup.c:77
int ast_do_pickup(struct ast_channel *chan, struct ast_channel *target)
Pickup a call target.
Definition: pickup.c:301
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
struct ast_channel * ast_pickup_find_by_group(struct ast_channel *chan)
Find a pickup channel target by group.
Definition: pickup.c:133
static struct ast_manager_event_blob * call_pickup_to_ami(struct stasis_message *message)
Definition: pickup.c:245
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:1511
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:502
A multi channel blob data structure for multi_channel_blob stasis messages.
Connected Line/Party information.
Definition: channel.h:456
int source
Information about the source of an update.
Definition: channel.h:482
struct ast_party_id priv
Private connected party ID.
Definition: channel.h:468
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