Wed Oct 28 11:52:16 2009

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 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.
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.
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)
 Find devicestate as text message 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 []
 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 588 of file devicestate.c.

Referenced by devstate_cache_cb().


Function Documentation

static void __fini_devstate_provs ( void   )  [static]

Definition at line 169 of file devicestate.c.

00171 {

static void __init_devstate_provs ( void   )  [static]

Definition at line 169 of file devicestate.c.

00171 {

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

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

Referenced by ast_device_state(), and do_state_change().

00335 {
00336    char *buf;
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    /*! \brief Another provider of device state */
00343    char *provider = NULL;
00344 
00345    /* If the last known state is cached, just return that */
00346    if (check_cache) {
00347       res = devstate_cached(device);
00348       if (res != AST_DEVICE_UNKNOWN) {
00349          return res;
00350       }
00351    }
00352 
00353    buf = ast_strdupa(device);
00354    tech = strsep(&buf, "/");
00355    if (!(number = buf)) {
00356       if (!(provider = strsep(&tech, ":")))
00357          return AST_DEVICE_INVALID;
00358       /* We have a provider */
00359       number = tech;
00360       tech = NULL;
00361    }
00362 
00363    if (provider)  {
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    if (!(chan_tech = ast_get_channel_tech(tech)))
00371       return AST_DEVICE_INVALID;
00372 
00373    if (!(chan_tech->devicestate)) /* Does the channel driver support device state notification? */
00374       return ast_parse_device_state(device); /* No, try the generic function */
00375 
00376    res = chan_tech->devicestate(number);
00377 
00378    if (res != AST_DEVICE_UNKNOWN)
00379       return res;
00380 
00381    res = ast_parse_device_state(device);
00382 
00383    return res;
00384 }

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

References _ast_device_state().

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

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

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

00547 {
00548    char buf[AST_MAX_EXTENSION];
00549    va_list ap;
00550 
00551    va_start(ap, fmt);
00552    vsnprintf(buf, sizeof(buf), fmt, ap);
00553    va_end(ap);
00554 
00555    return ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, buf);
00556 }

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

References AST_DEVICE_UNKNOWN, and ast_devstate_changed_literal().

00530 {
00531    return ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, dev);
00532 }

int ast_device_state_engine_init ( void   ) 

Initialize the device state engine in separate thread.

Provided by devicestate.c

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

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

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

00770 {
00771    switch (state) {
00772    case AST_DEVICE_NOT_INUSE:
00773       agg->all_unknown = 0;
00774       agg->all_unavail = 0;
00775       agg->all_busy = 0;
00776       break;
00777    case AST_DEVICE_INUSE:
00778       agg->in_use = 1;
00779       agg->all_unavail = 0;
00780       agg->all_free = 0;
00781       agg->all_unknown = 0;
00782       break;
00783    case AST_DEVICE_RINGING:
00784       agg->ring = 1;
00785       agg->all_unavail = 0;
00786       agg->all_free = 0;
00787       agg->all_unknown = 0;
00788       break;
00789    case AST_DEVICE_RINGINUSE:
00790       agg->in_use = 1;
00791       agg->ring = 1;
00792       agg->all_unavail = 0;
00793       agg->all_free = 0;
00794       agg->all_unknown = 0;
00795       break;
00796    case AST_DEVICE_ONHOLD:
00797       agg->all_unknown = 0;
00798       agg->all_unavail = 0;
00799       agg->all_free = 0;
00800       agg->on_hold = 1;
00801       break;
00802    case AST_DEVICE_BUSY:
00803       agg->all_unknown = 0;
00804       agg->all_unavail = 0;
00805       agg->all_free = 0;
00806       agg->busy = 1;
00807       agg->in_use = 1;
00808       break;
00809    case AST_DEVICE_UNAVAILABLE:
00810       agg->all_unknown = 0;
00811    case AST_DEVICE_INVALID:
00812       agg->all_busy = 0;
00813       agg->all_free = 0;
00814       break;
00815    case AST_DEVICE_UNKNOWN:
00816       agg->all_busy = 0;
00817       agg->all_free = 0;
00818       break;
00819    case AST_DEVICE_TOTAL: /* not a device state, included for completeness. */
00820       break;
00821    }
00822 }

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

00760 {
00761    memset(agg, 0, sizeof(*agg));
00762 
00763    agg->all_unknown = 1;
00764    agg->all_unavail = 1;
00765    agg->all_busy = 1;
00766    agg->all_free = 1;
00767 }

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

00826 {
00827    if (agg->all_free)
00828       return AST_DEVICE_NOT_INUSE;
00829    if ((agg->in_use || agg->on_hold) && agg->ring)
00830       return AST_DEVICE_RINGINUSE;
00831    if (agg->ring)
00832       return AST_DEVICE_RINGING;
00833    if (agg->busy)
00834       return AST_DEVICE_BUSY;
00835    if (agg->in_use)
00836       return AST_DEVICE_INUSE;
00837    if (agg->on_hold)
00838       return AST_DEVICE_ONHOLD;
00839    if (agg->all_busy)
00840       return AST_DEVICE_BUSY;
00841    if (agg->all_unknown)
00842       return AST_DEVICE_UNKNOWN;
00843    if (agg->all_unavail)
00844       return AST_DEVICE_UNAVAILABLE;
00845 
00846    return AST_DEVICE_NOT_INUSE;
00847 }

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

00535 {
00536    char buf[AST_MAX_EXTENSION];
00537    va_list ap;
00538 
00539    va_start(ap, fmt);
00540    vsnprintf(buf, sizeof(buf), fmt, ap);
00541    va_end(ap);
00542 
00543    return ast_devstate_changed_literal(state, buf);
00544 }

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

00492 {
00493    struct state_change *change;
00494 
00495    /* 
00496     * If we know the state change (how nice of the caller of this function!)
00497     * then we can just generate a device state event. 
00498     *
00499     * Otherwise, we do the following:
00500     *   - Queue an event up to another thread that the state has changed
00501     *   - In the processing thread, it calls the callback provided by the
00502     *     device state provider (which may or may not be a channel driver)
00503     *     to determine the state.
00504     *   - If the device state provider does not know the state, or this is
00505     *     for a channel and the channel driver does not implement a device
00506     *     state callback, then we will look through the channel list to
00507     *     see if we can determine a state based on active calls.
00508     *   - Once a state has been determined, a device state event is generated.
00509     */
00510 
00511    if (state != AST_DEVICE_UNKNOWN) {
00512       devstate_event(device, state);
00513    } else if (change_thread == AST_PTHREADT_NULL || !(change = ast_calloc(1, sizeof(*change) + strlen(device)))) {
00514       /* we could not allocate a change struct, or */
00515       /* there is no background thread, so process the change now */
00516       do_state_change(device);
00517    } else {
00518       /* queue the change */
00519       strcpy(change->device, device);
00520       AST_LIST_LOCK(&state_changes);
00521       AST_LIST_INSERT_TAIL(&state_changes, change, list);
00522       ast_cond_signal(&change_pending);
00523       AST_LIST_UNLOCK(&state_changes);
00524    }
00525 
00526    return 1;
00527 }

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

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

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

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

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 226 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_TOTAL, AST_DEVICE_UNAVAILABLE, and AST_DEVICE_UNKNOWN.

Referenced by devstate_read().

00227 {
00228    const char *res = "UNKNOWN";
00229 
00230    switch (state) {
00231    case AST_DEVICE_UNKNOWN:
00232       break;
00233    case AST_DEVICE_NOT_INUSE:
00234       res = "NOT_INUSE";
00235       break;
00236    case AST_DEVICE_INUSE:
00237       res = "INUSE";
00238       break;
00239    case AST_DEVICE_BUSY:
00240       res = "BUSY";
00241       break;
00242    case AST_DEVICE_INVALID:
00243       res = "INVALID";
00244       break;
00245    case AST_DEVICE_UNAVAILABLE:
00246       res = "UNAVAILABLE";
00247       break;
00248    case AST_DEVICE_RINGING:
00249       res = "RINGING";
00250       break;
00251    case AST_DEVICE_RINGINUSE:
00252       res = "RINGINUSE";
00253       break;
00254    case AST_DEVICE_ONHOLD:
00255       res = "ONHOLD";
00256       break;
00257    case AST_DEVICE_TOTAL:
00258       break;
00259    }
00260 
00261    return res;
00262 }

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

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

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

00850 {
00851    if (devstate_collector.enabled) {
00852       return 0;
00853    }
00854 
00855    devstate_collector.event_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE_CHANGE,
00856       devstate_change_collector_cb, NULL, AST_EVENT_IE_END);
00857 
00858    if (!devstate_collector.event_sub) {
00859       ast_log(LOG_ERROR, "Failed to create subscription for the device state change collector\n");
00860       return -1;
00861    }
00862 
00863    ast_mutex_init(&devstate_collector.lock);
00864    ast_cond_init(&devstate_collector.cond, NULL);
00865    if (ast_pthread_create_background(&devstate_collector.thread, NULL, run_devstate_collector, NULL) < 0) {
00866       ast_log(LOG_ERROR, "Unable to start device state collector thread.\n");
00867       return -1;
00868    }
00869 
00870    devstate_collector.enabled = 1;
00871 
00872    return 0;
00873 }

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

