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...

Defines

#define DEVSTATE_TOPIC_BUCKETS   57

Functions

static void __fini_devstate_provs (void)
static void __init_devstate_provs (void)
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.
struct stasis_cacheast_device_state_cache (void)
 Backend cache for ast_device_state_topic_cached().
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_clear_cache (const char *device)
 Clear the device from the stasis cache.
int ast_device_state_engine_init (void)
 Initialize the device state engine in separate thread.
struct stasis_topicast_device_state_topic (const char *device)
 Get the Stasis topic for device state messages for a specific device.
struct stasis_topicast_device_state_topic_all (void)
 Get the Stasis topic for device state messages.
struct stasis_topicast_device_state_topic_cached (void)
 Get the Stasis caching topic for device state messages.
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.
enum ast_device_state ast_parse_device_state (const char *device)
 Find out if device is active in a call or not.
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.
enum ast_device_state ast_state_chan2dev (enum ast_channel_state chanstate)
 Convert channel state to devicestate.
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_message
device_state_alloc (const char *device, enum ast_device_state state, enum ast_devstate_cache cachable, const struct ast_eid *eid)
static const char * device_state_get_id (struct stasis_message *message)
const char * devstate2str (enum ast_device_state devstate)
 Convert device state to text string for output.
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.
static struct
ast_manager_event_blob
devstate_to_ami (struct stasis_message *msg)
static struct ast_eventdevstate_to_event (struct stasis_message *message)
 Convert a stasis_message to a ast_event.
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, enum ast_devstate_cache cachable)
static int getproviderstate (const char *provider, const char *address)
 Get provider device state.
 STASIS_MESSAGE_TYPE_DEFN (ast_device_state_message_type,.to_ami=devstate_to_ami,.to_event=devstate_to_event,)

Variables

static ast_cond_t change_pending
 Flag for the queue.
static pthread_t change_thread = AST_PTHREADT_NULL
 The device state change notification thread.
static struct stasis_cachedevice_state_cache
static struct stasis_topicdevice_state_topic_all
static struct
stasis_caching_topic
device_state_topic_cached
static struct stasis_topic_pooldevice_state_topic_pool
struct stasis_subscriptiondevstate_message_sub
static const char *const devstatestring [][2]
 Device state strings for printing.


Detailed Description

Device state management.

Author:
Mark Spencer <markster@digium.com>

Russell Bryant <russell@digium.com>

Definition in file devicestate.c.


Define Documentation

#define DEVSTATE_TOPIC_BUCKETS   57

Definition at line 160 of file devicestate.c.


Function Documentation

static void __fini_devstate_provs ( void   )  [static]

Definition at line 200 of file devicestate.c.

