Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Functions | Variables
devicestate.c File Reference

Device state management. More...

#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/channel.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/linkedlists.h"
#include "asterisk/devicestate.h"
#include "asterisk/pbx.h"
#include "asterisk/app.h"
#include "asterisk/astobj2.h"
#include "asterisk/stasis.h"
Include dependency graph for devicestate.c:

Go to the source code of this file.

Data Structures

struct  chan2dev
 Mapping for channel states to device states. More...
 
struct  devstate_prov
 A device state provider (not a channel) More...
 
struct  devstate_provs
 A list of providers. More...
 
struct  state_change
 
struct  state_changes
 The state change queue. State changes are queued for processing by a separate thread. More...
 

Macros

#define DEVSTATE_TOPIC_BUCKETS   57
 

Functions

static enum ast_device_state _ast_device_state (const char *device, int check_cache)
 Check device state through channel specific function or generic function. More...
 
enum ast_device_state ast_device_state (const char *device)
 Asks a channel for device state. More...
 
struct stasis_cacheast_device_state_cache (void)
 Backend cache for ast_device_state_topic_cached() More...
 
int ast_device_state_clear_cache (const char *device)
 Clear the device from the stasis cache. More...
 
int ast_device_state_engine_init (void)
 Initialize the device state engine in separate thread. More...
 
struct stasis_topicast_device_state_topic (const char *device)
 Get the Stasis topic for device state messages for a specific device. More...
 
struct stasis_topicast_device_state_topic_all (void)
 Get the Stasis topic for device state messages. More...
 
struct stasis_topicast_device_state_topic_cached (void)
 Get the Stasis caching topic for device state messages. More...
 
const char * ast_devstate2str (enum ast_device_state devstate)
 Find devicestate as text message for output. More...
 
void ast_devstate_aggregate_add (struct ast_devstate_aggregate *agg, enum ast_device_state state)
 Add a device state to the aggregate device state. More...
 
void ast_devstate_aggregate_init (struct ast_devstate_aggregate *agg)
 Initialize aggregate device state. More...
 
enum ast_device_state ast_devstate_aggregate_result (struct ast_devstate_aggregate *agg)
 Get the aggregate device state result. More...
 
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. More...
 
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. More...
 
int ast_devstate_prov_add (const char *label, ast_devstate_prov_cb_type callback)
 Add device state provider. More...
 
int ast_devstate_prov_del (const char *label)
 Remove device state provider. More...
 
const char * ast_devstate_str (enum ast_device_state state)
 Convert device state to text string that is easier to parse. More...
 
enum ast_device_state ast_devstate_val (const char *val)
 Convert device state from text to integer value. More...
 
enum ast_device_state ast_parse_device_state (const char *device)
 Find out if device is active in a call or not. More...
 
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. More...
 
enum ast_device_state ast_state_chan2dev (enum ast_channel_state chanstate)
 Convert channel state to devicestate. More...
 
static struct stasis_messagedevice_state_aggregate_calc (struct stasis_cache_entry *entry, struct stasis_message *new_snapshot)
 
static void device_state_aggregate_publish (struct stasis_topic *cache_topic, struct stasis_message *aggregate)
 
static struct ast_device_state_messagedevice_state_alloc (const char *device, enum ast_device_state state, enum ast_devstate_cache cachable, const struct ast_eid *eid)
 
static void device_state_engine_cleanup (void)
 
static const char * device_state_get_id (struct stasis_message *message)
 
static enum ast_device_state devstate_cached (const char *device)
 
static void devstate_change_cb (void *data, struct stasis_subscription *sub, struct stasis_message *msg)
 
static void devstate_cleanup (void)
 
int devstate_init (void)
 Initialize the device state core. More...
 
static struct ast_manager_event_blobdevstate_to_ami (struct stasis_message *msg)
 
static struct ast_eventdevstate_to_event (struct stasis_message *message)
 Convert a stasis_message to a ast_event. More...
 
static void * do_devstate_changes (void *data)
 Go through the dev state change queue and update changes in the dev state thread. More...
 
static void do_state_change (const char *device, enum ast_devstate_cache cachable)
 
static int getproviderstate (const char *provider, const char *address)
 Get provider device state. More...
 
 STASIS_MESSAGE_TYPE_DEFN (ast_device_state_message_type,.to_ami=devstate_to_ami,.to_event=devstate_to_event,)
 

Variables

static const struct chan2dev chan2dev []
 
static ast_cond_t change_pending
 Flag for the queue. More...
 
static pthread_t change_thread = AST_PTHREADT_NULL
 The device state change notification thread. More...
 
static struct stasis_cachedevice_state_cache
 
static struct stasis_topicdevice_state_topic_all
 
static struct stasis_caching_topicdevice_state_topic_cached
 
static struct stasis_topic_pooldevice_state_topic_pool
 
struct stasis_subscriptiondevstate_message_sub
 
static struct devstate_provs devstate_provs = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 
static const char *const devstatestring [][2]
 Device state strings for printing. More...
 
static volatile int shuttingdown
 
static struct state_changes state_changes = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
 

Detailed Description

Device state management.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m
Russell Bryant russe.nosp@m.ll@d.nosp@m.igium.nosp@m..com

Definition in file devicestate.c.

Macro Definition Documentation

◆ DEVSTATE_TOPIC_BUCKETS

#define DEVSTATE_TOPIC_BUCKETS   57

Definition at line 158 of file devicestate.c.

Function Documentation

◆ _ast_device_state()

static enum ast_device_state _ast_device_state ( const char *  device,
int  check_cache 
)
static

Check device state through channel specific function or generic function.

Channel driver that provides device state

Another provider of device state

Definition at line 328 of file devicestate.c.

References ast_debug, AST_DEVICE_INVALID, AST_DEVICE_UNKNOWN, ast_get_channel_tech(), ast_parse_device_state(), ast_strdupa, ast_channel_tech::devicestate, devstate_cached(), getproviderstate(), provider, and strsep().

Referenced by ast_device_state(), and do_state_change().

329 {
330  char *number;
331  const struct ast_channel_tech *chan_tech;
332  enum ast_device_state res;
333  /*! \brief Channel driver that provides device state */
334  char *tech;
335 
336  /* If the last known state is cached, just return that */
337  if (check_cache) {
338  res = devstate_cached(device);
339  if (res != AST_DEVICE_UNKNOWN) {
340  return res;
341  }
342  }
343 
344  number = ast_strdupa(device);
345  tech = strsep(&number, "/");
346  if (!number) {
347  /*! \brief Another provider of device state */
348  char *provider;
349 
350  provider = strsep(&tech, ":");
351  if (!tech) {
352  return AST_DEVICE_INVALID;
353  }
354  /* We have a provider */
355  number = tech;
356 
357  ast_debug(3, "Checking if I can find provider for \"%s\" - number: %s\n", provider, number);
358  return getproviderstate(provider, number);
359  }
360 
361  ast_debug(4, "No provider found, checking channel drivers for %s - %s\n", tech, number);
362 
363  chan_tech = ast_get_channel_tech(tech);
364  if (!chan_tech) {
365  return AST_DEVICE_INVALID;
366  }
367 
368  /* Does the channel driver support device state notification? */
369  if (!chan_tech->devicestate) {
370  /* No, try the generic function */
371  return ast_parse_device_state(device);
372  }
373 
374  res = chan_tech->devicestate(number);
375  if (res == AST_DEVICE_UNKNOWN) {
376  res = ast_parse_device_state(device);
377  }
378 
379  return res;
380 }
ast_device_state
Device States.
Definition: devicestate.h:52
static int getproviderstate(const char *provider, const char *address)
Get provider device state.
Definition: devicestate.c:439
const struct ast_channel_tech * ast_get_channel_tech(const char *name)
Get a channel technology structure by name.
Definition: channel.c:592
static enum ast_device_state devstate_cached(const char *device)
Definition: devicestate.c:309
Number structure.
Definition: app_followme.c:154
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Definition: channel.h:629
char * strsep(char **str, const char *delims)
enum ast_device_state ast_parse_device_state(const char *device)
Find out if device is active in a call or not.
Definition: devicestate.c:287
int(*const devicestate)(const char *device_number)
Definition: channel.h:676
static struct prometheus_metrics_provider provider
Definition: bridges.c:178

