82#define HINTDEVICE_DATA_LENGTH 16
123#define EXTENSION_STATE_BUCKETS 17
125#define EXTENSION_STATE_BUCKETS 563
195 size_t context_len = strlen(
context) + 1;
196 size_t extension_len = strlen(
extension) + 1;
199 update_message =
ao2_alloc_options(
sizeof(*update_message) + context_len + extension_len,
201 if (!update_message) {
214 return update_message;
255 strcpy(info->device,
device);
299 if (!device_snapshot) {
303 device_snapshot->
state = device_state;
313 if (causing_device && source->
info == causing_device) {
320 return device_snapshot;
342 unsigned int updated = 0;
352 if (device_state->
eid) {
365 if (!extension_device_state_info) {
383 ao2_ref(extension_device_state_info, -1);
410 extension_device_state_info);
411 if (!device_snapshot) {
417 state->device_snapshot, device_snapshot,
state->presence_snapshot,
state->presence_snapshot);
423 if (!update_message) {
534 if (!presence_snapshot) {
543 ao2_ref(presence_snapshot, -1);
550 ao2_ref(presence_snapshot, -1);
555 return presence_snapshot;
567#define DEVICE_SOURCE_ELEM_VERSION_CMP(elem, value) ((elem)->version != (value))
583 char *
devices, *device, *presence_state_sources;
599 presence_state_sources = strchr(
devices,
',');
600 if (presence_state_sources) {
601 *presence_state_sources++ =
'\0';
621 if (!strcmp(existing_source->
info->
device, device)) {
622 source = existing_source;
651 if (
state->device_snapshot->state != new_device_state) {
654 if (!device_snapshot) {
656 device_snapshot =
state->device_snapshot;
660 if ((!
state->presence_sources_string && presence_state_sources) ||
661 (
state->presence_sources_string && strcmp(
state->presence_sources_string, presence_state_sources))) {
663 char *presence_subtype =
NULL, *presence_message =
NULL;
681 if (!presence_snapshot) {
683 presence_snapshot =
state->presence_snapshot;
687 if (
state->device_snapshot != device_snapshot ||
state->presence_snapshot != presence_snapshot) {
691 device_snapshot,
state->presence_snapshot, presence_snapshot);
692 if (update_message) {
704 if (
state->device_snapshot != device_snapshot) {
708 if (
state->presence_snapshot != presence_snapshot) {
710 ao2_ref(presence_snapshot, -1);
753 size_t context_len = strlen(context) + 1;
754 size_t extension_len = strlen(
extension) + 1;
760 if (!remove_message) {
792 if (!
state->extension_state_topic) {
798 state->dialplan_extension);
799 if (remove_message) {
839 char *presence_subtype, *presence_message;
850 if (!
state->presence_sources_string || !
strcasestr(
state->presence_sources_string, presence_state->provider)) {
869 if ((
state->presence_snapshot->presence_state == presence_state_new) &&
870 ((!presence_subtype && !
state->presence_snapshot->presence_subtype) ||
871 (presence_subtype &&
state->presence_snapshot->presence_subtype &&
872 !strcmp(presence_subtype,
state->presence_snapshot->presence_subtype))) &&
873 ((!presence_message && !
state->presence_snapshot->presence_message) ||
874 (presence_message &&
state->presence_snapshot->presence_message &&
875 !strcmp(presence_message,
state->presence_snapshot->presence_message)))) {
884 if (!presence_snapshot) {
892 state->dialplan_extension,
state->device_snapshot,
state->device_snapshot,
state->presence_snapshot, presence_snapshot);
894 ao2_ref(presence_snapshot, -1);
895 if (update_message) {
929 char *extension_state_topic_name;
952 if (!
state->device_snapshot || !
state->presence_snapshot) {
961 state->hint_extension = exten;
980 ast_free(extension_state_topic_name);
981 if (!
state->extension_state_topic) {
987 if (!
state->extension_state_forwarder) {
1015 snprintf(location,
sizeof(location),
"%s@%s",
extension, context);
1076 struct timeval chantime = {0, };
1078 switch (device_state) {
1103 snprintf(
match,
sizeof(
match),
"%s-", device);
1203 if (
state->extension[0] ==
'_') {
1219 "StatusText: %s\r\n\r\n",
1220 state->dialplan_extension,
1221 state->dialplan_context,
1223 state->device_snapshot->state,
1252 ast_log(
LOG_WARNING,
"Could not create extension state for hint '%s', it will be unavailable\n",
1260 state->hint_extension = exten;
1281 if (!
state ||
state->hint_extension != exten) {
1318 const char *exten,
const char *context)
1333 return device_snapshot;
1337 const char *exten,
const char *context)
1352 return presence_snapshot;
1373 e->
command =
"core show hints";
1375 "Usage: core show hints\n"
1376 " List registered hints.\n"
1377 " Hint details are shown in five columns. In order from left to right, they are:\n"
1378 " 1. Hint extension URI.\n"
1379 " 2. List of mapped device or presence state identifiers.\n"
1380 " 3. Current extension state. The aggregate of mapped device states.\n"
1381 " 4. Current presence state for the mapped presence state provider.\n"
1382 " 5. Watchers - number of subscriptions and other entities watching this hint.\n";
1389 ast_cli(
a->fd,
"There are no registered dialplan hints\n");
1393 ast_cli(
a->fd,
"\n -= Registered Asterisk Dial Plan Hints =-\n");
1398 ast_cli(
a->fd,
"%-30.30s: %-60.60s State:%-15.15s Presence:%-15.15s Watchers %2zd\n",
1410 ast_cli(
a->fd,
"----------------\n");
1411 ast_cli(
a->fd,
"- %d hints registered\n", num);
1437 wordlen = strlen(
word);
1469 int num = 0, extenlen;
1474 e->
command =
"core show hint";
1476 "Usage: core show hint <exten>\n"
1477 " List registered hint.\n"
1478 " Hint details are shown in five columns. In order from left to right, they are:\n"
1479 " 1. Hint extension URI.\n"
1480 " 2. List of mapped device or presence state identifiers.\n"
1481 " 3. Current extension state. The aggregate of mapped device states.\n"
1482 " 4. Current presence state for the mapped presence state provider.\n"
1483 " 5. Watchers - number of subscriptions and other entities watching this hint.\n";
1493 ast_cli(
a->fd,
"There are no registered dialplan hints\n");
1497 extenlen = strlen(
a->argv[3]);
1501 if (!strncasecmp(extstate->
extension,
a->argv[3], extenlen)) {
1502 ast_cli(
a->fd,
"%-30.30s: %-60.60s State:%-15.15s Presence:%-15.15s Watchers %2zd\n",
1514 ast_cli(
a->fd,
"No hints matching extension %s\n",
a->argv[3]);
1516 ast_cli(
a->fd,
"%d hint%s matching extension %s\n", num, (num!=1 ?
"s":
""),
a->argv[3]);
1572 extension_state_sort_fn, extension_state_cmp_fn);
1586 ast_log(
LOG_ERROR,
"Failed to create subscription to receive presence state updates\n");
Prototypes for public functions only of internal interest,.
void ast_cli_unregister_multiple(void)
char * strsep(char **str, const char *delims)
char * strcasestr(const char *, const char *)
Asterisk main include file. File version handling, generic pbx functions.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
#define ast_strdup(str)
A wrapper for strdup()
void ast_free_ptr(void *ptr)
free() wrapper
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
#define ast_calloc(num, len)
A wrapper for calloc()
#define ao2_iterator_next(iter)
@ AO2_ALLOC_OPT_LOCK_NOLOCK
@ AO2_ALLOC_OPT_LOCK_MUTEX
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define AO2_STRING_FIELD_CMP_FN(stype, field)
Creates a compare function for a structure string field.
#define ao2_unlink_flags(container, obj, flags)
Remove an object from a container.
#define ao2_link_flags(container, obj, flags)
Add an object to a container.
#define ao2_find(container, arg, flags)
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define AO2_STRING_FIELD_SORT_FN(stype, field)
Creates a sort function for a structure string field.
#define ao2_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a red-black tree container.
#define ao2_replace(dst, src)
Replace one object reference with another cleaning up the original.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define ao2_alloc_options(data_size, destructor_fn, options)
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
@ OBJ_NOLOCK
Assume that the ao2_container is already locked.
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
#define ao2_alloc(data_size, destructor_fn)
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
static char version[AST_MAX_EXTENSION]
struct ast_channel_iterator * ast_channel_iterator_by_name_new(const char *name, size_t name_len)
Create a new channel iterator based on name.
struct ast_channel_iterator * ast_channel_iterator_destroy(struct ast_channel_iterator *i)
Destroy a channel iterator.
#define ast_channel_lock(chan)
struct ast_channel * ast_channel_iterator_next(struct ast_channel_iterator *i)
Get the next channel for a channel iterator.
#define ast_channel_ref(c)
Increase channel reference count.
struct timeval ast_channel_creationtime(struct ast_channel *chan)
#define ast_channel_unref(c)
Decrease channel reference count.
#define ast_channel_unlock(chan)
#define AST_MAX_EXTENSION
ast_channel_state
ast_channel states
Standard Command Line Interface.
#define AST_CLI_DEFINE(fn, txt,...)
void ast_cli(int fd, const char *fmt,...)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
void ast_devstate_aggregate_add(struct ast_devstate_aggregate *agg, enum ast_device_state state)
Add a device state to the aggregate device state.
void ast_devstate_aggregate_init(struct ast_devstate_aggregate *agg)
Initialize aggregate device state.
enum ast_device_state ast_devstate_aggregate_result(struct ast_devstate_aggregate *agg)
Get the aggregate device state result.
struct stasis_topic * ast_device_state_topic(const char *device)
Get the Stasis topic for device state messages for a specific device.
ast_device_state
Device States.
static void extension_state_destroy(void *obj)
static struct stasis_topic * extension_state_topic_all
Topic which receives all extension state updates.
static void extension_state_device_source_destroy(struct extension_state_device_source *source)
const char * ast_extension_state2str(int extension_state)
Return string representation of the state of an extension.
static struct ast_cli_entry extension_state_cli[]
static void extension_state_update_message_destroy(void *obj)
static int action_extensionstatelist(struct mansession *s, const struct message *m)
static struct stasis_subscription * presence_state_sub
Single presence state subscription, for all extension states.
static void extension_state_device_snapshot_destroy(void *obj)
static int extension_state_update_sources(struct extension_state *state, struct ast_exten *exten)
static void extension_state_presence_state_cb(void *unused, struct stasis_subscription *sub, struct stasis_message *msg)
static void extension_state_device_state_cb(void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
enum ast_extension_states ast_devstate_to_extenstate(enum ast_device_state devstate)
Map devstate to an extension state.
static const struct cfextension_states extension_state_mappings[]
static char * complete_core_show_hint(const char *line, const char *word, int pos, int state)
void pbx_extension_state_hint_set(struct ast_exten *exten, struct ast_context *context)
struct ast_extension_state_device_snapshot * ast_extension_state_get_latest_device_snapshot(struct ast_channel *chan, const char *exten, const char *context)
Get the latest device state message for an extension.
static char * handle_show_hints(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct ast_extension_state_update_message * extension_state_update_message_create(const char *context, const char *extension, struct ast_extension_state_device_snapshot *old_device_snapshot, struct ast_extension_state_device_snapshot *new_device_snapshot, struct ast_extension_state_presence_snapshot *old_presence_snapshot, struct ast_extension_state_presence_snapshot *new_presence_snapshot)
int ast_extension_state_init(void)
static struct extension_state_device_source * extension_state_device_source_alloc(struct extension_state *state, const char *device)
#define HINTDEVICE_DATA_LENGTH
#define DEVICE_SOURCE_ELEM_VERSION_CMP(elem, value)
device source non-matching version comparator for AST_VECTOR_REMOVE_CMP_UNORDERED()
static struct extension_state * extension_state_alloc(struct ast_exten *exten, struct ast_context *context)
struct ast_extension_state_presence_snapshot * ast_extension_state_get_latest_presence_snapshot(struct ast_channel *chan, const char *exten, const char *context)
Get the latest presence state message for an extension.
static char * handle_show_hint(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct extension_state * extension_state_get(struct ast_channel *chan, const char *context, const char *extension)
static struct ast_extension_state_presence_snapshot * extension_state_presence_snapshot_create(enum ast_presence_state presence_state, const char *presence_subtype, const char *presence_message)
static void extension_state_cleanup(void)
static void extension_state_shutdown(struct extension_state *state)
static struct stasis_message * extension_state_remove_message_create(const char *context, const char *extension)
static void extension_state_presence_snapshot_destroy(void *obj)
struct stasis_topic * ast_extension_state_topic(const char *exten, const char *context)
Get the Stasis topic to receive extension state messages for a specific extension.
struct stasis_topic * ast_extension_state_topic_all(void)
Get the Stasis topic to receive all extension state messages.
static struct ast_extension_state_device_snapshot * extension_state_device_snapshot_create(enum ast_extension_states device_state, struct device_state_sources_vector *device_state_sources, struct ast_extension_state_device_state_info *causing_device)
static struct ast_extension_state_device_state_info * extension_state_device_state_info_alloc(const char *device, enum ast_device_state state)
static int extension_state_cleanup_individual(void *obj, void *arg, int flags)
struct ast_channel * ast_extension_state_get_device_causing_channel(const char *device, enum ast_device_state device_state)
Get the channel that is causing the device to be in the given state, if any.
void pbx_extension_state_hint_remove(struct ast_exten *exten, struct ast_context *context)
static struct ao2_container * extension_states
The global container of extension states.
struct stasis_message_type * ast_extension_state_update_message_type(void)
Get extension state update message type.
struct stasis_message_type * ast_extension_state_remove_message_type(void)
Get extension state remove message type.
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
void astman_append(struct mansession *s, const char *fmt,...)
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
#define EVENT_FLAG_REPORTING
#define ast_manager_register_xml_core(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Asterisk module definitions.
Core PBX routines and definitions.
void * ast_get_extension_app_data(struct ast_exten *e)
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.
int ast_wrlock_contexts(void)
Write locks the context list.
int ast_get_extension_matchcid(struct ast_exten *e)
const char * ast_get_extension_app(struct ast_exten *e)
const char * ast_get_extension_cidmatch(struct ast_exten *e)
const char * ast_get_extension_label(struct ast_exten *e)
ast_extension_states
Extension states.
@ AST_EXTENSION_NOT_INUSE
@ AST_EXTENSION_UNAVAILABLE
const char * ast_get_context_name(struct ast_context *con)
struct ast_exten * pbx_find_extension(struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
int ast_unlock_contexts(void)
Unlocks contexts.
const char * ast_get_extension_name(struct ast_exten *exten)
const char * ast_get_extension_registrar(struct ast_exten *e)
Private include file for pbx.
struct stasis_topic * ast_presence_state_topic_all(void)
Get presence state topic.
const char * ast_presence_state2str(enum ast_presence_state state)
Convert presence state to text string for output.
struct stasis_message_type * ast_presence_state_message_type(void)
Get presence state message type.
static struct stasis_subscription * sub
Statsd channel stats. Exmaple of how to subscribe to Stasis events.
Stasis Message Bus API. See Stasis Message Bus API for detailed documentation.
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
@ STASIS_SUBSCRIPTION_FILTER_SELECTIVE
struct stasis_forward * stasis_forward_cancel(struct stasis_forward *forward)
struct stasis_topic * stasis_topic_create(const char *name)
Create a new topic.
#define stasis_subscribe_synchronous(topic, callback, data)
size_t stasis_topic_subscribers(const struct stasis_topic *topic)
Return the number of subscribers of a topic.
int stasis_subscription_accept_message_type(struct stasis_subscription *subscription, const struct stasis_message_type *type)
Indicate to a subscription that we are interested in a message type.
int stasis_subscription_set_filter(struct stasis_subscription *subscription, enum stasis_subscription_message_filter filter)
Set the message type filtering level on a subscription.
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
#define STASIS_MESSAGE_TYPE_DEFN(name,...)
Boiler-plate messaging macro for defining public message types.
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
struct stasis_subscription * stasis_unsubscribe(struct stasis_subscription *subscription)
Cancel a subscription.
struct stasis_forward * stasis_forward_all(struct stasis_topic *from_topic, struct stasis_topic *to_topic)
Create a subscription which forwards all messages from one topic to another.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
#define stasis_subscribe(topic, callback, data)
static force_inline int attribute_pure ast_strlen_zero(const char *s)
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Main Channel structure associated with a channel.
descriptor for a cli entry.
ast_context: An extension context
The structure that contains device state.
enum ast_device_state state
const struct ast_eid * eid
The EID of the server where this message originated.
You shouldn't care about the contents of this struct.
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own link...
Device snapshot for an extension state.
struct ast_extension_state_device_snapshot::@232 additional_devices
Vector of additional device states that contributed to update.
struct ast_extension_state_device_state_info * causing_device
The device that caused this update.
enum ast_extension_states state
The state of the extension.
Individual device states that contributed to snapshot.
enum ast_device_state state
The state of the device.
char device[0]
The name of the device.
Presence snapshot for an extension state.
char * presence_subtype
The subtype of the presence state.
char * presence_message
An optional message for the presence.
enum ast_presence_state presence_state
The presence state of the extension.
Stasis message for extension state removal message.
char * context
The dialplan context.
char extension[0]
The dialplan extension.
Stasis message for extension state update message.
char * context
The dialplan context.
struct ast_extension_state_presence_snapshot * old_presence_snapshot
The old presence snapshot.
char extension[0]
The dialplan extension.
struct ast_extension_state_device_snapshot * old_device_snapshot
The old device snapshot.
struct ast_extension_state_presence_snapshot * new_presence_snapshot
The new presence snapshot - will be pointer equivalent to old if unchanged.
struct ast_extension_state_device_snapshot * new_device_snapshot
The new device snapshot - will be pointer equivalent to old if unchanged.
Stasis message payload representing a presence state update.
Support for dynamic strings.
Device state source feeding an extension state.
struct stasis_subscription * device_state_subscription
Synchronous subscription to the device state topic.
unsigned int version
The current version for this source.
struct ast_extension_state_device_state_info * info
The current state of the device - this is immutable.
Extension state information.
struct ast_extension_state_device_snapshot * device_snapshot
The current device snapshot for the extension.
struct stasis_forward * extension_state_forwarder
Forwarder from per-extension topic to all topic.
struct device_state_sources_vector device_state_sources
Device state sources feeding the hint topic, and their forwarding.
char * presence_sources_string
The string representation of all presence state sources feeding this extension state.
char extension[0]
The combined extension this state is for (extension@context)
char dialplan_extension[AST_MAX_EXTENSION]
The dialplan extension.
struct stasis_topic * extension_state_topic
The extension state topic for this extension.
char dialplan_context[AST_MAX_CONTEXT]
The dialplan context.
struct ast_extension_state_presence_snapshot * presence_snapshot
The current presence snapshot for the extension.
struct ast_exten * hint_extension
The dialplan hint that last configured this extension state.
structure to hold extensions
In case you didn't read that giant block of text above the mansession_session struct,...
const char * foundcontext
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
int ast_tvcmp(struct timeval _a, struct timeval _b)
Compress two struct timeval instances returning -1, 0, 1 if the first arg is smaller,...
long int ast_random(void)
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
#define AST_VECTOR_REMOVE_ALL_CMP_UNORDERED(vec, value, cmp, cleanup)
Remove all elements from a vector that matches the given comparison.
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
#define AST_VECTOR_CALLBACK_VOID(vec, callback,...)
Execute a callback on every element in a vector disregarding callback return.
#define AST_VECTOR(name, type)
Define a vector structure.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.