Asterisk - The Open Source Telephony Project GIT-master-f36a736
Data Structures | Macros | Enumerations | Functions | Variables
app_directed_pickup.c File Reference

Directed Call Pickup Support. More...

#include "asterisk.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/app.h"
#include "asterisk/pickup.h"
#include "asterisk/manager.h"
#include "asterisk/callerid.h"
Include dependency graph for app_directed_pickup.c:

Go to the source code of this file.

Data Structures

struct  pickup_by_name_args
 

Macros

#define PICKUPMARK   "PICKUPMARK"
 

Enumerations

enum  OPT_PICKUPCHAN_FLAGS { OPT_PICKUPCHAN_PARTIAL = (1 << 0) }
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static struct ast_channelfind_by_channel (struct ast_channel *chan, const char *channame)
 Helper Function to walk through ALL channels checking NAME and STATE. More...
 
static int find_by_mark (void *obj, void *arg, void *data, int flags)
 
static int find_by_name (void *obj, void *arg, void *data, int flags)
 
static struct ast_channelfind_by_part (struct ast_channel *chan, const char *part)
 
static int find_by_uniqueid (void *obj, void *arg, void *data, int flags)
 
static int load_module (void)
 
static int pickup_by_channel (struct ast_channel *chan, const char *name)
 Attempt to pick up named channel. More...
 
static int pickup_by_exten (struct ast_channel *chan, const char *exten, const char *context)
 
static int pickup_by_group (struct ast_channel *chan)
 
static int pickup_by_mark (struct ast_channel *chan, const char *mark)
 
static int pickup_by_part (struct ast_channel *chan, const char *part)
 
static int pickup_exec (struct ast_channel *chan, const char *data)
 
static int pickupchan_exec (struct ast_channel *chan, const char *data)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Directed Call Pickup Application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
 
static const char app [] = "Pickup"
 
static const char app2 [] = "PickupChan"
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static const struct ast_app_option pickupchan_opts [128] = { [ 'p' ] = { .flag = OPT_PICKUPCHAN_PARTIAL }, }
 

Detailed Description

Directed Call Pickup Support.

Author
Joshua Colp jcolp.nosp@m.@dig.nosp@m.ium.c.nosp@m.om
Gary Cook

Definition in file app_directed_pickup.c.

Macro Definition Documentation

◆ PICKUPMARK

#define PICKUPMARK   "PICKUPMARK"

Definition at line 48 of file app_directed_pickup.c.

Enumeration Type Documentation

◆ OPT_PICKUPCHAN_FLAGS

Enumerator
OPT_PICKUPCHAN_PARTIAL 

Definition at line 411 of file app_directed_pickup.c.

411 {
412 OPT_PICKUPCHAN_PARTIAL = (1 << 0), /* Channel name is a partial name. */
413};
@ OPT_PICKUPCHAN_PARTIAL

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 492 of file app_directed_pickup.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 492 of file app_directed_pickup.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 492 of file app_directed_pickup.c.

◆ find_by_channel()

static struct ast_channel * find_by_channel ( struct ast_channel chan,
const char *  channame 
)
static

Helper Function to walk through ALL channels checking NAME and STATE.

Definition at line 180 of file app_directed_pickup.c.

181{
182 struct ast_channel *target;
183 char *chkchan;
184 struct pickup_by_name_args pickup_args;
185
186 pickup_args.chan = chan;
187
188 if (strchr(channame, '-')) {
189 /*
190 * Use the given channel name string as-is. This allows a full channel
191 * name with a typical sequence number to be used as well as still
192 * allowing the odd partial channel name that has a '-' in it to still
193 * work, i.e. Local/bob@en-phone.
194 */
195 pickup_args.len = strlen(channame);
196 pickup_args.name = channame;
197 } else {
198 /*
199 * Append a '-' for the comparison so we check the channel name less
200 * a sequence number, i.e Find SIP/bob- and not SIP/bobby.
201 */
202 pickup_args.len = strlen(channame) + 1;
203 chkchan = ast_alloca(pickup_args.len + 1);
204 strcpy(chkchan, channame);/* Safe */
205 strcat(chkchan, "-");
206 pickup_args.name = chkchan;
207 }
208 target = ast_channel_callback(find_by_name, NULL, &pickup_args, 0);
209 if (target) {
210 return target;
211 }
212
213 /* Now try a search for uniqueid. */
214 pickup_args.name = channame;
215 pickup_args.len = 0;
216 return ast_channel_callback(find_by_uniqueid, NULL, &pickup_args, 0);
217}
static int find_by_name(void *obj, void *arg, void *data, int flags)
static int find_by_uniqueid(void *obj, void *arg, void *data, int flags)
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
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
#define NULL
Definition: resample.c:96
Main Channel structure associated with a channel.
const ast_string_field name
struct ast_channel * chan

