Asterisk - The Open Source Telephony Project GIT-master-27fb039
Loading...
Searching...
No Matches
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.
 
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.
 
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 = ASTERISK_GPL_KEY , .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:1335
#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:2982
#define ast_channel_unlock(chan)
Definition channel.h:2983
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)
static struct @519 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:3018
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:1348
struct ast_channel * ast_channel_iterator_next(struct ast_channel_iterator *i)
Get the next channel for a channel iterator.
Definition channel.c:1387
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:1356
#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, 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 {
363 if (ast_strlen_zero(context)) {
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(), ast_channel::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:220
static struct test_options options
#define ast_test_flag(p, flag)
Definition utils.h:64

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 = ASTERISK_GPL_KEY , .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().