#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 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. | |
| const char * | ast_devstate2str (enum ast_device_state devstate) |
| Find devicestate as text message for output. | |
| void | ast_devstate_aggregate_add (struct ast_devstate_aggregate *agg, enum ast_device_state state) |
| Add a device state to the aggregate device state. | |
| void | ast_devstate_aggregate_init (struct ast_devstate_aggregate *agg) |
| Initialize aggregate device state. | |
| enum ast_device_state | ast_devstate_aggregate_result (struct ast_devstate_aggregate *agg) |
| Get the aggregate device state result. | |
| int | ast_devstate_changed (enum ast_device_state state, const char *fmt,...) |
| Tells Asterisk the State for Device is changed. | |
| int | ast_devstate_changed_literal (enum ast_device_state state, const char *device) |
| Tells Asterisk the State for Device is changed. | |
| int | ast_devstate_prov_add (const char *label, ast_devstate_prov_cb_type callback) |
| Add device state provider. | |
| int | ast_devstate_prov_del (const char *label) |
| Remove device state provider. | |
| const char * | ast_devstate_str (enum ast_device_state state) |
| Convert device state to text string that is easier to parse. | |
| enum ast_device_state | ast_devstate_val (const char *val) |
| Convert device state from text to integer value. | |
| int | ast_enable_distributed_devstate (void) |
| Enable distributed device state processing. | |
| enum ast_device_state | ast_parse_device_state (const char *device) |
| Find out if device is active in a call or not. | |
| enum ast_device_state | ast_state_chan2dev (enum ast_channel_state chanstate) |
| Convert channel state to devicestate. | |
| static void | destroy_devstate_change (struct devstate_change *sc) |
| const char * | devstate2str (enum ast_device_state devstate) |
| Convert device state to text string for output. | |
| static void | devstate_cache_cb (const struct ast_event *event, void *data) |
| static enum ast_device_state | devstate_cached (const char *device) |
| static void | devstate_change_collector_cb (const struct ast_event *event, void *data) |
| static void | devstate_event (const char *device, enum ast_device_state state) |
| static void * | do_devstate_changes (void *data) |
| Go through the dev state change queue and update changes in the dev state thread. | |
| static void | do_state_change (const char *device) |
| static int | getproviderstate (const char *provider, const char *address) |
| Get provider device state. | |
| static void | handle_devstate_change (struct devstate_change *sc) |
| static void | process_collection (const char *device, struct change_collection *collection) |
| static void * | run_devstate_collector (void *data) |
Variables | |
| static ast_cond_t | change_pending |
| Flag for the queue. | |
| static pthread_t | change_thread = AST_PTHREADT_NULL |
| The device state change notification thread. | |
| struct { | |
| ast_cond_t cond | |
| struct { | |
| struct devstate_change * first | |
| struct devstate_change * last | |
| } devstate_change_q | |
| unsigned int enabled:1 | |
| struct ast_event_sub * event_sub | |
| ast_mutex_t lock | |
| pthread_t thread | |
| } | devstate_collector |
| static const char *const | devstatestring [][2] |
| Device state strings for printing. | |
Definition in file devicestate.c.
| #define MAX_SERVERS 64 |
| static void __fini_devstate_provs | ( | void | ) | [static] |
| static void __init_devstate_provs | ( | void | ) | [static] |
| 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_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().
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 if (!(provider = strsep(&tech, ":"))) 00327 return AST_DEVICE_INVALID; 00328 /* We have a provider */ 00329 number = tech; 00330 tech = NULL; 00331 } 00332 00333 if (provider) { 00334 ast_debug(3, "Checking if I can find provider for \"%s\" - number: %s\n", provider, number); 00335 return getproviderstate(provider, number); 00336 } 00337 00338 ast_debug(4, "No provider found, checking channel drivers for %s - %s\n", tech, number); 00339 00340 if (!(chan_tech = ast_get_channel_tech(tech))) 00341 return AST_DEVICE_INVALID; 00342 00343 if (!(chan_tech->devicestate)) /* Does the channel driver support device state notification? */ 00344 return ast_parse_device_state(device); /* No, try the generic function */ 00345 00346 res = chan_tech->devicestate(number); 00347 00348 if (res != AST_DEVICE_UNKNOWN) 00349 return res; 00350 00351 res = ast_parse_device_state(device); 00352 00353 return res; 00354 }
| 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 356 of file devicestate.c.
References _ast_device_state().
00357 { 00358 /* This function is called from elsewhere in the code to find out the 00359 * current state of a device. Check the cache, first. */ 00360 00361 return _ast_device_state(device, 1); 00362 }
| 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 516 of file devicestate.c.
References AST_DEVICE_UNKNOWN, ast_devstate_changed_literal(), AST_MAX_EXTENSION, and buf.
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(AST_DEVICE_UNKNOWN, buf); 00526 }
| 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 499 of file devicestate.c.
References AST_DEVICE_UNKNOWN, and ast_devstate_changed_literal().
00500 { 00501 return ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, dev); 00502 }
| int ast_device_state_engine_init | ( | void | ) |
Initialize the device state engine in separate thread.
Provided by devicestate.c
Definition at line 718 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().
00719 { 00720 ast_cond_init(&change_pending, NULL); 00721 if (ast_pthread_create_background(&change_thread, NULL, do_devstate_changes, NULL) < 0) { 00722 ast_log(LOG_ERROR, "Unable to start device state change thread.\n"); 00723 return -1; 00724 } 00725 00726 return 0; 00727 }
| const char* ast_devstate2str | ( | enum ast_device_state | devstate | ) |
Find devicestate as text message for output.
Definition at line 209 of file devicestate.c.
Referenced by __queues_show(), do_state_change(), handle_statechange(), notify_metermaids(), page_exec(), and process_collection().
00210 { 00211 return devstatestring[devstate][0]; 00212 }
| void ast_devstate_aggregate_add | ( | struct ast_devstate_aggregate * | agg, | |
| enum ast_device_state | state | |||
| ) |
Add a device state to the aggregate device state.
Definition at line 739 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().
00740 { 00741 switch (state) { 00742 case AST_DEVICE_NOT_INUSE: 00743 agg->all_unknown = 0; 00744 agg->all_unavail = 0; 00745 agg->all_busy = 0; 00746 break; 00747 case AST_DEVICE_INUSE: 00748 agg->in_use = 1; 00749 agg->all_unavail = 0; 00750 agg->all_free = 0; 00751 agg->all_unknown = 0; 00752 break; 00753 case AST_DEVICE_RINGING: 00754 agg->ring = 1; 00755 agg->all_unavail = 0; 00756 agg->all_free = 0; 00757 agg->all_unknown = 0; 00758 break; 00759 case AST_DEVICE_RINGINUSE: 00760 agg->in_use = 1; 00761 agg->ring = 1; 00762 agg->all_unavail = 0; 00763 agg->all_free = 0; 00764 agg->all_unknown = 0; 00765 break; 00766 case AST_DEVICE_ONHOLD: 00767 agg->all_unknown = 0; 00768 agg->all_unavail = 0; 00769 agg->all_free = 0; 00770 agg->on_hold = 1; 00771 break; 00772 case AST_DEVICE_BUSY: 00773 agg->all_unknown = 0; 00774 agg->all_unavail = 0; 00775 agg->all_free = 0; 00776 agg->busy = 1; 00777 agg->in_use = 1; 00778 break; 00779 case AST_DEVICE_UNAVAILABLE: 00780 agg->all_unknown = 0; 00781 case AST_DEVICE_INVALID: 00782 agg->all_busy = 0; 00783 agg->all_free = 0; 00784 break; 00785 case AST_DEVICE_UNKNOWN: 00786 agg->all_busy = 0; 00787 agg->all_free = 0; 00788 break; 00789 case AST_DEVICE_TOTAL: /* not a device state, included for completeness. */ 00790 break; 00791 } 00792 }
| void ast_devstate_aggregate_init | ( | struct ast_devstate_aggregate * | agg | ) |
Initialize aggregate device state.
| [in] | agg | the state object |
Definition at line 729 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().
00730 { 00731 memset(agg, 0, sizeof(*agg)); 00732 00733 agg->all_unknown = 1; 00734 agg->all_unavail = 1; 00735 agg->all_busy = 1; 00736 agg->all_free = 1; 00737 }
| 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 795 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().
00796 { 00797 if (agg->all_free) 00798 return AST_DEVICE_NOT_INUSE; 00799 if ((agg->in_use || agg->on_hold) && agg->ring) 00800 return AST_DEVICE_RINGINUSE; 00801 if (agg->ring) 00802 return AST_DEVICE_RINGING; 00803 if (agg->busy) 00804 return AST_DEVICE_BUSY; 00805 if (agg->in_use) 00806 return AST_DEVICE_INUSE; 00807 if (agg->on_hold) 00808 return AST_DEVICE_ONHOLD; 00809 if (agg->all_busy) 00810 return AST_DEVICE_BUSY; 00811 if (agg->all_unknown) 00812 return AST_DEVICE_UNKNOWN; 00813 if (agg->all_unavail) 00814 return AST_DEVICE_UNAVAILABLE; 00815 00816 return AST_DEVICE_NOT_INUSE; 00817 }
| 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 504 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_read(), 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(), 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().
00505 { 00506 char buf[AST_MAX_EXTENSION]; 00507 va_list ap; 00508 00509 va_start(ap, fmt); 00510 vsnprintf(buf, sizeof(buf), fmt, ap); 00511 va_end(ap); 00512 00513 return ast_devstate_changed_literal(state, buf); 00514 }
| 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 461 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_destructor(), ast_device_state_changed(), ast_device_state_changed_literal(), ast_devstate_changed(), ast_setstate(), and dahdi_new().
00462 { 00463 struct state_change *change; 00464 00465 /* 00466 * If we know the state change (how nice of the caller of this function!) 00467 * then we can just generate a device state event. 00468 * 00469 * Otherwise, we do the following: 00470 * - Queue an event up to another thread that the state has changed 00471 * - In the processing thread, it calls the callback provided by the 00472 * device state provider (which may or may not be a channel driver) 00473 * to determine the state. 00474 * - If the device state provider does not know the state, or this is 00475 * for a channel and the channel driver does not implement a device 00476 * state callback, then we will look through the channel list to 00477 * see if we can determine a state based on active calls. 00478 * - Once a state has been determined, a device state event is generated. 00479 */ 00480 00481 if (state != AST_DEVICE_UNKNOWN) { 00482 devstate_event(device, state); 00483 } else if (change_thread == AST_PTHREADT_NULL || !(change = ast_calloc(1, sizeof(*change) + strlen(device)))) { 00484 /* we could not allocate a change struct, or */ 00485 /* there is no background thread, so process the change now */ 00486 do_state_change(device); 00487 } else { 00488 /* queue the change */ 00489 strcpy(change->device, device); 00490 AST_LIST_LOCK(&state_changes); 00491 AST_LIST_INSERT_TAIL(&state_changes, change, list); 00492 ast_cond_signal(&change_pending); 00493 AST_LIST_UNLOCK(&state_changes); 00494 } 00495 00496 return 1; 00497 }
| 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 365 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().
00366 { 00367 struct devstate_prov *devprov; 00368 00369 if (!callback || !(devprov = ast_calloc(1, sizeof(*devprov)))) 00370 return -1; 00371 00372 devprov->callback = callback; 00373 ast_copy_string(devprov->label, label, sizeof(devprov->label)); 00374 00375 AST_RWLIST_WRLOCK(&devstate_provs); 00376 AST_RWLIST_INSERT_HEAD(&devstate_provs, devprov, list); 00377 AST_RWLIST_UNLOCK(&devstate_provs); 00378 00379 return 0; 00380 }
| 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 383 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().
00384 { 00385 struct devstate_prov *devcb; 00386 int res = -1; 00387 00388 AST_RWLIST_WRLOCK(&devstate_provs); 00389 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&devstate_provs, devcb, list) { 00390 if (!strcasecmp(devcb->label, label)) { 00391 AST_RWLIST_REMOVE_CURRENT(list); 00392 ast_free(devcb); 00393 res = 0; 00394 break; 00395 } 00396 } 00397 AST_RWLIST_TRAVERSE_SAFE_END; 00398 AST_RWLIST_UNLOCK(&devstate_provs); 00399 00400 return res; 00401 }
| 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 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 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 819 of file devicestate.c.
References ast_cond_init(), AST_EVENT_DEVICE_STATE_CHANGE, AST_EVENT_IE_END, ast_event_subscribe(), ast_log(), ast_mutex_init(), ast_pthread_create_background, devstate_change_collector_cb(), devstate_collector, LOG_ERROR, and run_devstate_collector().
Referenced by add_publish_event(), and add_subscribe_event().
00820 { 00821 if (devstate_collector.enabled) { 00822 return 0; 00823 } 00824 00825 devstate_collector.event_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE_CHANGE, 00826 devstate_change_collector_cb, "devicestate_engine_enable_distributed", NULL, AST_EVENT_IE_END); 00827 00828 if (!devstate_collector.event_sub) { 00829 ast_log(LOG_ERROR, "Failed to create subscription for the device state change collector\n"); 00830 return -1; 00831 } 00832 00833 ast_mutex_init(&devstate_collector.lock); 00834 ast_cond_init(&devstate_collector.cond, NULL); 00835 if (ast_pthread_create_background(&devstate_collector.thread, NULL, run_devstate_collector, NULL) < 0) { 00836 ast_log(LOG_ERROR, "Unable to start device state collector thread.\n"); 00837 return -1; 00838 } 00839 00840 devstate_collector.enabled = 1; 00841 00842 return 0; 00843 }
| 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 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_UNKNOWN, AST_STATE_RINGING, chan, and match().
Referenced by _ast_device_state(), and chanavail_exec().
00266 { 00267 struct ast_channel *chan; 00268 char match[AST_CHANNEL_NAME]; 00269 enum ast_device_state res; 00270 00271 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, and chan.
Referenced by dahdi_new().
00221 { 00222 int i; 00223 chanstate &= 0xFFFF; 00224 for (i = 0; chan2dev[i].chan != -100; i++) { 00225 if (chan2dev[i].chan == chanstate) { 00226 return chan2dev[i].dev; 00227 } 00228 } 00229 return AST_DEVICE_UNKNOWN; 00230 }
| static void destroy_devstate_change | ( | struct devstate_change * | sc | ) | [static] |
Definition at line 553 of file devicestate.c.
References ast_free.
Referenced by run_devstate_collector().
00554 { 00555 ast_free(sc); 00556 }
| 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 564 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().
00565 { 00566 struct change_collection *collection = data; 00567 int i; 00568 const struct ast_eid *eid; 00569 00570 if (collection->num_states == ARRAY_LEN(collection->states)) { 00571 ast_log(LOG_ERROR, "More per-server state values than we have room for (MAX_SERVERS is %d)\n", 00572 MAX_SERVERS); 00573 return; 00574 } 00575 00576 if (!(eid = ast_event_get_ie_raw(event, AST_EVENT_IE_EID))) { 00577 ast_log(LOG_ERROR, "Device state change event with no EID\n"); 00578 return; 00579 } 00580 00581 i = collection->num_states; 00582 00583 collection->states[i].state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE); 00584 collection->states[i].eid = *eid; 00585 00586 collection->num_states++; 00587 }
| static enum ast_device_state devstate_cached | ( | const char * | device | ) | [static] |
Definition at line 284 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().
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 688 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().
00689 { 00690 struct devstate_change *sc; 00691 const char *device; 00692 const struct ast_eid *eid; 00693 uint32_t state; 00694 00695 device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE); 00696 eid = ast_event_get_ie_raw(event, AST_EVENT_IE_EID); 00697 state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE); 00698 00699 if (ast_strlen_zero(device) || !eid) { 00700 ast_log(LOG_ERROR, "Invalid device state change event received\n"); 00701 return; 00702 } 00703 00704 if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device)))) 00705 return; 00706 00707 strcpy(sc->device, device); 00708 sc->eid = *eid; 00709 sc->state = state; 00710 00711 ast_mutex_lock(&devstate_collector.lock); 00712 AST_LIST_INSERT_TAIL(&devstate_collector.devstate_change_q, sc, entry); 00713 ast_cond_signal(&devstate_collector.cond); 00714 ast_mutex_unlock(&devstate_collector.lock); 00715 }
| static void devstate_event | ( | const char * | device, | |
| enum ast_device_state | state | |||
| ) | [static] |
Definition at line 423 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().
00424 { 00425 struct ast_event *event; 00426 enum ast_event_type event_type; 00427 00428 if (devstate_collector.enabled) { 00429 /* Distributed device state is enabled, so this state change is a change 00430 * for a single server, not the real state. */ 00431 event_type = AST_EVENT_DEVICE_STATE_CHANGE; 00432 } else { 00433 event_type = AST_EVENT_DEVICE_STATE; 00434 } 00435 00436 ast_debug(3, "device '%s' state '%d'\n", device, state); 00437 00438 if (!(event = ast_event_new(event_type, 00439 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device, 00440 AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_UINT, state, 00441 AST_EVENT_IE_END))) { 00442 return; 00443 } 00444 00445 ast_event_queue_and_cache(event); 00446 }
| 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 529 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().
00530 { 00531 struct state_change *next, *current; 00532 00533 for (;;) { 00534 /* This basically pops off any state change entries, resets the list back to NULL, unlocks, and processes each state change */ 00535 AST_LIST_LOCK(&state_changes); 00536 if (AST_LIST_EMPTY(&state_changes)) 00537 ast_cond_wait(&change_pending, &state_changes.lock); 00538 next = AST_LIST_FIRST(&state_changes); 00539 AST_LIST_HEAD_INIT_NOLOCK(&state_changes); 00540 AST_LIST_UNLOCK(&state_changes); 00541 00542 /* Process each state change */ 00543 while ((current = next)) { 00544 next = AST_LIST_NEXT(current, list); 00545 do_state_change(current->device); 00546 ast_free(current); 00547 } 00548 } 00549 00550 return NULL; 00551 }
| 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 450 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().
00451 { 00452 enum ast_device_state state; 00453 00454 state = _ast_device_state(device, 0); 00455 00456 ast_debug(3, "Changing state for %s - state %d (%s)\n", device, state, ast_devstate2str(state)); 00457 00458 devstate_event(device, state); 00459 }
| static int getproviderstate | ( | const char * | provider, | |
| const char * | address | |||
| ) | [static] |
Get provider device state.
Definition at line 404 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().
00405 { 00406 struct devstate_prov *devprov; 00407 int res = AST_DEVICE_INVALID; 00408 00409 AST_RWLIST_RDLOCK(&devstate_provs); 00410 AST_RWLIST_TRAVERSE(&devstate_provs, devprov, list) { 00411 ast_debug(5, "Checking provider %s with %s\n", devprov->label, provider); 00412 00413 if (!strcasecmp(devprov->label, provider)) { 00414 res = devprov->callback(address); 00415 break; 00416 } 00417 } 00418 AST_RWLIST_UNLOCK(&devstate_provs); 00419 00420 return res; 00421 }
| static void handle_devstate_change | ( | struct devstate_change * | sc | ) | [static] |
Definition at line 642 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().
00643 { 00644 struct ast_event_sub *tmp_sub; 00645 struct change_collection collection = { 00646 .num_states = 0, 00647 }; 00648 00649 ast_debug(1, "Processing device state change for '%s'\n", sc->device); 00650 00651 if (!(tmp_sub = ast_event_subscribe_new(AST_EVENT_DEVICE_STATE_CHANGE, devstate_cache_cb, &collection))) { 00652 ast_log(LOG_ERROR, "Failed to create subscription\n"); 00653 return; 00654 } 00655 00656 if (ast_event_sub_append_ie_str(tmp_sub, AST_EVENT_IE_DEVICE, sc->device)) { 00657 ast_log(LOG_ERROR, "Failed to append device IE\n"); 00658 ast_event_sub_destroy(tmp_sub); 00659 return; 00660 } 00661 00662 /* Populate the collection of device states from the cache */ 00663 ast_event_dump_cache(tmp_sub); 00664 00665 process_collection(sc->device, &collection); 00666 00667 ast_event_sub_destroy(tmp_sub); 00668 }
| static void process_collection | ( | const char * | device, | |
| struct change_collection * | collection | |||
| ) | [static] |
Definition at line 589 of file devicestate.c.
References ast_debug, ast_devstate2str(), ast_devstate_aggregate_add(), ast_devstate_aggregate_init(), ast_devstate_aggregate_result(), ast_event_destroy(), AST_EVENT_DEVICE_STATE, ast_event_get_cached(), ast_event_get_ie_uint(), AST_EVENT_IE_DEVICE, AST_EVENT_IE_END, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_IE_STATE, ast_event_new(), ast_event_queue_and_cache(), change_collection::num_states, devstate_change::state, and change_collection::states.
Referenced by handle_devstate_change().
00590 { 00591 int i; 00592 struct ast_devstate_aggregate agg; 00593 enum ast_device_state state; 00594 struct ast_event *event; 00595 00596 ast_devstate_aggregate_init(&agg); 00597 00598 for (i = 0; i < collection->num_states; i++) { 00599 ast_debug(1, "Adding per-server state of '%s' for '%s'\n", 00600 ast_devstate2str(collection->states[i].state), device); 00601 ast_devstate_aggregate_add(&agg, collection->states[i].state); 00602 } 00603 00604 state = ast_devstate_aggregate_result(&agg); 00605 00606 ast_debug(1, "Aggregate devstate result is %d\n", state); 00607 00608 event = ast_event_get_cached(AST_EVENT_DEVICE_STATE, 00609 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device, 00610 AST_EVENT_IE_END); 00611 00612 if (event) { 00613 enum ast_device_state old_state; 00614 00615 old_state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE); 00616 00617 ast_event_destroy(event); 00618 00619 if (state == old_state) { 00620 /* No change since last reported device state */ 00621 ast_debug(1, "Aggregate state for device '%s' has not changed from '%s'\n", 00622 device, ast_devstate2str(state)); 00623 return; 00624 } 00625 } 00626 00627 ast_debug(1, "Aggregate state for device '%s' has changed to '%s'\n", 00628 device, ast_devstate2str(state)); 00629 00630 event = ast_event_new(AST_EVENT_DEVICE_STATE, 00631 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device, 00632 AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_UINT, state, 00633 AST_EVENT_IE_END); 00634 00635 if (!event) { 00636 return; 00637 } 00638 00639 ast_event_queue_and_cache(event); 00640 }
| static void* run_devstate_collector | ( | void * | data | ) | [static] |
Definition at line 670 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().
00671 { 00672 for (;;) { 00673 struct devstate_change *sc; 00674 00675 ast_mutex_lock(&devstate_collector.lock); 00676 while (!(sc = AST_LIST_REMOVE_HEAD(&devstate_collector.devstate_change_q, entry))) 00677 ast_cond_wait(&devstate_collector.cond, &devstate_collector.lock); 00678 ast_mutex_unlock(&devstate_collector.lock); 00679 00680 handle_devstate_change(sc); 00681 00682 destroy_devstate_change(sc); 00683 } 00684 00685 return NULL; 00686 }
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 |
| 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.
1.5.6