Thu Apr 28 2011 17:15:27

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 dependency graph for app_directed_pickup.c:

Go to the source code of this file.

Data Structures

struct  pickup_criteria

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_exten (struct ast_channel *c, void *data)
static int find_by_mark (struct ast_channel *c, void *data)
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_do (struct ast_channel *chan, struct ast_channel *target)
static int pickup_exec (struct ast_channel *chan, void *data)
static int pickupchan_exec (struct ast_channel *chan, void *data)
static int unload_module (void)

Variables

static struct ast_module_info
__MODULE_INFO_SECTION 
__mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Directed Call Pickup Application" , .key = ASTERISK_GPL_KEY , .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 44 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 318 of file app_directed_pickup.c.

static void __unreg_module ( void  ) [static]

Definition at line 318 of file app_directed_pickup.c.

static int can_pickup ( struct ast_channel chan) [static]

Definition at line 116 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_exten(), find_by_mark(), and my_ast_get_channel_by_name_locked().

{
   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_exten ( struct ast_channel c,
void *  data 
) [static]

Definition at line 186 of file app_directed_pickup.c.

References can_pickup(), pickup_criteria::chan, pickup_criteria::context, ast_channel::dialcontext, ast_channel::exten, pickup_criteria::exten, and ast_channel::macroexten.

Referenced by pickup_by_exten().

{
   struct pickup_criteria *info = data;

   return (!strcasecmp(c->macroexten, info->exten) || !strcasecmp(c->exten, info->exten)) &&
      !strcasecmp(c->dialcontext, info->context) &&
      (info->chan != c) && can_pickup(c);
}
static int find_by_mark ( struct ast_channel c,
void *  data 
) [static]

Definition at line 217 of file app_directed_pickup.c.

References can_pickup(), pbx_builtin_getvar_helper(), and PICKUPMARK.

Referenced by pickup_by_mark().

{
   const char *mark = data;
   const char *tmp;

   return (tmp = pbx_builtin_getvar_helper(c, PICKUPMARK)) &&
      !strcasecmp(tmp, mark) &&
      can_pickup(c);
}
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 125 of file app_directed_pickup.c.

References ast_channel_unlock, ast_walk_channel_by_name_prefix_locked(), can_pickup(), chan, and ast_channel::name.

Referenced by pickup_by_channel().

{
   struct ast_channel *chan;
   char *chkchan;
   size_t channame_len, chkchan_len;

   channame_len = strlen(channame);

   /* 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 */
      chkchan_len = channame_len;
      chkchan = (char *)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.
       */
      chkchan_len = channame_len + 1;
      chkchan = alloca(chkchan_len + 1);
      strcpy(chkchan, channame);
      strcat(chkchan, "-");
   }

   for (chan = ast_walk_channel_by_name_prefix_locked(NULL, channame, channame_len);
       chan;
       chan = ast_walk_channel_by_name_prefix_locked(chan, channame, channame_len)) {
      if (!strncasecmp(chan->name, chkchan, chkchan_len) && can_pickup(chan)) {
         return chan;
      }
      ast_channel_unlock(chan);
   }
   return NULL;
}
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 163 of file app_directed_pickup.c.

References ast_channel_unlock, my_ast_get_channel_by_name_locked(), ast_channel::name, 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->name != target->name && chan != target) {
      res = pickup_do(chan, target);
   }
   ast_channel_unlock(target);

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

Definition at line 196 of file app_directed_pickup.c.

References ast_channel_search_locked(), ast_channel_unlock, chan, context, exten, pickup_criteria::exten, find_by_exten(), and pickup_do().

Referenced by pickup_exec().

{
   struct ast_channel *target = NULL;
   struct pickup_criteria search = {
      .exten = exten,
      .context = context,
      .chan = chan,
   };

   target = ast_channel_search_locked(find_by_exten, &search);

   if (target) {
      int res = pickup_do(chan, target);
      ast_channel_unlock(target);
      target = NULL;
      return res;
   }

   return -1;
}
static int pickup_by_mark ( struct ast_channel chan,
const char *  mark 
) [static]

Definition at line 228 of file app_directed_pickup.c.

References ast_channel_search_locked(), ast_channel_unlock, find_by_mark(), and pickup_do().

Referenced by pickup_exec().

{
   struct ast_channel *target = ast_channel_search_locked(find_by_mark, (char *) mark);

   if (target) {
      int res = pickup_do(chan, target);
      ast_channel_unlock(target);
      target = NULL;
      return res;
   }

   return -1;
}
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 91 of file app_directed_pickup.c.

References ast_answer(), ast_channel_masquerade(), AST_CONTROL_ANSWER, ast_debug, ast_log(), ast_queue_control(), LOG_WARNING, and ast_channel::name.

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

{
   int res = 0;

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

   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;
   }

   return res;
}
static int pickup_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 243 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,
void *  data 
) [static]

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

{
   int res = 0;
   char *tmp = ast_strdupa(data);
   char *pickup = NULL;

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

   /* Parse channel */
   while (!ast_strlen_zero(tmp) && (pickup = strsep(&tmp, "&"))) {
      if (!strncasecmp(chan->name, pickup, strlen(pickup))) {
         ast_log(LOG_NOTICE, "Cannot pickup your own channel %s.\n", pickup);
      } 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 298 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 __MODULE_INFO_SECTION __mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Directed Call Pickup Application" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, } [static]

Definition at line 318 of file app_directed_pickup.c.

const char* app = "Pickup" [static]

Definition at line 86 of file app_directed_pickup.c.

const char* app2 = "PickupChan" [static]

Definition at line 87 of file app_directed_pickup.c.

Referenced by _macro_exec().

Definition at line 318 of file app_directed_pickup.c.