00202 {

static void __init_devstate_provs ( void   )  [static]

Definition at line 200 of file devicestate.c.

00202 {

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 335 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(), and strsep().

Referenced by ast_device_state(), and do_state_change().

00336 {
00337    char *number;
00338    const struct ast_channel_tech *chan_tech;
00339    enum ast_device_state res;
00340    /*! \brief Channel driver that provides device state */
00341    char *tech;
00342 
00343    /* If the last known state is cached, just return that */
00344    if (check_cache) {
00345       res = devstate_cached(device);
00346       if (res != AST_DEVICE_UNKNOWN) {
00347          return res;
00348       }
00349    }
00350 
00351    number = ast_strdupa(device);
00352    tech = strsep(&number, "/");
00353    if (!number) {
00354       /*! \brief Another provider of device state */
00355       char *provider;
00356 
00357       provider = strsep(&tech, ":");
00358       if (!tech) {
00359          return AST_DEVICE_INVALID;
00360       }
00361       /* We have a provider */
00362       number = tech;
00363 
00364       ast_debug(3, "Checking if I can find provider for \"%s\" - number: %s\n", provider, number);
00365       return getproviderstate(provider, number);
00366    }
00367 
00368    ast_debug(4, "No provider found, checking channel drivers for %s - %s\n", tech, number);
00369 
00370    chan_tech = ast_get_channel_tech(tech);
00371    if (!chan_tech) {
00372       return AST_DEVICE_INVALID;
00373    }
00374 
00375    /* Does the channel driver support device state notification? */
00376    if (!chan_tech->devicestate) {
00377       /* No, try the generic function */
00378       return ast_parse_device_state(device);
00379    }
00380 
00381    res = chan_tech->devicestate(number);
00382    if (res == AST_DEVICE_UNKNOWN) {
00383       res = ast_parse_device_state(device);
00384    }
00385 
00386    return res;
00387 }

enum ast_device_state ast_device_state ( const char *  device  ) 

Asks a channel for device state.

Parameters:
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.

Return values:
an AST_DEVICE_??? state

Definition at line 389 of file devicestate.c.

References _ast_device_state().

00390 {
00391    /* This function is called from elsewhere in the code to find out the
00392     * current state of a device.  Check the cache, first. */
00393 
00394    return _ast_device_state(device, 1);
00395 }

struct stasis_cache* ast_device_state_cache ( void   )  [read]

int ast_device_state_changed ( const char *  fmt,
  ... 
)

Tells Asterisk the State for Device is changed. (Accept change notification, add it to change queue.).

Parameters:
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

Return values:
0 on success
-1 on failure
Note:
This is deprecated in favor of ast_devstate_changed()
Version:
1.6.1 deprecated

Definition at line 525 of file devicestate.c.

References AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, ast_devstate_changed_literal(), AST_MAX_EXTENSION, and buf.

00526 {
00527    char buf[AST_MAX_EXTENSION];
00528    va_list ap;
00529 
00530    va_start(ap, fmt);
00531    vsnprintf(buf, sizeof(buf), fmt, ap);
00532    va_end(ap);
00533 
00534    return ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, buf);
00535 }

int ast_device_state_changed_literal ( const char *  device  ) 

Tells Asterisk the State for Device is changed.

Parameters:
device device name like a dial string
Asterisk polls the new extension states and calls the registered callbacks for the changed extensions

Return values:
0 on success
-1 on failure
Note:
This is deprecated in favor of ast_devstate_changed_literal()
Version:
1.6.1 deprecated

Definition at line 508 of file devicestate.c.

References AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, and ast_devstate_changed_literal().

int ast_device_state_clear_cache ( const char *  device  ) 

Clear the device from the stasis cache.

Parameters:
The device to clear
Return values:
0 if successful
-1 nothing to clear
Since:
12

Definition at line 690 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().

00691 {
00692    struct stasis_message *cached_msg;
00693    struct stasis_message *msg;
00694 
00695    cached_msg = stasis_cache_get_by_eid(ast_device_state_cache(),
00696       ast_device_state_message_type(), device, &ast_eid_default);
00697    if (!cached_msg) {
00698       /* nothing to clear */
00699       return -1;
00700    }
00701 
00702    msg = stasis_cache_clear_create(cached_msg);
00703    if (msg) {
00704       stasis_publish(ast_device_state_topic(device), msg);
00705    }
00706    ao2_cleanup(msg);
00707    ao2_cleanup(cached_msg);
00708    return 0;
00709 }

int ast_device_state_engine_init ( void   ) 

Initialize the device state engine in separate thread.

Provided by devicestate.c

Definition at line 621 of file devicestate.c.

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

Referenced by main().

00622 {
00623    ast_cond_init(&change_pending, NULL);
00624    if (ast_pthread_create_background(&change_thread, NULL, do_devstate_changes, NULL) < 0) {
00625       ast_log(LOG_ERROR, "Unable to start device state change thread.\n");
00626       return -1;
00627    }
00628 
00629    return 0;
00630 }

struct stasis_topic* ast_device_state_topic ( const char *  device  )  [read]

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

Parameters:
uniqueid The device for which to get the topic
Return values:
The topic structure for MWI messages for a given device
NULL if it failed to be found or allocated
Since:
12

Definition at line 685 of file devicestate.c.

References device_state_topic_pool, and 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().

00686 {
00687    return stasis_topic_pool_get_topic(device_state_topic_pool, device);
00688 }

struct stasis_topic* ast_device_state_topic_all ( void   )  [read]

Get the Stasis topic for device state messages.

Return values:
The topic for device state messages
NULL if it has not been allocated
Since:
12

Definition at line 670 of file devicestate.c.

References device_state_topic_all.

Referenced by asterisk_start_devicestate_publishing(), devstate_init(), load_module(), load_pbx(), and xmpp_init_event_distribution().

00671 {
00672    return device_state_topic_all;
00673 }

struct stasis_topic* ast_device_state_topic_cached ( void   )  [read]

Get the Stasis caching topic for device state messages.

Return values:
The caching topic for device state messages
NULL if it has not been allocated
Since:
12

Definition at line 680 of file devicestate.c.

References device_state_topic_cached, and stasis_caching_get_topic().

Referenced by AST_TEST_DEFINE().

00681 {
00682    return stasis_caching_get_topic(device_state_topic_cached);
00683 }

const char* ast_devstate2str ( enum ast_device_state  devstate  ) 

Find devicestate as text message for output.

Definition at line 238 of file devicestate.c.

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

00239 {
00240    return devstatestring[devstate][0];
00241 }

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] agg the state object
[in] state the state to add
Returns:
nothing
Since:
1.6.1

