Fri Nov 12 11:59:25 2010

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"
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  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, const char *fmt,...)
 Tells Asterisk the State for Device is changed.
int ast_devstate_changed_literal (enum ast_device_state state, 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)
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)
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, 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 * 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 562 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 308 of file devicestate.c.

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

Referenced by ast_device_state(), and do_state_change().

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

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
-1 on failure

Definition at line 360 of file devicestate.c.

References _ast_device_state().

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

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

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

00521 {
00522    char buf[AST_MAX_EXTENSION];
00523    va_list ap;
00524 
00525    va_start(ap, fmt);
00526    vsnprintf(buf, sizeof(buf), fmt, ap);
00527    va_end(ap);
00528 
00529    return ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, buf);
00530 }

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

References AST_DEVICE_UNKNOWN, and ast_devstate_changed_literal().

00504 {
00505    return ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, dev);
00506 }

int ast_device_state_engine_init ( void   ) 

Initialize the device state engine in separate thread.

Provided by devicestate.c

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

00723 {
00724    ast_cond_init(&change_pending, NULL);
00725    if (ast_pthread_create_background(&change_thread, NULL, do_devstate_changes, NULL) < 0) {
00726       ast_log(LOG_ERROR, "Unable to start device state change thread.\n");
00727       return -1;
00728    }
00729 
00730    return 0;
00731 }

const char* ast_devstate2str ( enum ast_device_state  devstate  ) 

Find devicestate as text message for output.

Definition at line 209 of file devicestate.c.

Referenced by __queues_show(), do_state_change(), handle_statechange(), notify_metermaids(), page_exec(), and process_collection().

00210 {
00211    return devstatestring[devstate][0];
00212 }

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

References ast_devstate_aggregate::all_busy, ast_devstate_aggregate::all_free, ast_devstate_aggregate::all_unavail, ast_devstate_aggregate::all_unknown, AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, AST_DEVICE_TOTAL, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, ast_devstate_aggregate::busy, ast_devstate_aggregate::in_use, ast_devstate_aggregate::on_hold, and ast_devstate_aggregate::ring.

Referenced by ast_extension_state2(), and process_collection().

00744 {
00745    switch (state) {
00746    case AST_DEVICE_NOT_INUSE:
00747       agg->all_unknown = 0;
00748       agg->all_unavail = 0;
00749       agg->all_busy = 0;
00750       break;
00751    case AST_DEVICE_INUSE:
00752       agg->in_use = 1;
00753       agg->all_unavail = 0;
00754       agg->all_free = 0;
00755       agg->all_unknown = 0;
00756       break;
00757    case AST_DEVICE_RINGING:
00758       agg->ring = 1;
00759       agg->all_unavail = 0;
00760       agg->all_free = 0;
00761       agg->all_unknown = 0;
00762       break;
00763    case AST_DEVICE_RINGINUSE:
00764       agg->in_use = 1;
00765       agg->ring = 1;
00766       agg->all_unavail = 0;
00767       agg->all_free = 0;
00768       agg->all_unknown = 0;
00769       break;
00770    case AST_DEVICE_ONHOLD:
00771       agg->all_unknown = 0;
00772       agg->all_unavail = 0;
00773       agg->all_free = 0;
00774       agg->on_hold = 1;
00775       break;
00776    case AST_DEVICE_BUSY:
00777       agg->all_unknown = 0;
00778       agg->all_unavail = 0;
00779       agg->all_free = 0;
00780       agg->busy = 1;
00781       agg->in_use = 1;
00782       break;
00783    case AST_DEVICE_UNAVAILABLE:
00784       agg->all_unknown = 0;
00785    case AST_DEVICE_INVALID:
00786       agg->all_busy = 0;
00787       agg->all_free = 0;
00788       break;
00789    case AST_DEVICE_UNKNOWN:
00790       agg->all_busy = 0;
00791       agg->all_free = 0;
00792       break;
00793    case AST_DEVICE_TOTAL: /* not a device state, included for completeness. */
00794       break;
00795    }
00796 }

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

References ast_devstate_aggregate::all_busy, ast_devstate_aggregate::all_free, ast_devstate_aggregate::all_unavail, and ast_devstate_aggregate::all_unknown.

