44 #define AST_API_MODULE
93 static const char context_name[] =
"__func_periodic_hook_context__";
94 static const char exten_name[] =
"hook";
95 static const char full_exten_name[] =
"hook@__func_periodic_hook_context__";
97 static const char beep_exten[] =
"beep";
129 static void hook_datastore_destroy_callback(
void *data)
139 ast_free(state->
exten);
145 .destroy = hook_datastore_destroy_callback,
165 ast_free(arg->
exten);
169 static void *hook_launch_thread(
void *data)
177 .
name =
"HOOK_CHANNEL",
184 NULL, NULL, &chan_name_var, NULL, NULL, 1, NULL);
186 hook_thread_arg_destroy(arg);
200 ast_channel_lock(chan);
202 ast_channel_unlock(chan);
204 hook_thread_arg_destroy(arg);
209 hook_thread_arg_destroy(arg);
214 hook_thread_arg_destroy(arg);
219 hook_thread_arg_destroy(arg);
232 if (!(arg = hook_thread_arg_alloc(chan, state))) {
240 res = ast_pthread_create_detached_background(&t, NULL, hook_launch_thread, arg);
242 hook_thread_arg_destroy(arg);
261 if ((res = do_hook(chan, state))) {
263 ast_channel_lock(chan);
265 ast_channel_unlock(chan);
266 ast_log(LOG_WARNING,
"Failed to run hook on '%s'\n", name);
279 if (!(state =
ast_calloc(1,
sizeof(*state)))) {
295 static int init_hook(
struct ast_channel *chan,
const char *context,
const char *exten,
296 unsigned int interval,
unsigned int hook_id)
302 snprintf(uid,
sizeof(uid),
"%u", hook_id);
304 if (!(datastore = ast_datastore_alloc(&hook_datastore, uid))) {
308 if (!(state = hook_state_alloc(context, exten, interval, hook_id))) {
312 datastore->
data = state;
314 ast_channel_lock(chan);
317 ast_channel_unlock(chan);
322 static int hook_on(
struct ast_channel *chan,
const char *
data,
unsigned int hook_id)
330 unsigned int interval;
334 if (ast_strlen_zero(args.interval) ||
335 sscanf(args.interval,
"%30u", &interval) != 1 || interval == 0) {
336 ast_log(LOG_WARNING,
"Invalid hook interval: '%s'\n",
S_OR(args.interval,
""));
340 if (ast_strlen_zero(args.context) || ast_strlen_zero(args.exten)) {
341 ast_log(LOG_WARNING,
"A context and extension are required for PERIODIC_HOOK().\n");
345 ast_debug(1,
"hook to %s@%s enabled on %s with interval of %u seconds\n",
346 args.exten, args.context, ast_channel_name(chan), interval);
348 args.exten, ast_channel_name(chan), interval);
350 return init_hook(chan, args.context, args.exten, interval, hook_id);
353 static int hook_off(
struct ast_channel *chan,
const char *hook_id)
358 if (ast_strlen_zero(hook_id)) {
362 ast_channel_lock(chan);
365 ast_log(LOG_WARNING,
"Hook with ID '%s' not found on channel '%s'\n", hook_id,
366 ast_channel_name(chan));
367 ast_channel_unlock(chan);
371 state = datastore->
data;
374 ast_channel_unlock(chan);
379 static int hook_read(
struct ast_channel *chan,
const char *cmd,
char *data,
380 char *buf,
size_t len)
390 snprintf(buf, len,
"%u", hook_id);
392 return hook_on(chan, data, hook_id);
395 static int hook_re_enable(
struct ast_channel *chan,
const char *uid)
400 if (ast_strlen_zero(uid)) {
404 ast_channel_lock(chan);
407 ast_log(LOG_WARNING,
"Hook with ID '%s' not found on '%s'\n",
408 uid, ast_channel_name(chan));
409 ast_channel_unlock(chan);
413 state = datastore->
data;
416 ast_channel_unlock(chan);
421 static int hook_write(
struct ast_channel *chan,
const char *cmd,
char *data,
431 res = hook_off(chan, data);
433 res = hook_re_enable(chan, data);
435 ast_log(LOG_WARNING,
"Invalid value for PERIODIC_HOOK function: '%s'\n", value);
443 .
name =
"PERIODIC_HOOK",
448 static int unload_module(
void)
456 static int load_module(
void)
461 ast_log(LOG_ERROR,
"Failed to create %s dialplan context.\n", context_name);
469 "Set",
"EncodedChannel=${HOOK_CHANNEL}",
472 "Set",
"GROUP_NAME=${EncodedChannel}${HOOK_ID}",
475 "Set",
"GROUP(periodic-hook)=${GROUP_NAME}",
478 "$[${GROUP_COUNT(${GROUP_NAME}@periodic-hook)} > 1]?Hangup()",
481 "Set",
"ChannelToSpy=${URIDECODE(${EncodedChannel})}",
484 "ChanSpy",
"${ChannelToSpy},qEB", NULL, AST_MODULE);
487 "Answer",
"", NULL, AST_MODULE);
489 "Playback",
"beep", NULL, AST_MODULE);
491 "Hangup",
"", NULL, AST_MODULE);
503 unsigned int interval,
char *beep_id,
size_t len)
507 snprintf(args,
sizeof(args),
"%s,%s,%u",
508 context_name, beep_exten, interval);
510 if (hook_read(chan, NULL, args, beep_id, len)) {
511 ast_log(LOG_WARNING,
"Failed to enable periodic beep.\n");
520 return hook_write(chan, NULL, (
char *) beep_id,
"off");
523 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS,
"Periodic dialplan hooks.",
524 .support_level = AST_MODULE_SUPPORT_CORE,
526 .unload = unload_module,
527 .requires =
"app_chanspy,func_cut,func_groupcount,func_uri",
struct ast_audiohook audiohook
audiohook used as a callback into this module
Main Channel structure associated with a channel.
Asterisk main include file. File version handling, generic pbx functions.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
Structure for variables, used for configurations and for channel variables.
Structure for a data store type.
int ast_audiohook_attach(struct ast_channel *chan, struct ast_audiohook *audiohook)
Attach audiohook to channel.
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.
#define ast_strdup(str)
A wrapper for strdup()
Structure for a data store object.
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
int ast_pbx_outgoing_exten(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, int early_media, const struct ast_assigned_ids *assignedids)
Synchronously or asynchronously make an outbound call and send it to a particular extension...
int ast_audiohook_destroy(struct ast_audiohook *audiohook)
Destroys an audiohook structure.
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Periodic beeps into the audio of a call.
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
ast_audiohook_manipulate_callback manipulate_callback
int ast_audiohook_init(struct ast_audiohook *audiohook, enum ast_audiohook_type type, const char *source, enum ast_audiohook_init_flags flags)
Initialize an audiohook structure.
#define ast_custom_function_register_escalating(acf, escalation)
Register a custom function which requires escalated privileges.
#define ast_audiohook_unlock(ah)
Unlock an audiohook.
General Asterisk PBX channel definitions.
#define ast_strdupa(s)
duplicate a string in memory from the stack
Data structure associated with a custom dialplan function.
#define AST_MAX_EXTENSION
#define ast_debug(level,...)
Log a DEBUG message.
static unsigned int global_hook_id
Last used hook ID.
Core PBX routines and definitions.
#define ast_test_suite_event_notify(s, f,...)
int ast_audiohook_detach(struct ast_audiohook *audiohook)
Detach audiohook from channel.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
#define ast_calloc(num, len)
A wrapper for calloc()
Module has failed to load, may be in an inconsistent state.
int ast_add_extension(const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
Add and extension to an extension context.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"...
Data structure associated with a single frame of data.
void ast_context_destroy(struct ast_context *con, const char *registrar)
Destroy a context (matches the specified context or ANY context if NULL)
enum ast_audiohook_status status
#define AST_OPTIONAL_API_NAME(name)
Expands to the name of the implementation function.
struct ast_context * ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
Register a new context or find an existing one.
#define ASTERISK_GPL_KEY
The text the key() function should return.
#define ast_audiohook_lock(ah)
Lock an audiohook.
Asterisk module definitions.
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
#define AST_APP_ARG(name)
Define an application argument.