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

Defines

#define PICKUPMARK   "PICKUPMARK"

Enumerations

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

Functions

static void __reg_module (void)
static void __unreg_module (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 = "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 struct ast_module_infoast_module_info = &__mod_info
static struct ast_app_option pickupchan_opts [128] = { [ 'p' ] = { .flag = OPT_PICKUPCHAN_PARTIAL }, }


Detailed Description

Directed Call Pickup Support.

Author:
Joshua Colp <jcolp@digium.com>

Gary Cook

Definition in file app_directed_pickup.c.


Define Documentation

#define PICKUPMARK   "PICKUPMARK"

Definition at line 50 of file app_directed_pickup.c.

Referenced by find_by_mark(), and pickup_exec().


Enumeration Type Documentation

Enumerator:
OPT_PICKUPCHAN_PARTIAL 

Definition at line 413 of file app_directed_pickup.c.

00413                           {
00414    OPT_PICKUPCHAN_PARTIAL =   (1 << 0),   /* Channel name is a partial name. */
00415 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 494 of file app_directed_pickup.c.

static void __unreg_module ( void   )  [static]

Definition at line 494 of file app_directed_pickup.c.

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

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

Definition at line 182 of file app_directed_pickup.c.

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().

00183 {
00184    struct ast_channel *target;
00185    char *chkchan;
00186    struct pickup_by_name_args pickup_args;
00187 
00188    pickup_args.chan = chan;
00189 
00190    if (strchr(channame, '-')) {
00191       /*
00192        * Use the given channel name string as-is.  This allows a full channel
00193        * name with a typical sequence number to be used as well as still
00194        * allowing the odd partial channel name that has a '-' in it to still
00195        * work, i.e. Local/bob@en-phone.
00196        */
00197       pickup_args.len = strlen(channame);
00198       pickup_args.name = channame;
00199    } else {
00200       /*
00201        * Append a '-' for the comparison so we check the channel name less
00202        * a sequence number, i.e Find SIP/bob- and not SIP/bobby.
00203        */
00204       pickup_args.len = strlen(channame) + 1;
00205       chkchan = ast_alloca(pickup_args.len + 1);
00206       strcpy(chkchan, channame);/* Safe */
00207       strcat(chkchan, "-");
00208       pickup_args.name = chkchan;
00209    }
00210    target = ast_channel_callback(find_by_name, NULL, &pickup_args, 0);
00211    if (target) {
00212       return target;
00213    }
00214 
00215    /* Now try a search for uniqueid. */
00216    pickup_args.name = channame;
00217    pickup_args.len = 0;
00218    return ast_channel_callback(find_by_uniqueid, NULL, &pickup_args, 0);
00219 }

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

< Potential pickup target

Definition at line 270 of file app_directed_pickup.c.

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

Referenced by pickup_by_mark().

00271 {
00272    struct ast_channel *target = obj;/*!< Potential pickup target */
00273    struct ast_channel *chan = arg;
00274    const char *mark = data;
00275    const char *tmp;
00276 
00277    if (chan == target) {
00278       /* The channel attempting to pickup a call cannot pickup itself. */
00279       return 0;
00280    }
00281 
00282    ast_channel_lock(target);
00283    tmp = pbx_builtin_getvar_helper(target, PICKUPMARK);
00284    if (tmp && !strcasecmp(tmp, mark) && ast_can_pickup(target)) {
00285       /* Return with the channel still locked on purpose */
00286       return CMP_MATCH | CMP_STOP;
00287    }
00288    ast_channel_unlock(target);
00289 
00290    return 0;
00291 }

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

< Potential pickup target

Definition at line 139 of file app_directed_pickup.c.

References args, ast_can_pickup(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, pickup_by_name_args::chan, CMP_MATCH, CMP_STOP, pickup_by_name_args::len, and pickup_by_name_args::name.

Referenced by find_by_channel(), find_by_part(), and sip_find_peer_full().

00140 {
00141    struct ast_channel *target = obj;/*!< Potential pickup target */
00142    struct pickup_by_name_args *args = data;
00143 
00144    if (args->chan == target) {
00145       /* The channel attempting to pickup a call cannot pickup itself. */
00146       return 0;
00147    }
00148 
00149    ast_channel_lock(target);
00150    if (!strncasecmp(ast_channel_name(target), args->name, args->len)
00151       && ast_can_pickup(target)) {
00152       /* Return with the channel still locked on purpose */
00153       return CMP_MATCH | CMP_STOP;
00154    }
00155    ast_channel_unlock(target);
00156 
00157    return 0;
00158 }

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

Definition at line 375 of file app_directed_pickup.c.

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().

00376 {
00377    struct ast_channel *target;
00378    struct pickup_by_name_args pickup_args;
00379 
00380    pickup_args.chan = chan;
00381 
00382    /* Try a partial channel name search. */
00383    pickup_args.name = part;
00384    pickup_args.len = strlen(part);
00385    target = ast_channel_callback(find_by_name, NULL, &pickup_args, 0);
00386    if (target) {
00387       return target;
00388    }
00389 
00390    /* Now try a search for uniqueid. */
00391    pickup_args.name = part;
00392    pickup_args.len = 0;
00393    return ast_channel_callback(find_by_uniqueid, NULL, &pickup_args, 0);
00394 }

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

< Potential pickup target

Definition at line 160 of file app_directed_pickup.c.

References args, ast_can_pickup(), ast_channel_lock, ast_channel_uniqueid(), ast_channel_unlock, pickup_by_name_args::chan, CMP_MATCH, CMP_STOP, and pickup_by_name_args::name.

Referenced by find_by_channel(), and find_by_part().

00161 {
00162    struct ast_channel *target = obj;/*!< Potential pickup target */
00163    struct pickup_by_name_args *args = data;
00164 
00165    if (args->chan == target) {
00166       /* The channel attempting to pickup a call cannot pickup itself. */
00167       return 0;
00168    }
00169 
00170    ast_channel_lock(target);
00171    if (!strcasecmp(ast_channel_uniqueid(target), args->name)
00172       && ast_can_pickup(target)) {
00173       /* Return with the channel still locked on purpose */
00174       return CMP_MATCH | CMP_STOP;
00175    }
00176    ast_channel_unlock(target);
00177 
00178    return 0;
00179 }

static int load_module ( void   )  [static]

Definition at line 484 of file app_directed_pickup.c.

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

00485 {
00486    int res;
00487 
00488    res = ast_register_application_xml(app, pickup_exec);
00489    res |= ast_register_application_xml(app2, pickupchan_exec);
00490 
00491    return res;
00492 }

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

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

Referenced by pickupchan_exec().

00223 {
00224    int res = -1;
00225    struct ast_channel *target;/*!< Potential pickup target */
00226 
00227    /* The found channel is already locked. */
00228    target = find_by_channel(chan, name);
00229    if (target) {
00230       res = ast_do_pickup(chan, target);
00231       ast_channel_unlock(target);
00232       target = ast_channel_unref(target);
00233    }
00234 
00235    return res;
00236 }

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

< Potential pickup target

Definition at line 239 of file app_directed_pickup.c.

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().

00240 {
00241    struct ast_channel *target = NULL;/*!< Potential pickup target */
00242    struct ast_channel_iterator *iter;
00243    int res = -1;
00244 
00245    if (!(iter = ast_channel_iterator_by_exten_new(exten, context))) {
00246       return -1;
00247    }
00248 
00249    while ((target = ast_channel_iterator_next(iter))) {
00250       ast_channel_lock(target);
00251       if ((chan != target) && ast_can_pickup(target)) {
00252          ast_log(LOG_NOTICE, "%s pickup by %s\n", ast_channel_name(target), ast_channel_name(chan));
00253          break;
00254       }
00255       ast_channel_unlock(target);
00256       target = ast_channel_unref(target);
00257    }
00258 
00259    ast_channel_iterator_destroy(iter);
00260 
00261    if (target) {
00262       res = ast_do_pickup(chan, target);
00263       ast_channel_unlock(target);
00264       target = ast_channel_unref(target);
00265    }
00266 
00267    return res;
00268 }

static int pickup_by_group ( struct ast_channel chan  )  [static]

< Potential pickup target

Definition at line 310 of file app_directed_pickup.c.

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().

00311 {
00312    struct ast_channel *target;/*!< Potential pickup target */
00313    int res = -1;
00314 
00315    /* The found channel is already locked. */
00316    target = ast_pickup_find_by_group(chan);
00317    if (target) {
00318       ast_log(LOG_NOTICE, "pickup %s attempt by %s\n", ast_channel_name(target), ast_channel_name(chan));
00319       res = ast_do_pickup(chan, target);
00320       ast_channel_unlock(target);
00321       target = ast_channel_unref(target);
00322    }
00323 
00324    return res;
00325 }

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

< Potential pickup target

Definition at line 294 of file app_directed_pickup.c.

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

Referenced by pickup_exec().

00295 {
00296    struct ast_channel *target;/*!< Potential pickup target */
00297    int res = -1;
00298 
00299    /* The found channel is already locked. */
00300    target = ast_channel_callback(find_by_mark, chan, (char *) mark, 0);
00301    if (target) {
00302       res = ast_do_pickup(chan, target);
00303       ast_channel_unlock(target);
00304       target = ast_channel_unref(target);
00305    }
00306 
00307    return res;
00308 }

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

< Potential pickup target

Definition at line 397 of file app_directed_pickup.c.

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

Referenced by pickupchan_exec().

00398 {
00399    struct ast_channel *target;/*!< Potential pickup target */
00400    int res = -1;
00401 
00402    /* The found channel is already locked. */
00403    target = find_by_part(chan, part);
00404    if (target) {
00405       res = ast_do_pickup(chan, target);
00406       ast_channel_unlock(target);
00407       target = ast_channel_unref(target);
00408    }
00409 
00410    return res;
00411 }

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

Definition at line 328 of file app_directed_pickup.c.

References ast_channel_context(), ast_log, ast_strdupa, ast_strlen_zero, context, exten, LOG_NOTICE, parse(), pickup_by_exten(), pickup_by_group(), pickup_by_mark(), PICKUPMARK, and strsep().

Referenced by load_module().

00329 {
00330    char *parse;
00331    char *exten;
00332    char *context;
00333 
00334    if (ast_strlen_zero(data)) {
00335       return pickup_by_group(chan) ? 0 : -1;
00336    }
00337 
00338    /* Parse extension (and context if there) */
00339    parse = ast_strdupa(data);
00340    for (;;) {
00341       if (ast_strlen_zero(parse)) {
00342          break;
00343       }
00344       exten = strsep(&parse, "&");
00345       if (ast_strlen_zero(exten)) {
00346          continue;
00347       }
00348 
00349       context = strchr(exten, '@');
00350       if (context) {
00351          *context++ = '\0';
00352       }
00353       if (!ast_strlen_zero(context) && !strcasecmp(context, PICKUPMARK)) {
00354          if (!pickup_by_mark(chan, exten)) {
00355             /* Pickup successful.  Stop the dialplan this channel is a zombie. */
00356             return -1;
00357          }
00358       } else {
00359          if (ast_strlen_zero(context)) {
00360             context = (char *) ast_channel_context(chan);
00361          }
00362          if (!pickup_by_exten(chan, exten, context)) {
00363             /* Pickup successful.  Stop the dialplan this channel is a zombie. */
00364             return -1;
00365          }
00366       }
00367       ast_log(LOG_NOTICE, "No target channel found for %s@%s.\n", exten, context);
00368    }
00369 
00370    /* Pickup failed.  Keep going in the dialplan. */
00371    return 0;
00372 }

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

Definition at line 422 of file app_directed_pickup.c.

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, LOG_NOTICE, LOG_WARNING, NULL, OPT_PICKUPCHAN_PARTIAL, parse(), pickup_by_channel(), pickup_by_part(), pickupchan_opts, and strsep().

Referenced by load_module().

00423 {
00424    char *pickup = NULL;
00425    char *parse = ast_strdupa(data);
00426    AST_DECLARE_APP_ARGS(args,
00427       AST_APP_ARG(channel);
00428       AST_APP_ARG(options);
00429       AST_APP_ARG(other);  /* Any remining unused arguments */
00430    );
00431    struct ast_flags opts;
00432 
00433    AST_STANDARD_APP_ARGS(args, parse);
00434 
00435    if (ast_strlen_zero(args.channel)) {
00436       ast_log(LOG_WARNING, "PickupChan requires an argument (channel)!\n");
00437       /* Pickup failed.  Keep going in the dialplan. */
00438       return 0;
00439    }
00440    if (ast_app_parse_options(pickupchan_opts, &opts, NULL, args.options)) {
00441       /*
00442        * General invalid option syntax.
00443        * Pickup failed.  Keep going in the dialplan.
00444        */
00445       return 0;
00446    }
00447 
00448    /* Parse channel */
00449    for (;;) {
00450       if (ast_strlen_zero(args.channel)) {
00451          break;
00452       }
00453       pickup = strsep(&args.channel, "&");
00454       if (ast_strlen_zero(pickup)) {
00455          continue;
00456       }
00457 
00458       if (ast_test_flag(&opts, OPT_PICKUPCHAN_PARTIAL)) {
00459          if (!pickup_by_part(chan, pickup)) {
00460             /* Pickup successful.  Stop the dialplan this channel is a zombie. */
00461             return -1;
00462          }
00463       } else if (!pickup_by_channel(chan, pickup)) {
00464          /* Pickup successful.  Stop the dialplan this channel is a zombie. */
00465          return -1;
00466       }
00467       ast_log(LOG_NOTICE, "No target channel found for %s.\n", pickup);
00468    }
00469 
00470    /* Pickup failed.  Keep going in the dialplan. */
00471    return 0;
00472 }

static int unload_module ( void   )  [static]

Definition at line 474 of file app_directed_pickup.c.

References ast_unregister_application().

00475 {
00476    int res;
00477 
00478    res = ast_unregister_application(app);
00479    res |= ast_unregister_application(app2);
00480 
00481    return res;
00482 }


Variable Documentation

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

const char app[] = "Pickup" [static]

Definition at line 127 of file app_directed_pickup.c.

const char app2[] = "PickupChan" [static]

Definition at line 128 of file app_directed_pickup.c.

Referenced by _macro_exec().

Definition at line 494 of file app_directed_pickup.c.

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

Definition at line 419 of file app_directed_pickup.c.

Referenced by pickupchan_exec().


Generated on Thu Apr 16 06:28:25 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6