Definition at line 638 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, and ast_devstate_aggregate::state.

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

00639 {
00640    static enum ast_device_state state_order[] = {
00641       1, /* AST_DEVICE_UNKNOWN */
00642       3, /* AST_DEVICE_NOT_INUSE */
00643       6, /* AST_DEVICE_INUSE */
00644       7, /* AST_DEVICE_BUSY */
00645       0, /* AST_DEVICE_INVALID */
00646       2, /* AST_DEVICE_UNAVAILABLE */
00647       5, /* AST_DEVICE_RINGING */
00648       8, /* AST_DEVICE_RINGINUSE */
00649       4, /* AST_DEVICE_ONHOLD */
00650    };
00651 
00652    if (state == AST_DEVICE_RINGING) {
00653       agg->ringing = 1;
00654    } else if (state == AST_DEVICE_INUSE || state == AST_DEVICE_ONHOLD || state == AST_DEVICE_BUSY) {
00655       agg->inuse = 1;
00656    }
00657 
00658    if (agg->ringing && agg->inuse) {
00659       agg->state = AST_DEVICE_RINGINUSE;
00660    } else if (state_order[state] > state_order[agg->state]) {
00661       agg->state = state;
00662    }
00663 }

void ast_devstate_aggregate_init ( struct ast_devstate_aggregate agg  ) 

Initialize aggregate device state.

Parameters:
[in] agg the state object
Returns:
nothing
Since:
1.6.1

Definition at line 632 of file devicestate.c.

References AST_DEVICE_INVALID, and ast_devstate_aggregate::state.

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

00633 {
00634    memset(agg, 0, sizeof(*agg));
00635    agg->state = AST_DEVICE_INVALID;
00636 }

enum ast_device_state ast_devstate_aggregate_result ( struct ast_devstate_aggregate agg  ) 

Get the aggregate device state result.

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

Definition at line 665 of file devicestate.c.

References ast_devstate_aggregate::state.

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

00666 {
00667    return agg->state;
00668 }

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:
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.

Return values:
0 on success
-1 on failure

Definition at line 513 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(), 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_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(), parking_notify_metermaids(), persistent_endpoint_update_state(), populate_cache(), queue_function_mem_write(), reg_source_db(), register_verify(), remove_from_queue(), rt_handle_member_record(), set_member_paused(), 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().

00514 {
00515    char buf[AST_MAX_EXTENSION];
00516    va_list ap;
00517 
00518    va_start(ap, fmt);
00519    vsnprintf(buf, sizeof(buf), fmt, ap);
00520    va_end(ap);
00521 
00522    return ast_devstate_changed_literal(state, cachable, buf);
00523 }

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:
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.

Return values:
0 on success
-1 on failure

Definition at line 469 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, and do_state_change().

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