◆ ast_device_state()

enum ast_device_state ast_device_state ( const char *  device)

Asks a channel for device state.

Parameters
devicelike a dial string

Asks a channel for device state, data is normally a number from a dial string used by the low level module Tries the channel device state callback if not supported search in the active channels list for the device.

Return values
anAST_DEVICE_??? state

Definition at line 382 of file devicestate.c.

References _ast_device_state().

383 {
384  /* This function is called from elsewhere in the code to find out the
385  * current state of a device. Check the cache, first. */
386 
387  return _ast_device_state(device, 1);
388 }
static enum ast_device_state _ast_device_state(const char *device, int check_cache)
Check device state through channel specific function or generic function.
Definition: devicestate.c:328

◆ ast_device_state_cache()

struct stasis_cache* ast_device_state_cache ( void  )

◆ ast_device_state_clear_cache()

int ast_device_state_clear_cache ( const char *  device)

Clear the device from the stasis cache.

Parameters
Thedevice to clear
Return values
0if successful
-1nothing to clear
Since
12

Definition at line 688 of file devicestate.c.

References ao2_cleanup, ast_device_state_cache(), ast_device_state_message_type(), ast_device_state_topic(), ast_eid_default, stasis_cache_clear_create(), stasis_cache_get_by_eid(), and stasis_publish().

Referenced by stasis_app_device_state_delete().

689 {
690  struct stasis_message *cached_msg;
691  struct stasis_message *msg;
692 
695  if (!cached_msg) {
696  /* nothing to clear */
697  return -1;
698  }
699 
700  msg = stasis_cache_clear_create(cached_msg);
701  if (msg) {
703  }
704  ao2_cleanup(msg);
705  ao2_cleanup(cached_msg);
706  return 0;
707 }
struct stasis_cache * ast_device_state_cache(void)
Backend cache for ast_device_state_topic_cached()
Definition: devicestate.c:673
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.
Definition: stasis_cache.c:778
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.
Definition: stasis_cache.c:659
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition: stasis.c:1511
struct ast_eid ast_eid_default
Global EID.
Definition: options.c:93
struct stasis_topic * ast_device_state_topic(const char *device)
Get the Stasis topic for device state messages for a specific device.
Definition: devicestate.c:683
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ ast_device_state_engine_init()

int ast_device_state_engine_init ( void  )

Initialize the device state engine in separate thread.

Provided by devicestate.c

Definition at line 618 of file devicestate.c.

References ast_cond_init, ast_log, ast_pthread_create_background, ast_register_cleanup(), change_pending, change_thread, device_state_engine_cleanup(), do_devstate_changes(), LOG_ERROR, and NULL.

Referenced by asterisk_daemon().

619 {
622  ast_log(LOG_ERROR, "Unable to start device state change thread.\n");
623  return -1;
624  }
626 
627  return 0;
628 }
#define ast_cond_init(cond, attr)
Definition: lock.h:199
#define NULL
Definition: resample.c:96
static void device_state_engine_cleanup(void)
Definition: devicestate.c:605
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:567
#define ast_log
Definition: astobj2.c:42
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
#define LOG_ERROR
Definition: logger.h:285
static pthread_t change_thread
The device state change notification thread.
Definition: devicestate.c:211
static void * do_devstate_changes(void *data)
Go through the dev state change queue and update changes in the dev state thread. ...
Definition: devicestate.c:523
static ast_cond_t change_pending
Flag for the queue.
Definition: devicestate.c:214

◆ ast_device_state_topic()

struct stasis_topic* ast_device_state_topic ( const char *  device)

Get the Stasis topic for device state messages for a specific device.

Parameters
uniqueidThe device for which to get the topic
Return values
Thetopic structure for MWI messages for a given device
NULLif it failed to be found or allocated
Since
12

Definition at line 683 of file devicestate.c.

References stasis_topic_pool_get_topic().

Referenced by ast_device_state_clear_cache(), ast_publish_device_state_full(), cc_generic_agent_start_monitoring(), create_new_generic_list(), device_state_aggregate_publish(), remove_device_states_cb(), and subscribe_device_state().

684 {
686 }
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.
Definition: stasis.c:1884
static struct stasis_topic_pool * device_state_topic_pool
Definition: devicestate.c:222

◆ ast_device_state_topic_all()

struct stasis_topic* ast_device_state_topic_all ( void  )

Get the Stasis topic for device state messages.

Return values
Thetopic for device state messages
NULLif it has not been allocated
Since
12

Definition at line 668 of file devicestate.c.

References device_state_topic_all.

Referenced by ast_publish_device_state_full(), AST_TEST_DEFINE(), asterisk_start_devicestate_publishing(), devstate_init(), load_module(), load_pbx(), publish_hint_change(), publish_hint_remove(), subscribe_device_state(), and xmpp_init_event_distribution().

669 {
670  return device_state_topic_all;
671 }
static struct stasis_topic * device_state_topic_all
Definition: devicestate.c:219

◆ ast_device_state_topic_cached()

struct stasis_topic* ast_device_state_topic_cached ( void  )

Get the Stasis caching topic for device state messages.

Return values
Thecaching topic for device state messages
NULLif it has not been allocated
Since
12

Definition at line 678 of file devicestate.c.

References stasis_caching_get_topic().

Referenced by AST_TEST_DEFINE().

679 {
681 }
static struct stasis_caching_topic * device_state_topic_cached
Definition: devicestate.c:221
struct stasis_topic * stasis_caching_get_topic(struct stasis_caching_topic *caching_topic)
Returns the topic of cached events from a caching topics.
Definition: stasis_cache.c:85

◆ ast_devstate2str()

const char* ast_devstate2str ( enum ast_device_state  devstate)

Find devicestate as text message for output.

Convert device state to text string for output.

Definition at line 237 of file devicestate.c.

References devstatestring.

Referenced by ast_sip_get_device_state(), AST_TEST_DEFINE(), ccss_notify_device_state_change(), device_state_cb(), do_state_change(), extension_state_cb(), page_exec(), parking_notify_metermaids(), and print_queue().

238 {
239  return devstatestring[devstate][0];
240 }
static const char *const devstatestring[][2]
Device state strings for printing.
Definition: devicestate.c:161

◆ ast_devstate_aggregate_add()

void ast_devstate_aggregate_add ( struct ast_devstate_aggregate agg,
enum ast_device_state  state 
)

Add a device state to the aggregate device state.

