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/event.h"
Go to the source code of this file.
Data Structures | |
| struct | chan2dev |
| Mapping for channel states to device states. More... | |
| struct | change_collection |
| struct | devstate_change |
| 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... | |
Defines | |
| #define | MAX_SERVERS 64 |
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. | |
| enum ast_device_state | ast_device_state (const char *device) |
| Asks a channel for device state. | |
| int | ast_device_state_changed (const char *fmt,...) |
| Tells Asterisk the State for Device is changed. (Accept change notification, add it to change queue.) | |
| int | ast_device_state_changed_literal (const char *dev) |
| Tells Asterisk the State for Device is changed. | |
| int | ast_device_state_engine_init (void) |
| Initialize the device state engine in separate thread. | |
| const char * | ast_devstate2str (enum ast_device_state devstate) |
| Find devicestate as text message for output. | |
| 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. | |
| 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. | |
| 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. | |
| int | ast_devstate_prov_add (const char *label, ast_devstate_prov_cb_type callback) |
| Add device state provider. | |
| int | ast_devstate_prov_del (const char *label) |
| Remove device state provider. | |
| const char * | ast_devstate_str (enum ast_device_state state) |
| Convert device state to text string that is easier to parse. | |
| enum ast_device_state | ast_devstate_val (const char *val) |
| Convert device state from text to integer value. | |
| int | ast_enable_distributed_devstate (void) |
| Enable distributed device state processing. | |
| 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_state_chan2dev (enum ast_channel_state chanstate) |
| Convert channel state to devicestate. | |
| static void | destroy_devstate_change (struct devstate_change *sc) |
| const char * | devstate2str (enum ast_device_state devstate) |
| Convert device state to text string for output. | |
| static void | devstate_cache_cb (const struct ast_event *event, void *data) |
| static enum ast_device_state | devstate_cached (const char *device) |
| static void | devstate_change_collector_cb (const struct ast_event *event, void *data) |
| static void | devstate_event (const char *device, enum ast_device_state state, int cachable) |
| static void * | do_devstate_changes (void *data) |
| Go through the dev state change queue and update changes in the dev state thread. | |
| static void | do_state_change (const char *device, int cachable) |
| static int | getproviderstate (const char *provider, const char *address) |
| Get provider device state. | |
| static void | handle_devstate_change (struct devstate_change *sc) |
| static void | process_collection (const char *device, enum ast_devstate_cache cachable, struct change_collection *collection) |
| static void * | run_devstate_collector (void *data) |
Variables | |
| static struct chan2dev | chan2dev [] |
| static ast_cond_t | change_pending |
| Flag for the queue. | |
| static pthread_t | change_thread = AST_PTHREADT_NULL |
| The device state change notification thread. | |
| struct { | |
| ast_cond_t cond | |
| struct { | |
| struct devstate_change * first | |
| struct devstate_change * last | |
| } devstate_change_q | |
| unsigned int enabled:1 | |
| struct ast_event_sub * event_sub | |
| ast_mutex_t lock | |
| pthread_t thread | |
| } | devstate_collector |
| static struct devstate_provs | devstate_provs |
| static const char *const | devstatestring [][2] |
| Device state strings for printing. | |
| static struct state_changes | state_changes |
| #define MAX_SERVERS 64 |
Definition at line 570 of file devicestate.c.
Referenced by devstate_cache_cb().
| 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 310 of file devicestate.c.
References ast_debug, AST_DEVICE_INVALID, AST_DEVICE_UNKNOWN, ast_get_channel_tech(), ast_parse_device_state(), ast_channel_tech::devicestate, devstate_cached(), and getproviderstate().
Referenced by ast_device_state(), and do_state_change().
{
char *buf;
char *number;
const struct ast_channel_tech *chan_tech;
enum ast_device_state res;
/*! \brief Channel driver that provides device state */
char *tech;
/*! \brief Another provider of device state */
char *provider = NULL;
/* If the last known state is cached, just return that */
if (check_cache) {
res = devstate_cached(device);
if (res != AST_DEVICE_UNKNOWN) {
return res;
}
}
buf = ast_strdupa(device);
tech = strsep(&buf, "/");
if (!(number = buf)) {
provider = strsep(&tech, ":");
if (!tech) {
return AST_DEVICE_INVALID;
}
/* We have a provider */
number = tech;
tech = NULL;
ast_debug(3, "Checking if I can find provider for \"%s\" - number: %s\n", provider, number);
return getproviderstate(provider, number);
}
ast_debug(4, "No provider found, checking channel drivers for %s - %s\n", tech, number);
if (!(chan_tech = ast_get_channel_tech(tech)))
return AST_DEVICE_INVALID;
if (!(chan_tech->devicestate)) /* Does the channel driver support device state notification? */
return ast_parse_device_state(device); /* No, try the generic function */
res = chan_tech->devicestate(number);
if (res != AST_DEVICE_UNKNOWN)
return res;
res = ast_parse_device_state(device);
return res;
}
| enum ast_device_state ast_device_state | ( | const char * | device | ) |
Asks a channel for device state.
| device | like 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.
| an | AST_DEVICE_??? state |
Definition at line 362 of file devicestate.c.
References _ast_device_state().
{
/* This function is called from elsewhere in the code to find out the
* current state of a device. Check the cache, first. */
return _ast_device_state(device, 1);
}
| int ast_device_state_changed | ( | const char * | fmt, |
| ... | |||
| ) |
Tells Asterisk the State for Device is changed. (Accept change notification, add it to change queue.)
| fmt | device name like a dial string with format parameters |
Asterisk polls the new extension states and calls the registered callbacks for the changed extensions
| 0 | on success |
| -1 | on failure |
Definition at line 528 of file devicestate.c.
References AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, ast_devstate_changed_literal(), and AST_MAX_EXTENSION.
{
char buf[AST_MAX_EXTENSION];
va_list ap;
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
return ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, buf);
}
| int ast_device_state_changed_literal | ( | const char * | device | ) |
Tells Asterisk the State for Device is changed.
| device | device name like a dial string |
Asterisk polls the new extension states and calls the registered callbacks for the changed extensions
| 0 | on success |
| -1 | on failure |
Definition at line 511 of file devicestate.c.
References AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, and ast_devstate_changed_literal().
{
return ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, dev);
}
| int ast_device_state_engine_init | ( | void | ) |
Initialize the device state engine in separate thread.
Provided by devicestate.c
Definition at line 747 of file devicestate.c.
References ast_cond_init, ast_log(), ast_pthread_create_background, change_thread, do_devstate_changes(), and LOG_ERROR.
Referenced by main().
{
ast_cond_init(&change_pending, NULL);
if (ast_pthread_create_background(&change_thread, NULL, do_devstate_changes, NULL) < 0) {
ast_log(LOG_ERROR, "Unable to start device state change thread.\n");
return -1;
}
return 0;
}
| const char* ast_devstate2str | ( | enum ast_device_state | devstate | ) |
Find devicestate as text message for output.
Definition at line 215 of file devicestate.c.
Referenced by __queues_show(), ccss_notify_device_state_change(), do_state_change(), extension_state_cb(), handle_statechange(), notify_metermaids(), page_exec(), and process_collection().
{
return devstatestring[devstate][0];
}
| void ast_devstate_aggregate_add | ( | struct ast_devstate_aggregate * | agg, |
| enum ast_device_state | state | ||
| ) |
Add a device state to the aggregate device state.
| [in] | agg | the state object |
| [in] | state | the state to add |
Definition at line 764 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(), and process_collection().
{
static enum ast_device_state state_order[] = {
1, /* AST_DEVICE_UNKNOWN */
3, /* AST_DEVICE_NOT_INUSE */
6, /* AST_DEVICE_INUSE */
7, /* AST_DEVICE_BUSY */
0, /* AST_DEVICE_INVALID */
2, /* AST_DEVICE_UNAVAILABLE */
5, /* AST_DEVICE_RINGING */
8, /* AST_DEVICE_RINGINUSE */
4, /* AST_DEVICE_ONHOLD */
};
if (state == AST_DEVICE_RINGING) {
agg->ringing = 1;
} else if (state == AST_DEVICE_INUSE || state == AST_DEVICE_ONHOLD || state == AST_DEVICE_BUSY) {
agg->inuse = 1;
}
if (agg->ringing && agg->inuse) {
agg->state = AST_DEVICE_RINGINUSE;
} else if (state_order[state] > state_order[agg->state]) {
agg->state = state;
}
}
| void ast_devstate_aggregate_init | ( | struct ast_devstate_aggregate * | agg | ) |
Initialize aggregate device state.
| [in] | agg | the state object |
Definition at line 758 of file devicestate.c.
References AST_DEVICE_INVALID, and ast_devstate_aggregate::state.
Referenced by ast_extension_state3(), and process_collection().
{
memset(agg, 0, sizeof(*agg));
agg->state = AST_DEVICE_INVALID;
}
| enum ast_device_state ast_devstate_aggregate_result | ( | struct ast_devstate_aggregate * | agg | ) |
Get the aggregate device state result.
| [in] | agg | the state object |
Definition at line 791 of file devicestate.c.
References ast_devstate_aggregate::state.
Referenced by ast_extension_state3(), and process_collection().
{
return agg->state;
}
| 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.
| state | the new state of the device |
| cachable | whether this device state is cachable |
| fmt | device 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.
| 0 | on success |
| -1 | on failure |
Definition at line 516 of file devicestate.c.
References ast_devstate_changed_literal(), and AST_MAX_EXTENSION.
Referenced by __expire_registry(), __iax2_poke_noanswer(), add_to_queue(), calendar_devstate_change(), ccss_notify_device_state_change(), conf_handle_first_join(), conf_run(), dahdi_pri_update_span_devstate(), destroy_event(), devstate_write(), expire_register(), handle_cli_devstate_change(), handle_offhook_message(), handle_onhook_message(), handle_response_peerpoke(), handle_soft_key_event_message(), handle_statechange(), handle_stimulus_message(), init_queue(), join_queue(), leave_queue(), load_module(), login_exec(), notify_metermaids(), reg_source_db(), register_verify(), remove_from_queue(), set_member_paused(), sip_peer_hold(), sip_poke_noanswer(), skinny_register(), skinny_unregister(), sla_change_trunk_state(), sla_handle_hold_event(), sla_station_exec(), socket_process_helper(), update_call_counter(), and update_registry().
{
char buf[AST_MAX_EXTENSION];
va_list ap;
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
return ast_devstate_changed_literal(state, cachable, buf);
}
| 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.
| state | the new state of the device |
| cachable | whether this device state is cachable |
| device | device 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.
| 0 | on success |
| -1 | on failure |
Definition at line 472 of file devicestate.c.
References ast_calloc, ast_cond_signal, AST_DEVICE_UNKNOWN, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, state_change::cachable, change_thread, state_change::device, devstate_event(), and do_state_change().
Referenced by ast_channel_destructor(), ast_device_state_changed(), ast_device_state_changed_literal(), ast_devstate_changed(), ast_setstate(), and dahdi_new().
{
struct state_change *change;
/*
* If we know the state change (how nice of the caller of this function!)
* then we can just generate a device state event.
*
* Otherwise, we do the following:
* - Queue an event up to another thread that the state has changed
* - In the processing thread, it calls the callback provided by the
* device state provider (which may or may not be a channel driver)
* to determine the state.
* - If the device state provider does not know the state, or this is
* for a channel and the channel driver does not implement a device
* state callback, then we will look through the channel list to
* see if we can determine a state based on active calls.
* - Once a state has been determined, a device state event is generated.
*/
if (state != AST_DEVICE_UNKNOWN) {
devstate_event(device, state, cachable);
} else if (change_thread == AST_PTHREADT_NULL || !(change = ast_calloc(1, sizeof(*change) + strlen(device)))) {
/* we could not allocate a change struct, or */
/* there is no background thread, so process the change now */
do_state_change(device, cachable);
} else {
/* queue the change */
strcpy(change->device, device);
change->cachable = cachable;
AST_LIST_LOCK(&state_changes);
AST_LIST_INSERT_TAIL(&state_changes, change, list);
ast_cond_signal(&change_pending);
AST_LIST_UNLOCK(&state_changes);
}
return 0;
}
| int ast_devstate_prov_add | ( | const char * | label, |
| ast_devstate_prov_cb_type | callback | ||
| ) |
Add device state provider.
| label | to use in hint, like label:object |
| callback | Callback |
| 0 | success |
| -1 | failure |
Definition at line 371 of file devicestate.c.
References ast_calloc, ast_copy_string(), AST_RWLIST_INSERT_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, devstate_prov::callback, and devstate_prov::label.
Referenced by ast_cc_init(), ast_features_init(), and load_module().
{
struct devstate_prov *devprov;
if (!callback || !(devprov = ast_calloc(1, sizeof(*devprov))))
return -1;
devprov->callback = callback;
ast_copy_string(devprov->label, label, sizeof(devprov->label));
AST_RWLIST_WRLOCK(&devstate_provs);
AST_RWLIST_INSERT_HEAD(&devstate_provs, devprov, list);
AST_RWLIST_UNLOCK(&devstate_provs);
return 0;
}
| int ast_devstate_prov_del | ( | const char * | label | ) |
Remove device state provider.
| label | to use in hint, like label:object |
| -1 | on failure |
| 0 | on success |
Definition at line 389 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 cc_shutdown(), features_shutdown(), and unload_module().
{
struct devstate_prov *devcb;
int res = -1;
AST_RWLIST_WRLOCK(&devstate_provs);
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&devstate_provs, devcb, list) {
if (!strcasecmp(devcb->label, label)) {
AST_RWLIST_REMOVE_CURRENT(list);
ast_free(devcb);
res = 0;
break;
}
}
AST_RWLIST_TRAVERSE_SAFE_END;
AST_RWLIST_UNLOCK(&devstate_provs);
return res;
}
| const char* ast_devstate_str | ( | enum ast_device_state | devstate | ) |
Convert device state to text string that is easier to parse.
| devstate | Current device state |
Definition at line 239 of file devicestate.c.
References state.
Referenced by aji_devstate_cb(), devstate_read(), and xmpp_pubsub_devstate_cb().
{
return devstatestring[state][1];
}
| enum ast_device_state ast_devstate_val | ( | const char * | val | ) |
Convert device state from text to integer value.
| val | The text representing the device state. Valid values are anything that comes after AST_DEVICE_ in one of the defined values. |
Definition at line 244 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 aji_handle_pubsub_event(), custom_devstate_callback(), devstate_write(), handle_cli_devstate_change(), initialize_cc_devstate_map_helper(), load_module(), and xmpp_pubsub_handle_event().
{
if (!strcasecmp(val, "NOT_INUSE"))
return AST_DEVICE_NOT_INUSE;
else if (!strcasecmp(val, "INUSE"))
return AST_DEVICE_INUSE;
else if (!strcasecmp(val, "BUSY"))
return AST_DEVICE_BUSY;
else if (!strcasecmp(val, "INVALID"))
return AST_DEVICE_INVALID;
else if (!strcasecmp(val, "UNAVAILABLE"))
return AST_DEVICE_UNAVAILABLE;
else if (!strcasecmp(val, "RINGING"))
return AST_DEVICE_RINGING;
else if (!strcasecmp(val, "RINGINUSE"))
return AST_DEVICE_RINGINUSE;
else if (!strcasecmp(val, "ONHOLD"))
return AST_DEVICE_ONHOLD;
return AST_DEVICE_UNKNOWN;
}
| int ast_enable_distributed_devstate | ( | void | ) |
Enable distributed device state processing.
By default, Asterisk assumes that device state change events will only be originating from one instance. If a module gets loaded and configured such that multiple instances of Asterisk will be sharing device state, this function should be called to enable distributed device state processing. It is off by default to save on unnecessary processing.
| 0 | success |
| -1 | failure |
Definition at line 796 of file devicestate.c.
References ast_cond_init, AST_EVENT_DEVICE_STATE_CHANGE, AST_EVENT_IE_END, ast_event_subscribe(), ast_log(), ast_mutex_init, ast_pthread_create_background, devstate_change_collector_cb(), devstate_collector, LOG_ERROR, and run_devstate_collector().
Referenced by aji_init_event_distribution(), load_module(), and xmpp_init_event_distribution().
{
if (devstate_collector.enabled) {
return 0;
}
devstate_collector.event_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE_CHANGE,
devstate_change_collector_cb, "devicestate_engine_enable_distributed", NULL, AST_EVENT_IE_END);
if (!devstate_collector.event_sub) {
ast_log(LOG_ERROR, "Failed to create subscription for the device state change collector\n");
return -1;
}
ast_mutex_init(&devstate_collector.lock);
ast_cond_init(&devstate_collector.cond, NULL);
if (ast_pthread_create_background(&devstate_collector.thread, NULL, run_devstate_collector, NULL) < 0) {
ast_log(LOG_ERROR, "Unable to start device state collector thread.\n");
return -1;
}
devstate_collector.enabled = 1;
return 0;
}
| 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.
Definition at line 271 of file devicestate.c.
References ast_channel_get_by_name_prefix(), AST_CHANNEL_NAME, ast_channel_unref, AST_DEVICE_INUSE, AST_DEVICE_RINGING, AST_DEVICE_UNKNOWN, AST_STATE_RINGING, and match().
Referenced by _ast_device_state(), and chanavail_exec().
{
struct ast_channel *chan;
char match[AST_CHANNEL_NAME];
enum ast_device_state res;
snprintf(match, sizeof(match), "%s-", device);
if (!(chan = ast_channel_get_by_name_prefix(match, strlen(match)))) {
return AST_DEVICE_UNKNOWN;
}
res = (ast_channel_state(chan) == AST_STATE_RINGING) ? AST_DEVICE_RINGING : AST_DEVICE_INUSE;
chan = ast_channel_unref(chan);
return res;
}
| enum ast_device_state ast_state_chan2dev | ( | enum ast_channel_state | chanstate | ) |
Convert channel state to devicestate.
| chanstate | Current channel state |
Definition at line 226 of file devicestate.c.
References AST_DEVICE_UNKNOWN, chan2dev::chan, and chan2dev::dev.
| static void destroy_devstate_change | ( | struct devstate_change * | sc | ) | [static] |
Definition at line 565 of file devicestate.c.
References ast_free.
Referenced by run_devstate_collector().
{
ast_free(sc);
}
| const char* devstate2str | ( | enum ast_device_state | devstate | ) |
Convert device state to text string for output.
| devstate | Current device state |
Definition at line 221 of file devicestate.c.
{
return devstatestring[devstate][0];
}
| static void devstate_cache_cb | ( | const struct ast_event * | event, |
| void * | data | ||
| ) | [static] |
Definition at line 576 of file devicestate.c.
References ARRAY_LEN, ast_event_get_ie_raw(), ast_event_get_ie_uint(), AST_EVENT_IE_EID, AST_EVENT_IE_STATE, ast_log(), devstate_change::eid, ast_eid::eid, LOG_ERROR, MAX_SERVERS, change_collection::num_states, devstate_change::state, and change_collection::states.
Referenced by handle_devstate_change().
{
struct change_collection *collection = data;
int i;
const struct ast_eid *eid;
if (collection->num_states == ARRAY_LEN(collection->states)) {
ast_log(LOG_ERROR, "More per-server state values than we have room for (MAX_SERVERS is %d)\n",
MAX_SERVERS);
return;
}
if (!(eid = ast_event_get_ie_raw(event, AST_EVENT_IE_EID))) {
ast_log(LOG_ERROR, "Device state change event with no EID\n");
return;
}
i = collection->num_states;
collection->states[i].state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
collection->states[i].eid = *eid;
collection->num_states++;
}
| static enum ast_device_state devstate_cached | ( | const char * | device | ) | [static] |
Definition at line 290 of file devicestate.c.
References AST_DEVICE_UNKNOWN, ast_event_destroy(), AST_EVENT_DEVICE_STATE, ast_event_get_cached(), ast_event_get_ie_uint(), AST_EVENT_IE_DEVICE, AST_EVENT_IE_END, AST_EVENT_IE_PLTYPE_STR, and AST_EVENT_IE_STATE.
Referenced by _ast_device_state().
{
enum ast_device_state res = AST_DEVICE_UNKNOWN;
struct ast_event *event;
event = ast_event_get_cached(AST_EVENT_DEVICE_STATE,
AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device,
AST_EVENT_IE_END);
if (!event)
return res;
res = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
ast_event_destroy(event);
return res;
}
| static void devstate_change_collector_cb | ( | const struct ast_event * | event, |
| void * | data | ||
| ) | [static] |
Definition at line 705 of file devicestate.c.
References ast_calloc, ast_cond_signal, AST_DEVSTATE_CACHABLE, ast_event_get_ie_raw(), ast_event_get_ie_str(), ast_event_get_ie_uint(), AST_EVENT_IE_CACHABLE, AST_EVENT_IE_DEVICE, AST_EVENT_IE_EID, AST_EVENT_IE_STATE, AST_LIST_INSERT_TAIL, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero(), devstate_change::cachable, devstate_change::device, devstate_collector, devstate_change::eid, ast_eid::eid, LOG_ERROR, devstate_change::state, and state.
Referenced by ast_enable_distributed_devstate().
{
struct devstate_change *sc;
const char *device, *cachable_str;
const struct ast_eid *eid;
uint32_t state;
enum ast_devstate_cache cachable = AST_DEVSTATE_CACHABLE;
device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
eid = ast_event_get_ie_raw(event, AST_EVENT_IE_EID);
state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
if (ast_strlen_zero(device) || !eid) {
ast_log(LOG_ERROR, "Invalid device state change event received\n");
return;
}
if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device))))
return;
strcpy(sc->device, device);
sc->eid = *eid;
sc->state = state;
/* For 'cachable' we cannot use ast_event_get_ie_uint(), it overwrites the default of AST_DEVSTATE_CACHABLE we
* have already setup for 'cachable', if for whatever reason the AST_EVENT_IE_CACHABLE wasn't
* posted in the event ast_event_get_ie_uint() is going will return 0,
* which equates to AST_DEVSTATE_NOT_CACHABLE the first enumeration in 'ast_devstate_cache'.
*/
if ((cachable_str = ast_event_get_ie_str(event, AST_EVENT_IE_CACHABLE))) {
sscanf(cachable_str, "%30u", &cachable);
}
sc->cachable = cachable;
ast_mutex_lock(&devstate_collector.lock);
AST_LIST_INSERT_TAIL(&devstate_collector.devstate_change_q, sc, entry);
ast_cond_signal(&devstate_collector.cond);
ast_mutex_unlock(&devstate_collector.lock);
}
| static void devstate_event | ( | const char * | device, |
| enum ast_device_state | state, | ||
| int | cachable | ||
| ) | [static] |
Definition at line 429 of file devicestate.c.
References ast_debug, AST_EVENT_DEVICE_STATE, AST_EVENT_DEVICE_STATE_CHANGE, AST_EVENT_IE_CACHABLE, AST_EVENT_IE_DEVICE, AST_EVENT_IE_END, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_IE_STATE, ast_event_new(), ast_event_queue(), ast_event_queue_and_cache(), and devstate_collector.
Referenced by ast_devstate_changed_literal(), and do_state_change().
{
struct ast_event *event;
enum ast_event_type event_type;
if (devstate_collector.enabled) {
/* Distributed device state is enabled, so this state change is a change
* for a single server, not the real state. */
event_type = AST_EVENT_DEVICE_STATE_CHANGE;
} else {
event_type = AST_EVENT_DEVICE_STATE;
}
ast_debug(3, "device '%s' state '%d'\n", device, state);
if (!(event = ast_event_new(event_type,
AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device,
AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_UINT, state,
AST_EVENT_IE_CACHABLE, AST_EVENT_IE_PLTYPE_UINT, cachable,
AST_EVENT_IE_END))) {
return;
}
if (cachable) {
ast_event_queue_and_cache(event);
} else {
ast_event_queue(event);
}
}
| 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 541 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, state_change::device, do_state_change(), and state_change::next.
Referenced by ast_device_state_engine_init().
{
struct state_change *next, *current;
for (;;) {
/* This basically pops off any state change entries, resets the list back to NULL, unlocks, and processes each state change */
AST_LIST_LOCK(&state_changes);
if (AST_LIST_EMPTY(&state_changes))
ast_cond_wait(&change_pending, &state_changes.lock);
next = AST_LIST_FIRST(&state_changes);
AST_LIST_HEAD_INIT_NOLOCK(&state_changes);
AST_LIST_UNLOCK(&state_changes);
/* Process each state change */
while ((current = next)) {
next = AST_LIST_NEXT(current, list);
do_state_change(current->device, current->cachable);
ast_free(current);
}
}
return NULL;
}
| static void do_state_change | ( | const char * | device, |
| int | 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 461 of file devicestate.c.
References _ast_device_state(), ast_debug, ast_devstate2str(), devstate_event(), and state.
Referenced by ast_devstate_changed_literal(), and do_devstate_changes().
{
enum ast_device_state state;
state = _ast_device_state(device, 0);
ast_debug(3, "Changing state for %s - state %d (%s)\n", device, state, ast_devstate2str(state));
devstate_event(device, state, cachable);
}
| static int getproviderstate | ( | const char * | provider, |
| const char * | address | ||
| ) | [static] |
Get provider device state.
Definition at line 410 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().
{
struct devstate_prov *devprov;
int res = AST_DEVICE_INVALID;
AST_RWLIST_RDLOCK(&devstate_provs);
AST_RWLIST_TRAVERSE(&devstate_provs, devprov, list) {
ast_debug(5, "Checking provider %s with %s\n", devprov->label, provider);
if (!strcasecmp(devprov->label, provider)) {
res = devprov->callback(address);
break;
}
}
AST_RWLIST_UNLOCK(&devstate_provs);
return res;
}
| static void handle_devstate_change | ( | struct devstate_change * | sc | ) | [static] |
Definition at line 659 of file devicestate.c.
References ast_debug, AST_EVENT_DEVICE_STATE_CHANGE, ast_event_dump_cache(), AST_EVENT_IE_DEVICE, ast_event_sub_append_ie_str(), ast_event_sub_destroy(), ast_event_subscribe_new(), ast_log(), devstate_change::cachable, devstate_change::device, devstate_cache_cb(), LOG_ERROR, change_collection::num_states, and process_collection().
Referenced by run_devstate_collector().
{
struct ast_event_sub *tmp_sub;
struct change_collection collection = {
.num_states = 0,
};
ast_debug(1, "Processing device state change for '%s'\n", sc->device);
if (!(tmp_sub = ast_event_subscribe_new(AST_EVENT_DEVICE_STATE_CHANGE, devstate_cache_cb, &collection))) {
ast_log(LOG_ERROR, "Failed to create subscription\n");
return;
}
if (ast_event_sub_append_ie_str(tmp_sub, AST_EVENT_IE_DEVICE, sc->device)) {
ast_log(LOG_ERROR, "Failed to append device IE\n");
ast_event_sub_destroy(tmp_sub);
return;
}
/* Populate the collection of device states from the cache */
ast_event_dump_cache(tmp_sub);
process_collection(sc->device, sc->cachable, &collection);
ast_event_sub_destroy(tmp_sub);
}
| static void process_collection | ( | const char * | device, |
| enum ast_devstate_cache | cachable, | ||
| struct change_collection * | collection | ||
| ) | [static] |
Definition at line 601 of file devicestate.c.
References ast_debug, ast_devstate2str(), ast_devstate_aggregate_add(), ast_devstate_aggregate_init(), ast_devstate_aggregate_result(), ast_event_destroy(), AST_EVENT_DEVICE_STATE, ast_event_get_cached(), ast_event_get_ie_uint(), AST_EVENT_IE_DEVICE, AST_EVENT_IE_END, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_IE_STATE, ast_event_new(), ast_event_queue(), ast_event_queue_and_cache(), change_collection::num_states, devstate_change::state, state, and change_collection::states.
Referenced by handle_devstate_change().
{
int i;
struct ast_devstate_aggregate agg;
enum ast_device_state state;
struct ast_event *event;
ast_devstate_aggregate_init(&agg);
for (i = 0; i < collection->num_states; i++) {
ast_debug(1, "Adding per-server state of '%s' for '%s'\n",
ast_devstate2str(collection->states[i].state), device);
ast_devstate_aggregate_add(&agg, collection->states[i].state);
}
state = ast_devstate_aggregate_result(&agg);
ast_debug(1, "Aggregate devstate result is '%s' for '%s'\n",
ast_devstate2str(state), device);
event = ast_event_get_cached(AST_EVENT_DEVICE_STATE,
AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device,
AST_EVENT_IE_END);
if (event) {
enum ast_device_state old_state;
old_state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
ast_event_destroy(event);
if (state == old_state) {
/* No change since last reported device state */
ast_debug(1, "Aggregate state for device '%s' has not changed from '%s'\n",
device, ast_devstate2str(state));
return;
}
}
ast_debug(1, "Aggregate state for device '%s' has changed to '%s'\n",
device, ast_devstate2str(state));
event = ast_event_new(AST_EVENT_DEVICE_STATE,
AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device,
AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_UINT, state,
AST_EVENT_IE_END);
if (!event) {
return;
}
if (cachable) {
ast_event_queue_and_cache(event);
} else {
ast_event_queue(event);
}
}
| static void* run_devstate_collector | ( | void * | data | ) | [static] |
Definition at line 687 of file devicestate.c.
References ast_cond_wait, AST_LIST_REMOVE_HEAD, ast_mutex_lock, ast_mutex_unlock, destroy_devstate_change(), devstate_collector, and handle_devstate_change().
Referenced by ast_enable_distributed_devstate().
{
for (;;) {
struct devstate_change *sc;
ast_mutex_lock(&devstate_collector.lock);
while (!(sc = AST_LIST_REMOVE_HEAD(&devstate_collector.devstate_change_q, entry)))
ast_cond_wait(&devstate_collector.cond, &devstate_collector.lock);
ast_mutex_unlock(&devstate_collector.lock);
handle_devstate_change(sc);
destroy_devstate_change(sc);
}
return NULL;
}
ast_cond_t change_pending [static] |
Flag for the queue.
Definition at line 189 of file devicestate.c.
pthread_t change_thread = AST_PTHREADT_NULL [static] |
The device state change notification thread.
Definition at line 186 of file devicestate.c.
Referenced by ast_device_state_engine_init(), and ast_devstate_changed_literal().
Definition at line 202 of file devicestate.c.
| struct { ... } devstate_change_q |
struct { ... } devstate_collector [static] |
struct devstate_provs devstate_provs [static] |
const char* const devstatestring[][2] [static] |
Device state strings for printing.
Definition at line 135 of file devicestate.c.
| unsigned int enabled |
Definition at line 205 of file devicestate.c.
Referenced by __ast_http_load(), load_odbc_config(), and osp_check_destination().
| struct ast_event_sub* event_sub |
Definition at line 201 of file devicestate.c.
Referenced by cpg_confchg_cb(), and dump_cache_cb().
| struct devstate_change* first |
Definition at line 204 of file devicestate.c.
| struct devstate_change* last |
Definition at line 204 of file devicestate.c.
Definition at line 203 of file devicestate.c.
struct state_changes state_changes [static] |
| pthread_t thread |
Definition at line 200 of file devicestate.c.