00470 {
00471    struct state_change *change;
00472 
00473    /*
00474     * If we know the state change (how nice of the caller of this function!)
00475     * then we can just generate a device state event.
00476     *
00477     * Otherwise, we do the following:
00478     *   - Queue an event up to another thread that the state has changed
00479     *   - In the processing thread, it calls the callback provided by the
00480     *     device state provider (which may or may not be a channel driver)
00481     *     to determine the state.
00482     *   - If the device state provider does not know the state, or this is
00483     *     for a channel and the channel driver does not implement a device
00484     *     state callback, then we will look through the channel list to
00485     *     see if we can determine a state based on active calls.
00486     *   - Once a state has been determined, a device state event is generated.
00487     */
00488 
00489    if (state != AST_DEVICE_UNKNOWN) {
00490       ast_publish_device_state(device, state, cachable);
00491    } else if (change_thread == AST_PTHREADT_NULL || !(change = ast_calloc(1, sizeof(*change) + strlen(device)))) {
00492       /* we could not allocate a change struct, or */
00493       /* there is no background thread, so process the change now */
00494       do_state_change(device, cachable);
00495    } else {
00496       /* queue the change */
00497       strcpy(change->device, device);
00498       change->cachable = cachable;
00499       AST_LIST_LOCK(&state_changes);
00500       AST_LIST_INSERT_TAIL(&state_changes, change, list);
00501       ast_cond_signal(&change_pending);
00502       AST_LIST_UNLOCK(&state_changes);
00503    }
00504 
00505    return 0;
00506 }

int ast_devstate_prov_add ( const char *  label,
ast_devstate_prov_cb_type  callback 
)

Add device state provider.

Parameters:
label to use in hint, like label:object
callback Callback
Return values:
0 success
-1 failure

Definition at line 398 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(), load_module(), and load_parking_devstate().

00399 {
00400    struct devstate_prov *devprov;
00401 
00402    if (!callback || !(devprov = ast_calloc(1, sizeof(*devprov))))
00403       return -1;
00404 
00405    devprov->callback = callback;
00406    ast_copy_string(devprov->label, label, sizeof(devprov->label));
00407 
00408    AST_RWLIST_WRLOCK(&devstate_provs);
00409    AST_RWLIST_INSERT_HEAD(&devstate_provs, devprov, list);
00410    AST_RWLIST_UNLOCK(&devstate_provs);
00411 
00412    return 0;
00413 }

int ast_devstate_prov_del ( const char *  label  ) 

Remove device state provider.

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

Definition at line 416 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(), unload_module(), and unload_parking_devstate().

00417 {
00418    struct devstate_prov *devcb;
00419    int res = -1;
00420 
00421    AST_RWLIST_WRLOCK(&devstate_provs);
00422    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&devstate_provs, devcb, list) {
00423       if (!strcasecmp(devcb->label, label)) {
00424          AST_RWLIST_REMOVE_CURRENT(list);
00425          ast_free(devcb);
00426          res = 0;
00427          break;
00428       }
00429    }
00430    AST_RWLIST_TRAVERSE_SAFE_END;
00431    AST_RWLIST_UNLOCK(&devstate_provs);
00432 
00433    return res;
00434 }

const char* ast_devstate_str ( enum ast_device_state  devstate  ) 

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

Parameters:
devstate Current device state

Definition at line 262 of file devicestate.c.

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

00263 {
00264    return devstatestring[state][1];
00265 }

enum ast_device_state ast_devstate_val ( const char *  val  ) 

Convert device state from text to integer value.

Parameters:
val The 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 267 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 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().

00268 {
00269    if (!strcasecmp(val, "NOT_INUSE"))
00270       return AST_DEVICE_NOT_INUSE;
00271    else if (!strcasecmp(val, "INUSE"))
00272       return AST_DEVICE_INUSE;
00273    else if (!strcasecmp(val, "BUSY"))
00274       return AST_DEVICE_BUSY;
00275    else if (!strcasecmp(val, "INVALID"))
00276       return AST_DEVICE_INVALID;
00277    else if (!strcasecmp(val, "UNAVAILABLE"))
00278       return AST_DEVICE_UNAVAILABLE;
00279    else if (!strcasecmp(val, "RINGING"))
00280       return AST_DEVICE_RINGING;
00281    else if (!strcasecmp(val, "RINGINUSE"))
00282       return AST_DEVICE_RINGINUSE;
00283    else if (!strcasecmp(val, "ONHOLD"))
00284       return AST_DEVICE_ONHOLD;
00285 
00286    return AST_DEVICE_UNKNOWN;
00287 }

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 294 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(), and match().

