Wed Oct 28 13:31:21 2009

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

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 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_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_DEFAULT , .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, }
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 46 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 347 of file app_directed_pickup.c.

static void __unreg_module ( void   )  [static]

Definition at line 347 of file app_directed_pickup.c.

static int can_pickup ( struct ast_channel chan  )  [static]

Definition at line 135 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(), pickup_by_exten(), and pickup_by_name_cb().

00136 {
00137    if (!chan->pbx && (chan->_state == AST_STATE_RINGING || chan->_state == AST_STATE_RING || chan->_state == AST_STATE_DOWN))
00138       return 1;
00139    else
00140       return 0;
00141 }

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

Definition at line 237 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().

00238 {
00239    struct ast_channel *c = obj;
00240    const char *mark = data;
00241    const char *tmp;
00242    int res;
00243 
00244    ast_channel_lock(c);
00245 
00246    res = (tmp = pbx_builtin_getvar_helper(c, PICKUPMARK)) &&
00247       !strcasecmp(tmp, mark) &&
00248       can_pickup(c);
00249 
00250    ast_channel_unlock(c);
00251 
00252    return res ? CMP_MATCH | CMP_STOP : 0;
00253 }

static int load_module ( void   )  [static]

Definition at line 337 of file app_directed_pickup.c.

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

00338 {
00339    int res;
00340 
00341    res = ast_register_application_xml(app, pickup_exec);
00342    res |= ast_register_application_xml(app2, pickupchan_exec);
00343 
00344    return res;
00345 }

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

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

Definition at line 164 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().

00165 {
00166    char *chkchan;
00167    struct pickup_by_name_args pickup_args;
00168 
00169    pickup_args.len = strlen(channame) + 2;
00170 
00171    chkchan = alloca(pickup_args.len);
00172 
00173    /* need to append a '-' for the comparison so we check full channel name,
00174     * i.e SIP/hgc- , use a temporary variable so original stays the same for
00175     * debugging.
00176     */
00177    strcpy(chkchan, channame);
00178    strcat(chkchan, "-");
00179 
00180    pickup_args.name = chkchan;
00181 
00182    return ast_channel_callback(pickup_by_name_cb, NULL, &pickup_args, 0);
00183 }

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

00187 {
00188    int res = 0;
00189    struct ast_channel *target;
00190 
00191    if (!(target = my_ast_get_channel_by_name_locked(pickup))) {
00192       return -1;
00193    }
00194 
00195    /* Just check that we are not picking up the SAME as target */
00196    if (chan != target) {
00197       res = pickup_do(chan, target);
00198    }
00199 
00200    ast_channel_unlock(target);
00201    target = ast_channel_unref(target);
00202 
00203    return res;
00204 }

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

Definition at line 207 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().

00208 {
00209    struct ast_channel *target = NULL;
00210    struct ast_channel_iterator *iter;
00211    int res = -1;
00212 
00213    if (!(iter = ast_channel_iterator_by_exten_new(exten, context))) {
00214       return -1;
00215    }
00216 
00217    while ((target = ast_channel_iterator_next(iter))) {
00218       ast_channel_lock(target);
00219       if ((chan != target) && can_pickup(target)) {
00220          break;
00221       }
00222       ast_channel_unlock(target);
00223       target = ast_channel_unref(target);
00224    }
00225 
00226    ast_channel_iterator_destroy(iter);
00227 
00228    if (target) {
00229       res = pickup_do(chan, target);
00230       ast_channel_unlock(target);
00231       target = ast_channel_unref(target);
00232    }
00233 
00234    return res;
00235 }

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

Definition at line 256 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().

00257 {
00258    struct ast_channel *target;
00259    int res = -1;
00260 
00261    if ((target = ast_channel_callback(find_by_mark, NULL, (char *) mark, 0))) {
00262       ast_channel_lock(target);
00263       res = pickup_do(chan, target);
00264       ast_channel_unlock(target);
00265       target = ast_channel_unref(target);
00266    }
00267 
00268    return res;
00269 }

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

Definition at line 148 of file app_directed_pickup.c.

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

Referenced by my_ast_get_channel_by_name_locked().

00149 {
00150    struct ast_channel *chan = obj;
00151    struct pickup_by_name_args *args = data;
00152 
00153    ast_channel_lock(chan);
00154    if (!strncasecmp(chan->name, args->name, args->len) && can_pickup(chan)) {
00155       /* Return with the channel still locked on purpose */
00156       return CMP_MATCH | CMP_STOP;
00157    }
00158    ast_channel_unlock(chan);
00159 
00160    return 0;
00161 }

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 93 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_party_connected_line_copy(), ast_party_connected_line_free(), ast_party_connected_line_init(), ast_queue_control(), ast_channel::cid, ast_channel::connected, LOG_WARNING, ast_channel::name, and ast_party_connected_line::source.

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

