Fri Apr 29 2011 07:54:51

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

{
   if (!chan->pbx && (chan->_state == AST_STATE_RINGING || chan->_state == AST_STATE_RING || chan->_state == AST_STATE_DOWN))
      return 1;
   else
      return 0;
}
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, ast_channel::data, pbx_builtin_getvar_helper(), and PICKUPMARK.

Referenced by pickup_by_mark().

{
   struct ast_channel *c = obj;
   const char *mark = data;
   const char *tmp;
   int res;

   ast_channel_lock(c);

   res = (tmp = pbx_builtin_getvar_helper(c, PICKUPMARK)) &&
      !strcasecmp(tmp, mark) &&
      can_pickup(c);

   ast_channel_unlock(c);

   return res ? CMP_MATCH | CMP_STOP : 0;
}
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, ast_channel::data, len(), and ast_channel::name.

Referenced by pickup_by_part().

{
   struct ast_channel *c = obj; 
   const char *part = data;
   int res = 0;
   int len = strlen(part);

   ast_channel_lock(c);
   if (len <= strlen(c->name)) {
      res = !(strncmp(c->name, part, len)) && (can_pickup(c));
   }
   ast_channel_unlock(c);

   return res ? CMP_MATCH | CMP_STOP : 0;
}
static int load_module ( void  ) [static]
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 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().

{
   char *chkchan;
   struct pickup_by_name_args pickup_args;

   /* Check if channel name contains a '-'.
    * In this case the channel name will be interpreted as full channel name.
    */
   if (strchr(channame, '-')) {
      /* check full channel name */
      pickup_args.len = strlen(channame);
      pickup_args.name = channame;
   } else {
      /* need to append a '-' for the comparison so we check full channel name,
       * i.e SIP/hgc- , use a temporary variable so original stays the same for
       * debugging.
       */
      pickup_args.len = strlen(channame) + 1;
      chkchan = alloca(pickup_args.len + 1);
      strcpy(chkchan, channame);
      strcat(chkchan, "-");
      pickup_args.name = chkchan;
   }

   return ast_channel_callback(pickup_by_name_cb, NULL, &pickup_args, 0);
}
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().

{
   int res = 0;
   struct ast_channel *target;

   if (!(target = my_ast_get_channel_by_name_locked(pickup))) {
      return -1;
   }

   /* Just check that we are not picking up the SAME as target */
   if (chan != target) {
      res = pickup_do(chan, target);
   }

   ast_channel_unlock(target);
   target = ast_channel_unref(target);

   return res;
}
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().

{
   struct ast_channel *target = NULL;
   struct ast_channel_iterator *iter;
   int res = -1;

   if (!(iter = ast_channel_iterator_by_exten_new(exten, context))) {
      return -1;
   }

   while ((target = ast_channel_iterator_next(iter))) {
      ast_channel_lock(target);
      if ((chan != target) && can_pickup(target)) {
         break;
      }
      ast_channel_unlock(target);
      target = ast_channel_unref(target);
   }

   ast_channel_iterator_destroy(iter);

   if (target) {
      res = pickup_do(chan, target);
      ast_channel_unlock(target);
      target = ast_channel_unref(target);
   }

   return res;
}
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().

{
   struct ast_channel *target;
   int res = -1;

   if ((target = ast_channel_callback(find_by_mark, NULL, (char *) mark, 0))) {
      ast_channel_lock(target);
      res = pickup_do(chan, target);
      ast_channel_unlock(target);
      target = ast_channel_unref(target);
   }

   return res;
}
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, pickup_by_name_args::len, pickup_by_name_args::name, and ast_channel::name.

Referenced by my_ast_get_channel_by_name_locked().

{
   struct ast_channel *chan = obj;
   struct pickup_by_name_args *args = data;

   ast_channel_lock(chan);
   if (!strncasecmp(chan->name, args->name, args->len) && can_pickup(chan)) {
      /* Return with the channel still locked on purpose */
      return CMP_MATCH | CMP_STOP;
   }
   ast_channel_unlock(chan);

   return 0;
}
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().