Referenced by _ast_device_state(), and chanavail_exec().

00295 {
00296    struct ast_channel *chan;
00297    char match[AST_CHANNEL_NAME];
00298    enum ast_device_state res;
00299 
00300    snprintf(match, sizeof(match), "%s-", device);
00301 
00302    if (!(chan = ast_channel_get_by_name_prefix(match, strlen(match)))) {
00303       return AST_DEVICE_UNKNOWN;
00304    }
00305 
00306    if (ast_channel_hold_state(chan) == AST_CONTROL_HOLD) {
00307       res = AST_DEVICE_ONHOLD;
00308    } else {
00309       res = ast_state_chan2dev(ast_channel_state(chan));
00310    }
00311    ast_channel_unref(chan);
00312 
00313    return res;
00314 }

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] device The device name
[in] state The state of the device
[in] cachable Whether the device state can be cached
[in] eid The EID of the server that originally published the message
Return values:
0 Success
-1 Failure
Since:
12

Definition at line 711 of file devicestate.c.

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

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

00716 {
00717    RAII_VAR(struct ast_device_state_message *, device_state, NULL, ao2_cleanup);
00718    RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
00719    struct stasis_topic *device_specific_topic;
00720 
00721    ast_assert(!ast_strlen_zero(device));
00722 
00723    if (!ast_device_state_message_type()) {
00724       return -1;
00725    }
00726 
00727    device_state = device_state_alloc(device, state, cachable, eid);
00728    if (!device_state) {
00729       return -1;
00730    }
00731 
00732    message = stasis_message_create_full(ast_device_state_message_type(), device_state,
00733       eid);
00734    if (!message) {
00735       return -1;
00736    }
00737 
00738    device_specific_topic = ast_device_state_topic(device);
00739    if (!device_specific_topic) {
00740       return -1;
00741    }
00742 
00743    stasis_publish(device_specific_topic, message);
00744    return 0;
00745 }

enum ast_device_state ast_state_chan2dev ( enum ast_channel_state  chanstate  ) 

Convert channel state to devicestate.

Parameters:
chanstate Current channel state
Since:
1.6.1

Definition at line 249 of file devicestate.c.

References ARRAY_LEN, and AST_DEVICE_UNKNOWN.

Referenced by ast_parse_device_state(), and chan_pjsip_devicestate().

00250 {
00251    int i;
00252    chanstate &= 0xFFFF;
00253    for (i = 0; i < ARRAY_LEN(chan2dev); i++) {
00254       if (chan2dev[i].chan == chanstate) {
00255          return chan2dev[i].dev;
00256       }
00257    }
00258    return AST_DEVICE_UNKNOWN;
00259 }

static struct stasis_message* device_state_aggregate_calc ( struct stasis_cache_entry entry,
struct stasis_message new_snapshot 
) [static, read]

Definition at line 804 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().

00805 {
00806    struct stasis_message *aggregate_snapshot;
00807    struct stasis_message *snapshot;
00808    struct ast_device_state_message *device_state;
00809    const char *device = NULL;
00810    struct ast_devstate_aggregate aggregate;
00811    int idx;
00812 
00813    if (!ast_device_state_message_type()) {
00814       return NULL;
00815    }
00816 
00817    /* Determine the new aggregate device state. */
00818    ast_devstate_aggregate_init(&aggregate);
00819    snapshot = stasis_cache_entry_get_local(entry);
00820    if (snapshot) {
00821       device_state = stasis_message_data(snapshot);
00822       device = device_state->device;
00823       ast_devstate_aggregate_add(&aggregate, device_state->state);
00824    }
00825    for (idx = 0; ; ++idx) {
00826       snapshot = stasis_cache_entry_get_remote(entry, idx);
00827       if (!snapshot) {
00828          break;
00829       }
00830 
00831       device_state = stasis_message_data(snapshot);
00832       device = device_state->device;
00833       ast_devstate_aggregate_add(&aggregate, device_state->state);
00834    }
00835 
00836    if (!device) {
00837       /* There are no device states cached.  Delete the aggregate. */
00838       return NULL;
00839    }
00840 
00841    snapshot = stasis_cache_entry_get_aggregate(entry);
00842    if (snapshot) {
00843       device_state = stasis_message_data(snapshot);
00844       if (device_state->state == ast_devstate_aggregate_result(&aggregate)) {
00845          /* Aggregate device state did not change. */
00846          return ao2_bump(snapshot);
00847       }
00848    }
00849 
00850    device_state = device_state_alloc(device, ast_devstate_aggregate_result(&aggregate),
00851       AST_DEVSTATE_CACHABLE, NULL);
00852    if (!device_state) {
00853       /* Bummer.  We have to keep the old aggregate snapshot. */
00854       return ao2_bump(snapshot);
00855    }
00856    aggregate_snapshot = stasis_message_create_full(ast_device_state_message_type(),
00857       device_state, NULL);
00858    ao2_cleanup(device_state);
00859    if (!aggregate_snapshot) {
00860       /* Bummer.  We have to keep the old aggregate snapshot. */
00861       return ao2_bump(snapshot);
00862    }
00863 
00864    return aggregate_snapshot;
00865 }

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

