Wed Apr 6 11:29:49 2011

Asterisk developer's documentation


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/features.h"
#include "asterisk/manager.h"
#include "asterisk/callerid.h"
#include "asterisk/cel.h"

Go to the source code of this file.

Data Structures

struct  pickup_by_name_args

Defines

#define PICKUPMARK   "PICKUPMARK"

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int can_pickup (struct ast_channel *chan)
static int find_by_mark (void *obj, void *arg, void *data, int flags)
static int find_by_part (void *obj, void *arg, void *data, int flags)
static int load_module (void)
static struct ast_channelmy_ast_get_channel_by_name_locked (const char *channame)
 Helper Function to walk through ALL channels checking NAME and STATE.
static int pickup_by_channel (struct ast_channel *chan, char *pickup)
 Attempt to pick up specified channel named , does not use context.
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_name_cb (void *obj, void *arg, void *data, int flags)
static int pickup_by_part (struct ast_channel *chan, const char *part)
static int pickup_do (struct ast_channel *chan, struct ast_channel *target)
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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
static const char app [] = "Pickup"
static const char app2 [] = "PickupChan"
static struct ast_module_infoast_module_info = &__mod_info


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

Referenced by find_by_mark(), and pickup_exec().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 413 of file app_directed_pickup.c.

static void __unreg_module ( void   )  [static]

Definition at line 413 of file app_directed_pickup.c.

static int can_pickup ( struct ast_channel chan  )  [static]

Definition at line 148 of file app_directed_pickup.c.

References ast_channel::_state, AST_STATE_DOWN, AST_STATE_RING, AST_STATE_RINGING, and ast_channel::pbx.

Referenced by find_by_mark(), find_by_part(), pickup_by_exten(), and pickup_by_name_cb().

00149 {
00150    if (!chan->pbx && (chan->_state == AST_STATE_RINGING || chan->_state == AST_STATE_RING || chan->_state == AST_STATE_DOWN))
00151       return 1;
00152    else
00153       return 0;
00154 }

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

Definition at line 256 of file app_directed_pickup.c.

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

Referenced by pickup_by_mark().

00257 {
00258    struct ast_channel *c = obj;
00259    const char *mark = data;
00260    const char *tmp;
00261    int res;
00262 
00263    ast_channel_lock(c);
00264 
00265    res = (tmp = pbx_builtin_getvar_helper(c, PICKUPMARK)) &&
00266       !strcasecmp(tmp, mark) &&
00267       can_pickup(c);
00268 
00269    ast_channel_unlock(c);
00270 
00271    return res ? CMP_MATCH | CMP_STOP : 0;
00272 }

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

Definition at line 320 of file app_directed_pickup.c.

References ast_channel_lock, ast_channel_unlock, can_pickup(), CMP_MATCH, CMP_STOP, len(), and ast_channel::name.

Referenced by pickup_by_part().

00321 {
00322    struct ast_channel *c = obj; 
00323    const char *part = data;
00324    int res = 0;
00325    int len = strlen(part);
00326 
00327    ast_channel_lock(c);
00328    if (len <= strlen(c->name)) {
00329       res = !(strncmp(c->name, part, len)) && (can_pickup(c));
00330    }
00331    ast_channel_unlock(c);
00332 
00333    return res ? CMP_MATCH | CMP_STOP : 0;
00334 }

static int load_module ( void   )  [static]

Definition at line 403 of file app_directed_pickup.c.

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

00404 {
00405    int res;
00406 
00407    res = ast_register_application_xml(app, pickup_exec);
00408    res |= ast_register_application_xml(app2, pickupchan_exec);
00409 
00410    return res;
00411 }

static struct ast_channel* my_ast_get_channel_by_name_locked ( const char *  channame  )  [static]

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

Definition at line 177 of file app_directed_pickup.c.

References ast_channel_callback(), pickup_by_name_args::len, pickup_by_name_args::name, and pickup_by_name_cb().

Referenced by pickup_by_channel().

00178 {
00179    char *chkchan;
00180    struct pickup_by_name_args pickup_args;
00181 
00182    /* Check if channel name contains a '-'.
00183     * In this case the channel name will be interpreted as full channel name.
00184     */
00185    if (strchr(channame, '-')) {
00186       /* check full channel name */
00187       pickup_args.len = strlen(channame);
00188       pickup_args.name = channame;
00189    } else {
00190       /* need to append a '-' for the comparison so we check full channel name,
00191        * i.e SIP/hgc- , use a temporary variable so original stays the same for
00192        * debugging.
00193        */
00194       pickup_args.len = strlen(channame) + 1;
00195       chkchan = alloca(pickup_args.len + 1);
00196       strcpy(chkchan, channame);
00197       strcat(chkchan, "-");
00198       pickup_args.name = chkchan;
00199    }
00200 
00201    return ast_channel_callback(pickup_by_name_cb, NULL, &pickup_args, 0);
00202 }

static int pickup_by_channel ( struct ast_channel chan,
char *  pickup 
) [static]

Attempt to pick up specified channel named , does not use context.

