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. |
Device state management.
Definition in file devicestate.c.
#define MAX_SERVERS 64 |
Definition at line 570 of file devicestate.c.
Referenced by devstate_cache_cb().
static enum ast_device_state _ast_device_state | ( | const char * | device, | |
int | check_cache | |||
) | [static] |
Check device state through channel specific function or generic function.
Channel driver that provides device state
Another provider of device state
Definition at line 310 of file devicestate.c.
References ast_debug, AST_DEVICE_INVALID, AST_DEVICE_UNKNOWN, ast_get_channel_tech(), ast_parse_device_state(), ast_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.
device | like a dial string |
Asks a channel for device state, data is normally a number from a dial string used by the low level module Tries the channel device state callback if not supported search in the active channels list for the device.
an | AST_DEVICE_??? state |
Definition at line 362 of file devicestate.c.
References _ast_device_state().
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.).
fmt | device name like a dial string with format parameters |
Asterisk polls the new extension states and calls the registered callbacks for the changed extensions
0 | on success | |
-1 | on failure |
Definition at line 528 of file devicestate.c.
References AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, ast_devstate_changed_literal(), and AST_MAX_EXTENSION.
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.
device | device name like a dial string |
Asterisk polls the new extension states and calls the registered callbacks for the changed extensions
0 | on success | |
-1 | on failure |
Definition at line 511 of file devicestate.c.
References AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, and ast_devstate_changed_literal().
00512 { 00513 return ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, dev); 00514 }
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.
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.
[in] | agg | the state object |
Definition at line 758 of file devicestate.c.
References AST_DEVICE_INVALID, and ast_devstate_aggregate::state.
Referenced by ast_extension_state3(), and process_collection().
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.
[in] | agg | the state object |
Definition at line 791 of file devicestate.c.
References ast_devstate_aggregate::state.
Referenced by ast_extension_state3(), and process_collection().
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.
state | the new state of the device | |
cachable | whether this device state is cachable | |
fmt | device name like a dial string with format parameters |
The new state of the device will be sent off to any subscribers of device states. It will also be stored in the internal event cache.
0 | on success | |
-1 | on failure |
Definition at line 516 of file devicestate.c.
References ast_devstate_changed_literal(), and AST_MAX_EXTENSION.
Referenced by __expire_registry(), __iax2_poke_noanswer(), 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.
state | the new state of the device | |
cachable | whether this device state is cachable | |
device | device name like a dial string with format parameters |
The new state of the device will be sent off to any subscribers of device states. It will also be stored in the internal event cache.
0 | on success | |
-1 | on failure |
Definition at line 472 of file devicestate.c.
References ast_calloc, ast_cond_signal, AST_DEVICE_UNKNOWN, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, state_change::cachable, change_thread, state_change::device, devstate_event(), and do_state_change().
Referenced by ast_channel_destructor(), ast_device_state_changed(), ast_device_state_changed_literal(), ast_devstate_changed(), ast_setstate(), and dahdi_new().
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.
label | to use in hint, like label:object | |
callback | Callback |
0 | success | |
-1 | failure |
Definition at line 371 of file devicestate.c.
References ast_calloc, ast_copy_string(), AST_RWLIST_INSERT_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, devstate_prov::callback, and devstate_prov::label.
Referenced by ast_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.
label | to use in hint, like label:object |
-1 | on failure | |
0 | on success |
Definition at line 389 of file devicestate.c.
References ast_free, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and devstate_prov::label.
Referenced by cc_shutdown(), features_shutdown(), and unload_module().
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.
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.
val | The text representing the device state. Valid values are anything that comes after AST_DEVICE_ in one of the defined values. |
Definition at line 244 of file devicestate.c.
References AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, AST_DEVICE_UNAVAILABLE, and AST_DEVICE_UNKNOWN.
Referenced by aji_handle_pubsub_event(), custom_devstate_callback(), devstate_write(), handle_cli_devstate_change(), 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.
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.
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.
chanstate | Current channel state |
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.
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 }
ast_cond_t change_pending [static] |
Flag for the queue.
Definition at line 189 of file devicestate.c.
pthread_t change_thread = AST_PTHREADT_NULL [static] |
The device state change notification thread.
Definition at line 186 of file devicestate.c.
Referenced by ast_device_state_engine_init(), and ast_devstate_changed_literal().
Definition at line 202 of file devicestate.c.
struct { ... } devstate_change_q |
struct { ... } devstate_collector [static] |
const char* const devstatestring[][2] [static] |
Device state strings for printing.
Definition at line 135 of file devicestate.c.
unsigned int enabled |
Definition at line 205 of file devicestate.c.
Referenced by __ast_http_load(), load_odbc_config(), and osp_check_destination().
struct ast_event_sub* event_sub |
Definition at line 201 of file devicestate.c.
Referenced by dump_cache_cb().
struct devstate_change* first |
Definition at line 204 of file devicestate.c.
Referenced by ast_fax_caps_to_str(), ast_format_str_reduce(), ast_print_group(), ast_xmldoc_build_seealso(), cdr_handler(), check_goto(), context_merge(), gen_prios(), generate_filenames_string(), generic_thread_loop(), get_goto_target(), get_pattern_node(), h261_encap(), h263_encap(), h263p_encap(), h264_encap(), listfilter(), log_jack_status(), mpeg4_encap(), multiplexed_thread_function(), odbc_log(), pgsql_log(), realtime_update2_handler(), realtimefield_read(), update2_curl(), update2_pgsql(), update2_prepare(), xmldoc_get_syntax_cmd(), and xmldoc_parse_cmd_enumlist().
struct devstate_change* last |
Definition at line 204 of file devicestate.c.
Referenced by add_extensions(), aji_handle_presence(), apply_outgoing(), ast_config_engine_deregister(), ast_db_freetree(), config_odbc(), config_pgsql(), do_monitor(), get_pattern_node(), gtalk_free_candidates(), internal_ao2_callback(), jingle_free_candidates(), load_password(), parse_contact_header(), process_db_keys(), and try_firmware().
Definition at line 203 of file devicestate.c.
pthread_t thread |
Definition at line 200 of file devicestate.c.