Referenced by ast_extension_state2(), and process_collection().

00734 {
00735    memset(agg, 0, sizeof(*agg));
00736 
00737    agg->all_unknown = 1;
00738    agg->all_unavail = 1;
00739    agg->all_busy = 1;
00740    agg->all_free = 1;
00741 }

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

References ast_devstate_aggregate::all_busy, ast_devstate_aggregate::all_free, ast_devstate_aggregate::all_unavail, ast_devstate_aggregate::all_unknown, AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, ast_devstate_aggregate::busy, ast_devstate_aggregate::in_use, ast_devstate_aggregate::on_hold, and ast_devstate_aggregate::ring.

Referenced by ast_extension_state2(), and process_collection().

00800 {
00801    if (agg->all_free)
00802       return AST_DEVICE_NOT_INUSE;
00803    if ((agg->in_use || agg->on_hold) && agg->ring)
00804       return AST_DEVICE_RINGINUSE;
00805    if (agg->ring)
00806       return AST_DEVICE_RINGING;
00807    if (agg->busy)
00808       return AST_DEVICE_BUSY;
00809    if (agg->in_use)
00810       return AST_DEVICE_INUSE;
00811    if (agg->on_hold)
00812       return AST_DEVICE_ONHOLD;
00813    if (agg->all_busy)
00814       return AST_DEVICE_BUSY;
00815    if (agg->all_unknown)
00816       return AST_DEVICE_UNKNOWN;
00817    if (agg->all_unavail)
00818       return AST_DEVICE_UNAVAILABLE;
00819 
00820    return AST_DEVICE_NOT_INUSE;
00821 }

int ast_devstate_changed ( enum ast_device_state  state,
const char *  fmt,
  ... 
)

Tells Asterisk the State for Device is changed.

Parameters:
state the new state of the device
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 508 of file devicestate.c.

References ast_devstate_changed_literal(), AST_MAX_EXTENSION, and buf.

Referenced by __expire_registry(), __iax2_poke_noanswer(), agent_call(), agent_hangup(), agent_logoff_maintenance(), agent_read(), conf_run(), 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(), load_module(), login_exec(), notify_metermaids(), reg_source_db(), register_verify(), reload_agents(), 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().

00509 {
00510    char buf[AST_MAX_EXTENSION];
00511    va_list ap;
00512 
00513    va_start(ap, fmt);
00514    vsnprintf(buf, sizeof(buf), fmt, ap);
00515    va_end(ap);
00516 
00517    return ast_devstate_changed_literal(state, buf);
00518 }

int ast_devstate_changed_literal ( enum ast_device_state  state,
const char *  device 
)

Tells Asterisk the State for Device is changed.

Parameters:
state the new state of the device
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 465 of file devicestate.c.

References ast_calloc, ast_cond_signal(), AST_DEVICE_UNKNOWN, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, change_thread, state_change::device, devstate_event(), and do_state_change().

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

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

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

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

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

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

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

Referenced by devstate_read().

00234 {
00235    return devstatestring[state][1];
00236 }

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 238 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 custom_devstate_callback(), devstate_write(), handle_cli_devstate_change(), and load_module().

00239 {
00240    if (!strcasecmp(val, "NOT_INUSE"))
00241       return AST_DEVICE_NOT_INUSE;
00242    else if (!strcasecmp(val, "INUSE"))
00243       return AST_DEVICE_INUSE;
00244    else if (!strcasecmp(val, "BUSY"))
00245       return AST_DEVICE_BUSY;
00246    else if (!strcasecmp(val, "INVALID"))
00247       return AST_DEVICE_INVALID;
00248    else if (!strcasecmp(val, "UNAVAILABLE"))
00249       return AST_DEVICE_UNAVAILABLE;
00250    else if (!strcasecmp(val, "RINGING"))
00251       return AST_DEVICE_RINGING;
00252    else if (!strcasecmp(val, "RINGINUSE"))
00253       return AST_DEVICE_RINGINUSE;
00254    else if (!strcasecmp(val, "ONHOLD"))
00255       return AST_DEVICE_ONHOLD;
00256 
00257    return AST_DEVICE_UNKNOWN;
00258 }

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