Parameters
[in]aggthe state object
[in]statethe state to add
Returns
nothing
Since
1.6.1

Definition at line 636 of file devicestate.c.

References AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, ast_devstate_aggregate::inuse, ast_devstate_aggregate::ringing, ast_devstate_aggregate::state, and state.

Referenced by ast_extension_state3(), AST_TEST_DEFINE(), chan_pjsip_devicestate(), device_state_aggregate_calc(), and handle_show_device2extenstate().

637 {
638  static enum ast_device_state state_order[] = {
639  1, /* AST_DEVICE_UNKNOWN */
640  3, /* AST_DEVICE_NOT_INUSE */
641  6, /* AST_DEVICE_INUSE */
642  7, /* AST_DEVICE_BUSY */
643  0, /* AST_DEVICE_INVALID */
644  2, /* AST_DEVICE_UNAVAILABLE */
645  5, /* AST_DEVICE_RINGING */
646  8, /* AST_DEVICE_RINGINUSE */
647  4, /* AST_DEVICE_ONHOLD */
648  };
649 
650  if (state == AST_DEVICE_RINGING) {
651  agg->ringing = 1;
653  agg->inuse = 1;
654  }
655 
656  if (agg->ringing && agg->inuse) {
658  } else if (state_order[state] > state_order[agg->state]) {
659  agg->state = state;
660  }
661 }
enum sip_cc_notify_state state
Definition: chan_sip.c:959
ast_device_state
Device States.
Definition: devicestate.h:52
unsigned int ringing
Definition: devicestate.h:231
enum ast_device_state state
Definition: devicestate.h:233

◆ ast_devstate_aggregate_init()

void ast_devstate_aggregate_init ( struct ast_devstate_aggregate agg)

Initialize aggregate device state.

Parameters
[in]aggthe state object
Returns
nothing
Since
1.6.1

Definition at line 630 of file devicestate.c.

References AST_DEVICE_INVALID, and ast_devstate_aggregate::state.

Referenced by ast_extension_state3(), AST_TEST_DEFINE(), chan_pjsip_devicestate(), device_state_aggregate_calc(), and handle_show_device2extenstate().

631 {
632  memset(agg, 0, sizeof(*agg));
633  agg->state = AST_DEVICE_INVALID;
634 }
enum ast_device_state state
Definition: devicestate.h:233

◆ ast_devstate_aggregate_result()

enum ast_device_state ast_devstate_aggregate_result ( struct ast_devstate_aggregate agg)

Get the aggregate device state result.

Parameters
[in]aggthe state object
Returns
the aggregate device state after adding some number of device states.
Since
1.6.1

Definition at line 663 of file devicestate.c.

References ast_devstate_aggregate::state.

Referenced by ast_extension_state3(), AST_TEST_DEFINE(), chan_pjsip_devicestate(), device_state_aggregate_calc(), and handle_show_device2extenstate().

664 {
665  return agg->state;
666 }
enum ast_device_state state
Definition: devicestate.h:233

◆ ast_devstate_changed()

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.

Parameters
statethe new state of the device
cachablewhether this device state is cachable
fmtdevice name like a dial string with format parameters

The new state of the device will be sent off to any subscribers of device states. It will also be stored in the internal event cache.

Return values
0on success
-1on failure

Definition at line 510 of file devicestate.c.

References ast_devstate_changed_literal(), AST_MAX_EXTENSION, and buf.

Referenced by __expire_registry(), __iax2_poke_noanswer(), add_to_queue(), agent_devstate_changed(), ast_sip_persistent_endpoint_update_state(), calendar_devstate_change(), ccss_notify_device_state_change(), chan_pjsip_indicate(), conf_handle_first_join(), conf_run(), destroy_event(), device_state_cb(), devstate_write(), expire_register(), handle_cli_devstate_change(), handle_offhook_message(), handle_onhook_message(), handle_response_invite(), handle_response_peerpoke(), handle_soft_key_event_message(), handle_stimulus_message(), init_queue(), join_queue(), leave_queue(), load_module(), member_add_to_queue(), member_remove_from_queue(), mwi_update_cb(), my_on_hook(), parking_notify_metermaids(), populate_cache(), reg_source_db(), register_verify(), remove_from_queue(), rt_handle_member_record(), set_queue_member_pause(), sip_peer_hold(), sip_poke_noanswer(), skinny_register(), skinny_session_cleanup(), sla_change_trunk_state(), sla_handle_hold_event(), sla_station_exec(), socket_process_helper(), stasis_app_device_state_delete(), stasis_app_device_state_update(), transition_to_empty(), update_call_counter(), update_devstate(), update_registry(), and xmpp_pak_presence().

