Mon Jun 27 16:51:18 2011

Asterisk developer's documentation


pbx_realtime.c File Reference

Realtime PBX Module. More...

#include "asterisk.h"
#include <signal.h>
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/frame.h"
#include "asterisk/term.h"
#include "asterisk/manager.h"
#include "asterisk/cli.h"
#include "asterisk/lock.h"
#include "asterisk/md5.h"
#include "asterisk/linkedlists.h"
#include "asterisk/chanvars.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/utils.h"
#include "asterisk/astdb.h"
#include "asterisk/app.h"
#include "asterisk/astobj2.h"

Go to the source code of this file.

Data Structures

struct  cache_entry

Defines

#define EXT_DATA_SIZE   256
#define MODE_CANMATCH   2
#define MODE_MATCH   0
#define MODE_MATCHMORE   1

Enumerations

enum  option_flags { OPTION_PATTERNS_DISABLED = (1 << 0) }

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int cache_cmp (void *obj, void *arg, int flags)
static int cache_hash (const void *obj, const int flags)
static void * cleanup (void *unused)
static struct ast_variabledup_vars (struct ast_variable *v)
static void free_entry (void *obj)
static int load_module (void)
static int purge_old_fn (void *obj, void *arg, int flags)
static int realtime_canmatch (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
static struct ast_variablerealtime_common (const char *context, const char *exten, int priority, const char *data, int mode)
static int realtime_exec (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
static int realtime_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
static int realtime_matchmore (struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
static struct ast_variablerealtime_switch_common (const char *table, const char *context, const char *exten, int priority, int mode, struct ast_flags flags)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Realtime Switch" , .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 struct ast_module_infoast_module_info = &__mod_info
ao2_containercache
pthread_t cleanup_thread = 0
static struct ast_switch realtime_switch
static struct ast_app_option switch_opts [128] = { [ 'p' ] = { .flag = OPTION_PATTERNS_DISABLED },}


Detailed Description

Realtime PBX Module.

Definition in file pbx_realtime.c.


Define Documentation

#define EXT_DATA_SIZE   256

Definition at line 57 of file pbx_realtime.c.

#define MODE_CANMATCH   2

Definition at line 55 of file pbx_realtime.c.

Referenced by realtime_canmatch(), and realtime_switch_common().

#define MODE_MATCH   0

Definition at line 53 of file pbx_realtime.c.

Referenced by realtime_common(), realtime_exec(), realtime_exists(), and realtime_switch_common().

#define MODE_MATCHMORE   1

Definition at line 54 of file pbx_realtime.c.

Referenced by realtime_matchmore(), and realtime_switch_common().


Enumeration Type Documentation

enum option_flags

Enumerator:
OPTION_PATTERNS_DISABLED 

Definition at line 59 of file pbx_realtime.c.

00059                   {
00060    OPTION_PATTERNS_DISABLED = (1 << 0),
00061 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 422 of file pbx_realtime.c.

static void __unreg_module ( void   )  [static]

Definition at line 422 of file pbx_realtime.c.

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

Definition at line 84 of file pbx_realtime.c.

References CMP_MATCH, cache_entry::context, cache_entry::exten, f, and cache_entry::priority.

Referenced by load_module().

00085 {
00086    struct cache_entry *e = obj, *f = arg;
00087    return e->priority != f->priority ? 0 :
00088       strcmp(e->exten, f->exten) ? 0 :
00089       strcmp(e->context, f->context) ? 0 :
00090       CMP_MATCH;
00091 }

static int cache_hash ( const void *  obj,
const int  flags 
) [static]

Definition at line 78 of file pbx_realtime.c.

References ast_str_case_hash(), cache_entry::exten, and cache_entry::priority.

Referenced by load_module().

00079 {
00080    const struct cache_entry *e = obj;
00081    return ast_str_case_hash(e->exten) + e->priority;
00082 }

static void* cleanup ( void *  unused  )  [static]

Definition at line 122 of file pbx_realtime.c.

References ao2_callback, ao2_container_count(), ast_tvnow(), cache, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, and purge_old_fn().

Referenced by _sip_tcp_helper_thread(), ast_sockaddr_resolve(), build_user(), handle_uri(), and load_module().

00123 {
00124    struct timespec forever = { 999999999, 0 }, one_second = { 1, 0 };
00125    struct timeval now;
00126 
00127    for (;;) {
00128       pthread_testcancel();
00129       if (ao2_container_count(cache) == 0) {
00130          nanosleep(&forever, NULL);
00131       }
00132       pthread_testcancel();
00133       now = ast_tvnow();
00134       ao2_callback(cache, OBJ_MULTIPLE | OBJ_UNLINK | OBJ_NODATA, purge_old_fn, &now);
00135       pthread_testcancel();
00136       nanosleep(&one_second, NULL);
00137    }
00138 
00139    return NULL;
00140 }

static struct ast_variable* dup_vars ( struct ast_variable v  )  [static]

Definition at line 93 of file pbx_realtime.c.

References ast_variable_new(), ast_variables_destroy(), ast_variable::file, ast_variable::name, ast_variable::next, and ast_variable::value.

Referenced by realtime_common().

00094 {
00095    struct ast_variable *new, *list = NULL;
00096    for (; v; v = v->next) {
00097       if (!(new = ast_variable_new(v->name, v->value, v->file))) {
00098          ast_variables_destroy(list);
00099          return NULL;
00100       }
00101       /* Reversed list in cache, but when we duplicate out of the cache,
00102        * it's back to correct order. */
00103       new->next = list;
00104       list = new;
00105    }
00106    return list;
00107 }

static void free_entry ( void *  obj  )  [static]

Definition at line 109 of file pbx_realtime.c.

References ast_variables_destroy(), and cache_entry::var.

Referenced by realtime_common().

00110 {
00111    struct cache_entry *e = obj;
00112    ast_variables_destroy(e->var);
00113 }

static int load_module ( void   )  [static]

Definition at line 407 of file pbx_realtime.c.

References ao2_container_alloc, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_pthread_create, ast_register_switch(), cache, cache_cmp(), cache_hash(), cleanup(), cleanup_thread, and realtime_switch.

00408 {
00409    if (!(cache = ao2_container_alloc(573, cache_hash, cache_cmp))) {
00410       return AST_MODULE_LOAD_FAILURE;
00411    }
00412 
00413    if (ast_pthread_create(&cleanup_thread, NULL, cleanup, NULL)) {
00414       return AST_MODULE_LOAD_FAILURE;
00415    }
00416 
00417    if (ast_register_switch(&realtime_switch))
00418       return AST_MODULE_LOAD_FAILURE;
00419    return AST_MODULE_LOAD_SUCCESS;
00420 }

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

Definition at line 115 of file pbx_realtime.c.

References ast_tvdiff_ms(), CMP_MATCH, and cache_entry::when.

Referenced by cleanup().

00116 {
00117    struct cache_entry *e = obj;
00118    struct timeval *now = arg;
00119    return ast_tvdiff_ms(*now, e->when) >= 1000 ? CMP_MATCH : 0;
00120 }

static int realtime_canmatch ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority,
const char *  callerid,
const char *  data 
) [static]

Definition at line 288 of file pbx_realtime.c.

References ast_variables_destroy(), MODE_CANMATCH, realtime_common(), and var.

00289 {
00290    struct ast_variable *var = realtime_common(context, exten, priority, data, MODE_CANMATCH);
00291    if (var) {
00292       ast_variables_destroy(var);
00293       return 1;
00294    }
00295    return 0;
00296 }

static struct ast_variable* realtime_common ( const char *  context,
const char *  exten,
int  priority,
const char *  data,
int  mode 
) [static]

Definition at line 216 of file pbx_realtime.c.

References ao2_alloc, ao2_find, ao2_link, ao2_ref, ast_app_parse_options(), ast_copy_string(), AST_MAX_EXTENSION, ast_strdupa, ast_strlen_zero(), ast_tvnow(), ast_variables_destroy(), cache, cleanup_thread, dup_vars(), ast_flags::flags, free_entry(), MODE_MATCH, OBJ_POINTER, cache_entry::priority, realtime_switch_common(), S_OR, switch_opts, table, cache_entry::var, and var.

Referenced by realtime_canmatch(), realtime_exec(), realtime_exists(), and realtime_matchmore().

00217 {
00218    const char *ctx = NULL;
00219    char *table;
00220    struct ast_variable *var=NULL;
00221    struct ast_flags flags = { 0, };
00222    struct cache_entry *ce;
00223    struct {
00224       struct cache_entry ce;
00225       char exten[AST_MAX_EXTENSION];
00226    } cache_search = { { .priority = priority, .context = (char *) context }, };
00227    char *buf = ast_strdupa(data);
00228    if (buf) {
00229       /* "Realtime" prefix is stripped off in the parent engine.  The
00230        * remaining string is: [[context@]table][/opts] */
00231       char *opts = strchr(buf, '/');
00232       if (opts)
00233          *opts++ = '\0';
00234       table = strchr(buf, '@');
00235       if (table) {
00236          *table++ = '\0';
00237          ctx = buf;
00238       }
00239       ctx = S_OR(ctx, context);
00240       table = S_OR(table, "extensions");
00241       if (!ast_strlen_zero(opts)) {
00242          ast_app_parse_options(switch_opts, &flags, NULL, opts);
00243       }
00244       ast_copy_string(cache_search.exten, exten, sizeof(cache_search.exten));
00245       if (mode == MODE_MATCH && (ce = ao2_find(cache, &cache_search, OBJ_POINTER))) {
00246          var = dup_vars(ce->var);
00247          ao2_ref(ce, -1);
00248       } else {
00249          var = realtime_switch_common(table, ctx, exten, priority, mode, flags);
00250          do {
00251             struct ast_variable *new;
00252             /* Only cache matches */
00253             if (mode != MODE_MATCH) {
00254                break;
00255             }
00256             if (!(new = dup_vars(var))) {
00257                break;
00258             }
00259             if (!(ce = ao2_alloc(sizeof(*ce) + strlen(exten) + strlen(context), free_entry))) {
00260                ast_variables_destroy(new);
00261                break;
00262             }
00263             ce->context = ce->exten + strlen(exten) + 1;
00264             strcpy(ce->exten, exten); /* SAFE */
00265             strcpy(ce->context, context); /* SAFE */
00266             ce->priority = priority;
00267             ce->var = new;
00268             ce->when = ast_tvnow();
00269             ao2_link(cache, ce);
00270             pthread_kill(cleanup_thread, SIGURG);
00271             ao2_ref(ce, -1);
00272          } while (0);
00273       }
00274    }
00275    return var;
00276 }

static int realtime_exec ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority,
const char *  callerid,
const char *  data 
) [static]

Definition at line 298 of file pbx_realtime.c.

References app, ast_compat_pbx_realtime, ast_strdupa, MODE_MATCH, ast_variable::name, ast_variable::next, realtime_common(), ast_variable::value, and var.

00299 {
00300    int res = -1;
00301    struct ast_variable *var = realtime_common(context, exten, priority, data, MODE_MATCH);
00302 
00303    if (var) {
00304       char *tmp="";
00305       char *app = NULL;
00306       struct ast_variable *v;
00307 
00308       for (v = var; v ; v = v->next) {
00309          if (!strcasecmp(v->name, "app"))
00310             app = ast_strdupa(v->value);
00311          else if (!strcasecmp(v->name, "appdata")) {
00312             if (ast_compat_pbx_realtime) {
00313                char *ptr;
00314                int in = 0;
00315                tmp = alloca(strlen(v->value) * 2 + 1);
00316                for (ptr = tmp; *v->value; v->value++) {
00317                   if (*v->value == ',') {
00318                      *ptr++ = '\\';
00319                      *ptr++ = ',';
00320                   } else if (*v->value == '|' && !in) {
00321                      *ptr++ = ',';
00322                   } else {
00323                      *ptr++ = *v->value;
00324                   }
00325 
00326                   /* Don't escape '|', meaning 'or', inside expressions ($[ ]) */
00327                   if (v->value[0] == '[' && v->value[-1] == '$') {
00328                      in++;
00329                   } else if (v->value[0] == ']' && in) {
00330                      in--;
00331                   }
00332                }
00333                *ptr = '\0';
00334             } else {
00335                tmp = ast_strdupa(v->value);
00336             }
00337          }
00338       }
00339       ast_variables_destroy(var);
00340       if (!ast_strlen_zero(app)) {
00341          struct ast_app *a = pbx_findapp(app);
00342          if (a) {
00343             char appdata[512];
00344             char tmp1[80];
00345             char tmp2[80];
00346             char tmp3[EXT_DATA_SIZE];
00347 
00348             appdata[0] = 0; /* just in case the substitute var func isn't called */
00349             if(!ast_strlen_zero(tmp))
00350                pbx_substitute_variables_helper(chan, tmp, appdata, sizeof(appdata) - 1);
00351             ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\")\n",
00352                   chan->exten, chan->context, chan->priority,
00353                    term_color(tmp1, app, COLOR_BRCYAN, 0, sizeof(tmp1)),
00354                    term_color(tmp2, chan->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
00355                    term_color(tmp3, S_OR(appdata, ""), COLOR_BRMAGENTA, 0, sizeof(tmp3)));
00356             manager_event(EVENT_FLAG_DIALPLAN, "Newexten",
00357                        "Channel: %s\r\n"
00358                        "Context: %s\r\n"
00359                        "Extension: %s\r\n"
00360                        "Priority: %d\r\n"
00361                        "Application: %s\r\n"
00362                        "AppData: %s\r\n"
00363                        "Uniqueid: %s\r\n",
00364                        chan->name, chan->context, chan->exten, chan->priority, app, !ast_strlen_zero(appdata) ? appdata : "(NULL)", chan->uniqueid);
00365             
00366             res = pbx_exec(chan, a, appdata);
00367          } else
00368             ast_log(LOG_NOTICE, "No such application '%s' for extension '%s' in context '%s'\n", app, exten, context);
00369       } else {
00370          ast_log(LOG_WARNING, "No application specified for realtime extension '%s' in context '%s'\n", exten, context);
00371       }
00372    }
00373    return res;
00374 }

static int realtime_exists ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority,
const char *  callerid,
const char *  data 
) [static]

Definition at line 278 of file pbx_realtime.c.

References ast_variables_destroy(), MODE_MATCH, realtime_common(), and var.

00279 {
00280    struct ast_variable *var = realtime_common(context, exten, priority, data, MODE_MATCH);
00281    if (var) {
00282       ast_variables_destroy(var);
00283       return 1;
00284    }
00285    return 0;
00286 }

static int realtime_matchmore ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority,
const char *  callerid,
const char *  data 
) [static]