00824 {
00825    if (devstate_collector.enabled) {
00826       return 0;
00827    }
00828 
00829    devstate_collector.event_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE_CHANGE,
00830       devstate_change_collector_cb, NULL, AST_EVENT_IE_END);
00831 
00832    if (!devstate_collector.event_sub) {
00833       ast_log(LOG_ERROR, "Failed to create subscription for the device state change collector\n");
00834       return -1;
00835    }
00836 
00837    ast_mutex_init(&devstate_collector.lock);
00838    ast_cond_init(&devstate_collector.cond, NULL);
00839    if (ast_pthread_create_background(&devstate_collector.thread, NULL, run_devstate_collector, NULL) < 0) {
00840       ast_log(LOG_ERROR, "Unable to start device state collector thread.\n");
00841       return -1;
00842    }
00843 
00844    devstate_collector.enabled = 1;
00845 
00846    return 0;
00847 }

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

References ast_channel::_state, AST_CHANNEL_NAME, ast_channel_unlock, ast_copy_string(), AST_DEVICE_INUSE, AST_DEVICE_RINGING, AST_DEVICE_UNKNOWN, ast_get_channel_by_name_prefix_locked(), AST_STATE_RINGING, chan, and match().

Referenced by _ast_device_state(), and chanavail_exec().

00266 {
00267    struct ast_channel *chan;
00268    char match[AST_CHANNEL_NAME];
00269    enum ast_device_state res;
00270 
00271    ast_copy_string(match, device, sizeof(match)-1);
00272    strcat(match, "-");
00273    chan = ast_get_channel_by_name_prefix_locked(match, strlen(match));
00274 
00275    if (!chan)
00276       return AST_DEVICE_UNKNOWN;
00277 
00278    if (chan->_state == AST_STATE_RINGING)
00279       res = AST_DEVICE_RINGING;
00280    else
00281       res = AST_DEVICE_INUSE;
00282    
00283    ast_channel_unlock(chan);
00284 
00285    return res;
00286 }

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

References AST_DEVICE_UNKNOWN, and chan.

Referenced by dahdi_new().

00221 {
00222    int i;
00223    chanstate &= 0xFFFF;
00224    for (i = 0; chan2dev[i].chan != -100; i++) {
00225       if (chan2dev[i].chan == chanstate) {
00226          return chan2dev[i].dev;
00227       }
00228    }
00229    return AST_DEVICE_UNKNOWN;
00230 }

static void destroy_devstate_change ( struct devstate_change sc  )  [static]

Definition at line 557 of file devicestate.c.

References ast_free.

Referenced by run_devstate_collector().

00558 {
00559    ast_free(sc);
00560 }

const char* devstate2str ( enum ast_device_state  devstate  ) 

Convert device state to text string for output.

Parameters:
devstate Current device state

Definition at line 215 of file devicestate.c.

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

static void devstate_cache_cb ( const struct ast_event event,
void *  data 
) [static]

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

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

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

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

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

static void devstate_change_collector_cb ( const struct ast_event event,
void *  data 
) [static]

Definition at line 692 of file devicestate.c.

References ast_calloc, ast_cond_signal(), ast_event_get_ie_raw(), ast_event_get_ie_str(), ast_event_get_ie_uint(), 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::device, devstate_collector, devstate_change::eid, LOG_ERROR, and devstate_change::state.

Referenced by ast_enable_distributed_devstate().

00693 {
00694    struct devstate_change *sc;
00695    const char *device;
00696    const struct ast_eid *eid;
00697    uint32_t state;
00698 
00699    device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
00700    eid = ast_event_get_ie_raw(event, AST_EVENT_IE_EID);
00701    state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
00702 
00703    if (ast_strlen_zero(device) || !eid) {
00704       ast_log(LOG_ERROR, "Invalid device state change event received\n");
00705       return;
00706    }
00707 
00708    if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device))))
00709       return;
00710 
00711    strcpy(sc->device, device);
00712    sc->eid = *eid;
00713    sc->state = state;
00714 
00715    ast_mutex_lock(&devstate_collector.lock);
00716    AST_LIST_INSERT_TAIL(&devstate_collector.devstate_change_q, sc, entry);
00717    ast_cond_signal(&devstate_collector.cond);
00718    ast_mutex_unlock(&devstate_collector.lock);
00719 }