511 {
512  char buf[AST_MAX_EXTENSION];
513  va_list ap;
514 
515  va_start(ap, fmt);
516  vsnprintf(buf, sizeof(buf), fmt, ap);
517  va_end(ap);
518 
519  return ast_devstate_changed_literal(state, cachable, buf);
520 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
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.
Definition: devicestate.c:471
#define AST_MAX_EXTENSION
Definition: channel.h:135

◆ ast_devstate_changed_literal()

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.

Parameters
statethe new state of the device
cachablewhether this device state is cachable
devicedevice name like a dial string with format parameters

The new state of the device will be sent off to any subscribers of device states. It will also be stored in the internal event cache.

Return values
0on success
-1on failure

Definition at line 471 of file devicestate.c.

References ast_calloc, ast_cond_signal, AST_DEVICE_UNKNOWN, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, AST_PTHREADT_NULL, ast_publish_device_state, state_change::cachable, change_pending, change_thread, state_change::device, do_state_change(), and state_change::list.

Referenced by ast_channel_destructor(), ast_devstate_changed(), ast_setstate(), AST_TEST_DEFINE(), chan_pjsip_indicate(), and dahdi_new().

472 {
473  struct state_change *change;
474 
475  /*
476  * If we know the state change (how nice of the caller of this function!)
477  * then we can just generate a device state event.
478  *
479  * Otherwise, we do the following:
480  * - Queue an event up to another thread that the state has changed
481  * - In the processing thread, it calls the callback provided by the
482  * device state provider (which may or may not be a channel driver)
483  * to determine the state.
484  * - If the device state provider does not know the state, or this is
485  * for a channel and the channel driver does not implement a device
486  * state callback, then we will look through the channel list to
487  * see if we can determine a state based on active calls.
488  * - Once a state has been determined, a device state event is generated.
489  */
490 
491  if (state != AST_DEVICE_UNKNOWN) {
493  } else if (change_thread == AST_PTHREADT_NULL || !(change = ast_calloc(1, sizeof(*change) + strlen(device)))) {
494  /* we could not allocate a change struct, or */
495  /* there is no background thread, so process the change now */
497  } else {
498  /* queue the change */
499  strcpy(change->device, device);
500  change->cachable = cachable;
505  }
506 
507  return 0;
508 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static void do_state_change(const char *device, enum ast_devstate_cache cachable)
Definition: devicestate.c:460
struct state_change::@380 list
enum ast_devstate_cache cachable
Definition: devicestate.c:202
#define ast_cond_signal(cond)
Definition: lock.h:201
#define AST_PTHREADT_NULL
Definition: lock.h:66
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
static pthread_t change_thread
The device state change notification thread.
Definition: devicestate.c:211
char device[1]
Definition: devicestate.c:203
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
static ast_cond_t change_pending
Flag for the queue.
Definition: devicestate.c:214
The state change queue. State changes are queued for processing by a separate thread.
Definition: devicestate.c:208
#define ast_publish_device_state(device, state, cachable)
Publish a device state update.
Definition: devicestate.h:323

◆ ast_devstate_prov_add()

int ast_devstate_prov_add ( const char *  label,
ast_devstate_prov_cb_type  callback 
)

Add device state provider.

Parameters
labelto use in hint, like label:object
callbackCallback
Return values
0success
-1failure

Definition at line 391 of file devicestate.c.

References ast_calloc, ast_copy_string(), ast_free, ast_log, AST_RWLIST_INSERT_HEAD, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, devstate_prov::callback, devstate_prov::label, and LOG_WARNING.

Referenced by AST_TEST_DEFINE(), load_module(), and load_parking_devstate().

392 {
393  struct devstate_prov *devcb;
394  struct devstate_prov *devprov;
395 
396  if (!callback || !(devprov = ast_calloc(1, sizeof(*devprov))))
397  return -1;
398 
399  devprov->callback = callback;
400  ast_copy_string(devprov->label, label, sizeof(devprov->label));
401 
403  AST_RWLIST_TRAVERSE(&devstate_provs, devcb, list) {
404  if (!strcasecmp(devcb->label, label)) {
405  ast_log(LOG_WARNING, "Device state provider '%s' already registered\n", label);
406  ast_free(devprov);
408  return -1;
409  }
410  }
411  AST_RWLIST_INSERT_HEAD(&devstate_provs, devprov, list);
413 
414  return 0;
415 }
A list of providers.
Definition: devicestate.c:198
A device state provider (not a channel)
Definition: devicestate.c:191
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define LOG_WARNING
Definition: logger.h:274
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
ast_devstate_prov_cb_type callback
Definition: devicestate.c:193
#define AST_RWLIST_INSERT_HEAD
Definition: linkedlists.h:717
#define ast_log
Definition: astobj2.c:42
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
char label[40]
Definition: devicestate.c:192
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401

◆ ast_devstate_prov_del()

int ast_devstate_prov_del ( const char *  label)

Remove device state provider.

Parameters
labelto use in hint, like label:object
Return values
-1on failure
0on success

Definition at line 418 of file devicestate.c.

References ast_free, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and devstate_prov::label.

Referenced by AST_TEST_DEFINE(), load_module(), unload_module(), and unload_parking_devstate().

419 {
420  struct devstate_prov *devcb;
421  int res = -1;
422 
425  if (!strcasecmp(devcb->label, label)) {
427  ast_free(devcb);
428  res = 0;
429  break;
430  }
431  }
434 
435  return res;
436 }
A list of providers.
Definition: devicestate.c:198
A device state provider (not a channel)
Definition: devicestate.c:191
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:569
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:544
#define ast_free(a)
Definition: astmm.h:182
char label[40]
Definition: devicestate.c:192
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:616

◆ ast_devstate_str()

const char* ast_devstate_str ( enum ast_device_state  devstate)

Convert device state to text string that is easier to parse.

Parameters
devstateCurrent device state

Definition at line 255 of file devicestate.c.

References devstatestring, and state.

Referenced by agent_handle_show_specific(), agent_show_requested(), AST_TEST_DEFINE(), asterisk_publisher_devstate_cb(), devstate_read(), devstate_to_ami(), handle_show_device2extenstate(), stasis_app_device_state_to_json(), and xmpp_pubsub_devstate_cb().

256 {
257  return devstatestring[state][1];
258 }
enum sip_cc_notify_state state
Definition: chan_sip.c:959
static const char *const devstatestring[][2]
Device state strings for printing.
Definition: devicestate.c:161

◆ ast_devstate_val()

enum ast_device_state ast_devstate_val ( const char *  val)

Convert device state from text to integer value.

Parameters
valThe text representing the device state. Valid values are anything that comes after AST_DEVICE_ in one of the defined values.
Returns
The AST_DEVICE_ integer value

Definition at line 260 of file devicestate.c.

References AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, AST_DEVICE_UNAVAILABLE, and AST_DEVICE_UNKNOWN.

Referenced by AST_TEST_DEFINE(), asterisk_publication_devicestate(), custom_devstate_callback(), devstate_write(), handle_cli_devstate_change(), initialize_cc_devstate_map_helper(), load_module(), populate_cache(), stasis_app_device_state_update(), stasis_device_state_cb(), and xmpp_pubsub_handle_event().

261 {
262  if (!strcasecmp(val, "NOT_INUSE"))
263  return AST_DEVICE_NOT_INUSE;
264  else if (!strcasecmp(val, "INUSE"))
265  return AST_DEVICE_INUSE;
266  else if (!strcasecmp(val, "BUSY"))
267  return AST_DEVICE_BUSY;
268  else if (!strcasecmp(val, "INVALID"))
269  return AST_DEVICE_INVALID;
270  else if (!strcasecmp(val, "UNAVAILABLE"))
271  return AST_DEVICE_UNAVAILABLE;
272  else if (!strcasecmp(val, "RINGING"))
273  return AST_DEVICE_RINGING;
274  else if (!strcasecmp(val, "RINGINUSE"))
275  return AST_DEVICE_RINGINUSE;
276  else if (!strcasecmp(val, "ONHOLD"))
277  return AST_DEVICE_ONHOLD;
278 
279  return AST_DEVICE_UNKNOWN;
280 }
Definition: ast_expr2.c:325

◆ ast_parse_device_state()

enum ast_device_state ast_parse_device_state ( const char *  device)

Find out if device is active in a call or not.

Search the Channels by Name.

Note
find channels with the device's name in it This function is only used for channels that does not implement devicestate natively

Definition at line 287 of file devicestate.c.

References ast_channel_get_by_name_prefix(), ast_channel_hold_state(), AST_CHANNEL_NAME, ast_channel_unref, AST_CONTROL_HOLD, AST_DEVICE_ONHOLD, AST_DEVICE_UNKNOWN, ast_state_chan2dev(), chan2dev::chan, and match().

Referenced by _ast_device_state(), AST_TEST_DEFINE(), and chanavail_exec().

288 {
289  struct ast_channel *chan;
290  char match[AST_CHANNEL_NAME];
291  enum ast_device_state res;
292 
293  snprintf(match, sizeof(match), "%s-", device);
294 
295  if (!(chan = ast_channel_get_by_name_prefix(match, strlen(match)))) {
296  return AST_DEVICE_UNKNOWN;
297  }
298 
300  res = AST_DEVICE_ONHOLD;
301  } else {
303  }
304  ast_channel_unref(chan);
305 
306  return res;
307 }
Main Channel structure associated with a channel.
ast_device_state
Device States.
Definition: devicestate.h:52
int ast_channel_hold_state(const struct ast_channel *chan)
enum ast_device_state ast_state_chan2dev(enum ast_channel_state chanstate)
Convert channel state to devicestate.
Definition: devicestate.c:242
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
ast_channel_state
ast_channel states
Definition: channelstate.h:35
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition: chan_iax2.c:2315
struct ast_channel * ast_channel_get_by_name_prefix(const char *name, size_t name_len)
Find a channel by a name prefix.
Definition: channel.c:1434
#define AST_CHANNEL_NAME
Definition: channel.h:172

◆ ast_publish_device_state_full()

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.