Definition at line 376 of file pbx_realtime.c.

References ast_variables_destroy(), MODE_MATCHMORE, realtime_common(), and var.

00377 {
00378    struct ast_variable *var = realtime_common(context, exten, priority, data, MODE_MATCHMORE);
00379    if (var) {
00380       ast_variables_destroy(var);
00381       return 1;
00382    }
00383    return 0;
00384 }

static struct ast_variable* realtime_switch_common ( const char *  table,
const char *  context,
const char *  exten,
int  priority,
int  mode,
struct ast_flags  flags 
) [static]

Definition at line 157 of file pbx_realtime.c.

References ast_category_browse(), ast_category_detach_variables(), ast_category_get(), ast_config_destroy(), ast_copy_string(), ast_extension_close(), ast_extension_match(), ast_load_realtime(), ast_load_realtime_multientry(), AST_MAX_EXTENSION, ast_test_flag, match(), MODE_CANMATCH, MODE_MATCH, MODE_MATCHMORE, OPTION_PATTERNS_DISABLED, SENTINEL, and var.

Referenced by realtime_common().

00158 {
00159    struct ast_variable *var;
00160    struct ast_config *cfg;
00161    char pri[20];
00162    char *ematch;
00163    char rexten[AST_MAX_EXTENSION + 20]="";
00164    int match;
00165    /* Optimization: since we don't support hints in realtime, it's silly to
00166     * query for a hint here, since we won't actually do anything with it.
00167     * This just wastes CPU time and resources. */
00168    if (priority < 0) {
00169       return NULL;
00170    }
00171    snprintf(pri, sizeof(pri), "%d", priority);
00172    switch(mode) {
00173    case MODE_MATCHMORE:
00174       ematch = "exten LIKE";
00175       snprintf(rexten, sizeof(rexten), "%s_%%", exten);
00176       break;
00177    case MODE_CANMATCH:
00178       ematch = "exten LIKE";
00179       snprintf(rexten, sizeof(rexten), "%s%%", exten);
00180       break;
00181    case MODE_MATCH:
00182    default:
00183       ematch = "exten";
00184       ast_copy_string(rexten, exten, sizeof(rexten));
00185    }
00186    var = ast_load_realtime(table, ematch, rexten, "context", context, "priority", pri, SENTINEL);
00187    if (!var && !ast_test_flag(&flags, OPTION_PATTERNS_DISABLED)) {
00188       cfg = ast_load_realtime_multientry(table, "exten LIKE", "\\_%", "context", context, "priority", pri, SENTINEL);   
00189       if (cfg) {
00190          char *cat = ast_category_browse(cfg, NULL);
00191 
00192          while(cat) {
00193             switch(mode) {
00194             case MODE_MATCHMORE:
00195                match = ast_extension_close(cat, exten, 1);
00196                break;
00197             case MODE_CANMATCH:
00198                match = ast_extension_close(cat, exten, 0);
00199                break;
00200             case MODE_MATCH:
00201             default:
00202                match = ast_extension_match(cat, exten);
00203             }
00204             if (match) {
00205                var = ast_category_detach_variables(ast_category_get(cfg, cat));
00206                break;
00207             }
00208             cat = ast_category_browse(cfg, cat);
00209          }
00210          ast_config_destroy(cfg);
00211       }
00212    }
00213    return var;
00214 }