References ast_alloca, ast_channel_callback(), pickup_by_name_args::chan, find_by_name(), find_by_uniqueid(), pickup_by_name_args::len, pickup_by_name_args::name, and NULL.

Referenced by pickup_by_channel().

◆ find_by_mark()

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

< Potential pickup target

Definition at line 268 of file app_directed_pickup.c.

269{
270 struct ast_channel *target = obj;/*!< Potential pickup target */
271 struct ast_channel *chan = arg;
272 const char *mark = data;
273 const char *tmp;
274
275 if (chan == target) {
276 /* The channel attempting to pickup a call cannot pickup itself. */
277 return 0;
278 }
279
280 ast_channel_lock(target);
282 if (tmp && !strcasecmp(tmp, mark) && ast_can_pickup(target)) {
283 /* Return with the channel still locked on purpose */
284 return CMP_MATCH | CMP_STOP;
285 }
286 ast_channel_unlock(target);
287
288 return 0;
289}
#define PICKUPMARK
@ CMP_MATCH
Definition: astobj2.h:1027
@ CMP_STOP
Definition: astobj2.h:1028
static int tmp()
Definition: bt_open.c:389
#define ast_channel_lock(chan)
Definition: channel.h:2968
#define ast_channel_unlock(chan)
Definition: channel.h:2969
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
int ast_can_pickup(struct ast_channel *chan)
Test if a channel can be picked up.
Definition: pickup.c:77
const char * data

References ast_can_pickup(), ast_channel_lock, ast_channel_unlock, CMP_MATCH, CMP_STOP, ast_channel::data, pbx_builtin_getvar_helper(), PICKUPMARK, and tmp().

Referenced by pickup_by_mark().

◆ find_by_name()

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

< Potential pickup target

Definition at line 137 of file app_directed_pickup.c.

138{
139 struct ast_channel *target = obj;/*!< Potential pickup target */
140 struct pickup_by_name_args *args = data;
141
142 if (args->chan == target) {
143 /* The channel attempting to pickup a call cannot pickup itself. */
144 return 0;
145 }
146
147 ast_channel_lock(target);
148 if (!strncasecmp(ast_channel_name(target), args->name, args->len)
149 && ast_can_pickup(target)) {
150 /* Return with the channel still locked on purpose */
151 return CMP_MATCH | CMP_STOP;
152 }
153 ast_channel_unlock(target);
154
155 return 0;
156}
const char * ast_channel_name(const struct ast_channel *chan)
const char * args