00292 {
00293    struct ast_channel *chan;
00294    char match[AST_CHANNEL_NAME];
00295    enum ast_device_state res;
00296 
00297    ast_copy_string(match, device, sizeof(match)-1);
00298    strcat(match, "-");
00299    chan = ast_get_channel_by_name_prefix_locked(match, strlen(match));
00300 
00301    if (!chan)
00302       return AST_DEVICE_UNKNOWN;
00303 
00304    if (chan->_state == AST_STATE_RINGING)
00305       res = AST_DEVICE_RINGING;
00306    else
00307       res = AST_DEVICE_INUSE;
00308    
00309    ast_channel_unlock(chan);
00310 
00311    return res;
00312 }

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

References AST_DEVICE_UNKNOWN, and chan.

Referenced by dahdi_new().

00215 {
00216    int i;
00217    chanstate &= 0xFFFF;
00218    for (i = 0; chan2dev[i].chan != -100; i++) {
00219       if (chan2dev[i].chan == chanstate) {
00220          return chan2dev[i].dev;
00221       }
00222    }
00223    return AST_DEVICE_UNKNOWN;
00224 }

static void destroy_devstate_change ( struct devstate_change sc  )  [static]

Definition at line 583 of file devicestate.c.

References ast_free.

Referenced by run_devstate_collector().

