Asterisk - The Open Source Telephony Project GIT-master-8f1982c
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
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 417 of file app_directed_pickup.c.

417 {
418 OPT_PICKUPCHAN_PARTIAL = (1 << 0), /* Channel name is a partial name. */
419};
@ OPT_PICKUPCHAN_PARTIAL

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 498 of file app_directed_pickup.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 498 of file app_directed_pickup.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 498 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 186 of file app_directed_pickup.c.

187{
188 struct ast_channel *target;
189 char *chkchan;
190 struct pickup_by_name_args pickup_args;
191
192 pickup_args.chan = chan;
193
194 if (strchr(channame, '-')) {
195 /*
196 * Use the given channel name string as-is. This allows a full channel
197 * name with a typical sequence number to be used as well as still
198 * allowing the odd partial channel name that has a '-' in it to still
199 * work, i.e. Local/bob@en-phone.
200 */
201 pickup_args.len = strlen(channame);
202 pickup_args.name = channame;
203 } else {
204 /*
205 * Append a '-' for the comparison so we check the channel name less
206 * a sequence number, i.e Find SIP/bob- and not SIP/bobby.
207 */
208 pickup_args.len = strlen(channame) + 1;
209 chkchan = ast_alloca(pickup_args.len + 1);
210 strcpy(chkchan, channame);/* Safe */
211 strcat(chkchan, "-");
212 pickup_args.name = chkchan;
213 }
214 target = ast_channel_callback(find_by_name, NULL, &pickup_args, 0);
215 if (target) {
216 return target;
217 }
218
219 /* Now try a search for uniqueid. */
220 pickup_args.name = channame;
221 pickup_args.len = 0;
222 return ast_channel_callback(find_by_uniqueid, NULL, &pickup_args, 0);
223}
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:1316
#define NULL
Definition: resample.c:96
Main Channel structure associated with a channel.
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 274 of file app_directed_pickup.c.

275{
276 struct ast_channel *target = obj;/*!< Potential pickup target */
277 struct ast_channel *chan = arg;
278 const char *mark = data;
279 const char *tmp;
280
281 if (chan == target) {
282 /* The channel attempting to pickup a call cannot pickup itself. */
283 return 0;
284 }
285
286 ast_channel_lock(target);
288 if (tmp && !strcasecmp(tmp, mark) && ast_can_pickup(target)) {
289 /* Return with the channel still locked on purpose */
290 return CMP_MATCH | CMP_STOP;
291 }
292 ast_channel_unlock(target);
293
294 return 0;
295}
#define PICKUPMARK
@ CMP_MATCH
Definition: astobj2.h:1027
@ CMP_STOP
Definition: astobj2.h:1028
#define ast_channel_lock(chan)
Definition: channel.h:2972
#define ast_channel_unlock(chan)
Definition: channel.h:2973
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:80
const char * data

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

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 143 of file app_directed_pickup.c.

144{
145 struct ast_channel *target = obj;/*!< Potential pickup target */
146 struct pickup_by_name_args *args = data;
147
148 if (args->chan == target) {
149 /* The channel attempting to pickup a call cannot pickup itself. */
150 return 0;
151 }
152
153 ast_channel_lock(target);
154 if (!strncasecmp(ast_channel_name(target), args->name, args->len)
155 && ast_can_pickup(target)) {
156 /* Return with the channel still locked on purpose */
157 return CMP_MATCH | CMP_STOP;
158 }
159 ast_channel_unlock(target);
160
161 return 0;
162}
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 379 of file app_directed_pickup.c.

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

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 164 of file app_directed_pickup.c.

165{
166 struct ast_channel *target = obj;/*!< Potential pickup target */
167 struct pickup_by_name_args *args = data;
168
169 if (args->chan == target) {
170 /* The channel attempting to pickup a call cannot pickup itself. */
171 return 0;
172 }
173
174 ast_channel_lock(target);
175 if (!strcasecmp(ast_channel_uniqueid(target), args->name)
176 && ast_can_pickup(target)) {
177 /* Return with the channel still locked on purpose */
178 return CMP_MATCH | CMP_STOP;
179 }
180 ast_channel_unlock(target);
181
182 return 0;
183}
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 488 of file app_directed_pickup.c.

489{
490 int res;
491
494
495 return res;
496}
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 226 of file app_directed_pickup.c.

227{
228 int res = -1;
229 struct ast_channel *target;/*!< Potential pickup target */
230
231 /* The found channel is already locked. */
232 target = find_by_channel(chan, name);
233 if (target) {
234 res = ast_do_pickup(chan, target);
235 ast_channel_unlock(target);
236 target = ast_channel_unref(target);
237 }
238
239 return res;
240}
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:3008
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:304

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 243 of file app_directed_pickup.c.