References args, ast_can_pickup(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, CMP_MATCH, and CMP_STOP.

Referenced by find_by_channel(), and find_by_part().

◆ find_by_part()

static struct ast_channel * find_by_part ( struct ast_channel chan,
const char *  part 
)
static

Definition at line 373 of file app_directed_pickup.c.

374{
375 struct ast_channel *target;
376 struct pickup_by_name_args pickup_args;
377
378 pickup_args.chan = chan;
379
380 /* Try a partial channel name search. */
381 pickup_args.name = part;
382 pickup_args.len = strlen(part);
383 target = ast_channel_callback(find_by_name, NULL, &pickup_args, 0);
384 if (target) {
385 return target;
386 }
387
388 /* Now try a search for uniqueid. */
389 pickup_args.name = part;
390 pickup_args.len = 0;
391 return ast_channel_callback(find_by_uniqueid, NULL, &pickup_args, 0);
392}

References ast_channel_callback(), pickup_by_name_args::chan, find_by_name(), find_by_uniqueid(), pickup_by_name_args::len, pickup_by_name_args::name, and NULL.

Referenced by pickup_by_part().

◆ find_by_uniqueid()

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

< Potential pickup target

Definition at line 158 of file app_directed_pickup.c.

159{
160 struct ast_channel *target = obj;/*!< Potential pickup target */
161 struct pickup_by_name_args *args = data;
162
163 if (args->chan == target) {
164 /* The channel attempting to pickup a call cannot pickup itself. */
165 return 0;
166 }
167
168 ast_channel_lock(target);
169 if (!strcasecmp(ast_channel_uniqueid(target), args->name)
170 && ast_can_pickup(target)) {
171 /* Return with the channel still locked on purpose */
172 return CMP_MATCH | CMP_STOP;
173 }
174 ast_channel_unlock(target);
175
176 return 0;
177}
const char * ast_channel_uniqueid(const struct ast_channel *chan)

References args, ast_can_pickup(), ast_channel_lock, ast_channel_uniqueid(), ast_channel_unlock, CMP_MATCH, and CMP_STOP.

Referenced by find_by_channel(), and find_by_part().

◆ load_module()

static int load_module ( void  )
static

Definition at line 482 of file app_directed_pickup.c.

483{
484 int res;
485
488
489 return res;
490}
static const char app[]
static int pickupchan_exec(struct ast_channel *chan, const char *data)
static int pickup_exec(struct ast_channel *chan, const char *data)
static const char app2[]
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:640

References app, app2, ast_register_application_xml, pickup_exec(), and pickupchan_exec().

◆ pickup_by_channel()

static int pickup_by_channel ( struct ast_channel chan,
const char *  name 
)
static

Attempt to pick up named channel.

< Potential pickup target

Definition at line 220 of file app_directed_pickup.c.

221{
222 int res = -1;
223 struct ast_channel *target;/*!< Potential pickup target */
224
225 /* The found channel is already locked. */
226 target = find_by_channel(chan, name);
227 if (target) {
228 res = ast_do_pickup(chan, target);
229 ast_channel_unlock(target);
230 target = ast_channel_unref(target);
231 }
232
233 return res;
234}
static struct ast_channel * find_by_channel(struct ast_channel *chan, const char *channame)
Helper Function to walk through ALL channels checking NAME and STATE.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3004
static const char name[]
Definition: format_mp3.c:68
int ast_do_pickup(struct ast_channel *chan, struct ast_channel *target)
Pickup a call target.
Definition: pickup.c:301

References ast_channel_unlock, ast_channel_unref, ast_do_pickup(), find_by_channel(), and name.

Referenced by pickupchan_exec().

◆ pickup_by_exten()

static int pickup_by_exten ( struct ast_channel chan,
const char *  exten,
const char *  context 
)
static

< Potential pickup target

Definition at line 237 of file app_directed_pickup.c.

238{
239 struct ast_channel *target = NULL;/*!< Potential pickup target */
240 struct ast_channel_iterator *iter;
241 int res = -1;
242
243 if (!(iter = ast_channel_iterator_by_exten_new(exten, context))) {
244 return -1;
245 }
246
247 while ((target = ast_channel_iterator_next(iter))) {
248 ast_channel_lock(target);
249 if ((chan != target) && ast_can_pickup(target)) {
250 ast_log(LOG_NOTICE, "%s pickup by %s\n", ast_channel_name(target), ast_channel_name(chan));
251 break;
252 }
253 ast_channel_unlock(target);
254 target = ast_channel_unref(target);
255 }
256
258
259 if (target) {
260 res = ast_do_pickup(chan, target);
261 ast_channel_unlock(target);
262 target = ast_channel_unref(target);
263 }
264
265 return res;
266}
#define ast_log
Definition: astobj2.c:42
struct ast_channel_iterator * ast_channel_iterator_destroy(struct ast_channel_iterator *i)
Destroy a channel iterator.
Definition: channel.c:1379
struct ast_channel * ast_channel_iterator_next(struct ast_channel_iterator *i)
Get the next channel for a channel iterator.
Definition: channel.c:1441
struct ast_channel_iterator * ast_channel_iterator_by_exten_new(const char *exten, const char *context)
Create a new channel iterator based on extension.
Definition: channel.c:1387
#define LOG_NOTICE

References ast_can_pickup(), ast_channel_iterator_by_exten_new(), ast_channel_iterator_destroy(), ast_channel_iterator_next(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_channel_unref, ast_do_pickup(), ast_log, voicemailpwcheck::context, LOG_NOTICE, and NULL.

Referenced by pickup_exec().

◆ pickup_by_group()

static int pickup_by_group ( struct ast_channel chan)
static

< Potential pickup target

Definition at line 308 of file app_directed_pickup.c.

309{
310 struct ast_channel *target;/*!< Potential pickup target */
311 int res = -1;
312
313 /* The found channel is already locked. */
314 target = ast_pickup_find_by_group(chan);
315 if (target) {
316 ast_log(LOG_NOTICE, "pickup %s attempt by %s\n", ast_channel_name(target), ast_channel_name(chan));
317 res = ast_do_pickup(chan, target);
318 ast_channel_unlock(target);
319 target = ast_channel_unref(target);
320 }
321
322 return res;
323}
struct ast_channel * ast_pickup_find_by_group(struct ast_channel *chan)
Find a pickup channel target by group.
Definition: pickup.c:133

References ast_channel_name(), ast_channel_unlock, ast_channel_unref, ast_do_pickup(), ast_log, ast_pickup_find_by_group(), and LOG_NOTICE.

Referenced by pickup_exec().

◆ pickup_by_mark()

static int pickup_by_mark ( struct ast_channel chan,
const char *  mark 
)
static

< Potential pickup target

Definition at line 292 of file app_directed_pickup.c.

293{
294 struct ast_channel *target;/*!< Potential pickup target */
295 int res = -1;
296
297 /* The found channel is already locked. */
298 target = ast_channel_callback(find_by_mark, chan, (char *) mark, 0);
299 if (target) {
300 res = ast_do_pickup(chan, target);
301 ast_channel_unlock(target);
302 target = ast_channel_unref(target);
303 }
304
305 return res;
306}
static int find_by_mark(void *obj, void *arg, void *data, int flags)

References ast_channel_callback(), ast_channel_unlock, ast_channel_unref, ast_do_pickup(), and find_by_mark().

Referenced by pickup_exec().

◆ pickup_by_part()

static int pickup_by_part ( struct ast_channel chan,
const char *  part 
)
static

< Potential pickup target

Definition at line 395 of file app_directed_pickup.c.

396{
397 struct ast_channel *target;/*!< Potential pickup target */
398 int res = -1;
399
400 /* The found channel is already locked. */
401 target = find_by_part(chan, part);
402 if (target) {
403 res = ast_do_pickup(chan, target);
404 ast_channel_unlock(target);
405 target = ast_channel_unref(target);
406 }
407
408 return res;
409}
static struct ast_channel * find_by_part(struct ast_channel *chan, const char *part)

References ast_channel_unlock, ast_channel_unref, ast_do_pickup(), and find_by_part().

Referenced by pickupchan_exec().

◆ pickup_exec()

static int pickup_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 326 of file app_directed_pickup.c.

327{
328 char *parse;
329 char *exten;
330 char *context;
331
332 if (ast_strlen_zero(data)) {
333 return pickup_by_group(chan) ? 0 : -1;
334 }
335
336 /* Parse extension (and context if there) */
337 parse = ast_strdupa(data);
338 for (;;) {
339 if (ast_strlen_zero(parse)) {
340 break;
341 }
342 exten = strsep(&parse, "&");
343 if (ast_strlen_zero(exten)) {
344 continue;
345 }
346
347 context = strchr(exten, '@');
348 if (context) {
349 *context++ = '\0';
350 }
351 if (!ast_strlen_zero(context) && !strcasecmp(context, PICKUPMARK)) {
352 if (!pickup_by_mark(chan, exten)) {
353 /* Pickup successful. Stop the dialplan this channel is a zombie. */
354 return -1;
355 }
356 } else {
358 context = (char *) ast_channel_context(chan);
359 }
360 if (!pickup_by_exten(chan, exten, context)) {
361 /* Pickup successful. Stop the dialplan this channel is a zombie. */
362 return -1;
363 }
364 }
365 ast_log(LOG_NOTICE, "No target channel found for %s@%s.\n", exten, context);
366 }
367
368 /* Pickup failed. Keep going in the dialplan. */
369 return 0;
370}
static int pickup_by_exten(struct ast_channel *chan, const char *exten, const char *context)
static int pickup_by_mark(struct ast_channel *chan, const char *mark)
static int pickup_by_group(struct ast_channel *chan)
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
const char * ast_channel_context(const struct ast_channel *chan)
char * strsep(char **str, const char *delims)
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65

References ast_channel_context(), ast_log, ast_strdupa, ast_strlen_zero(), voicemailpwcheck::context, ast_channel::data, ast_channel::exten, LOG_NOTICE, pickup_by_exten(), pickup_by_group(), pickup_by_mark(), PICKUPMARK, and strsep().

Referenced by load_module().

◆ pickupchan_exec()

static int pickupchan_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 420 of file app_directed_pickup.c.

421{
422 char *pickup = NULL;
423 char *parse = ast_strdupa(data);
425 AST_APP_ARG(channel);
427 AST_APP_ARG(other); /* Any remining unused arguments */
428 );
429 struct ast_flags opts;
430
432
433 if (ast_strlen_zero(args.channel)) {
434 ast_log(LOG_WARNING, "PickupChan requires an argument (channel)!\n");
435 /* Pickup failed. Keep going in the dialplan. */
436 return 0;
437 }
438 if (ast_app_parse_options(pickupchan_opts, &opts, NULL, args.options)) {
439 /*
440 * General invalid option syntax.
441 * Pickup failed. Keep going in the dialplan.
442 */
443 return 0;
444 }
445
446 /* Parse channel */
447 for (;;) {
448 if (ast_strlen_zero(args.channel)) {
449 break;
450 }
451 pickup = strsep(&args.channel, "&");
452 if (ast_strlen_zero(pickup)) {
453 continue;
454 }
455
457 if (!pickup_by_part(chan, pickup)) {
458 /* Pickup successful. Stop the dialplan this channel is a zombie. */
459 return -1;
460 }
461 } else if (!pickup_by_channel(chan, pickup)) {
462 /* Pickup successful. Stop the dialplan this channel is a zombie. */
463 return -1;
464 }
465 ast_log(LOG_NOTICE, "No target channel found for %s.\n", pickup);
466 }
467
468 /* Pickup failed. Keep going in the dialplan. */
469 return 0;
470}
static int pickup_by_part(struct ast_channel *chan, const char *part)
static const struct ast_app_option pickupchan_opts[128]
static int pickup_by_channel(struct ast_channel *chan, const char *name)
Attempt to pick up named channel.
#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.
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:3066
#define LOG_WARNING
Structure used to handle boolean flags.
Definition: utils.h:199
static struct test_options options
#define ast_test_flag(p, flag)
Definition: utils.h:63

References args, AST_APP_ARG, ast_app_parse_options(), AST_DECLARE_APP_ARGS, ast_log, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_channel::data, LOG_NOTICE, LOG_WARNING, NULL, OPT_PICKUPCHAN_PARTIAL, options, pickup_by_channel(), pickup_by_part(), pickupchan_opts, and strsep().

Referenced by load_module().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 472 of file app_directed_pickup.c.

473{
474 int res;
475
478
479 return res;
480}
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392

References app, app2, and ast_unregister_application().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Directed Call Pickup Application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static

Definition at line 492 of file app_directed_pickup.c.

◆ app

const char app[] = "Pickup"
static

Definition at line 125 of file app_directed_pickup.c.

Referenced by load_module(), and unload_module().

◆ app2

const char app2[] = "PickupChan"
static

Definition at line 126 of file app_directed_pickup.c.

Referenced by load_module(), and unload_module().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 492 of file app_directed_pickup.c.

◆ pickupchan_opts

const struct ast_app_option pickupchan_opts[128] = { [ 'p' ] = { .flag = OPT_PICKUPCHAN_PARTIAL }, }
static

Definition at line 417 of file app_directed_pickup.c.

Referenced by pickupchan_exec().