Definition at line 773 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().

00774 {
00775    const char *device;
00776    struct stasis_topic *device_specific_topic;
00777 
00778    device = device_state_get_id(aggregate);
00779    if (!device) {
00780       return;
00781    }
00782    device_specific_topic = ast_device_state_topic(device);
00783    if (!device_specific_topic) {
00784       return;
00785    }
00786 
00787    stasis_publish(device_specific_topic, aggregate);
00788 }

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, read]

Definition at line 562 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, and ast_device_state_message::stuff.

Referenced by ast_publish_device_state_full(), and device_state_aggregate_calc().

00563 {
00564    struct ast_device_state_message *new_device_state;
00565    char *pos;
00566    size_t stuff_len;
00567 
00568    ast_assert(!ast_strlen_zero(device));
00569 
00570    stuff_len = strlen(device) + 1;
00571    if (eid) {
00572       stuff_len += sizeof(*eid);
00573    }
00574    new_device_state = ao2_alloc_options(sizeof(*new_device_state) + stuff_len, NULL,
00575       AO2_ALLOC_OPT_LOCK_NOLOCK);
00576    if (!new_device_state) {
00577       return NULL;
00578    }
00579 
00580    if (eid) {
00581       /* non-aggregate device state. */
00582       new_device_state->stuff[0] = *eid;
00583       new_device_state->eid = &new_device_state->stuff[0];
00584       pos = (char *) &new_device_state->stuff[1];
00585    } else {
00586       pos = (char *) &new_device_state->stuff[0];
00587    }
00588 
00589    strcpy(pos, device);/* Safe */
00590    new_device_state->device = pos;
00591 
00592    new_device_state->state = state;
00593    new_device_state->cachable = cachable;
00594 
00595    return new_device_state;
00596 }

static const char* device_state_get_id ( struct stasis_message message  )  [static]

Definition at line 747 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().

00748 {
00749    struct ast_device_state_message *device_state;
00750 
00751    if (ast_device_state_message_type() != stasis_message_type(message)) {
00752       return NULL;
00753    }
00754 
00755    device_state = stasis_message_data(message);
00756    if (device_state->cachable == AST_DEVSTATE_NOT_CACHABLE) {
00757       return NULL;
00758    }
00759 
00760    return device_state->device;
00761 }

const char* devstate2str ( enum ast_device_state  devstate  ) 

Convert device state to text string for output.

Parameters:
devstate Current device state

Definition at line 244 of file devicestate.c.

00245 {
00246    return devstatestring[devstate][0];
00247 }

static enum ast_device_state devstate_cached ( const char *  device  )  [static]

Definition at line 316 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(), and ast_device_state_message::state.

Referenced by _ast_device_state().

00317 {
00318    struct stasis_message *cached_msg;
00319    struct ast_device_state_message *device_state;
00320    enum ast_device_state state;
00321 
00322    cached_msg = stasis_cache_get_by_eid(ast_device_state_cache(),
00323       ast_device_state_message_type(), device, NULL);
00324    if (!cached_msg) {
00325       return AST_DEVICE_UNKNOWN;
00326    }
00327    device_state = stasis_message_data(cached_msg);
00328    state = device_state->state;
00329    ao2_cleanup(cached_msg);
00330 
00331    return state;
00332 }

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