Definition at line 205 of file app_directed_pickup.c.

References ast_channel_unlock, ast_channel_unref, my_ast_get_channel_by_name_locked(), and pickup_do().

Referenced by pickupchan_exec().

00206 {
00207    int res = 0;
00208    struct ast_channel *target;
00209 
00210    if (!(target = my_ast_get_channel_by_name_locked(pickup))) {
00211       return -1;
00212    }
00213 
00214    /* Just check that we are not picking up the SAME as target */
00215    if (chan != target) {
00216       res = pickup_do(chan, target);
00217    }
00218 
00219    ast_channel_unlock(target);
00220    target = ast_channel_unref(target);
00221 
00222    return res;
00223 }

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

Definition at line 226 of file app_directed_pickup.c.

References ast_channel_iterator_by_exten_new(), ast_channel_iterator_destroy(), ast_channel_iterator_next(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, can_pickup(), and pickup_do().

Referenced by pickup_exec().

00227 {
00228    struct ast_channel *target = NULL;
00229    struct ast_channel_iterator *iter;
00230    int res = -1;
00231 
00232    if (!(iter = ast_channel_iterator_by_exten_new(exten, context))) {
00233       return -1;
00234    }
00235 
00236    while ((target = ast_channel_iterator_next(iter))) {
00237       ast_channel_lock(target);
00238       if ((chan != target) && can_pickup(target)) {
00239          break;
00240       }
00241       ast_channel_unlock(target);
00242       target = ast_channel_unref(target);
00243    }
00244 
00245    ast_channel_iterator_destroy(iter);
00246 
00247    if (target) {
00248       res = pickup_do(chan, target);
00249       ast_channel_unlock(target);
00250       target = ast_channel_unref(target);
00251    }
00252 
00253    return res;
00254 }

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

Definition at line 275 of file app_directed_pickup.c.

References ast_channel_callback(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, find_by_mark(), and pickup_do().

Referenced by pickup_exec().

00276 {
00277    struct ast_channel *target;
00278    int res = -1;
00279 
00280    if ((target = ast_channel_callback(find_by_mark, NULL, (char *) mark, 0))) {
00281       ast_channel_lock(target);
00282       res = pickup_do(chan, target);
00283       ast_channel_unlock(target);
00284       target = ast_channel_unref(target);
00285    }
00286 
00287    return res;
00288 }

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

Definition at line 161 of file app_directed_pickup.c.

References args, ast_channel_lock, ast_channel_unlock, can_pickup(), CMP_MATCH, CMP_STOP, and ast_channel::name.

Referenced by my_ast_get_channel_by_name_locked().

00162 {
00163    struct ast_channel *chan = obj;
00164    struct pickup_by_name_args *args = data;
00165 
00166    ast_channel_lock(chan);
00167    if (!strncasecmp(chan->name, args->name, args->len) && can_pickup(chan)) {
00168       /* Return with the channel still locked on purpose */
00169       return CMP_MATCH | CMP_STOP;
00170    }
00171    ast_channel_unlock(chan);
00172 
00173    return 0;
00174 }

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

Definition at line 337 of file app_directed_pickup.c.

References ast_channel_callback(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, find_by_part(), and pickup_do().

Referenced by pickupchan_exec().

00338 {
00339    struct ast_channel *target;
00340    int res = -1;
00341 
00342    if ((target = ast_channel_callback(find_by_part, NULL, (char *) part, 0))) {
00343       ast_channel_lock(target);
00344       res = pickup_do(chan, target);
00345       ast_channel_unlock(target);
00346       target = ast_channel_unref(target);
00347    }
00348 
00349    return res;
00350 }

static int pickup_do ( struct ast_channel chan,
struct ast_channel target 
) [static]

Todo:
This application should return a result code, like PICKUPRESULT

Definition at line 101 of file app_directed_pickup.c.

References ast_answer(), AST_CEL_PICKUP, ast_cel_report_event(), ast_channel_connected_line_macro(), ast_channel_lock, ast_channel_masquerade(), ast_channel_queue_connected_line_update(), ast_channel_unlock, ast_channel_update_connected_line(), ast_connected_line_copy_from_caller(), AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, AST_CONTROL_ANSWER, ast_debug, ast_log(), ast_manager_event_multichan, ast_party_connected_line_copy(), ast_party_connected_line_free(), ast_party_connected_line_init(), ast_queue_control(), ast_channel::caller, EVENT_FLAG_CALL, LOG_WARNING, ast_channel::name, and ast_party_connected_line::source.

Referenced by pickup_by_channel(), pickup_by_exten(), pickup_by_mark(), and pickup_by_part().

00102 {
00103    int res = 0;
00104    struct ast_party_connected_line connected_caller;
00105    struct ast_channel *chans[2] = { chan, target };
00106 
00107    ast_debug(1, "Call pickup on '%s' by '%s'\n", target->name, chan->name);
00108    ast_cel_report_event(target, AST_CEL_PICKUP, NULL, NULL, chan);
00109 
00110    ast_party_connected_line_init(&connected_caller);
00111    ast_party_connected_line_copy(&connected_caller, &target->connected);
00112    connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
00113    if (ast_channel_connected_line_macro(NULL, chan, &connected_caller, 0, 0)) {
00114       ast_channel_update_connected_line(chan, &connected_caller, NULL);
00115    }
00116    ast_party_connected_line_free(&connected_caller);
00117 
00118    ast_channel_lock(chan);
00119    ast_connected_line_copy_from_caller(&connected_caller, &chan->caller);
00120    ast_channel_unlock(chan);
00121    connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
00122    ast_channel_queue_connected_line_update(chan, &connected_caller, NULL);
00123    ast_party_connected_line_free(&connected_caller);
00124 
00125    if ((res = ast_answer(chan))) {
00126       ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
00127       return -1;
00128    }
00129 
00130    if ((res = ast_queue_control(chan, AST_CONTROL_ANSWER))) {
00131       ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
00132       return -1;
00133    }
00134 
00135    if ((res = ast_channel_masquerade(target, chan))) {
00136       ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, target->name);
00137       return -1;
00138    }
00139 
00140    /* If you want UniqueIDs, set channelvars in manager.conf to CHANNEL(uniqueid) */
00141    ast_manager_event_multichan(EVENT_FLAG_CALL, "Pickup", 2, chans,
00142       "Channel: %s\r\nTargetChannel: %s\r\n", chan->name, target->name);
00143 
00144    return res;
00145 }

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

Definition at line 291 of file app_directed_pickup.c.

References ast_log(), ast_pickup_call(), ast_strdupa, ast_strlen_zero(), ast_channel::context, context, exten, LOG_NOTICE, pickup_by_exten(), pickup_by_mark(), PICKUPMARK, and strsep().

Referenced by load_module().

00292 {
00293    int res = 0;
00294    char *tmp = ast_strdupa(data);
00295    char *exten = NULL, *context = NULL;
00296 
00297    if (ast_strlen_zero(data)) {
00298       res = ast_pickup_call(chan);
00299       return res;
00300    }
00301    
00302    /* Parse extension (and context if there) */
00303    while (!ast_strlen_zero(tmp) && (exten = strsep(&tmp, "&"))) {
00304       if ((context = strchr(exten, '@')))
00305          *context++ = '\0';
00306       if (!ast_strlen_zero(context) && !strcasecmp(context, PICKUPMARK)) {
00307          if (!pickup_by_mark(chan, exten))
00308             break;
00309       } else {
00310          if (!pickup_by_exten(chan, exten, !ast_strlen_zero(context) ? context : chan->context))
00311             break;
00312       }
00313       ast_log(LOG_NOTICE, "No target channel found for %s.\n", exten);
00314    }
00315 
00316    return res;
00317 }

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

Definition at line 353 of file app_directed_pickup.c.

References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), LOG_NOTICE, LOG_WARNING, ast_channel::name, parse(), pickup_by_channel(), pickup_by_part(), and strsep().

Referenced by load_module().

00354 {
00355    int res = 0;
00356    int partial_pickup = 0;
00357    char *pickup = NULL;
00358    char *parse = ast_strdupa(data);
00359    AST_DECLARE_APP_ARGS(args,
00360       AST_APP_ARG(channel);
00361       AST_APP_ARG(options);
00362    );
00363    AST_STANDARD_APP_ARGS(args, parse);
00364 
00365    if (ast_strlen_zero(args.channel)) {
00366       ast_log(LOG_WARNING, "PickupChan requires an argument (channel)!\n");
00367       return -1;
00368    }
00369 
00370    if (!ast_strlen_zero(args.options) && strchr(args.options, 'p')) {
00371       partial_pickup = 1;
00372    }
00373 
00374    /* Parse channel */
00375    while (!ast_strlen_zero(args.channel) && (pickup = strsep(&args.channel, "&"))) {
00376       if (!strncasecmp(chan->name, pickup, strlen(pickup))) {
00377          ast_log(LOG_NOTICE, "Cannot pickup your own channel %s.\n", pickup);
00378       } else {
00379          if (partial_pickup) {
00380             if (!pickup_by_part(chan, pickup)) {
00381                break;
00382             }
00383          } else if (!pickup_by_channel(chan, pickup)) {
00384             break;
00385          }
00386          ast_log(LOG_NOTICE, "No target channel found for %s.\n", pickup);
00387       }
00388    }
00389 
00390    return res;
00391 }

static int unload_module ( void   )  [static]

Definition at line 393 of file app_directed_pickup.c.

References ast_unregister_application().

00394 {
00395    int res;
00396 
00397    res = ast_unregister_application(app);
00398    res |= ast_unregister_application(app2);
00399 
00400    return res;
00401 }


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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static]

Definition at line 413 of file app_directed_pickup.c.

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

Definition at line 96 of file app_directed_pickup.c.

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

Definition at line 97 of file app_directed_pickup.c.

Referenced by _macro_exec(), and app_cmp().

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 413 of file app_directed_pickup.c.


Generated on Wed Apr 6 11:29:49 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7