00584 {
00585    ast_free(sc);
00586 }

const char* devstate2str ( enum ast_device_state  devstate  ) 

Find devicestate as text message for output.

Convert device state to text string 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];
00212 }

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

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

00595 {
00596    struct change_collection *collection = data;
00597    int i;
00598    const struct ast_eid *eid;
00599 
00600    if (collection->num_states == ARRAY_LEN(collection->states)) {
00601       ast_log(LOG_ERROR, "More per-server state values than we have room for (MAX_SERVERS is %d)\n",
00602          MAX_SERVERS);
00603       return;
00604    }
00605 
00606    if (!(eid = ast_event_get_ie_raw(event, AST_EVENT_IE_EID))) {
00607       ast_log(LOG_ERROR, "Device state change event with no EID\n");
00608       return;
00609    }
00610 
00611    i = collection->num_states;
00612 
00613    collection->states[i].state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
00614    collection->states[i].eid = *eid;
00615 
00616    collection->num_states++;
00617 }

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

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

00315 {
00316    enum ast_device_state res = AST_DEVICE_UNKNOWN;
00317    struct ast_event *event;
00318 
00319    event = ast_event_get_cached(AST_EVENT_DEVICE_STATE,
00320       AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device,
00321       AST_EVENT_IE_END);
00322 
00323    if (!event)
00324       return res;
00325 
00326    res = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
00327 
00328    ast_event_destroy(event);
00329 
00330    return res;
00331 }

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

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

00719 {
00720    struct devstate_change *sc;
00721    const char *device;
00722    const struct ast_eid *eid;
00723    uint32_t state;
00724 
00725    device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
00726    eid = ast_event_get_ie_raw(event, AST_EVENT_IE_EID);
00727    state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
00728 
00729    if (ast_strlen_zero(device) || !eid) {
00730       ast_log(LOG_ERROR, "Invalid device state change event received\n");
00731       return;
00732    }
00733 
00734    if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device))))
00735       return;
00736 
00737    strcpy(sc->device, device);
00738    sc->eid = *eid;
00739    sc->state = state;
00740 
00741    ast_mutex_lock(&devstate_collector.lock);
00742    AST_LIST_INSERT_TAIL(&devstate_collector.devstate_change_q, sc, entry);
00743    ast_cond_signal(&devstate_collector.cond);
00744    ast_mutex_unlock(&devstate_collector.lock);
00745 }

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

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

00454 {
00455    struct ast_event *event;
00456    enum ast_event_type event_type;
00457 
00458    if (devstate_collector.enabled) {
00459       /* Distributed device state is enabled, so this state change is a change
00460        * for a single server, not the real state. */
00461       event_type = AST_EVENT_DEVICE_STATE_CHANGE;
00462    } else {
00463       event_type = AST_EVENT_DEVICE_STATE;
00464    }
00465 
00466    ast_debug(3, "device '%s' state '%d'\n", device, state);
00467 
00468    if (!(event = ast_event_new(event_type,
00469          AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device,
00470          AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_UINT, state,
00471          AST_EVENT_IE_END))) {
00472       return;
00473    }
00474 
00475    ast_event_queue_and_cache(event);
00476 }

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

00560 {
00561    struct state_change *next, *current;
00562 
00563    for (;;) {
00564       /* This basically pops off any state change entries, resets the list back to NULL, unlocks, and processes each state change */
00565       AST_LIST_LOCK(&state_changes);
00566       if (AST_LIST_EMPTY(&state_changes))
00567          ast_cond_wait(&change_pending, &state_changes.lock);
00568       next = AST_LIST_FIRST(&state_changes);
00569       AST_LIST_HEAD_INIT_NOLOCK(&state_changes);
00570       AST_LIST_UNLOCK(&state_changes);
00571 
00572       /* Process each state change */
00573       while ((current = next)) {
00574          next = AST_LIST_NEXT(current, list);
00575          do_state_change(current->device);
00576          ast_free(current);
00577       }
00578    }
00579 
00580    return NULL;
00581 }

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