Parameters
[in]deviceThe device name
[in]stateThe state of the device
[in]cachableWhether the device state can be cached
[in]eidThe EID of the server that originally published the message
Return values
0Success
-1Failure
Since
12

Definition at line 709 of file devicestate.c.

References ao2_cleanup, ast_assert, ast_device_state_message_type(), ast_device_state_topic(), ast_device_state_topic_all(), ast_strlen_zero, device_state_alloc(), NULL, RAII_VAR, stasis_message_create_full(), stasis_publish(), and stasis_topic_pool_topic_exists().

Referenced by AST_TEST_DEFINE(), asterisk_publication_devicestate(), devstate_change_cb(), publish_device_state_to_stasis(), and xmpp_pubsub_handle_event().

714 {
715  RAII_VAR(struct ast_device_state_message *, device_state, NULL, ao2_cleanup);
717  struct stasis_topic *topic;
718 
719  ast_assert(!ast_strlen_zero(device));
720 
722  return -1;
723  }
724 
725  device_state = device_state_alloc(device, state, cachable, eid);
726  if (!device_state) {
727  return -1;
728  }
729 
731  eid);
732  if (!message) {
733  return -1;
734  }
735 
736  /* When a device state is to be cached it is likely that something
737  * external will either be monitoring it or will want to pull the
738  * information from the cache, so we always publish to the device
739  * specific topic. Cachable updates traditionally come from such things
740  * as a SIP or PJSIP device.
741  * When a device state is not to be cached we only publish to its
742  * specific topic if something has already created the topic. Publishing
743  * to its topic otherwise would create the topic, which may not be
744  * necessary as it could be an ephemeral device. Uncachable updates
745  * traditionally come from such things as Local channels.
746  */
747  if (cachable || stasis_topic_pool_topic_exists(device_state_topic_pool, device)) {
748  topic = ast_device_state_topic(device);
749  } else {
750  topic = ast_device_state_topic_all();
751  }
752 
753  if (!topic) {
754  return -1;
755  }
756 
757  stasis_publish(topic, message);
758  return 0;
759 }
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
static struct stasis_topic_pool * device_state_topic_pool
Definition: devicestate.c:222
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
struct stasis_topic * ast_device_state_topic_all(void)
Get the Stasis topic for device state messages.
Definition: devicestate.c:668
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
int stasis_topic_pool_topic_exists(const struct stasis_topic_pool *pool, const char *topic_name)
Check if a topic exists in a pool.
Definition: stasis.c:1927
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition: stasis.c:1511
static struct ast_device_state_message * device_state_alloc(const char *device, enum ast_device_state state, enum ast_devstate_cache cachable, const struct ast_eid *eid)
Definition: devicestate.c:547
struct stasis_topic * ast_device_state_topic(const char *device)
Get the Stasis topic for device state messages for a specific device.
Definition: devicestate.c:683
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
The structure that contains device state.
Definition: devicestate.h:240
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.

◆ ast_state_chan2dev()

enum ast_device_state ast_state_chan2dev ( enum ast_channel_state  chanstate)

Convert channel state to devicestate.

Parameters
chanstateCurrent channel state
Since
1.6.1

Definition at line 242 of file devicestate.c.

References ARRAY_LEN, AST_DEVICE_UNKNOWN, chan2dev::chan, and chan2dev::dev.

Referenced by ast_parse_device_state(), AST_TEST_DEFINE(), and chan_pjsip_devicestate().

243 {
244  int i;
245  chanstate &= 0xFFFF;
246  for (i = 0; i < ARRAY_LEN(chan2dev); i++) {
247  if (chan2dev[i].chan == chanstate) {
248  return chan2dev[i].dev;
249  }
250  }
251  return AST_DEVICE_UNKNOWN;
252 }
enum ast_device_state dev
Definition: devicestate.c:176
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
Mapping for channel states to device states.
Definition: devicestate.c:174

◆ device_state_aggregate_calc()

static struct stasis_message* device_state_aggregate_calc ( struct stasis_cache_entry entry,
struct stasis_message new_snapshot 
)
static

Definition at line 818 of file devicestate.c.

References ao2_bump, ao2_cleanup, ast_device_state_message_type(), ast_devstate_aggregate_add(), ast_devstate_aggregate_init(), ast_devstate_aggregate_result(), AST_DEVSTATE_CACHABLE, ast_device_state_message::device, device_state_alloc(), NULL, stasis_cache_entry_get_aggregate(), stasis_cache_entry_get_local(), stasis_cache_entry_get_remote(), stasis_message_create_full(), stasis_message_data(), and ast_device_state_message::state.

Referenced by devstate_init().

819 {
820  struct stasis_message *aggregate_snapshot;
821  struct stasis_message *snapshot;
822  struct ast_device_state_message *device_state;
823  const char *device = NULL;
824  struct ast_devstate_aggregate aggregate;
825  int idx;
826 
828  return NULL;
829  }
830 
831  /* Determine the new aggregate device state. */
832  ast_devstate_aggregate_init(&aggregate);
833  snapshot = stasis_cache_entry_get_local(entry);
834  if (snapshot) {
835  device_state = stasis_message_data(snapshot);
836  device = device_state->device;
837  ast_devstate_aggregate_add(&aggregate, device_state->state);
838  }
839  for (idx = 0; ; ++idx) {
840  snapshot = stasis_cache_entry_get_remote(entry, idx);
841  if (!snapshot) {
842  break;
843  }
844 
845  device_state = stasis_message_data(snapshot);
846  device = device_state->device;
847  ast_devstate_aggregate_add(&aggregate, device_state->state);
848  }
849 
850  if (!device) {
851  /* There are no device states cached. Delete the aggregate. */
852  return NULL;
853  }
854 
855  snapshot = stasis_cache_entry_get_aggregate(entry);
856  if (snapshot) {
857  device_state = stasis_message_data(snapshot);
858  if (device_state->state == ast_devstate_aggregate_result(&aggregate)) {
859  /* Aggregate device state did not change. */
860  return ao2_bump(snapshot);
861  }
862  }
863 
864  device_state = device_state_alloc(device, ast_devstate_aggregate_result(&aggregate),
866  if (!device_state) {
867  /* Bummer. We have to keep the old aggregate snapshot. */
868  return ao2_bump(snapshot);
869  }
871  device_state, NULL);
872  ao2_cleanup(device_state);
873  if (!aggregate_snapshot) {
874  /* Bummer. We have to keep the old aggregate snapshot. */
875  return ao2_bump(snapshot);
876  }
877 
878  return aggregate_snapshot;
879 }
void ast_devstate_aggregate_init(struct ast_devstate_aggregate *agg)
Initialize aggregate device state.
Definition: devicestate.c:630
void ast_devstate_aggregate_add(struct ast_devstate_aggregate *agg, enum ast_device_state state)
Add a device state to the aggregate device state.
Definition: devicestate.c:636
enum ast_device_state state
Definition: devicestate.h:250
struct stasis_message * stasis_cache_entry_get_aggregate(struct stasis_cache_entry *entry)
Get the aggregate cache entry snapshot.
Definition: stasis_cache.c:365
#define NULL
Definition: resample.c:96
#define ao2_bump(obj)
Definition: astobj2.h:491
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
struct stasis_message * stasis_cache_entry_get_remote(struct stasis_cache_entry *entry, int idx)
Get a remote entity&#39;s cache entry snapshot by index.
Definition: stasis_cache.c:375
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
static struct ast_device_state_message * device_state_alloc(const char *device, enum ast_device_state state, enum ast_devstate_cache cachable, const struct ast_eid *eid)
Definition: devicestate.c:547
struct stasis_message * stasis_cache_entry_get_local(struct stasis_cache_entry *entry)
Get the local entity&#39;s cache entry snapshot.
Definition: stasis_cache.c:370
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
You shouldn&#39;t care about the contents of this struct.
Definition: devicestate.h:230
The structure that contains device state.
Definition: devicestate.h:240
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.
enum ast_device_state ast_devstate_aggregate_result(struct ast_devstate_aggregate *agg)
Get the aggregate device state result.
Definition: devicestate.c:663

