Thu Sep 7 01:03:27 2017

Asterisk developer's documentation


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/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 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 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 MAX_SERVERS   64

Definition at line 570 of file devicestate.c.

Referenced by devstate_cache_cb().


Function Documentation

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_strdupa, ast_channel_tech::devicestate, devstate_cached(), and getproviderstate().

Referenced by ast_device_state(), and do_state_change().

00311 {
00312    char *buf;
00313    char *number;
00314    const struct ast_channel_tech *chan_tech;
00315    enum ast_device_state res;
00316    /*! \brief Channel driver that provides device state */
00317    char *tech;
00318    /*! \brief Another provider of device state */
00319    char *provider = NULL;
00320 
00321    /* If the last known state is cached, just return that */
00322    if (check_cache) {
00323       res = devstate_cached(device);
00324       if (res != AST_DEVICE_UNKNOWN) {
00325          return res;
00326       }
00327    }
00328 
00329    buf = ast_strdupa(device);
00330    tech = strsep(&buf, "/");
00331    if (!(number = buf)) {
00332       provider = strsep(&tech, ":");
00333       if (!tech) {
00334          return AST_DEVICE_INVALID;
00335       }
00336       /* We have a provider */
00337       number = tech;
00338       tech = NULL;
00339 
00340       ast_debug(3, "Checking if I can find provider for \"%s\" - number: %s\n", provider, number);
00341       return getproviderstate(provider, number);
00342    }
00343 
00344    ast_debug(4, "No provider found, checking channel drivers for %s - %s\n", tech, number);
00345 
00346    if (!(chan_tech = ast_get_channel_tech(tech)))
00347       return AST_DEVICE_INVALID;
00348 
00349    if (!(chan_tech->devicestate)) /* Does the channel driver support device state notification? */
00350       return ast_parse_device_state(device); /* No, try the generic function */
00351 
00352    res = chan_tech->devicestate(number);
00353 
00354    if (res != AST_DEVICE_UNKNOWN)
00355       return res;
00356 
00357    res = ast_parse_device_state(device);
00358 
00359    return res;
00360 }

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

References _ast_device_state().

00363 {
00364    /* This function is called from elsewhere in the code to find out the
00365     * current state of a device.  Check the cache, first. */
00366 
00367    return _ast_device_state(device, 1);
00368 }

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

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

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

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

References AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, and ast_devstate_changed_literal().

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

00748 {
00749    ast_cond_init(&change_pending, NULL);
00750    if (ast_pthread_create_background(&change_thread, NULL, do_devstate_changes, NULL) < 0) {
00751       ast_log(LOG_ERROR, "Unable to start device state change thread.\n");
00752       return -1;
00753    }
00754 
00755    return 0;
00756 }

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(), do_state_change(), extension_state_cb(), handle_statechange(), notify_metermaids(), page_exec(), process_collection(), and queue_function_queuememberstatus().

00216 {
00217    return devstatestring[devstate][0];
00218 }

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 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, and ast_devstate_aggregate::state.

Referenced by ast_extension_state3(), and process_collection().

00765 {
00766    static enum ast_device_state state_order[] = {
00767       1, /* AST_DEVICE_UNKNOWN */
00768       3, /* AST_DEVICE_NOT_INUSE */
00769       6, /* AST_DEVICE_INUSE */
00770       7, /* AST_DEVICE_BUSY */
00771       0, /* AST_DEVICE_INVALID */
00772       2, /* AST_DEVICE_UNAVAILABLE */
00773       5, /* AST_DEVICE_RINGING */
00774       8, /* AST_DEVICE_RINGINUSE */
00775       4, /* AST_DEVICE_ONHOLD */
00776    };
00777 
00778    if (state == AST_DEVICE_RINGING) {
00779       agg->ringing = 1;
00780    } else if (state == AST_DEVICE_INUSE || state == AST_DEVICE_ONHOLD || state == AST_DEVICE_BUSY) {
00781       agg->inuse = 1;
00782    }
00783 
00784    if (agg->ringing && agg->inuse) {
00785       agg->state = AST_DEVICE_RINGINUSE;
00786    } else if (state_order[state] > state_order[agg->state]) {
00787       agg->state = state;
00788    }
00789 }

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

References AST_DEVICE_INVALID, and ast_devstate_aggregate::state.

Referenced by ast_extension_state3(), and process_collection().

00759 {
00760    memset(agg, 0, sizeof(*agg));
00761    agg->state = AST_DEVICE_INVALID;
00762 }

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

References ast_devstate_aggregate::state.

Referenced by ast_extension_state3(), and process_collection().

00792 {
00793    return agg->state;
00794 }

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

References ast_devstate_changed_literal(), and AST_MAX_EXTENSION.

