53 #include "asterisk/stasis_channels.h"
56 #define MODE_MATCHMORE 1
57 #define MODE_CANMATCH 2
59 #define EXT_DATA_SIZE 256
62 OPTION_PATTERNS_DISABLED = (1 << 0),
78 pthread_t cleanup_thread = 0;
80 static int cache_hash(
const void *obj,
const int flags)
86 static int cache_cmp(
void *obj,
void *arg,
int flags)
89 return e->priority != f->priority ? 0 :
90 strcmp(e->exten, f->exten) ? 0 :
91 strcmp(e->context, f->context) ? 0 :
98 for (; v; v = v->
next) {
111 static void free_entry(
void *obj)
117 static int purge_old_fn(
void *obj,
void *arg,
int flags)
120 struct timeval *now = arg;
124 static void *
cleanup(
void *unused)
126 struct timespec forever = { 999999999, 0 }, one_second = { 1, 0 };
130 pthread_testcancel();
132 nanosleep(&forever, NULL);
134 pthread_testcancel();
137 pthread_testcancel();
138 nanosleep(&one_second, NULL);
149 return strlen(extenp) - strlen(extenq);
166 static struct ast_variable *realtime_switch_common(
const char *table,
const char *context,
const char *exten,
int priority,
int mode,
struct ast_flags flags)
180 snprintf(pri,
sizeof(pri),
"%d", priority);
183 ematch =
"exten LIKE";
184 snprintf(rexten,
sizeof(rexten),
"%s_%%", exten);
187 ematch =
"exten LIKE";
188 snprintf(rexten,
sizeof(rexten),
"%s%%", exten);
195 var = ast_load_realtime(table, ematch, rexten,
"context", context,
"priority", pri, SENTINEL);
196 if (!var && !ast_test_flag(&flags, OPTION_PATTERNS_DISABLED)) {
205 const char *realtime_exten = ast_variable_retrieve(cfg, cat,
"exten");
209 match = ast_extension_close(realtime_exten, exten, 1);
212 match = ast_extension_close(realtime_exten, exten, 0);
229 static struct ast_variable *realtime_common(
const char *context,
const char *exten,
int priority,
const char *data,
int mode)
231 const char *ctx = NULL;
239 } cache_search = { { .priority = priority, .context = (
char *) context }, };
243 char *opts = strchr(buf,
'/');
246 table = strchr(buf,
'@');
251 ctx =
S_OR(ctx, context);
252 table =
S_OR(table,
"extensions");
253 if (!ast_strlen_zero(opts)) {
256 ast_copy_string(cache_search.exten, exten,
sizeof(cache_search.exten));
257 if (mode == MODE_MATCH && (ce = ao2_find(cache, &cache_search,
OBJ_POINTER))) {
258 var = dup_vars(ce->var);
261 var = realtime_switch_common(table, ctx, exten, priority, mode, flags);
265 if (mode != MODE_MATCH) {
268 if (!(
new = dup_vars(var))) {
271 if (!(ce = ao2_alloc(
sizeof(*ce) + strlen(exten) + strlen(context), free_entry))) {
275 ce->context = ce->exten + strlen(exten) + 1;
276 strcpy(ce->exten, exten);
277 strcpy(ce->context, context);
278 ce->priority = priority;
282 pthread_kill(cleanup_thread, SIGURG);
289 static int realtime_exists(
struct ast_channel *chan,
const char *context,
const char *exten,
int priority,
const char *callerid,
const char *data)
291 struct ast_variable *var = realtime_common(context, exten, priority, data, MODE_MATCH);
299 static int realtime_canmatch(
struct ast_channel *chan,
const char *context,
const char *exten,
int priority,
const char *callerid,
const char *data)
301 struct ast_variable *var = realtime_common(context, exten, priority, data, MODE_CANMATCH);
309 static int realtime_exec(
struct ast_channel *chan,
const char *context,
const char *exten,
int priority,
const char *callerid,
const char *data)
312 struct ast_variable *var = realtime_common(context, exten, priority, data, MODE_MATCH);
315 char *appdata_tmp =
"";
319 for (v = var; v ; v = v->
next) {
320 if (!strcasecmp(v->
name,
"app"))
322 else if (!strcasecmp(v->
name,
"appdata")) {
327 if (!ast_strlen_zero(app)) {
336 if(!ast_strlen_zero(appdata_tmp))
337 pbx_substitute_variables_helper(chan, appdata_tmp, appdata,
sizeof(appdata) - 1);
338 ast_verb(3,
"Executing [%s@%s:%d] %s(\"%s\", \"%s\")\n",
339 ast_channel_exten(chan), ast_channel_context(chan), ast_channel_priority(chan),
340 term_color(tmp1, app, COLOR_BRCYAN, 0,
sizeof(tmp1)),
341 term_color(tmp2, ast_channel_name(chan), COLOR_BRMAGENTA, 0,
sizeof(tmp2)),
342 term_color(tmp3,
S_OR(appdata,
""), COLOR_BRMAGENTA, 0,
sizeof(tmp3)));
347 ast_channel_lock(chan);
359 tmp_appl = ast_channel_appl(chan) ?
ast_strdupa(ast_channel_appl(chan)) : NULL;
360 tmp_data = ast_channel_data(chan) ?
ast_strdupa(ast_channel_data(chan)) : NULL;
362 ast_channel_appl_set(chan, app);
363 ast_channel_data_set(chan, !ast_strlen_zero(appdata) ? appdata :
"(NULL)");
367 ast_channel_appl_set(chan, tmp_appl);
368 ast_channel_data_set(chan, tmp_data);
370 ast_channel_unlock(chan);
374 ast_log(LOG_NOTICE,
"No such application '%s' for extension '%s' in context '%s'\n", app, exten, context);
376 ast_log(LOG_WARNING,
"No application specified for realtime extension '%s' in context '%s'\n", exten, context);
382 static int realtime_matchmore(
struct ast_channel *chan,
const char *context,
const char *exten,
int priority,
const char *callerid,
const char *data)
384 struct ast_variable *var = realtime_common(context, exten, priority, data, MODE_MATCHMORE);
395 .description =
"Realtime Dialplan Switch",
396 .exists = realtime_exists,
397 .canmatch = realtime_canmatch,
398 .exec = realtime_exec,
399 .matchmore = realtime_matchmore,
402 static int unload_module(
void)
405 pthread_cancel(cleanup_thread);
406 pthread_kill(cleanup_thread, SIGURG);
407 pthread_join(cleanup_thread, NULL);
413 static int load_module(
void)
416 cache_hash, NULL, cache_cmp);
421 if (ast_pthread_create(&cleanup_thread, NULL,
cleanup, NULL)) {
struct ast_variable * next
Main Channel structure associated with a channel.
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
void ast_channel_snapshot_invalidate_segment(struct ast_channel *chan, enum ast_channel_snapshot_segment_invalidation segment)
Invalidate a channel snapshot segment from being reused.
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
Structure for variables, used for configurations and for channel variables.
void ast_unregister_switch(struct ast_switch *sw)
Unregister an alternative switch.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
I/O Management (derived from Cheops-NG)
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
Configuration File Parser.
static void cleanup(void)
Clean up any old apps that we don't need any more.
General Asterisk PBX channel definitions.
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define AST_MAX_EXTENSION
Scheduler Routines (derived from cheops)
Asterisk internal frame definitions.
A set of macros to manage forward-linked lists.
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Core PBX routines and definitions.
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Colorize a specified string by adding terminal color codes.
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
struct ast_config * ast_load_realtime_multientry(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
int ast_extension_match(const char *pattern, const char *extension)
Determine if a given extension matches a given pattern (in NXX format)
int ast_register_switch(struct ast_switch *sw)
Register an alternative dialplan switch.
Module could not be loaded properly.
Support for logging to various files, console and syslog Configuration in file logger.conf.
const char * ast_variable_find(const struct ast_category *category, const char *variable)
Gets a variable value from a specific category structure by name.
struct stasis_message_type * ast_channel_snapshot_type(void)
Message type for ast_channel_snapshot_update.
Structure used to handle boolean flags.
void ast_config_sort_categories(struct ast_config *config, int descending, int(*comparator)(struct ast_category *p, struct ast_category *q))
Sorts categories in a config in the order of a numerical value contained within them.
Standard Command Line Interface.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
ast_app: A registered application
Handy terminal functions for vt* terms.
void ast_channel_publish_snapshot(struct ast_channel *chan)
Publish a ast_channel_snapshot for a channel.
static struct sorcery_test_caching cache
Global scope caching structure for testing.
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
struct ast_category * ast_category_get(const struct ast_config *config, const char *category_name, const char *filter)
Retrieve a category if it exists.
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
struct ast_app * pbx_findapp(const char *app)
Look up an application.
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
Persistent data storage (akin to *doze registry)
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
static force_inline int attribute_pure ast_str_case_hash(const char *str)
Compute a hash value on a case-insensitive string.
#define ao2_link(container, obj)
Add an object to a container.