#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, 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) |
Search the Channels by Name. | |
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 { | |
devstate_change * first | |
devstate_change * last | |
} devstate_change_q | |
unsigned int enabled:1 | |
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. |
Russell Bryant <russell@digium.com>
Definition in file devicestate.c.
#define MAX_SERVERS 64 |
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 304 of file devicestate.c.
References ast_debug, AST_DEVICE_INVALID, ast_device_state(), AST_DEVICE_UNKNOWN, ast_get_channel_tech(), ast_parse_device_state(), ast_strdupa, ast_channel_tech::devicestate, devstate_cached(), getproviderstate(), and strsep().
Referenced by ast_device_state(), and do_state_change().
00305 { 00306 char *buf; 00307 char *number; 00308 const struct ast_channel_tech *chan_tech; 00309 enum ast_device_state res; 00310 /*! \brief Channel driver that provides device state */ 00311 char *tech; 00312 /*! \brief Another provider of device state */ 00313 char *provider = NULL; 00314 00315 /* If the last known state is cached, just return that */ 00316 if (check_cache) { 00317 res = devstate_cached(device); 00318 if (res != AST_DEVICE_UNKNOWN) { 00319 return res; 00320 } 00321 } 00322 00323 buf = ast_strdupa(device); 00324 tech = strsep(&buf, "/"); 00325 if (!(number = buf)) { 00326 provider = strsep(&tech, ":"); 00327 if (!tech) { 00328 return AST_DEVICE_INVALID; 00329 } 00330 /* We have a provider */ 00331 number = tech; 00332 tech = NULL; 00333 } 00334 00335 if (provider) { 00336 ast_debug(3, "Checking if I can find provider for \"%s\" - number: %s\n", provider, number); 00337 return getproviderstate(provider, number); 00338 } 00339 00340 ast_debug(4, "No provider found, checking channel drivers for %s - %s\n", tech, number); 00341 00342 if (!(chan_tech = ast_get_channel_tech(tech))) 00343 return AST_DEVICE_INVALID; 00344 00345 if (!(chan_tech->devicestate)) /* Does the channel driver support device state notification? */ 00346 return ast_parse_device_state(device); /* No, try the generic function */ 00347 00348 res = chan_tech->devicestate(number); 00349 00350 if (res != AST_DEVICE_UNKNOWN) 00351 return res; 00352 00353 res = ast_parse_device_state(device); 00354 00355 return res; 00356 }
enum ast_device_state ast_device_state | ( | const char * | device | ) |
Asks a channel for device state.
device | like a dial string |
an | AST_DEVICE_??? state | |
-1 | on failure |
Definition at line 358 of file devicestate.c.
References _ast_device_state().
Referenced by _ast_device_state(), ast_extension_state2(), ast_parse_device_state(), cc_generic_agent_recall(), cc_generic_agent_status_request(), cc_generic_monitor_suspend(), cc_generic_monitor_unsuspend(), cc_status_response(), chanavail_exec(), create_new_generic_list(), dahdi_pri_update_span_devstate(), device_state_cb(), devstate_cached(), devstate_read(), devstate_write(), do_state_change(), generic_monitor_devstate_tp_cb(), get_queue_member_status(), handle_cli_devstate_change(), page_exec(), process_collection(), sip_cc_agent_status_request(), skinny_extensionstate_cb(), sla_state(), and state_notify_build_xml().
00359 { 00360 /* This function is called from elsewhere in the code to find out the 00361 * current state of a device. Check the cache, first. */ 00362 00363 return _ast_device_state(device, 1); 00364 }
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 |
0 | on success | |
-1 | on failure |
Definition at line 518 of file devicestate.c.
References AST_DEVICE_UNKNOWN, ast_devstate_changed_literal(), and AST_MAX_EXTENSION.
00519 { 00520 char buf[AST_MAX_EXTENSION]; 00521 va_list ap; 00522 00523 va_start(ap, fmt); 00524 vsnprintf(buf, sizeof(buf), fmt, ap); 00525 va_end(ap); 00526 00527 return ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, buf); 00528 }
int ast_device_state_changed_literal | ( | const char * | device | ) |
Tells Asterisk the State for Device is changed.
device | device name like a dial string |
0 | on success | |
-1 | on failure |
Definition at line 501 of file devicestate.c.
References AST_DEVICE_UNKNOWN, and ast_devstate_changed_literal().
00502 { 00503 return ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, dev); 00504 }
int ast_device_state_engine_init | ( | void | ) |
Initialize the device state engine in separate thread.
Provided by devicestate.c
Definition at line 721 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().
00722 { 00723 ast_cond_init(&change_pending, NULL); 00724 if (ast_pthread_create_background(&change_thread, NULL, do_devstate_changes, NULL) < 0) { 00725 ast_log(LOG_ERROR, "Unable to start device state change thread.\n"); 00726 return -1; 00727 } 00728 00729 return 0; 00730 }
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(), extension_state_cb(), 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.
[in] | agg | the state object |
[in] | state | the state to add |
Definition at line 742 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().
00743 { 00744 switch (state) { 00745 case AST_DEVICE_NOT_INUSE: 00746 agg->all_unknown = 0; 00747 agg->all_unavail = 0; 00748 agg->all_busy = 0; 00749 break; 00750 case AST_DEVICE_INUSE: 00751 agg->in_use = 1; 00752 agg->all_unavail = 0; 00753 agg->all_free = 0; 00754 agg->all_unknown = 0; 00755 break; 00756 case AST_DEVICE_RINGING: 00757 agg->ring = 1; 00758 agg->all_unavail = 0; 00759 agg->all_free = 0; 00760 agg->all_unknown = 0; 00761 break; 00762 case AST_DEVICE_RINGINUSE: 00763 agg->in_use = 1; 00764 agg->ring = 1; 00765 agg->all_unavail = 0; 00766 agg->all_free = 0; 00767 agg->all_unknown = 0; 00768 break; 00769 case AST_DEVICE_ONHOLD: 00770 agg->all_unknown = 0; 00771 agg->all_unavail = 0; 00772 agg->all_free = 0; 00773 agg->on_hold = 1; 00774 break; 00775 case AST_DEVICE_BUSY: 00776 agg->all_unknown = 0; 00777 agg->all_unavail = 0; 00778 agg->all_free = 0; 00779 agg->busy = 1; 00780 agg->in_use = 1; 00781 break; 00782 case AST_DEVICE_UNAVAILABLE: 00783 agg->all_unknown = 0; 00784 case AST_DEVICE_INVALID: 00785 agg->all_busy = 0; 00786 agg->all_free = 0; 00787 break; 00788 case AST_DEVICE_UNKNOWN: 00789 agg->all_busy = 0; 00790 agg->all_free = 0; 00791 break; 00792 case AST_DEVICE_TOTAL: /* not a device state, included for completeness. */ 00793 break; 00794 } 00795 }
void ast_devstate_aggregate_init | ( | struct ast_devstate_aggregate * | agg | ) |
Initialize aggregate device state.
[in] | agg | the state object |
Definition at line 732 of file devicestate.c.
Referenced by ast_extension_state2(), and process_collection().
00733 { 00734 memset(agg, 0, sizeof(*agg)); 00735 00736 agg->all_unknown = 1; 00737 agg->all_unavail = 1; 00738 agg->all_busy = 1; 00739 agg->all_free = 1; 00740 }
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 798 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().
00799 { 00800 if (agg->all_free) 00801 return AST_DEVICE_NOT_INUSE; 00802 if ((agg->in_use || agg->on_hold) && agg->ring) 00803 return AST_DEVICE_RINGINUSE; 00804 if (agg->ring) 00805 return AST_DEVICE_RINGING; 00806 if (agg->busy) 00807 return AST_DEVICE_BUSY; 00808 if (agg->in_use) 00809 return AST_DEVICE_INUSE; 00810 if (agg->on_hold) 00811 return AST_DEVICE_ONHOLD; 00812 if (agg->all_busy) 00813 return AST_DEVICE_BUSY; 00814 if (agg->all_unknown) 00815 return AST_DEVICE_UNKNOWN; 00816 if (agg->all_unavail) 00817 return AST_DEVICE_UNAVAILABLE; 00818 00819 return AST_DEVICE_NOT_INUSE; 00820 }
int ast_devstate_changed | ( | enum ast_device_state | state, | |
const char * | fmt, | |||
... | ||||
) |
Tells Asterisk the State for Device is changed.
state | the new state of the device | |
fmt | device name like a dial string with format parameters |
0 | on success | |
-1 | on failure |
Definition at line 506 of file devicestate.c.
References ast_devstate_changed_literal(), and AST_MAX_EXTENSION.
Referenced by __expire_registry(), __iax2_poke_noanswer(), agent_call(), agent_hangup(), agent_read(), calendar_devstate_change(), conf_run(), dahdi_pri_update_span_devstate(), 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().
00507 { 00508 char buf[AST_MAX_EXTENSION]; 00509 va_list ap; 00510 00511 va_start(ap, fmt); 00512 vsnprintf(buf, sizeof(buf), fmt, ap); 00513 va_end(ap); 00514 00515 return ast_devstate_changed_literal(state, buf); 00516 }
int ast_devstate_changed_literal | ( | enum ast_device_state | state, | |
const char * | device | |||
) |
Tells Asterisk the State for Device is changed.
state | the new state of the device | |
device | device name like a dial string with format parameters |
0 | on success | |
-1 | on failure |
Definition at line 463 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, devstate_event(), do_state_change(), and devstate_prov::list.
Referenced by ast_channel_destructor(), ast_device_state_changed(), ast_device_state_changed_literal(), ast_devstate_changed(), ast_setstate(), and dahdi_new().
00464 { 00465 struct state_change *change; 00466 00467 /* 00468 * If we know the state change (how nice of the caller of this function!) 00469 * then we can just generate a device state event. 00470 * 00471 * Otherwise, we do the following: 00472 * - Queue an event up to another thread that the state has changed 00473 * - In the processing thread, it calls the callback provided by the 00474 * device state provider (which may or may not be a channel driver) 00475 * to determine the state. 00476 * - If the device state provider does not know the state, or this is 00477 * for a channel and the channel driver does not implement a device 00478 * state callback, then we will look through the channel list to 00479 * see if we can determine a state based on active calls. 00480 * - Once a state has been determined, a device state event is generated. 00481 */ 00482 00483 if (state != AST_DEVICE_UNKNOWN) { 00484 devstate_event(device, state); 00485 } else if (change_thread == AST_PTHREADT_NULL || !(change = ast_calloc(1, sizeof(*change) + strlen(device)))) { 00486 /* we could not allocate a change struct, or */ 00487 /* there is no background thread, so process the change now */ 00488 do_state_change(device); 00489 } else { 00490 /* queue the change */ 00491 strcpy(change->device, device); 00492 AST_LIST_LOCK(&state_changes); 00493 AST_LIST_INSERT_TAIL(&state_changes, change, list); 00494 ast_cond_signal(&change_pending); 00495 AST_LIST_UNLOCK(&state_changes); 00496 } 00497 00498 return 1; 00499 }
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 367 of file devicestate.c.
References ast_calloc, ast_copy_string(), AST_RWLIST_INSERT_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and devstate_prov::list.
Referenced by ast_features_init(), and load_module().
00368 { 00369 struct devstate_prov *devprov; 00370 00371 if (!callback || !(devprov = ast_calloc(1, sizeof(*devprov)))) 00372 return -1; 00373 00374 devprov->callback = callback; 00375 ast_copy_string(devprov->label, label, sizeof(devprov->label)); 00376 00377 AST_RWLIST_WRLOCK(&devstate_provs); 00378 AST_RWLIST_INSERT_HEAD(&devstate_provs, devprov, list); 00379 AST_RWLIST_UNLOCK(&devstate_provs); 00380 00381 return 0; 00382 }
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 385 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, devstate_prov::label, and devstate_prov::list.
Referenced by unload_module().
00386 { 00387 struct devstate_prov *devcb; 00388 int res = -1; 00389 00390 AST_RWLIST_WRLOCK(&devstate_provs); 00391 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&devstate_provs, devcb, list) { 00392 if (!strcasecmp(devcb->label, label)) { 00393 AST_RWLIST_REMOVE_CURRENT(list); 00394 ast_free(devcb); 00395 res = 0; 00396 break; 00397 } 00398 } 00399 AST_RWLIST_TRAVERSE_SAFE_END; 00400 AST_RWLIST_UNLOCK(&devstate_provs); 00401 00402 return res; 00403 }
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 233 of file devicestate.c.
Referenced by aji_devstate_cb(), and 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.
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 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 aji_handle_pubsub_event(), 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.
0 | success | |
-1 | failure |
Definition at line 822 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().
00823 { 00824 if (devstate_collector.enabled) { 00825 return 0; 00826 } 00827 00828 devstate_collector.event_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE_CHANGE, 00829 devstate_change_collector_cb, "devicestate_engine_enable_distributed", NULL, AST_EVENT_IE_END); 00830 00831 if (!devstate_collector.event_sub) { 00832 ast_log(LOG_ERROR, "Failed to create subscription for the device state change collector\n"); 00833 return -1; 00834 } 00835 00836 ast_mutex_init(&devstate_collector.lock); 00837 ast_cond_init(&devstate_collector.cond, NULL); 00838 if (ast_pthread_create_background(&devstate_collector.thread, NULL, run_devstate_collector, NULL) < 0) { 00839 ast_log(LOG_ERROR, "Unable to start device state collector thread.\n"); 00840 return -1; 00841 } 00842 00843 devstate_collector.enabled = 1; 00844 00845 return 0; 00846 }
enum ast_device_state ast_parse_device_state | ( | const char * | device | ) |
Search the Channels by Name.
Definition at line 265 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_state(), AST_DEVICE_UNKNOWN, AST_STATE_RINGING, 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 snprintf(match, sizeof(match), "%s-", device); 00272 00273 if (!(chan = ast_channel_get_by_name_prefix(match, strlen(match)))) { 00274 return AST_DEVICE_UNKNOWN; 00275 } 00276 00277 res = (chan->_state == AST_STATE_RINGING) ? AST_DEVICE_RINGING : AST_DEVICE_INUSE; 00278 00279 chan = ast_channel_unref(chan); 00280 00281 return res; 00282 }
enum ast_device_state ast_state_chan2dev | ( | enum ast_channel_state | chanstate | ) |
Convert channel state to devicestate.
chanstate | Current channel state |
Definition at line 220 of file devicestate.c.
References AST_DEVICE_UNKNOWN.
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 555 of file devicestate.c.
References ast_free.
Referenced by run_devstate_collector().
00556 { 00557 ast_free(sc); 00558 }
const char* devstate2str | ( | enum ast_device_state | devstate | ) |
Convert device state to text string for output.
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 566 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, ast_eid::eid, LOG_ERROR, MAX_SERVERS, change_collection::num_states, devstate_change::state, and change_collection::states.
Referenced by handle_devstate_change().
00567 { 00568 struct change_collection *collection = data; 00569 int i; 00570 const struct ast_eid *eid; 00571 00572 if (collection->num_states == ARRAY_LEN(collection->states)) { 00573 ast_log(LOG_ERROR, "More per-server state values than we have room for (MAX_SERVERS is %d)\n", 00574 MAX_SERVERS); 00575 return; 00576 } 00577 00578 if (!(eid = ast_event_get_ie_raw(event, AST_EVENT_IE_EID))) { 00579 ast_log(LOG_ERROR, "Device state change event with no EID\n"); 00580 return; 00581 } 00582 00583 i = collection->num_states; 00584 00585 collection->states[i].state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE); 00586 collection->states[i].eid = *eid; 00587 00588 collection->num_states++; 00589 }
static enum ast_device_state devstate_cached | ( | const char * | device | ) | [static] |
Definition at line 284 of file devicestate.c.
References ast_device_state(), 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().
00285 { 00286 enum ast_device_state res = AST_DEVICE_UNKNOWN; 00287 struct ast_event *event; 00288 00289 event = ast_event_get_cached(AST_EVENT_DEVICE_STATE, 00290 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device, 00291 AST_EVENT_IE_END); 00292 00293 if (!event) 00294 return res; 00295 00296 res = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE); 00297 00298 ast_event_destroy(event); 00299 00300 return res; 00301 }
static void devstate_change_collector_cb | ( | const struct ast_event * | event, | |
void * | data | |||
) | [static] |
Definition at line 691 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_collector, ast_eid::eid, and LOG_ERROR.
Referenced by ast_enable_distributed_devstate().
00692 { 00693 struct devstate_change *sc; 00694 const char *device; 00695 const struct ast_eid *eid; 00696 uint32_t state; 00697 00698 device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE); 00699 eid = ast_event_get_ie_raw(event, AST_EVENT_IE_EID); 00700 state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE); 00701 00702 if (ast_strlen_zero(device) || !eid) { 00703 ast_log(LOG_ERROR, "Invalid device state change event received\n"); 00704 return; 00705 } 00706 00707 if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device)))) 00708 return; 00709 00710 strcpy(sc->device, device); 00711 sc->eid = *eid; 00712 sc->state = state; 00713 00714 ast_mutex_lock(&devstate_collector.lock); 00715 AST_LIST_INSERT_TAIL(&devstate_collector.devstate_change_q, sc, entry); 00716 ast_cond_signal(&devstate_collector.cond); 00717 ast_mutex_unlock(&devstate_collector.lock); 00718 }
static void devstate_event | ( | const char * | device, | |
enum ast_device_state | state | |||
) | [static] |
Definition at line 425 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().
00426 { 00427 struct ast_event *event; 00428 enum ast_event_type event_type; 00429 00430 if (devstate_collector.enabled) { 00431 /* Distributed device state is enabled, so this state change is a change 00432 * for a single server, not the real state. */ 00433 event_type = AST_EVENT_DEVICE_STATE_CHANGE; 00434 } else { 00435 event_type = AST_EVENT_DEVICE_STATE; 00436 } 00437 00438 ast_debug(3, "device '%s' state '%d'\n", device, state); 00439 00440 if (!(event = ast_event_new(event_type, 00441 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device, 00442 AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_UINT, state, 00443 AST_EVENT_IE_END))) { 00444 return; 00445 } 00446 00447 ast_event_queue_and_cache(event); 00448 }
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 531 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(), devstate_prov::list, state_changes::lock, and devstate_prov::next.
Referenced by ast_device_state_engine_init().
00532 { 00533 struct state_change *next, *current; 00534 00535 for (;;) { 00536 /* This basically pops off any state change entries, resets the list back to NULL, unlocks, and processes each state change */ 00537 AST_LIST_LOCK(&state_changes); 00538 if (AST_LIST_EMPTY(&state_changes)) 00539 ast_cond_wait(&change_pending, &state_changes.lock); 00540 next = AST_LIST_FIRST(&state_changes); 00541 AST_LIST_HEAD_INIT_NOLOCK(&state_changes); 00542 AST_LIST_UNLOCK(&state_changes); 00543 00544 /* Process each state change */ 00545 while ((current = next)) { 00546 next = AST_LIST_NEXT(current, list); 00547 do_state_change(current->device); 00548 ast_free(current); 00549 } 00550 } 00551 00552 return NULL; 00553 }
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 452 of file devicestate.c.
References _ast_device_state(), ast_debug, ast_device_state(), ast_devstate2str(), and devstate_event().
Referenced by ast_devstate_changed_literal(), and do_devstate_changes().
00453 { 00454 enum ast_device_state state; 00455 00456 state = _ast_device_state(device, 0); 00457 00458 ast_debug(3, "Changing state for %s - state %d (%s)\n", device, state, ast_devstate2str(state)); 00459 00460 devstate_event(device, state); 00461 }
static int getproviderstate | ( | const char * | provider, | |
const char * | address | |||
) | [static] |
Get provider device state.
Definition at line 406 of file devicestate.c.
References ast_debug, AST_DEVICE_INVALID, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, devstate_prov::callback, devstate_prov::label, and devstate_prov::list.
Referenced by _ast_device_state().
00407 { 00408 struct devstate_prov *devprov; 00409 int res = AST_DEVICE_INVALID; 00410 00411 AST_RWLIST_RDLOCK(&devstate_provs); 00412 AST_RWLIST_TRAVERSE(&devstate_provs, devprov, list) { 00413 ast_debug(5, "Checking provider %s with %s\n", devprov->label, provider); 00414 00415 if (!strcasecmp(devprov->label, provider)) { 00416 res = devprov->callback(address); 00417 break; 00418 } 00419 } 00420 AST_RWLIST_UNLOCK(&devstate_provs); 00421 00422 return res; 00423 }
static void handle_devstate_change | ( | struct devstate_change * | sc | ) | [static] |
Definition at line 645 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().
00646 { 00647 struct ast_event_sub *tmp_sub; 00648 struct change_collection collection = { 00649 .num_states = 0, 00650 }; 00651 00652 ast_debug(1, "Processing device state change for '%s'\n", sc->device); 00653 00654 if (!(tmp_sub = ast_event_subscribe_new(AST_EVENT_DEVICE_STATE_CHANGE, devstate_cache_cb, &collection))) { 00655 ast_log(LOG_ERROR, "Failed to create subscription\n"); 00656 return; 00657 } 00658 00659 if (ast_event_sub_append_ie_str(tmp_sub, AST_EVENT_IE_DEVICE, sc->device)) { 00660 ast_log(LOG_ERROR, "Failed to append device IE\n"); 00661 ast_event_sub_destroy(tmp_sub); 00662 return; 00663 } 00664 00665 /* Populate the collection of device states from the cache */ 00666 ast_event_dump_cache(tmp_sub); 00667 00668 process_collection(sc->device, &collection); 00669 00670 ast_event_sub_destroy(tmp_sub); 00671 }
static void process_collection | ( | const char * | device, | |
struct change_collection * | collection | |||
) | [static] |
Definition at line 591 of file devicestate.c.
References ast_debug, ast_device_state(), 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().
00592 { 00593 int i; 00594 struct ast_devstate_aggregate agg; 00595 enum ast_device_state state; 00596 struct ast_event *event; 00597 00598 ast_devstate_aggregate_init(&agg); 00599 00600 for (i = 0; i < collection->num_states; i++) { 00601 ast_debug(1, "Adding per-server state of '%s' for '%s'\n", 00602 ast_devstate2str(collection->states[i].state), device); 00603 ast_devstate_aggregate_add(&agg, collection->states[i].state); 00604 } 00605 00606 state = ast_devstate_aggregate_result(&agg); 00607 00608 ast_debug(1, "Aggregate devstate result is '%s' for '%s'\n", 00609 ast_devstate2str(state), device); 00610 00611 event = ast_event_get_cached(AST_EVENT_DEVICE_STATE, 00612 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device, 00613 AST_EVENT_IE_END); 00614 00615 if (event) { 00616 enum ast_device_state old_state; 00617 00618 old_state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE); 00619 00620 ast_event_destroy(event); 00621 00622 if (state == old_state) { 00623 /* No change since last reported device state */ 00624 ast_debug(1, "Aggregate state for device '%s' has not changed from '%s'\n", 00625 device, ast_devstate2str(state)); 00626 return; 00627 } 00628 } 00629 00630 ast_debug(1, "Aggregate state for device '%s' has changed to '%s'\n", 00631 device, ast_devstate2str(state)); 00632 00633 event = ast_event_new(AST_EVENT_DEVICE_STATE, 00634 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device, 00635 AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_UINT, state, 00636 AST_EVENT_IE_END); 00637 00638 if (!event) { 00639 return; 00640 } 00641 00642 ast_event_queue_and_cache(event); 00643 }
static void* run_devstate_collector | ( | void * | data | ) | [static] |
Definition at line 673 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().
00674 { 00675 for (;;) { 00676 struct devstate_change *sc; 00677 00678 ast_mutex_lock(&devstate_collector.lock); 00679 while (!(sc = AST_LIST_REMOVE_HEAD(&devstate_collector.devstate_change_q, entry))) 00680 ast_cond_wait(&devstate_collector.cond, &devstate_collector.lock); 00681 ast_mutex_unlock(&devstate_collector.lock); 00682 00683 handle_devstate_change(sc); 00684 00685 destroy_devstate_change(sc); 00686 } 00687 00688 return NULL; 00689 }
ast_cond_t change_pending [static] |
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 [static] |
const char* const devstatestring[][2] [static] |
unsigned int enabled |
Definition at line 199 of file devicestate.c.
struct ast_event_sub* event_sub |
Definition at line 195 of file devicestate.c.
Referenced by ast_event_dump_cache(), ast_event_report_subs(), and dump_cache_cb().
struct devstate_change* first |
Definition at line 198 of file devicestate.c.
struct devstate_change* last |
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.