static void devstate_event ( const char *  device,
enum ast_device_state  state 
) [static]

Definition at line 427 of file devicestate.c.

References ast_debug, AST_EVENT_DEVICE_STATE, AST_EVENT_DEVICE_STATE_CHANGE, 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_and_cache(), and devstate_collector.

Referenced by ast_devstate_changed_literal(), and do_state_change().

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

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 533 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::device, do_state_change(), and devstate_prov::next.

Referenced by ast_device_state_engine_init().

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

static void do_state_change ( const char *  device  )  [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 454 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().

00455 {
00456    enum ast_device_state state;
00457 
00458    state = _ast_device_state(device, 0);
00459 
00460    ast_debug(3, "Changing state for %s - state %d (%s)\n", device, state, ast_devstate2str(state));
00461 
00462    devstate_event(device, state);
00463 }

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

Get provider device state.

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

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

static void handle_devstate_change ( struct devstate_change sc  )  [static]

Definition at line 646 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::device, devstate_cache_cb(), LOG_ERROR, change_collection::num_states, and process_collection().

Referenced by run_devstate_collector().

00647 {
00648    struct ast_event_sub *tmp_sub;
00649    struct change_collection collection = {
00650       .num_states = 0,
00651    };
00652 
00653    ast_debug(1, "Processing device state change for '%s'\n", sc->device);
00654 
00655    if (!(tmp_sub = ast_event_subscribe_new(AST_EVENT_DEVICE_STATE_CHANGE, devstate_cache_cb, &collection))) {
00656       ast_log(LOG_ERROR, "Failed to create subscription\n");
00657       return;
00658    }
00659 
00660    if (ast_event_sub_append_ie_str(tmp_sub, AST_EVENT_IE_DEVICE, sc->device)) {
00661       ast_log(LOG_ERROR, "Failed to append device IE\n");
00662       ast_event_sub_destroy(tmp_sub);
00663       return;
00664    }
00665 
00666    /* Populate the collection of device states from the cache */
00667    ast_event_dump_cache(tmp_sub);
00668 
00669    process_collection(sc->device, &collection);
00670 
00671    ast_event_sub_destroy(tmp_sub);
00672 }

static void process_collection ( const char *  device,
struct change_collection collection 
) [static]

Definition at line 593 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_and_cache(), change_collection::num_states, devstate_change::state, and change_collection::states.

Referenced by handle_devstate_change().

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

static void* run_devstate_collector ( void *  data  )  [static]

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

00675 {
00676    for (;;) {
00677       struct devstate_change *sc;
00678 
00679       ast_mutex_lock(&devstate_collector.lock);
00680       while (!(sc = AST_LIST_REMOVE_HEAD(&devstate_collector.devstate_change_q, entry)))
00681          ast_cond_wait(&devstate_collector.cond, &devstate_collector.lock);
00682       ast_mutex_unlock(&devstate_collector.lock);
00683 
00684       handle_devstate_change(sc);
00685 
00686       destroy_devstate_change(sc);
00687    }
00688 
00689    return NULL;
00690 }


Variable Documentation

Flag for the queue.

Definition at line 184 of file devicestate.c.

pthread_t change_thread = AST_PTHREADT_NULL [static]

The device state change notification thread.

Definition at line 181 of file devicestate.c.

Referenced by ast_device_state_engine_init(), and ast_devstate_changed_literal().

Definition at line 196 of file devicestate.c.

struct { ... } devstate_change_q
struct { ... } devstate_collector
const char* devstatestring[][2] [static]

Device state strings for printing.

Definition at line 131 of file devicestate.c.

unsigned int enabled

Definition at line 199 of file devicestate.c.

Referenced by __ast_http_load(), load_odbc_config(), and osp_check_destination().

Definition at line 195 of file devicestate.c.

Referenced by dump_cache_cb().

Definition at line 198 of file devicestate.c.

Definition at line 198 of file devicestate.c.

Definition at line 197 of file devicestate.c.

pthread_t thread

Definition at line 194 of file devicestate.c.


Generated by  doxygen 1.6.2