Referenced by __expire_registry(), __iax2_poke_noanswer(), calendar_devstate_change(), conf_run(), 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_stimulus_message(), join_conference_bridge(), leave_conference_bridge(), load_module(), login_exec(), notify_metermaids(), reg_source_db(), register_verify(), sip_peer_hold(), sip_poke_noanswer(), skinny_register(), skinny_unregister(), sla_change_trunk_state(), sla_handle_hold_event(), sla_station_exec(), socket_process(), update_call_counter(), and update_registry().

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

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

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

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 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_features_init(), and load_module().

00372 {
00373    struct devstate_prov *devprov;
00374 
00375    if (!callback || !(devprov = ast_calloc(1, sizeof(*devprov))))
00376       return -1;
00377 
00378    devprov->callback = callback;
00379    ast_copy_string(devprov->label, label, sizeof(devprov->label));
00380 
00381    AST_RWLIST_WRLOCK(&devstate_provs);
00382    AST_RWLIST_INSERT_HEAD(&devstate_provs, devprov, list);
00383    AST_RWLIST_UNLOCK(&devstate_provs);
00384 
00385    return 0;
00386 }

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

00390 {
00391    struct devstate_prov *devcb;
00392    int res = -1;
00393 
00394    AST_RWLIST_WRLOCK(&devstate_provs);
00395    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&devstate_provs, devcb, list) {
00396       if (!strcasecmp(devcb->label, label)) {
00397          AST_RWLIST_REMOVE_CURRENT(list);
00398          ast_free(devcb);
00399          res = 0;
00400          break;
00401       }
00402    }
00403    AST_RWLIST_TRAVERSE_SAFE_END;
00404    AST_RWLIST_UNLOCK(&devstate_provs);
00405 
00406    return res;
00407 }

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

Referenced by aji_devstate_cb(), and devstate_read().

00240 {
00241    return devstatestring[state][1];
00242 }

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

00245 {
00246    if (!strcasecmp(val, "NOT_INUSE"))
00247       return AST_DEVICE_NOT_INUSE;
00248    else if (!strcasecmp(val, "INUSE"))
00249       return AST_DEVICE_INUSE;
00250    else if (!strcasecmp(val, "BUSY"))
00251       return AST_DEVICE_BUSY;
00252    else if (!strcasecmp(val, "INVALID"))
00253       return AST_DEVICE_INVALID;
00254    else if (!strcasecmp(val, "UNAVAILABLE"))
00255       return AST_DEVICE_UNAVAILABLE;
00256    else if (!strcasecmp(val, "RINGING"))
00257       return AST_DEVICE_RINGING;
00258    else if (!strcasecmp(val, "RINGINUSE"))
00259       return AST_DEVICE_RINGINUSE;
00260    else if (!strcasecmp(val, "ONHOLD"))
00261       return AST_DEVICE_ONHOLD;
00262 
00263    return AST_DEVICE_UNKNOWN;
00264 }

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.

Return values:
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 add_publish_event(), add_subscribe_event(), and aji_init_event_distribution().

00797 {
00798    if (devstate_collector.enabled) {
00799       return 0;
00800    }
00801 
00802    devstate_collector.event_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE_CHANGE,
00803       devstate_change_collector_cb, "devicestate_engine_enable_distributed", NULL, AST_EVENT_IE_END);
00804 
00805    if (!devstate_collector.event_sub) {
00806       ast_log(LOG_ERROR, "Failed to create subscription for the device state change collector\n");
00807       return -1;
00808    }
00809 
00810    ast_mutex_init(&devstate_collector.lock);
00811    ast_cond_init(&devstate_collector.cond, NULL);
00812    if (ast_pthread_create_background(&devstate_collector.thread, NULL, run_devstate_collector, NULL) < 0) {
00813       ast_log(LOG_ERROR, "Unable to start device state collector thread.\n");
00814       return -1;
00815    }
00816 
00817    devstate_collector.enabled = 1;
00818 
00819    return 0;
00820 }

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

References ast_channel::_state, 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().

00272 {
00273    struct ast_channel *chan;
00274    char match[AST_CHANNEL_NAME];
00275    enum ast_device_state res;
00276 
00277    snprintf(match, sizeof(match), "%s-", device);
00278 
00279    if (!(chan = ast_channel_get_by_name_prefix(match, strlen(match)))) {
00280       return AST_DEVICE_UNKNOWN;
00281    }
00282 
00283    res = (chan->_state == AST_STATE_RINGING) ? AST_DEVICE_RINGING : AST_DEVICE_INUSE;
00284    
00285    chan = ast_channel_unref(chan);
00286 
00287    return res;
00288 }

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

References AST_DEVICE_UNKNOWN.