References _ast_device_state(), ast_debug, devstate2str(), and devstate_event().

Referenced by ast_devstate_changed_literal(), and do_devstate_changes().

00481 {
00482    enum ast_device_state state;
00483 
00484    state = _ast_device_state(device, 0);
00485 
00486    ast_debug(3, "Changing state for %s - state %d (%s)\n", device, state, devstate2str(state));
00487 
00488    devstate_event(device, state);
00489 }

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

Get provider device state.

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

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

static void handle_devstate_change ( struct devstate_change sc  )  [static]

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

00673 {
00674    struct ast_event_sub *tmp_sub;
00675    struct change_collection collection = {
00676       .num_states = 0,
00677    };
00678 
00679    ast_debug(1, "Processing device state change for '%s'\n", sc->device);
00680 
00681    if (!(tmp_sub = ast_event_subscribe_new(AST_EVENT_DEVICE_STATE_CHANGE, devstate_cache_cb, &collection))) {
00682       ast_log(LOG_ERROR, "Failed to create subscription\n");
00683       return;
00684    }
00685 
00686    if (ast_event_sub_append_ie_str(tmp_sub, AST_EVENT_IE_DEVICE, sc->device)) {
00687       ast_log(LOG_ERROR, "Failed to append device IE\n");
00688       ast_event_sub_destroy(tmp_sub);
00689       return;
00690    }
00691 
00692    /* Populate the collection of device states from the cache */
00693    ast_event_dump_cache(tmp_sub);
00694 
00695    process_collection(sc->device, &collection);
00696 
00697    ast_event_sub_destroy(tmp_sub);
00698 }

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

Definition at line 619 of file devicestate.c.

References ast_debug, 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(), devstate2str(), change_collection::num_states, devstate_change::state, and change_collection::states.

Referenced by handle_devstate_change().

00620 {
00621    int i;
00622    struct ast_devstate_aggregate agg;
00623    enum ast_device_state state;
00624    struct ast_event *event;
00625 
00626    ast_devstate_aggregate_init(&agg);
00627 
00628    for (i = 0; i < collection->num_states; i++) {
00629       ast_debug(1, "Adding per-server state of '%s' for '%s'\n", 
00630          devstate2str(collection->states[i].state), device);
00631       ast_devstate_aggregate_add(&agg, collection->states[i].state);
00632    }
00633 
00634    state = ast_devstate_aggregate_result(&agg);
00635 
00636    ast_debug(1, "Aggregate devstate result is %d\n", state);
00637 
00638    event = ast_event_get_cached(AST_EVENT_DEVICE_STATE,
00639       AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device,
00640       AST_EVENT_IE_END);
00641    
00642    if (event) {
00643       enum ast_device_state old_state;
00644 
00645       old_state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
00646       
00647       ast_event_destroy(event);
00648 
00649       if (state == old_state) {
00650          /* No change since last reported device state */
00651          ast_debug(1, "Aggregate state for device '%s' has not changed from '%s'\n",
00652             device, devstate2str(state));
00653          return;
00654       }
00655    }
00656 
00657    ast_debug(1, "Aggregate state for device '%s' has changed to '%s'\n",
00658       device, devstate2str(state));
00659 
00660    event = ast_event_new(AST_EVENT_DEVICE_STATE,
00661       AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device,
00662       AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_UINT, state,
00663       AST_EVENT_IE_END);
00664 
00665    if (!event) {
00666       return;
00667    }
00668 
00669    ast_event_queue_and_cache(event);
00670 }

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

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

00701 {
00702    for (;;) {
00703       struct devstate_change *sc;
00704 
00705       ast_mutex_lock(&devstate_collector.lock);
00706       while (!(sc = AST_LIST_REMOVE_HEAD(&devstate_collector.devstate_change_q, entry)))
00707          ast_cond_wait(&devstate_collector.cond, &devstate_collector.lock);
00708       ast_mutex_unlock(&devstate_collector.lock);
00709 
00710       handle_devstate_change(sc);
00711 
00712       destroy_devstate_change(sc);
00713    }
00714 
00715    return NULL;
00716 }


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

struct { ... } devstate_change_q

struct { ... } devstate_collector

const char* devstatestring[] [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.

Definition at line 195 of file devicestate.c.

Referenced by dump_cache_cb().

pthread_t thread


Generated on Wed Oct 28 11:52:17 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6