◆ device_state_aggregate_publish()

static void device_state_aggregate_publish ( struct stasis_topic cache_topic,
struct stasis_message aggregate 
)
static

Definition at line 787 of file devicestate.c.

References ast_device_state_topic(), ast_device_state_message::device, device_state_get_id(), and stasis_publish().

Referenced by devstate_init().

788 {
789  const char *device;
790  struct stasis_topic *device_specific_topic;
791 
792  device = device_state_get_id(aggregate);
793  if (!device) {
794  return;
795  }
796  device_specific_topic = ast_device_state_topic(device);
797  if (!device_specific_topic) {
798  return;
799  }
800 
801  stasis_publish(device_specific_topic, aggregate);
802 }
static const char * device_state_get_id(struct stasis_message *message)
Definition: devicestate.c:761
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic&#39;s subscribers.
Definition: stasis.c:1511
struct stasis_topic * ast_device_state_topic(const char *device)
Get the Stasis topic for device state messages for a specific device.
Definition: devicestate.c:683

◆ device_state_alloc()

static struct ast_device_state_message* device_state_alloc ( const char *  device,
enum ast_device_state  state,
enum ast_devstate_cache  cachable,
const struct ast_eid eid 
)
static

Definition at line 547 of file devicestate.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ast_assert, ast_strlen_zero, ast_device_state_message::cachable, ast_device_state_message::device, ast_device_state_message::eid, NULL, ast_device_state_message::state, state, and ast_device_state_message::stuff.

Referenced by ast_publish_device_state_full(), and device_state_aggregate_calc().

548 {
549  struct ast_device_state_message *new_device_state;
550  char *pos;
551  size_t stuff_len;
552 
554 
555  stuff_len = strlen(device) + 1;
556  if (eid) {
557  stuff_len += sizeof(*eid);
558  }
559  new_device_state = ao2_alloc_options(sizeof(*new_device_state) + stuff_len, NULL,
561  if (!new_device_state) {
562  return NULL;
563  }
564 
565  if (eid) {
566  /* non-aggregate device state. */
567  new_device_state->stuff[0] = *eid;
568  new_device_state->eid = &new_device_state->stuff[0];
569  pos = (char *) &new_device_state->stuff[1];
570  } else {
571  pos = (char *) &new_device_state->stuff[0];
572  }
573 
574  strcpy(pos, device);/* Safe */
575  new_device_state->device = pos;
576 
577  new_device_state->state = state;
578  new_device_state->cachable = cachable;
579 
580  return new_device_state;
581 }
enum sip_cc_notify_state state
Definition: chan_sip.c:959
enum ast_device_state state
Definition: devicestate.h:250
enum ast_devstate_cache cachable
Definition: devicestate.h:252
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
const struct ast_eid * eid
The EID of the server where this message originated.
Definition: devicestate.h:248
The structure that contains device state.
Definition: devicestate.h:240
struct ast_eid stuff[0]
Definition: devicestate.h:254

◆ device_state_engine_cleanup()

static void device_state_engine_cleanup ( void  )
static

Definition at line 605 of file devicestate.c.

References ast_cond_signal, AST_LIST_LOCK, AST_LIST_UNLOCK, AST_PTHREADT_NULL, change_pending, change_thread, NULL, and shuttingdown.

Referenced by ast_device_state_engine_init().

606 {
607  shuttingdown = 1;
611 
613  pthread_join(change_thread, NULL);
614  }
615 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static volatile int shuttingdown
Definition: devicestate.c:215
#define NULL
Definition: resample.c:96
#define ast_cond_signal(cond)
Definition: lock.h:201
#define AST_PTHREADT_NULL
Definition: lock.h:66
static pthread_t change_thread
The device state change notification thread.
Definition: devicestate.c:211
static ast_cond_t change_pending
Flag for the queue.
Definition: devicestate.c:214
The state change queue. State changes are queued for processing by a separate thread.
Definition: devicestate.c:208

◆ device_state_get_id()

static const char* device_state_get_id ( struct stasis_message message)
static

Definition at line 761 of file devicestate.c.

References ast_device_state_message_type(), AST_DEVSTATE_NOT_CACHABLE, ast_device_state_message::cachable, ast_device_state_message::device, NULL, stasis_message_data(), and stasis_message_type().

Referenced by device_state_aggregate_publish(), and devstate_init().

762 {
763  struct ast_device_state_message *device_state;
764 
766  return NULL;
767  }
768 
769  device_state = stasis_message_data(message);
770  if (device_state->cachable == AST_DEVSTATE_NOT_CACHABLE) {
771  return NULL;
772  }
773 
774  return device_state->device;
775 }
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
enum ast_devstate_cache cachable
Definition: devicestate.h:252
#define NULL
Definition: resample.c:96
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
The structure that contains device state.
Definition: devicestate.h:240

◆ devstate_cached()

static enum ast_device_state devstate_cached ( const char *  device)
static

Definition at line 309 of file devicestate.c.

References ao2_cleanup, ast_device_state_cache(), ast_device_state_message_type(), AST_DEVICE_UNKNOWN, NULL, stasis_cache_get_by_eid(), stasis_message_data(), ast_device_state_message::state, and state.

Referenced by _ast_device_state().

310 {
311  struct stasis_message *cached_msg;
312  struct ast_device_state_message *device_state;
313  enum ast_device_state state;
314 
317  if (!cached_msg) {
318  return AST_DEVICE_UNKNOWN;
319  }
320  device_state = stasis_message_data(cached_msg);
321  state = device_state->state;
322  ao2_cleanup(cached_msg);
323 
324  return state;
325 }
enum sip_cc_notify_state state
Definition: chan_sip.c:959
ast_device_state
Device States.
Definition: devicestate.h:52
struct stasis_cache * ast_device_state_cache(void)
Backend cache for ast_device_state_topic_cached()
Definition: devicestate.c:673
enum ast_device_state state
Definition: devicestate.h:250
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.
Definition: stasis_cache.c:659
#define NULL
Definition: resample.c:96
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
The structure that contains device state.
Definition: devicestate.h:240

◆ devstate_change_cb()

static void devstate_change_cb ( void *  data,
struct stasis_subscription sub,
struct stasis_message msg 
)
static

Definition at line 583 of file devicestate.c.

References ast_device_state_message_type(), AST_DEVSTATE_CACHABLE, ast_publish_device_state_full(), ast_device_state_message::cachable, ast_device_state_message::device, ast_device_state_message::eid, NULL, stasis_message_data(), stasis_message_type(), and ast_device_state_message::state.

Referenced by devstate_init().