00094 {
00095    int res = 0;
00096    struct ast_party_connected_line connected_caller;
00097 
00098    ast_debug(1, "Call pickup on '%s' by '%s'\n", target->name, chan->name);
00099    ast_cel_report_event(target, AST_CEL_PICKUP, NULL, NULL, chan);
00100 
00101    ast_party_connected_line_init(&connected_caller);
00102    ast_party_connected_line_copy(&connected_caller, &target->connected);
00103    connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
00104    if (ast_channel_connected_line_macro(NULL, chan, &connected_caller, 0, 0)) {
00105       ast_channel_update_connected_line(chan, &connected_caller);
00106    }
00107    ast_party_connected_line_free(&connected_caller);
00108 
00109    ast_channel_lock(chan);
00110    ast_connected_line_copy_from_caller(&connected_caller, &chan->cid);
00111    ast_channel_unlock(chan);
00112    connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
00113    ast_channel_queue_connected_line_update(chan, &connected_caller);
00114    ast_party_connected_line_free(&connected_caller);
00115 
00116    if ((res = ast_answer(chan))) {
00117       ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
00118       return -1;
00119    }
00120 
00121    if ((res = ast_queue_control(chan, AST_CONTROL_ANSWER))) {
00122       ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
00123       return -1;
00124    }
00125 
00126    if ((res = ast_channel_masquerade(target, chan))) {
00127       ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, target->name);
00128       return -1;
00129    }
00130 
00131    return res;
00132 }

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

Definition at line 272 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().

00273 {
00274    int res = 0;
00275    char *tmp = ast_strdupa(data);
00276    char *exten = NULL, *context = NULL;
00277 
00278    if (ast_strlen_zero(data)) {
00279       res = ast_pickup_call(chan);
00280       return res;
00281    }
00282    
00283    /* Parse extension (and context if there) */
00284    while (!ast_strlen_zero(tmp) && (exten = strsep(&tmp, "&"))) {
00285       if ((context = strchr(exten, '@')))
00286          *context++ = '\0';
00287       if (!ast_strlen_zero(context) && !strcasecmp(context, PICKUPMARK)) {
00288          if (!pickup_by_mark(chan, exten))
00289             break;
00290       } else {
00291          if (!pickup_by_exten(chan, exten, !ast_strlen_zero(context) ? context : chan->context))
00292             break;
00293       }
00294       ast_log(LOG_NOTICE, "No target channel found for %s.\n", exten);
00295    }
00296 
00297    return res;
00298 }

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

Definition at line 301 of file app_directed_pickup.c.

References ast_log(), ast_strdupa, ast_strlen_zero(), LOG_NOTICE, LOG_WARNING, ast_channel::name, pickup_by_channel(), and strsep().

Referenced by load_module().

00302 {
00303    int res = 0;
00304    char *tmp = ast_strdupa(data);
00305    char *pickup = NULL;
00306 
00307    if (ast_strlen_zero(data)) {
00308       ast_log(LOG_WARNING, "PickupChan requires an argument (channel)!\n");
00309       return -1;  
00310    }
00311 
00312    /* Parse channel */
00313    while (!ast_strlen_zero(tmp) && (pickup = strsep(&tmp, "&"))) {
00314       if (!strncasecmp(chan->name, pickup, strlen(pickup))) {
00315          ast_log(LOG_NOTICE, "Cannot pickup your own channel %s.\n", pickup);
00316       } else {
00317          if (!pickup_by_channel(chan, pickup)) {
00318             break;
00319          }
00320          ast_log(LOG_NOTICE, "No target channel found for %s.\n", pickup);
00321       }
00322    }
00323 
00324    return res;
00325 }

static int unload_module ( void   )  [static]

Definition at line 327 of file app_directed_pickup.c.

References ast_unregister_application().

00328 {
00329    int res;
00330 
00331    res = ast_unregister_application(app);
00332    res |= ast_unregister_application(app2);
00333 
00334    return res;
00335 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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, } [static]

Definition at line 347 of file app_directed_pickup.c.

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

Definition at line 88 of file app_directed_pickup.c.

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

Definition at line 89 of file app_directed_pickup.c.

Referenced by _macro_exec(), and app_cmp().

Definition at line 347 of file app_directed_pickup.c.


Generated on Wed Oct 28 13:31:21 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6