00227 {
00228    int i;
00229    chanstate &= 0xFFFF;
00230    for (i = 0; chan2dev[i].chan != -100; i++) {
00231       if (chan2dev[i].chan == chanstate) {
00232          return chan2dev[i].dev;
00233       }
00234    }
00235    return AST_DEVICE_UNKNOWN;
00236 }

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

00566 {
00567    ast_free(sc);
00568 }

const char* devstate2str ( enum ast_device_state  devstate  ) 

Convert device state to text string for output.

Parameters:
devstate Current device state

Definition at line 221 of file devicestate.c.

00222 {
00223    return devstatestring[devstate][0];
00224 }

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, LOG_ERROR, MAX_SERVERS, change_collection::num_states, devstate_change::state, and change_collection::states.

Referenced by handle_devstate_change().

00577 {
00578    struct change_collection *collection = data;
00579    int i;
00580    const struct ast_eid *eid;
00581 
00582    if (collection->num_states == ARRAY_LEN(collection->states)) {
00583       ast_log(LOG_ERROR, "More per-server state values than we have room for (MAX_SERVERS is %d)\n",
00584          MAX_SERVERS);
00585       return;
00586    }
00587 
00588    if (!(eid = ast_event_get_ie_raw(event, AST_EVENT_IE_EID))) {
00589       ast_log(LOG_ERROR, "Device state change event with no EID\n");
00590       return;
00591    }
00592 
00593    i = collection->num_states;
00594 
00595    collection->states[i].state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
00596    collection->states[i].eid = *eid;
00597 
00598    collection->num_states++;
00599 }

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

00291 {
00292    enum ast_device_state res = AST_DEVICE_UNKNOWN;
00293    struct ast_event *event;
00294 
00295    event = ast_event_get_cached(AST_EVENT_DEVICE_STATE,
00296       AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device,
00297       AST_EVENT_IE_END);
00298 
00299    if (!event)
00300       return res;
00301 
00302    res = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
00303 
00304    ast_event_destroy(event);
00305 
00306    return res;
00307 }

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, LOG_ERROR, and devstate_change::state.

Referenced by ast_enable_distributed_devstate().

00706 {
00707    struct devstate_change *sc;
00708    const char *device, *cachable_str;
00709    const struct ast_eid *eid;
00710    uint32_t state;
00711    enum ast_devstate_cache cachable = AST_DEVSTATE_CACHABLE;
00712 
00713    device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
00714    eid = ast_event_get_ie_raw(event, AST_EVENT_IE_EID);
00715    state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
00716 
00717    if (ast_strlen_zero(device) || !eid) {
00718       ast_log(LOG_ERROR, "Invalid device state change event received\n");
00719       return;
00720    }
00721 
00722    if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device))))
00723       return;
00724 
00725    strcpy(sc->device, device);
00726    sc->eid = *eid;
00727    sc->state = state;
00728 
00729    /* For 'cachable' we cannot use ast_event_get_ie_uint(), it overwrites the default of AST_DEVSTATE_CACHABLE we
00730     * have already setup for 'cachable', if for whatever reason the AST_EVENT_IE_CACHABLE wasn't
00731     * posted in the event ast_event_get_ie_uint() is going will return 0,
00732     * which equates to AST_DEVSTATE_NOT_CACHABLE the first enumeration in 'ast_devstate_cache'.
00733     */
00734 
00735    if ((cachable_str = ast_event_get_ie_str(event, AST_EVENT_IE_CACHABLE))) {
00736       sscanf(cachable_str, "%30u", &cachable);
00737    }
00738    sc->cachable = cachable;
00739 
00740    ast_mutex_lock(&devstate_collector.lock);
00741    AST_LIST_INSERT_TAIL(&devstate_collector.devstate_change_q, sc, entry);
00742    ast_cond_signal(&devstate_collector.cond);
00743    ast_mutex_unlock(&devstate_collector.lock);
00744 }

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

00430 {
00431    struct ast_event *event;
00432    enum ast_event_type event_type;
00433 
00434    if (devstate_collector.enabled) {
00435       /* Distributed device state is enabled, so this state change is a change
00436        * for a single server, not the real state. */
00437       event_type = AST_EVENT_DEVICE_STATE_CHANGE;
00438    } else {
00439       event_type = AST_EVENT_DEVICE_STATE;
00440    }
00441 
00442    ast_debug(3, "device '%s' state '%u'\n", device, state);
00443 
00444    if (!(event = ast_event_new(event_type,
00445                 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device,
00446                 AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_UINT, state,
00447                 AST_EVENT_IE_CACHABLE, AST_EVENT_IE_PLTYPE_UINT, cachable,
00448                 AST_EVENT_IE_END))) {
00449       return;
00450    }
00451 
00452    if (cachable) {
00453       ast_event_queue_and_cache(event);
00454    } else {
00455       ast_event_queue(event);
00456    }
00457 }

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