{
   struct ast_channel *target;
   int res = -1;

   if ((target = ast_channel_callback(find_by_part, NULL, (char *) part, 0))) {
      ast_channel_lock(target);
      res = pickup_do(chan, target);
      ast_channel_unlock(target);
      target = ast_channel_unref(target);
   }

   return res;
}
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, ast_channel::connected, 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().

{
   int res = 0;
   struct ast_party_connected_line connected_caller;
   struct ast_channel *chans[2] = { chan, target };

   ast_debug(1, "Call pickup on '%s' by '%s'\n", target->name, chan->name);
   ast_cel_report_event(target, AST_CEL_PICKUP, NULL, NULL, chan);

   ast_party_connected_line_init(&connected_caller);
   ast_party_connected_line_copy(&connected_caller, &target->connected);
   connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
   if (ast_channel_connected_line_macro(NULL, chan, &connected_caller, 0, 0)) {
      ast_channel_update_connected_line(chan, &connected_caller, NULL);
   }
   ast_party_connected_line_free(&connected_caller);

   ast_channel_lock(chan);
   ast_connected_line_copy_from_caller(&connected_caller, &chan->caller);
   ast_channel_unlock(chan);
   connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
   ast_channel_queue_connected_line_update(chan, &connected_caller, NULL);
   ast_party_connected_line_free(&connected_caller);

   if ((res = ast_answer(chan))) {
      ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
      return -1;
   }

   if ((res = ast_queue_control(chan, AST_CONTROL_ANSWER))) {
      ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
      return -1;
   }

   if ((res = ast_channel_masquerade(target, chan))) {
      ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, target->name);
      return -1;
   }

   /* If you want UniqueIDs, set channelvars in manager.conf to CHANNEL(uniqueid) */
   ast_manager_event_multichan(EVENT_FLAG_CALL, "Pickup", 2, chans,
      "Channel: %s\r\nTargetChannel: %s\r\n", chan->name, target->name);

   return res;
}
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().

{
   int res = 0;
   char *tmp = ast_strdupa(data);
   char *exten = NULL, *context = NULL;

   if (ast_strlen_zero(data)) {
      res = ast_pickup_call(chan);
      return res;
   }
   
   /* Parse extension (and context if there) */
   while (!ast_strlen_zero(tmp) && (exten = strsep(&tmp, "&"))) {
      if ((context = strchr(exten, '@')))
         *context++ = '\0';
      if (!ast_strlen_zero(context) && !strcasecmp(context, PICKUPMARK)) {
         if (!pickup_by_mark(chan, exten))
            break;
      } else {
         if (!pickup_by_exten(chan, exten, !ast_strlen_zero(context) ? context : chan->context))
            break;
      }
      ast_log(LOG_NOTICE, "No target channel found for %s.\n", exten);
   }

   return res;
}
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().

{
   int res = 0;
   int partial_pickup = 0;
   char *pickup = NULL;
   char *parse = ast_strdupa(data);
   AST_DECLARE_APP_ARGS(args,
      AST_APP_ARG(channel);
      AST_APP_ARG(options);
   );
   AST_STANDARD_APP_ARGS(args, parse);

   if (ast_strlen_zero(args.channel)) {
      ast_log(LOG_WARNING, "PickupChan requires an argument (channel)!\n");
      return -1;
   }

   if (!ast_strlen_zero(args.options) && strchr(args.options, 'p')) {
      partial_pickup = 1;
   }

   /* Parse channel */
   while (!ast_strlen_zero(args.channel) && (pickup = strsep(&args.channel, "&"))) {
      if (!strncasecmp(chan->name, pickup, strlen(pickup))) {
         ast_log(LOG_NOTICE, "Cannot pickup your own channel %s.\n", pickup);
      } else {
         if (partial_pickup) {
            if (!pickup_by_part(chan, pickup)) {
               break;
            }
         } else if (!pickup_by_channel(chan, pickup)) {
            break;
         }
         ast_log(LOG_NOTICE, "No target channel found for %s.\n", pickup);
      }
   }

   return res;
}
static int unload_module ( void  ) [static]

Definition at line 393 of file app_directed_pickup.c.

References ast_unregister_application().

{
   int res;

   res = ast_unregister_application(app);
   res |= ast_unregister_application(app2);

   return res;
}

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

Definition at line 413 of file app_directed_pickup.c.