Definition at line 598 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().

00599 {
00600    struct ast_device_state_message *device_state;
00601 
00602    if (ast_device_state_message_type() != stasis_message_type(msg)) {
00603       return;
00604    }
00605 
00606    device_state = stasis_message_data(msg);
00607    if (device_state->cachable == AST_DEVSTATE_CACHABLE || !device_state->eid) {
00608       /* Ignore cacheable and aggregate messages. */
00609       return;
00610    }
00611 
00612    /*
00613     * Non-cacheable device state aggregates are just the
00614     * device state republished as the aggregate.
00615     */
00616    ast_publish_device_state_full(device_state->device, device_state->state,
00617       device_state->cachable, NULL);
00618 }

static void devstate_cleanup ( void   )  [static]

int devstate_init ( void   ) 

Initialize the device state core.

Return values:
0 Success
-1 Failure
Since:
12

Definition at line 884 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_cache, device_state_get_id(), device_state_topic_all, device_state_topic_cached, device_state_topic_pool, devstate_change_cb(), devstate_cleanup(), devstate_message_sub, LOG_ERROR, NULL, stasis_cache_create_full(), stasis_caching_topic_create(), STASIS_MESSAGE_TYPE_INIT, stasis_subscribe(), stasis_topic_create(), and stasis_topic_pool_create().

Referenced by main().

00885 {
00886    ast_register_cleanup(devstate_cleanup);
00887 
00888    if (STASIS_MESSAGE_TYPE_INIT(ast_device_state_message_type) != 0) {
00889       return -1;
00890    }
00891    device_state_topic_all = stasis_topic_create("ast_device_state_topic");
00892    if (!device_state_topic_all) {
00893       devstate_cleanup();
00894       return -1;
00895    }
00896    device_state_topic_pool = stasis_topic_pool_create(ast_device_state_topic_all());
00897    if (!device_state_topic_pool) {
00898       devstate_cleanup();
00899       return -1;
00900    }
00901    device_state_cache = stasis_cache_create_full(device_state_get_id,
00902       device_state_aggregate_calc, device_state_aggregate_publish);
00903    if (!device_state_cache) {
00904       devstate_cleanup();
00905       return -1;
00906    }
00907    device_state_topic_cached = stasis_caching_topic_create(ast_device_state_topic_all(),
00908       device_state_cache);
00909    if (!device_state_topic_cached) {
00910       devstate_cleanup();
00911       return -1;
00912    }
00913 
00914    devstate_message_sub = stasis_subscribe(ast_device_state_topic_all(),
00915       devstate_change_cb, NULL);
00916    if (!devstate_message_sub) {
00917       ast_log(LOG_ERROR, "Failed to create subscription creating uncached device state aggregate events.\n");
00918       devstate_cleanup();
00919       return -1;
00920    }
00921 
00922    return 0;
00923 }

static struct ast_manager_event_blob * devstate_to_ami ( struct stasis_message msg  )  [static, read]

Definition at line 925 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.

00926 {
00927    struct ast_device_state_message *dev_state;
00928 
00929    dev_state = stasis_message_data(msg);
00930 
00931    /* Ignore non-aggregate states */
00932    if (dev_state->eid) {
00933       return NULL;
00934    }
00935 
00936    return ast_manager_event_blob_create(EVENT_FLAG_CALL, "DeviceStateChange",
00937       "Device: %s\r\n"
00938       "State: %s\r\n",
00939       dev_state->device, ast_devstate_str(dev_state->state));
00940 }

static struct ast_event * devstate_to_event ( struct stasis_message msg  )  [static, read]

Convert a stasis_message to a ast_event.

Definition at line 943 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.