Referenced by ast_device_state_engine_init().

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

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

Referenced by ast_devstate_changed_literal(), and do_devstate_changes().

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

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

00411 {
00412    struct devstate_prov *devprov;
00413    int res = AST_DEVICE_INVALID;
00414 
00415    AST_RWLIST_RDLOCK(&devstate_provs);
00416    AST_RWLIST_TRAVERSE(&devstate_provs, devprov, list) {
00417       ast_debug(5, "Checking provider %s with %s\n", devprov->label, provider);
00418 
00419       if (!strcasecmp(devprov->label, provider)) {
00420          res = devprov->callback(address);
00421          break;
00422       }
00423    }
00424    AST_RWLIST_UNLOCK(&devstate_provs);
00425 
00426    return res;
00427 }

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

00660 {
00661    struct ast_event_sub *tmp_sub;
00662    struct change_collection collection = {
00663       .num_states = 0,
00664    };
00665 
00666    ast_debug(1, "Processing device state change for '%s'\n", sc->device);
00667 
00668    if (!(tmp_sub = ast_event_subscribe_new(AST_EVENT_DEVICE_STATE_CHANGE, devstate_cache_cb, &collection))) {
00669       ast_log(LOG_ERROR, "Failed to create subscription\n");
00670       return;
00671    }
00672 
00673    if (ast_event_sub_append_ie_str(tmp_sub, AST_EVENT_IE_DEVICE, sc->device)) {
00674       ast_log(LOG_ERROR, "Failed to append device IE\n");
00675       ast_event_sub_destroy(tmp_sub);
00676       return;
00677    }
00678 
00679    /* Populate the collection of device states from the cache */
00680    ast_event_dump_cache(tmp_sub);
00681 
00682    process_collection(sc->device, sc->cachable, &collection);
00683 
00684    ast_event_sub_destroy(tmp_sub);
00685 }

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, and change_collection::states.

Referenced by handle_devstate_change().

00602 {
00603    int i;
00604    struct ast_devstate_aggregate agg;
00605    enum ast_device_state state;
00606    struct ast_event *event;
00607 
00608    ast_devstate_aggregate_init(&agg);
00609 
00610    for (i = 0; i < collection->num_states; i++) {
00611       ast_debug(1, "Adding per-server state of '%s' for '%s'\n", 
00612          ast_devstate2str(collection->states[i].state), device);
00613       ast_devstate_aggregate_add(&agg, collection->states[i].state);
00614    }
00615 
00616    state = ast_devstate_aggregate_result(&agg);
00617 
00618    ast_debug(1, "Aggregate devstate result is '%s' for '%s'\n",
00619       ast_devstate2str(state), device);
00620 
00621    event = ast_event_get_cached(AST_EVENT_DEVICE_STATE,
00622       AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device,
00623       AST_EVENT_IE_END);
00624    
00625    if (event) {
00626       enum ast_device_state old_state;
00627 
00628       old_state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
00629       
00630       ast_event_destroy(event);
00631 
00632       if (state == old_state) {
00633          /* No change since last reported device state */
00634          ast_debug(1, "Aggregate state for device '%s' has not changed from '%s'\n",
00635             device, ast_devstate2str(state));
00636          return;
00637       }
00638    }
00639 
00640    ast_debug(1, "Aggregate state for device '%s' has changed to '%s'\n",
00641       device, ast_devstate2str(state));
00642 
00643    event = ast_event_new(AST_EVENT_DEVICE_STATE,
00644       AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device,
00645       AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_UINT, state,
00646       AST_EVENT_IE_END);
00647 
00648    if (!event) {
00649       return;
00650    }
00651 
00652    if (cachable) {
00653       ast_event_queue_and_cache(event);
00654    } else {
00655       ast_event_queue(event);
00656    }
00657 }

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

00688 {
00689    for (;;) {
00690       struct devstate_change *sc;
00691 
00692       ast_mutex_lock(&devstate_collector.lock);
00693       while (!(sc = AST_LIST_REMOVE_HEAD(&devstate_collector.devstate_change_q, entry)))
00694          ast_cond_wait(&devstate_collector.cond, &devstate_collector.lock);
00695       ast_mutex_unlock(&devstate_collector.lock);
00696 
00697       handle_devstate_change(sc);
00698 
00699       destroy_devstate_change(sc);
00700    }
00701 
00702    return NULL;
00703 }


Variable Documentation

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]
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().

Definition at line 201 of file devicestate.c.

Referenced by dump_cache_cb().

Definition at line 203 of file devicestate.c.

pthread_t thread

Definition at line 200 of file devicestate.c.


Generated on 7 Sep 2017 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1