158 #define DEVSTATE_TOPIC_BUCKETS 57
162 {
"Unknown",
"UNKNOWN" },
163 {
"Not in use",
"NOT_INUSE" },
164 {
"In use",
"INUSE" },
166 {
"Invalid",
"INVALID" },
167 {
"Unavailable",
"UNAVAILABLE" },
168 {
"Ringing",
"RINGING" },
169 {
"Ring+Inuse",
"RINGINUSE" },
170 {
"On Hold",
"ONHOLD" },
215 static volatile int shuttingdown;
229 .to_ami = devstate_to_ami,
246 for (i = 0; i < ARRAY_LEN(
chan2dev); i++) {
247 if (
chan2dev[i].chan == chanstate) {
262 if (!strcasecmp(val,
"NOT_INUSE"))
264 else if (!strcasecmp(val,
"INUSE"))
266 else if (!strcasecmp(val,
"BUSY"))
268 else if (!strcasecmp(val,
"INVALID"))
270 else if (!strcasecmp(val,
"UNAVAILABLE"))
272 else if (!strcasecmp(val,
"RINGING"))
274 else if (!strcasecmp(val,
"RINGINUSE"))
276 else if (!strcasecmp(val,
"ONHOLD"))
293 snprintf(match,
sizeof(match),
"%s-", device);
321 state = device_state->
state;
322 ao2_cleanup(cached_msg);
338 res = devstate_cached(device);
345 tech = strsep(&number,
"/");
350 provider = strsep(&tech,
":");
357 ast_debug(3,
"Checking if I can find provider for \"%s\" - number: %s\n", provider, number);
361 ast_debug(4,
"No provider found, checking channel drivers for %s - %s\n", tech, number);
396 if (!callback || !(devprov =
ast_calloc(1,
sizeof(*devprov))))
399 devprov->callback = callback;
404 if (!strcasecmp(devcb->label, label)) {
405 ast_log(LOG_WARNING,
"Device state provider '%s' already registered\n", label);
425 if (!strcasecmp(devcb->label, label)) {
426 AST_RWLIST_REMOVE_CURRENT(list);
432 AST_RWLIST_TRAVERSE_SAFE_END;
446 ast_debug(5,
"Checking provider %s with %s\n", devprov->label, provider);
448 if (!strcasecmp(devprov->label, provider)) {
449 res = devprov->callback(address);
493 }
else if (
change_thread == AST_PTHREADT_NULL || !(change =
ast_calloc(1,
sizeof(*change) + strlen(device)))) {
499 strcpy(change->device, device);
500 change->cachable = cachable;
516 vsnprintf(buf,
sizeof(buf), fmt, ap);
527 while (!shuttingdown) {
537 while ((current = next)) {
553 ast_assert(!ast_strlen_zero(device));
555 stuff_len = strlen(device) + 1;
557 stuff_len +=
sizeof(*eid);
559 new_device_state = ao2_alloc_options(
sizeof(*new_device_state) + stuff_len, NULL,
561 if (!new_device_state) {
568 new_device_state->
eid = &new_device_state->
stuff[0];
569 pos = (
char *) &new_device_state->
stuff[1];
571 pos = (
char *) &new_device_state->
stuff[0];
575 new_device_state->
device = pos;
580 return new_device_state;
605 static void device_state_engine_cleanup(
void)
622 ast_log(LOG_ERROR,
"Unable to start device state change thread.\n");
632 memset(agg, 0,
sizeof(*agg));
656 if (agg->ringing && agg->inuse) {
658 }
else if (state_order[state] > state_order[agg->state]) {
670 return device_state_topic_all;
675 return device_state_cache;
705 ao2_cleanup(cached_msg);
719 ast_assert(!ast_strlen_zero(device));
725 device_state = device_state_alloc(device, state, cachable, eid);
774 return device_state->
device;
790 device = device_state_get_id(aggregate);
795 if (!device_specific_topic) {
821 const char *device = NULL;
834 device = device_state->
device;
837 for (idx = 0; ; ++idx) {
844 device = device_state->
device;
870 ao2_cleanup(device_state);
871 if (!aggregate_snapshot) {
876 return aggregate_snapshot;
879 static void devstate_cleanup(
void)
884 ao2_cleanup(device_state_cache);
885 device_state_cache = NULL;
887 ao2_cleanup(device_state_topic_pool);
888 device_state_topic_pool = NULL;
890 ao2_cleanup(device_state_topic_all);
891 device_state_topic_all = NULL;
904 if (!device_state_topic_all) {
908 if (!device_state_topic_pool) {
912 device_state_aggregate_calc, device_state_aggregate_publish);
913 if (!device_state_cache) {
918 if (!device_state_topic_cached) {
925 devstate_change_cb, NULL);
926 if (!devstate_message_sub) {
927 ast_log(LOG_ERROR,
"Failed to create subscription creating uncached device state aggregate events.\n");
943 if (dev_state->
eid) {
965 if (device_state->
eid) {
Struct containing info for an AMI event to send out.
Main Channel structure associated with a channel.
ast_device_state
Device States.
#define AST_LIST_LOCK(head)
Locks a list.
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
int devstate_init(void)
Initialize the device state core.
static int getproviderstate(const char *provider, const char *address)
Get provider device state.
int stasis_caching_accept_message_type(struct stasis_caching_topic *caching_topic, struct stasis_message_type *type)
Indicate to a caching topic that we are interested in a message type.
static struct ast_event * devstate_to_event(struct stasis_message *msg)
Convert a stasis_message to a ast_event.
void ast_devstate_aggregate_init(struct ast_devstate_aggregate *agg)
Initialize aggregate device state.
enum ast_device_state ast_state_chan2dev(enum ast_channel_state chanstate)
Convert channel state to devicestate.
const struct ast_channel_tech * ast_get_channel_tech(const char *name)
Get a channel technology structure by name.
#define ast_channel_unref(c)
Decrease channel reference count.
A device state provider (not a channel)
void ast_devstate_aggregate_add(struct ast_devstate_aggregate *agg, enum ast_device_state state)
Add a device state to the aggregate device state.
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Stasis Message Bus API. See Stasis Message Bus API for detailed documentation.
struct stasis_caching_topic * stasis_caching_topic_create(struct stasis_topic *original_topic, struct stasis_cache *cache)
Create a topic which monitors and caches messages from another topic.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
struct stasis_cache * ast_device_state_cache(void)
Backend cache for ast_device_state_topic_cached()
enum ast_device_state state
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
int ast_devstate_changed(enum ast_device_state state, enum ast_devstate_cache cachable, const char *fmt,...)
Tells Asterisk the State for Device is changed.
enum ast_device_state ast_devstate_val(const char *val)
Convert device state from text to integer value.
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
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 AST_RWLIST_WRLOCK(head)
Write locks a list.
static void do_state_change(const char *device, enum ast_devstate_cache cachable)
ast_channel_state
ast_channel states
struct stasis_message * stasis_cache_clear_create(struct stasis_message *message)
A message which instructs the caching topic to remove an entry from its cache.
enum ast_devstate_cache cachable
struct stasis_message * stasis_cache_entry_get_aggregate(struct stasis_cache_entry *entry)
Get the aggregate cache entry snapshot.
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
struct stasis_message * stasis_cache_get_by_eid(struct stasis_cache *cache, struct stasis_message_type *type, const char *id, const struct ast_eid *eid)
Retrieve an item from the cache for a specific entity.
struct stasis_topic * stasis_topic_pool_get_topic(struct stasis_topic_pool *pool, const char *topic_name)
Find or create a topic in the pool.
int ast_devstate_changed_literal(enum ast_device_state state, enum ast_devstate_cache cachable, const char *device)
Tells Asterisk the State for Device is changed.
An Entity ID is essentially a MAC address, brief and unique.
struct stasis_caching_topic * stasis_caching_unsubscribe_and_join(struct stasis_caching_topic *caching_topic)
Unsubscribes a caching topic from its upstream topic, blocking until all messages have been forwarded...
struct ast_manager_event_blob * ast_manager_event_blob_create(int event_flags, const char *manager_event, const char *extra_fields_fmt,...)
Construct a ast_manager_event_blob.
Entity ID Used by All events Payload type: RAW This IE indicates which server the event originated fr...
int ast_publish_device_state_full(const char *device, enum ast_device_state state, enum ast_devstate_cache cachable, struct ast_eid *eid)
Publish a device state update with EID.
struct ast_channel * ast_channel_get_by_name_prefix(const char *name, size_t name_len)
Find a channel by a name prefix.
struct stasis_topic_pool * stasis_topic_pool_create(struct stasis_topic *pooled_topic)
Create a topic pool that routes messages from dynamically generated topics to the given topic...
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
int ast_device_state_engine_init(void)
Initialize the device state engine in separate thread.
struct stasis_topic * ast_device_state_topic_all(void)
Get the Stasis topic for device state messages.
General Asterisk PBX channel definitions.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
const struct ast_eid * eid
The EID of the server where this message originated.
#define ast_strdupa(s)
duplicate a string in memory from the stack
int ast_devstate_prov_del(const char *label)
Remove device state provider.
int stasis_topic_pool_topic_exists(const struct stasis_topic_pool *pool, const char *topic_name)
Check if a topic exists in a pool.
#define AST_MAX_EXTENSION
int ast_devstate_prov_add(const char *label, ast_devstate_prov_cb_type callback)
Add device state provider.
struct stasis_cache * stasis_cache_create_full(snapshot_get_id id_fn, cache_aggregate_calc_fn aggregate_calc_fn, cache_aggregate_publish_fn aggregate_publish_fn)
Create a cache.
A set of macros to manage forward-linked lists.
#define ast_debug(level,...)
Log a DEBUG message.
struct stasis_topic * stasis_topic_create(const char *name)
Create a new topic.
Event non-cacheability flag Used by: All events Payload type: UINT.
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Core PBX routines and definitions.
#define AST_LIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
#define STASIS_MESSAGE_TYPE_DEFN(name,...)
Boiler-plate messaging macro for defining public message types.
int stasis_caching_set_filter(struct stasis_caching_topic *caching_topic, enum stasis_subscription_message_filter filter)
Set the message type filtering level on a cache.
static const char *const devstatestring[][2]
Device state strings for printing.
enum ast_device_state ast_device_state(const char *device)
Asks a channel for device state.
int ast_device_state_clear_cache(const char *device)
Clear the device from the stasis cache.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
struct stasis_message * stasis_cache_entry_get_remote(struct stasis_cache_entry *entry, int idx)
Get a remote entity's cache entry snapshot by index.
static pthread_t change_thread
The device state change notification thread.
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
const char * ast_devstate2str(enum ast_device_state devstate)
Find devicestate as text message for output.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
ast_devstate_cache
Device State Cachability.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
#define ast_calloc(num, len)
A wrapper for calloc()
Prototypes for public functions only of internal interest,.
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
Mapping for channel states to device states.
struct ast_eid ast_eid_default
Global EID.
const char * ast_devstate_str(enum ast_device_state state)
Convert device state to text string that is easier to parse.
struct stasis_topic * ast_device_state_topic(const char *device)
Get the Stasis topic for device state messages for a specific device.
static void * do_devstate_changes(void *data)
Go through the dev state change queue and update changes in the dev state thread. ...
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
struct stasis_message * stasis_cache_entry_get_local(struct stasis_cache_entry *entry)
Get the local entity's cache entry snapshot.
static ast_cond_t change_pending
Flag for the queue.
struct ast_event * ast_event_new(enum ast_event_type event_type,...)
Create a new event.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
enum ast_device_state ast_parse_device_state(const char *device)
Find out if device is active in a call or not.
enum ast_device_state(* ast_devstate_prov_cb_type)(const char *data)
Devicestate provider call back.
struct stasis_topic * ast_device_state_topic_cached(void)
Get the Stasis caching topic for device state messages.
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(*const devicestate)(const char *device_number)
You shouldn't care about the contents of this struct.
The structure that contains device state.
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
static enum ast_device_state _ast_device_state(const char *device, int check_cache)
Check device state through channel specific function or generic function.
Generic State IE Used by AST_EVENT_DEVICE_STATE_CHANGE Payload type: UINT The actual state values dep...
The state change queue. State changes are queued for processing by a separate thread.
struct stasis_message * stasis_message_create_full(struct stasis_message_type *type, void *data, const struct ast_eid *eid)
Create a new message for an entity.
struct stasis_topic * stasis_caching_get_topic(struct stasis_caching_topic *caching_topic)
Returns the topic of cached events from a caching topics.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Device Name Used by AST_EVENT_DEVICE_STATE_CHANGE Payload type: STR.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
enum ast_device_state ast_devstate_aggregate_result(struct ast_devstate_aggregate *agg)
Get the aggregate device state result.
#define ast_publish_device_state(device, state, cachable)
Publish a device state update.