584 {
585  struct ast_device_state_message *device_state;
586 
588  return;
589  }
590 
591  device_state = stasis_message_data(msg);
592  if (device_state->cachable == AST_DEVSTATE_CACHABLE || !device_state->eid) {
593  /* Ignore cacheable and aggregate messages. */
594  return;
595  }
596 
597  /*
598  * Non-cacheable device state aggregates are just the
599  * device state republished as the aggregate.
600  */
601  ast_publish_device_state_full(device_state->device, device_state->state,
602  device_state->cachable, NULL);
603 }
enum ast_device_state state
Definition: devicestate.h:250
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
enum ast_devstate_cache cachable
Definition: devicestate.h:252
#define NULL
Definition: resample.c:96
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.
Definition: devicestate.c:709
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
const struct ast_eid * eid
The EID of the server where this message originated.
Definition: devicestate.h:248
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
The structure that contains device state.
Definition: devicestate.h:240

◆ devstate_cleanup()

static void devstate_cleanup ( void  )
static

Definition at line 881 of file devicestate.c.

References ao2_cleanup, ast_device_state_message_type(), NULL, stasis_caching_unsubscribe_and_join(), STASIS_MESSAGE_TYPE_CLEANUP, and stasis_unsubscribe_and_join().

Referenced by devstate_init().

882 {
885 
888 
891 
894 
896 }
static struct stasis_topic * device_state_topic_all
Definition: devicestate.c:219
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1523
#define NULL
Definition: resample.c:96
static struct stasis_caching_topic * device_state_topic_cached
Definition: devicestate.c:221
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...
Definition: stasis_cache.c:146
static struct stasis_topic_pool * device_state_topic_pool
Definition: devicestate.c:222
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
static struct stasis_cache * device_state_cache
Definition: devicestate.c:220
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
Definition: stasis.c:1136
struct stasis_subscription * devstate_message_sub
Definition: devicestate.c:217
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ devstate_init()

int devstate_init ( void  )

Initialize the device state core.

Return values
0Success
-1Failure
Since
12

Definition at line 898 of file devicestate.c.

References ast_device_state_message_type(), ast_device_state_topic_all(), ast_log, ast_register_cleanup(), device_state_aggregate_calc(), device_state_aggregate_publish(), device_state_get_id(), devstate_change_cb(), devstate_cleanup(), LOG_ERROR, NULL, stasis_cache_create_full(), stasis_caching_accept_message_type(), stasis_caching_set_filter(), stasis_caching_topic_create(), STASIS_MESSAGE_TYPE_INIT, stasis_subscribe, stasis_subscription_accept_message_type(), STASIS_SUBSCRIPTION_FILTER_SELECTIVE, stasis_subscription_set_filter(), stasis_topic_create(), and stasis_topic_pool_create().

Referenced by asterisk_daemon().

899 {
901 
903  return -1;
904  }
905  device_state_topic_all = stasis_topic_create("devicestate:all");
906  if (!device_state_topic_all) {
907  return -1;
908  }
911  return -1;
912  }
915  if (!device_state_cache) {
916  return -1;
917  }
921  return -1;
922  }
925 
928  if (!devstate_message_sub) {
929  ast_log(LOG_ERROR, "Failed to create subscription creating uncached device state aggregate events.\n");
930  return -1;
931  }
934 
935  return 0;
936 }
static struct stasis_message * device_state_aggregate_calc(struct stasis_cache_entry *entry, struct stasis_message *new_snapshot)
Definition: devicestate.c:818
static struct stasis_topic * device_state_topic_all
Definition: devicestate.c:219
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.
Definition: stasis_cache.c:90
static void devstate_change_cb(void *data, struct stasis_subscription *sub, struct stasis_message *msg)
Definition: devicestate.c:583
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition: stasis.h:1501
static void devstate_cleanup(void)
Definition: devicestate.c:881
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.
Definition: stasis_cache.c:948
int stasis_subscription_set_filter(struct stasis_subscription *subscription, enum stasis_subscription_message_filter filter)
Set the message type filtering level on a subscription.
Definition: stasis.c:1079
#define NULL
Definition: resample.c:96
static struct stasis_caching_topic * device_state_topic_cached
Definition: devicestate.c:221
static const char * device_state_get_id(struct stasis_message *message)
Definition: devicestate.c:761
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...
Definition: stasis.c:1833
static struct stasis_topic_pool * device_state_topic_pool
Definition: devicestate.c:222
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
#define ast_log
Definition: astobj2.c:42
struct stasis_topic * ast_device_state_topic_all(void)
Get the Stasis topic for device state messages.
Definition: devicestate.c:668
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
static struct stasis_cache * device_state_cache
Definition: devicestate.c:220
static void device_state_aggregate_publish(struct stasis_topic *cache_topic, struct stasis_message *aggregate)
Definition: devicestate.c:787
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.
Definition: stasis_cache.c:334
struct stasis_topic * stasis_topic_create(const char *name)
Create a new topic.
Definition: stasis.c:618
#define stasis_subscribe(topic, callback, data)
Definition: stasis.h:652
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.
Definition: stasis_cache.c:109
#define LOG_ERROR
Definition: logger.h:285
struct stasis_subscription * devstate_message_sub
Definition: devicestate.c:217
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.
Definition: stasis.c:1025

◆ devstate_to_ami()

static struct ast_manager_event_blob * devstate_to_ami ( struct stasis_message msg)
static

Definition at line 938 of file devicestate.c.

References ast_devstate_str(), ast_manager_event_blob_create(), ast_device_state_message::device, ast_device_state_message::eid, EVENT_FLAG_CALL, NULL, stasis_message_data(), and ast_device_state_message::state.

939 {
940  struct ast_device_state_message *dev_state;
941 
942  dev_state = stasis_message_data(msg);
943 
944  /* Ignore non-aggregate states */
945  if (dev_state->eid) {
946  return NULL;
947  }
948 
949  return ast_manager_event_blob_create(EVENT_FLAG_CALL, "DeviceStateChange",
950  "Device: %s\r\n"
951  "State: %s\r\n",
952  dev_state->device, ast_devstate_str(dev_state->state));
953 }
enum ast_device_state state
Definition: devicestate.h:250
#define EVENT_FLAG_CALL
Definition: manager.h:72
#define NULL
Definition: resample.c:96
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.
Definition: manager.c:9727
const struct ast_eid * eid
The EID of the server where this message originated.
Definition: devicestate.h:248
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
const char * ast_devstate_str(enum ast_device_state state)
Convert device state to text string that is easier to parse.
Definition: devicestate.c:255
The structure that contains device state.
Definition: devicestate.h:240

◆ devstate_to_event()

static struct ast_event * devstate_to_event ( struct stasis_message msg)
static

Convert a stasis_message to a ast_event.

Definition at line 956 of file devicestate.c.

References AST_EVENT_DEVICE_STATE, AST_EVENT_DEVICE_STATE_CHANGE, AST_EVENT_IE_CACHABLE, AST_EVENT_IE_DEVICE, AST_EVENT_IE_EID, AST_EVENT_IE_END, AST_EVENT_IE_PLTYPE_RAW, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_IE_STATE, ast_event_new(), ast_device_state_message::cachable, ast_device_state_message::device, ast_device_state_message::eid, NULL, stasis_message_data(), and ast_device_state_message::state.