static int unload_module ( void   )  [static]

Definition at line 396 of file pbx_realtime.c.

References ao2_ref, ast_unregister_switch(), cache, cleanup_thread, and realtime_switch.

00397 {
00398    ast_unregister_switch(&realtime_switch);
00399    pthread_cancel(cleanup_thread);
00400    pthread_kill(cleanup_thread, SIGURG);
00401    pthread_join(cleanup_thread, NULL);
00402    /* Destroy all remaining entries */
00403    ao2_ref(cache, -1);
00404    return 0;
00405 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Realtime Switch" , .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 422 of file pbx_realtime.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 422 of file pbx_realtime.c.

struct ao2_container* cache

Definition at line 75 of file pbx_realtime.c.

Referenced by cleanup(), load_module(), realtime_common(), and unload_module().

pthread_t cleanup_thread = 0

Definition at line 76 of file pbx_realtime.c.

Referenced by load_module(), realtime_common(), and unload_module().

struct ast_switch realtime_switch [static]

Definition at line 386 of file pbx_realtime.c.

Referenced by load_module(), and unload_module().

struct ast_app_option switch_opts[128] = { [ 'p' ] = { .flag = OPTION_PATTERNS_DISABLED },} [static]

Definition at line 65 of file pbx_realtime.c.

Referenced by realtime_common().


Generated on Mon Jun 27 16:51:18 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7