00944 {
00945    struct ast_event *event;
00946    struct ast_device_state_message *device_state;
00947 
00948    if (!message) {
00949       return NULL;
00950    }
00951 
00952    device_state = stasis_message_data(message);
00953 
00954    if (device_state->eid) {
00955       event = ast_event_new(AST_EVENT_DEVICE_STATE_CHANGE,
00956                    AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device_state->device,
00957                    AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_UINT, device_state->state,
00958                    AST_EVENT_IE_CACHABLE, AST_EVENT_IE_PLTYPE_UINT, device_state->cachable,
00959                    AST_EVENT_IE_EID, AST_EVENT_IE_PLTYPE_RAW, device_state->eid, sizeof(*device_state->eid),
00960                    AST_EVENT_IE_END);
00961    } else {
00962       event = ast_event_new(AST_EVENT_DEVICE_STATE,
00963                    AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device_state->device,
00964                    AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_UINT, device_state->state,
00965                    AST_EVENT_IE_CACHABLE, AST_EVENT_IE_PLTYPE_UINT, device_state->cachable,
00966                    AST_EVENT_IE_END);
00967    }
00968 
00969    return event;
00970 }

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 538 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(), devstate_prov::next, and NULL.

Referenced by ast_device_state_engine_init().

00539 {
00540    struct state_change *next, *current;
00541 
00542    for (;;) {
00543       /* This basically pops off any state change entries, resets the list back to NULL, unlocks, and processes each state change */
00544       AST_LIST_LOCK(&state_changes);
00545       if (AST_LIST_EMPTY(&state_changes))
00546          ast_cond_wait(&change_pending, &state_changes.lock);
00547       next = AST_LIST_FIRST(&state_changes);
00548       AST_LIST_HEAD_INIT_NOLOCK(&state_changes);
00549       AST_LIST_UNLOCK(&state_changes);
00550 
00551       /* Process each state change */
00552       while ((current = next)) {
00553          next = AST_LIST_NEXT(current, list);
00554          do_state_change(current->device, current->cachable);
00555          ast_free(current);
00556       }
00557    }
00558 
00559    return NULL;
00560 }

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 458 of file devicestate.c.

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

Referenced by ast_devstate_changed_literal(), and do_devstate_changes().

00459 {
00460    enum ast_device_state state;
00461 
00462    state = _ast_device_state(device, 0);
00463 
00464    ast_debug(3, "Changing state for %s - state %u (%s)\n", device, state, ast_devstate2str(state));
00465 
00466    ast_publish_device_state(device, state, cachable);
00467 }

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

Get provider device state.

Definition at line 437 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().

00438 {
00439    struct devstate_prov *devprov;
00440    int res = AST_DEVICE_INVALID;
00441 
00442    AST_RWLIST_RDLOCK(&devstate_provs);
00443    AST_RWLIST_TRAVERSE(&devstate_provs, devprov, list) {
00444       ast_debug(5, "Checking provider %s with %s\n", devprov->label, provider);
00445 
00446       if (!strcasecmp(devprov->label, provider)) {
00447          res = devprov->callback(address);
00448          break;
00449       }
00450    }
00451    AST_RWLIST_UNLOCK(&devstate_provs);
00452 
00453    return res;
00454 }

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


Variable Documentation

Flag for the queue.

Definition at line 216 of file devicestate.c.

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

pthread_t change_thread = AST_PTHREADT_NULL [static]

The device state change notification thread.

Definition at line 213 of file devicestate.c.

Referenced by ast_device_state_engine_init(), and ast_devstate_changed_literal().

struct stasis_cache* device_state_cache [static]

Definition at line 221 of file devicestate.c.

Referenced by ast_device_state_cache(), devstate_cleanup(), and devstate_init().

Definition at line 220 of file devicestate.c.

Referenced by ast_device_state_topic_all(), devstate_cleanup(), and devstate_init().

Definition at line 222 of file devicestate.c.

Referenced by ast_device_state_topic_cached(), devstate_cleanup(), and devstate_init().

Definition at line 223 of file devicestate.c.

Referenced by ast_device_state_topic(), devstate_cleanup(), and devstate_init().

Definition at line 218 of file devicestate.c.

Referenced by devstate_cleanup(), and devstate_init().

const char* const devstatestring[][2] [static]

Device state strings for printing.

Definition at line 163 of file devicestate.c.


Generated on Thu Apr 16 06:30:37 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6