244{
245 struct ast_channel *target = NULL;/*!< Potential pickup target */
246 struct ast_channel_iterator *iter;
247 int res = -1;
248
249 if (!(iter = ast_channel_iterator_by_exten_new(exten, context))) {
250 return -1;
251 }
252
253 while ((target = ast_channel_iterator_next(iter))) {
254 ast_channel_lock(target);
255 if ((chan != target) && ast_can_pickup(target)) {
256 ast_log(LOG_NOTICE, "%s pickup by %s\n", ast_channel_name(target), ast_channel_name(chan));
257 break;
258 }
259 ast_channel_unlock(target);
260 target = ast_channel_unref(target);
261 }
262
264
265 if (target) {
266 res = ast_do_pickup(chan, target);
267 ast_channel_unlock(target);
268 target = ast_channel_unref(target);
269 }
270
271 return res;
272}
#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:1329
struct ast_channel * ast_channel_iterator_next(struct ast_channel_iterator *i)
Get the next channel for a channel iterator.
Definition: channel.c:1368
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:1337
#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 314 of file app_directed_pickup.c.

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

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 298 of file app_directed_pickup.c.

299{
300 struct ast_channel *target;/*!< Potential pickup target */
301 int res = -1;
302
303 /* The found channel is already locked. */
304 target = ast_channel_callback(find_by_mark, chan, (char *) mark, 0);
305 if (target) {
306 res = ast_do_pickup(chan, target);
307 ast_channel_unlock(target);
308 target = ast_channel_unref(target);
309 }
310
311 return res;
312}
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 401 of file app_directed_pickup.c.

402{
403 struct ast_channel *target;/*!< Potential pickup target */
404 int res = -1;
405
406 /* The found channel is already locked. */
407 target = find_by_part(chan, part);
408 if (target) {
409 res = ast_do_pickup(chan, target);
410 ast_channel_unlock(target);
411 target = ast_channel_unref(target);
412 }
413
414 return res;
415}
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 332 of file app_directed_pickup.c.

333{
334 char *parse;
335 char *exten;
336 char *context;
337
338 if (ast_strlen_zero(data)) {
339 return pickup_by_group(chan) ? 0 : -1;
340 }
341
342 /* Parse extension (and context if there) */
343 parse = ast_strdupa(data);
344 for (;;) {
345 if (ast_strlen_zero(parse)) {
346 break;
347 }
348 exten = strsep(&parse, "&");
349 if (ast_strlen_zero(exten)) {
350 continue;
351 }
352
353 context = strchr(exten, '@');
354 if (context) {
355 *context++ = '\0';
356 }
357 if (!ast_strlen_zero(context) && !strcasecmp(context, PICKUPMARK)) {
358 if (!pickup_by_mark(chan, exten)) {
359 /* Pickup successful. Stop the dialplan this channel is a zombie. */
360 return -1;
361 }
362 } else {
364 context = (char *) ast_channel_context(chan);
365 }
366 if (!pickup_by_exten(chan, exten, context)) {
367 /* Pickup successful. Stop the dialplan this channel is a zombie. */
368 return -1;
369 }
370 }
371 ast_log(LOG_NOTICE, "No target channel found for %s@%s.\n", exten, context);
372 }
373
374 /* Pickup failed. Keep going in the dialplan. */
375 return 0;
376}
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)
char * strsep(char **str, const char *delims)
#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)
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 426 of file app_directed_pickup.c.

427{
428 char *pickup = NULL;
429 char *parse = ast_strdupa(data);
431 AST_APP_ARG(channel);
433 AST_APP_ARG(other); /* Any remining unused arguments */
434 );
435 struct ast_flags opts;
436
438
439 if (ast_strlen_zero(args.channel)) {
440 ast_log(LOG_WARNING, "PickupChan requires an argument (channel)!\n");
441 /* Pickup failed. Keep going in the dialplan. */
442 return 0;
443 }
444 if (ast_app_parse_options(pickupchan_opts, &opts, NULL, args.options)) {
445 /*
446 * General invalid option syntax.
447 * Pickup failed. Keep going in the dialplan.
448 */
449 return 0;
450 }
451
452 /* Parse channel */
453 for (;;) {
454 if (ast_strlen_zero(args.channel)) {
455 break;
456 }
457 pickup = strsep(&args.channel, "&");
458 if (ast_strlen_zero(pickup)) {
459 continue;
460 }
461
463 if (!pickup_by_part(chan, pickup)) {
464 /* Pickup successful. Stop the dialplan this channel is a zombie. */
465 return -1;
466 }
467 } else if (!pickup_by_channel(chan, pickup)) {
468 /* Pickup successful. Stop the dialplan this channel is a zombie. */
469 return -1;
470 }
471 ast_log(LOG_NOTICE, "No target channel found for %s.\n", pickup);
472 }
473
474 /* Pickup failed. Keep going in the dialplan. */
475 return 0;
476}
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 478 of file app_directed_pickup.c.

479{
480 int res;
481
484
485 return res;
486}
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 498 of file app_directed_pickup.c.

◆ app

const char app[] = "Pickup"
static

Definition at line 131 of file app_directed_pickup.c.

Referenced by load_module(), and unload_module().

◆ app2

const char app2[] = "PickupChan"
static

Definition at line 132 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 498 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 423 of file app_directed_pickup.c.

Referenced by pickupchan_exec().