957 {
958  struct ast_event *event;
959  struct ast_device_state_message *device_state;
960 
961  if (!message) {
962  return NULL;
963  }
964 
965  device_state = stasis_message_data(message);
966 
967  if (device_state->eid) {
972  AST_EVENT_IE_EID, AST_EVENT_IE_PLTYPE_RAW, device_state->eid, sizeof(*device_state->eid),
974  } else {
980  }
981 
982  return event;
983 }
An event.
Definition: event.c:81
enum ast_device_state state
Definition: devicestate.h:250
Definition: astman.c:222
enum ast_devstate_cache cachable
Definition: devicestate.h:252
#define NULL
Definition: resample.c:96
Entity ID Used by All events Payload type: RAW This IE indicates which server the event originated fr...
Definition: event_defs.h:272
const struct ast_eid * eid
The EID of the server where this message originated.
Definition: devicestate.h:248
Event non-cachability flag Used by: All events Payload type: UINT.
Definition: event_defs.h:306
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
struct ast_event * ast_event_new(enum ast_event_type event_type,...)
Create a new event.
Definition: event.c:402
The structure that contains device state.
Definition: devicestate.h:240
Generic State IE Used by AST_EVENT_DEVICE_STATE_CHANGE Payload type: UINT The actual state values dep...
Definition: event_defs.h:121
Device Name Used by AST_EVENT_DEVICE_STATE_CHANGE Payload type: STR.
Definition: event_defs.h:113

◆ do_devstate_changes()

static void* do_devstate_changes ( void *  data)
static

Go through the dev state change queue and update changes in the dev state thread.

Definition at line 523 of file devicestate.c.

References ast_cond_wait, ast_free, AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_LOCK, AST_LIST_NEXT, AST_LIST_UNLOCK, state_change::cachable, change_pending, state_change::device, do_state_change(), state_change::list, state_changes::lock, state_change::next, NULL, and shuttingdown.

Referenced by ast_device_state_engine_init().

524 {
525  struct state_change *next, *current;
526 
527  while (!shuttingdown) {
528  /* This basically pops off any state change entries, resets the list back to NULL, unlocks, and processes each state change */
532  next = AST_LIST_FIRST(&state_changes);
535 
536  /* Process each state change */
537  while ((current = next)) {
538  next = AST_LIST_NEXT(current, list);
539  do_state_change(current->device, current->cachable);
540  ast_free(current);
541  }
542  }
543 
544  return NULL;
545 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
struct state_change * next
Definition: devicestate.c:201
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438
static void do_state_change(const char *device, enum ast_devstate_cache cachable)
Definition: devicestate.c:460
static volatile int shuttingdown
Definition: devicestate.c:215
#define ast_cond_wait(cond, mutex)
Definition: lock.h:203
struct state_change::@380 list
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
#define NULL
Definition: resample.c:96
enum ast_devstate_cache cachable
Definition: devicestate.c:202
ast_mutex_t lock
Definition: devicestate.c:208
char device[1]
Definition: devicestate.c:203
#define ast_free(a)
Definition: astmm.h:182
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:680
static ast_cond_t change_pending
Flag for the queue.
Definition: devicestate.c:214
The state change queue. State changes are queued for processing by a separate thread.
Definition: devicestate.c:208

◆ do_state_change()

static void do_state_change ( const char *  device,
enum ast_devstate_cache  cachable 
)
static

Called by the state change thread to find out what the state is, and then to queue up the state change event

Definition at line 460 of file devicestate.c.

References _ast_device_state(), ast_debug, ast_devstate2str(), ast_publish_device_state, and state.

Referenced by ast_devstate_changed_literal(), and do_devstate_changes().

461 {
462  enum ast_device_state state;
463 
464  state = _ast_device_state(device, 0);
465 
466  ast_debug(3, "Changing state for %s - state %u (%s)\n", device, state, ast_devstate2str(state));
467 
469 }
enum sip_cc_notify_state state
Definition: chan_sip.c:959
ast_device_state
Device States.
Definition: devicestate.h:52
enum ast_devstate_cache cachable
Definition: devicestate.c:202
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
const char * ast_devstate2str(enum ast_device_state devstate)
Find devicestate as text message for output.
Definition: devicestate.c:237
char device[1]
Definition: devicestate.c:203
static enum ast_device_state _ast_device_state(const char *device, int check_cache)
Check device state through channel specific function or generic function.
Definition: devicestate.c:328
#define ast_publish_device_state(device, state, cachable)
Publish a device state update.
Definition: devicestate.h:323

◆ getproviderstate()

static int getproviderstate ( const char *  provider,
const char *  address 
)
static

Get provider device state.

Definition at line 439 of file devicestate.c.

References ast_debug, AST_DEVICE_INVALID, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, devstate_prov::callback, and devstate_prov::label.

Referenced by _ast_device_state().

440 {
441  struct devstate_prov *devprov;
442  int res = AST_DEVICE_INVALID;
443 
445  AST_RWLIST_TRAVERSE(&devstate_provs, devprov, list) {
446  ast_debug(5, "Checking provider %s with %s\n", devprov->label, provider);
447 
448  if (!strcasecmp(devprov->label, provider)) {
449  res = devprov->callback(address);
450  break;
451  }
452  }
454 
455  return res;
456 }
A list of providers.
Definition: devicestate.c:198
A device state provider (not a channel)
Definition: devicestate.c:191
char * address
Definition: f2c.h:59
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
ast_devstate_prov_cb_type callback
Definition: devicestate.c:193
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
char label[40]
Definition: devicestate.c:192
static struct prometheus_metrics_provider provider
Definition: bridges.c:178

◆ STASIS_MESSAGE_TYPE_DEFN()

STASIS_MESSAGE_TYPE_DEFN ( ast_device_state_message_type  ,
to_ami = devstate_to_ami,
to_event = devstate_to_event 
)

Variable Documentation

◆ chan2dev

const struct chan2dev chan2dev[]
static

◆ change_pending

ast_cond_t change_pending
static

◆ change_thread

pthread_t change_thread = AST_PTHREADT_NULL
static

The device state change notification thread.

Definition at line 211 of file devicestate.c.

Referenced by ast_device_state_engine_init(), ast_devstate_changed_literal(), and device_state_engine_cleanup().

◆ device_state_cache

struct stasis_cache* device_state_cache
static

Definition at line 220 of file devicestate.c.

Referenced by ast_device_state_cache().

◆ device_state_topic_all

struct stasis_topic* device_state_topic_all
static

Definition at line 219 of file devicestate.c.

Referenced by ast_device_state_topic_all().

◆ device_state_topic_cached

struct stasis_caching_topic* device_state_topic_cached
static

Definition at line 221 of file devicestate.c.

◆ device_state_topic_pool

struct stasis_topic_pool* device_state_topic_pool
static

Definition at line 222 of file devicestate.c.

◆ devstate_message_sub

struct stasis_subscription* devstate_message_sub

Definition at line 217 of file devicestate.c.

◆ devstate_provs

struct devstate_provs devstate_provs = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
static

◆ devstatestring

const char* const devstatestring[][2]
static

Device state strings for printing.

Definition at line 161 of file devicestate.c.

Referenced by ast_devstate2str(), and ast_devstate_str().

◆ shuttingdown

volatile int shuttingdown
static

Definition at line 215 of file devicestate.c.

Referenced by device_state_engine_cleanup(), and do_devstate_changes().

◆ state_changes

struct state_changes state_changes = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
static