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, const char *fmt,...) |
| Tells Asterisk the State for Device is changed. | |
| int | ast_devstate_changed_literal (enum ast_device_state state, const char *device) |
| Tells Asterisk the State for Device is changed. | |
| int | ast_devstate_prov_add (const char *label, ast_devstate_prov_cb_type callback) |
| Add device state provider. | |
| int | ast_devstate_prov_del (const char *label) |
| Remove device state provider. | |
| const char * | ast_devstate_str (enum ast_device_state state) |
| Convert device state to text string that is easier to parse. | |
| enum ast_device_state | ast_devstate_val (const char *val) |
| Convert device state from text to integer value. | |
| int | ast_enable_distributed_devstate (void) |
| Enable distributed device state processing. | |
| enum ast_device_state | ast_parse_device_state (const char *device) |
| Find out if device is active in a call or not. | |
| enum ast_device_state | ast_state_chan2dev (enum ast_channel_state chanstate) |
| Convert channel state to devicestate. | |
| static void | destroy_devstate_change (struct devstate_change *sc) |
| const char * | devstate2str (enum ast_device_state devstate) |
| Convert device state to text string for output. | |
| static void | devstate_cache_cb (const struct ast_event *event, void *data) |
| static enum ast_device_state | devstate_cached (const char *device) |
| static void | devstate_change_collector_cb (const struct ast_event *event, void *data) |
| static void | devstate_event (const char *device, enum ast_device_state state) |
| static void * | do_devstate_changes (void *data) |
| Go through the dev state change queue and update changes in the dev state thread. | |
| static void | do_state_change (const char *device) |
| static int | getproviderstate (const char *provider, const char *address) |
| Get provider device state. | |
| static void | handle_devstate_change (struct devstate_change *sc) |
| static void | process_collection (const char *device, struct change_collection *collection) |
| static void * | run_devstate_collector (void *data) |
Variables | |
| static ast_cond_t | change_pending |
| Flag for the queue. | |
| static pthread_t | change_thread = AST_PTHREADT_NULL |
| The device state change notification thread. | |
| struct { | |
| ast_cond_t cond | |
| struct { | |
| struct devstate_change * first | |
| struct devstate_change * last | |
| } devstate_change_q | |
| unsigned int enabled:1 | |
| struct ast_event_sub * event_sub | |
| ast_mutex_t lock | |
| pthread_t thread | |
| } | devstate_collector |
| static const char * | devstatestring [][2] |
| Device state strings for printing. | |
Device state management.
Definition in file devicestate.c.
| #define MAX_SERVERS 64 |
Definition at line 562 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 308 of file devicestate.c.
References ast_debug, AST_DEVICE_INVALID, AST_DEVICE_UNKNOWN, ast_get_channel_tech(), ast_parse_device_state(), buf, ast_channel_tech::devicestate, devstate_cached(), and getproviderstate().
Referenced by ast_device_state(), and do_state_change().
00309 { 00310 char *buf; 00311 char *number; 00312 const struct ast_channel_tech *chan_tech; 00313 enum ast_device_state res; 00314 /*! \brief Channel driver that provides device state */ 00315 char *tech; 00316 /*! \brief Another provider of device state */ 00317 char *provider = NULL; 00318 00319 /* If the last known state is cached, just return that */ 00320 if (check_cache) { 00321 res = devstate_cached(device); 00322 if (res != AST_DEVICE_UNKNOWN) { 00323 return res; 00324 } 00325 } 00326 00327 buf = ast_strdupa(device); 00328 tech = strsep(&buf, "/"); 00329 if (!(number = buf)) { 00330 if (!(provider = strsep(&tech, ":"))) 00331 return AST_DEVICE_INVALID; 00332 /* We have a provider */ 00333 number = tech; 00334 tech = NULL; 00335 } 00336 00337 if (provider) { 00338 ast_debug(3, "Checking if I can find provider for \"%s\" - number: %s\n", provider, number); 00339 return getproviderstate(provider, number); 00340 } 00341 00342 ast_debug(4, "No provider found, checking channel drivers for %s - %s\n", tech, number); 00343 00344 if (!(chan_tech = ast_get_channel_tech(tech))) 00345 return AST_DEVICE_INVALID; 00346 00347 if (!(chan_tech->devicestate)) /* Does the channel driver support device state notification? */ 00348 return ast_parse_device_state(device); /* No, try the generic function */ 00349 00350 res = chan_tech->devicestate(number); 00351 00352 if (res != AST_DEVICE_UNKNOWN) 00353 return res; 00354 00355 res = ast_parse_device_state(device); 00356 00357 return res; 00358 }
| enum ast_device_state ast_device_state | ( | const char * | device | ) |
Asks a channel for device state.
| 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 | |
| -1 | on failure |
Definition at line 360 of file devicestate.c.
References _ast_device_state().
00361 { 00362 /* This function is called from elsewhere in the code to find out the 00363 * current state of a device. Check the cache, first. */ 00364 00365 return _ast_device_state(device, 1); 00366 }
| int ast_device_state_changed | ( | const char * | fmt, | |
| ... | ||||
| ) |
Tells Asterisk the State for Device is changed. (Accept change notification, add it to change queue.).
| 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 520 of file devicestate.c.
References AST_DEVICE_UNKNOWN, ast_devstate_changed_literal(), AST_MAX_EXTENSION, and buf.
00521 { 00522 char buf[AST_MAX_EXTENSION]; 00523 va_list ap; 00524 00525 va_start(ap, fmt); 00526 vsnprintf(buf, sizeof(buf), fmt, ap); 00527 va_end(ap); 00528 00529 return ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, buf); 00530 }
| int ast_device_state_changed_literal | ( | const char * | device | ) |
Tells Asterisk the State for Device is changed.
| 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 503 of file devicestate.c.
References AST_DEVICE_UNKNOWN, and ast_devstate_changed_literal().
00504 { 00505 return ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, dev); 00506 }
| int ast_device_state_engine_init | ( | void | ) |
Initialize the device state engine in separate thread.
Provided by devicestate.c
Definition at line 722 of file devicestate.c.
References ast_cond_init(), ast_log(), ast_pthread_create_background, change_thread, do_devstate_changes(), and LOG_ERROR.
Referenced by main().
00723 { 00724 ast_cond_init(&change_pending, NULL); 00725 if (ast_pthread_create_background(&change_thread, NULL, do_devstate_changes, NULL) < 0) { 00726 ast_log(LOG_ERROR, "Unable to start device state change thread.\n"); 00727 return -1; 00728 } 00729 00730 return 0; 00731 }
| const char* ast_devstate2str | ( | enum ast_device_state | devstate | ) |
Find devicestate as text message for output.
Definition at line 209 of file devicestate.c.
Referenced by __queues_show(), do_state_change(), handle_statechange(), notify_metermaids(), page_exec(), and process_collection().
00210 { 00211 return devstatestring[devstate][0]; 00212 }
| void ast_devstate_aggregate_add | ( | struct ast_devstate_aggregate * | agg, | |
| enum ast_device_state | state | |||
| ) |
Add a device state to the aggregate device state.
| [in] | agg | the state object |
| [in] | state | the state to add |
Definition at line 743 of file devicestate.c.
References ast_devstate_aggregate::all_busy, ast_devstate_aggregate::all_free, ast_devstate_aggregate::all_unavail, ast_devstate_aggregate::all_unknown, AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, AST_DEVICE_TOTAL, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, ast_devstate_aggregate::busy, ast_devstate_aggregate::in_use, ast_devstate_aggregate::on_hold, and ast_devstate_aggregate::ring.
Referenced by ast_extension_state2(), and process_collection().
00744 { 00745 switch (state) { 00746 case AST_DEVICE_NOT_INUSE: 00747 agg->all_unknown = 0; 00748 agg->all_unavail = 0; 00749 agg->all_busy = 0; 00750 break; 00751 case AST_DEVICE_INUSE: 00752 agg->in_use = 1; 00753 agg->all_unavail = 0; 00754 agg->all_free = 0; 00755 agg->all_unknown = 0; 00756 break; 00757 case AST_DEVICE_RINGING: 00758 agg->ring = 1; 00759 agg->all_unavail = 0; 00760 agg->all_free = 0; 00761 agg->all_unknown = 0; 00762 break; 00763 case AST_DEVICE_RINGINUSE: 00764 agg->in_use = 1; 00765 agg->ring = 1; 00766 agg->all_unavail = 0; 00767 agg->all_free = 0; 00768 agg->all_unknown = 0; 00769 break; 00770 case AST_DEVICE_ONHOLD: 00771 agg->all_unknown = 0; 00772 agg->all_unavail = 0; 00773 agg->all_free = 0; 00774 agg->on_hold = 1; 00775 break; 00776 case AST_DEVICE_BUSY: 00777 agg->all_unknown = 0; 00778 agg->all_unavail = 0; 00779 agg->all_free = 0; 00780 agg->busy = 1; 00781 agg->in_use = 1; 00782 break; 00783 case AST_DEVICE_UNAVAILABLE: 00784 agg->all_unknown = 0; 00785 case AST_DEVICE_INVALID: 00786 agg->all_busy = 0; 00787 agg->all_free = 0; 00788 break; 00789 case AST_DEVICE_UNKNOWN: 00790 agg->all_busy = 0; 00791 agg->all_free = 0; 00792 break; 00793 case AST_DEVICE_TOTAL: /* not a device state, included for completeness. */ 00794 break; 00795 } 00796 }
| void ast_devstate_aggregate_init | ( | struct ast_devstate_aggregate * | agg | ) |
Initialize aggregate device state.
| [in] | agg | the state object |
Definition at line 733 of file devicestate.c.
References ast_devstate_aggregate::all_busy, ast_devstate_aggregate::all_free, ast_devstate_aggregate::all_unavail, and ast_devstate_aggregate::all_unknown.
Referenced by ast_extension_state2(), and process_collection().
00734 { 00735 memset(agg, 0, sizeof(*agg)); 00736 00737 agg->all_unknown = 1; 00738 agg->all_unavail = 1; 00739 agg->all_busy = 1; 00740 agg->all_free = 1; 00741 }
| enum ast_device_state ast_devstate_aggregate_result | ( | struct ast_devstate_aggregate * | agg | ) |
Get the aggregate device state result.
| [in] | agg | the state object |
Definition at line 799 of file devicestate.c.
References ast_devstate_aggregate::all_busy, ast_devstate_aggregate::all_free, ast_devstate_aggregate::all_unavail, ast_devstate_aggregate::all_unknown, AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, ast_devstate_aggregate::busy, ast_devstate_aggregate::in_use, ast_devstate_aggregate::on_hold, and ast_devstate_aggregate::ring.
Referenced by ast_extension_state2(), and process_collection().
00800 { 00801 if (agg->all_free) 00802 return AST_DEVICE_NOT_INUSE; 00803 if ((agg->in_use || agg->on_hold) && agg->ring) 00804 return AST_DEVICE_RINGINUSE; 00805 if (agg->ring) 00806 return AST_DEVICE_RINGING; 00807 if (agg->busy) 00808 return AST_DEVICE_BUSY; 00809 if (agg->in_use) 00810 return AST_DEVICE_INUSE; 00811 if (agg->on_hold) 00812 return AST_DEVICE_ONHOLD; 00813 if (agg->all_busy) 00814 return AST_DEVICE_BUSY; 00815 if (agg->all_unknown) 00816 return AST_DEVICE_UNKNOWN; 00817 if (agg->all_unavail) 00818 return AST_DEVICE_UNAVAILABLE; 00819 00820 return AST_DEVICE_NOT_INUSE; 00821 }
| int ast_devstate_changed | ( | enum ast_device_state | state, | |
| const char * | fmt, | |||
| ... | ||||
| ) |
Tells Asterisk the State for Device is changed.
| state | the new state of the device | |
| fmt | device name like a dial string with format parameters |
The new state of the device will be sent off to any subscribers of device states. It will also be stored in the internal event cache.
| 0 | on success | |
| -1 | on failure |
Definition at line 508 of file devicestate.c.
References ast_devstate_changed_literal(), AST_MAX_EXTENSION, and buf.
Referenced by __expire_registry(), __iax2_poke_noanswer(), agent_call(), agent_hangup(), agent_logoff_maintenance(), agent_read(), conf_run(), devstate_write(), expire_register(), handle_cli_devstate_change(), handle_offhook_message(), handle_onhook_message(), handle_response_peerpoke(), handle_soft_key_event_message(), handle_stimulus_message(), load_module(), login_exec(), notify_metermaids(), reg_source_db(), register_verify(), reload_agents(), sip_peer_hold(), sip_poke_noanswer(), skinny_register(), skinny_unregister(), sla_change_trunk_state(), sla_handle_hold_event(), sla_station_exec(), socket_process(), update_call_counter(), and update_registry().
00509 { 00510 char buf[AST_MAX_EXTENSION]; 00511 va_list ap; 00512 00513 va_start(ap, fmt); 00514 vsnprintf(buf, sizeof(buf), fmt, ap); 00515 va_end(ap); 00516 00517 return ast_devstate_changed_literal(state, buf); 00518 }
| int ast_devstate_changed_literal | ( | enum ast_device_state | state, | |
| const char * | device | |||
| ) |
Tells Asterisk the State for Device is changed.
| state | the new state of the device | |
| device | device name like a dial string with format parameters |
The new state of the device will be sent off to any subscribers of device states. It will also be stored in the internal event cache.
| 0 | on success | |
| -1 | on failure |
Definition at line 465 of file devicestate.c.
References ast_calloc, ast_cond_signal(), AST_DEVICE_UNKNOWN, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, change_thread, state_change::device, devstate_event(), and do_state_change().
Referenced by ast_channel_free(), ast_device_state_changed(), ast_device_state_changed_literal(), ast_devstate_changed(), ast_setstate(), and dahdi_new().
00466 { 00467 struct state_change *change; 00468 00469 /* 00470 * If we know the state change (how nice of the caller of this function!) 00471 * then we can just generate a device state event. 00472 * 00473 * Otherwise, we do the following: 00474 * - Queue an event up to another thread that the state has changed 00475 * - In the processing thread, it calls the callback provided by the 00476 * device state provider (which may or may not be a channel driver) 00477 * to determine the state. 00478 * - If the device state provider does not know the state, or this is 00479 * for a channel and the channel driver does not implement a device 00480 * state callback, then we will look through the channel list to 00481 * see if we can determine a state based on active calls. 00482 * - Once a state has been determined, a device state event is generated. 00483 */ 00484 00485 if (state != AST_DEVICE_UNKNOWN) { 00486 devstate_event(device, state); 00487 } else if (change_thread == AST_PTHREADT_NULL || !(change = ast_calloc(1, sizeof(*change) + strlen(device)))) { 00488 /* we could not allocate a change struct, or */ 00489 /* there is no background thread, so process the change now */ 00490 do_state_change(device); 00491 } else { 00492 /* queue the change */ 00493 strcpy(change->device, device); 00494 AST_LIST_LOCK(&state_changes); 00495 AST_LIST_INSERT_TAIL(&state_changes, change, list); 00496 ast_cond_signal(&change_pending); 00497 AST_LIST_UNLOCK(&state_changes); 00498 } 00499 00500 return 1; 00501 }
| int ast_devstate_prov_add | ( | const char * | label, | |
| ast_devstate_prov_cb_type | callback | |||
| ) |
Add device state provider.
| label | to use in hint, like label:object | |
| callback | Callback |
| 0 | success | |
| -1 | failure |
Definition at line 369 of file devicestate.c.
References ast_calloc, ast_copy_string(), AST_RWLIST_INSERT_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, devstate_prov::callback, and devstate_prov::label.
Referenced by ast_features_init(), and load_module().
00370 { 00371 struct devstate_prov *devprov; 00372 00373 if (!callback || !(devprov = ast_calloc(1, sizeof(*devprov)))) 00374 return -1; 00375 00376 devprov->callback = callback; 00377 ast_copy_string(devprov->label, label, sizeof(devprov->label)); 00378 00379 AST_RWLIST_WRLOCK(&devstate_provs); 00380 AST_RWLIST_INSERT_HEAD(&devstate_provs, devprov, list); 00381 AST_RWLIST_UNLOCK(&devstate_provs); 00382 00383 return 0; 00384 }
| int ast_devstate_prov_del | ( | const char * | label | ) |
Remove device state provider.
| label | to use in hint, like label:object |
| -1 | on failure | |
| 0 | on success |
Definition at line 387 of file devicestate.c.
References ast_free, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and devstate_prov::label.
Referenced by unload_module().
00388 { 00389 struct devstate_prov *devcb; 00390 int res = -1; 00391 00392 AST_RWLIST_WRLOCK(&devstate_provs); 00393 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&devstate_provs, devcb, list) { 00394 if (!strcasecmp(devcb->label, label)) { 00395 AST_RWLIST_REMOVE_CURRENT(list); 00396 ast_free(devcb); 00397 res = 0; 00398 break; 00399 } 00400 } 00401 AST_RWLIST_TRAVERSE_SAFE_END; 00402 AST_RWLIST_UNLOCK(&devstate_provs); 00403 00404 return res; 00405 }
| const char* ast_devstate_str | ( | enum ast_device_state | devstate | ) |
Convert device state to text string that is easier to parse.
| 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 823 of file devicestate.c.
References ast_cond_init(), AST_EVENT_DEVICE_STATE_CHANGE, AST_EVENT_IE_END, ast_event_subscribe(), ast_log(), ast_mutex_init(), ast_pthread_create_background, devstate_change_collector_cb(), devstate_collector, LOG_ERROR, and run_devstate_collector().
Referenced by add_publish_event(), and add_subscribe_event().
00824 { 00825 if (devstate_collector.enabled) { 00826 return 0; 00827 } 00828 00829 devstate_collector.event_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE_CHANGE, 00830 devstate_change_collector_cb, NULL, AST_EVENT_IE_END); 00831 00832 if (!devstate_collector.event_sub) { 00833 ast_log(LOG_ERROR, "Failed to create subscription for the device state change collector\n"); 00834 return -1; 00835 } 00836 00837 ast_mutex_init(&devstate_collector.lock); 00838 ast_cond_init(&devstate_collector.cond, NULL); 00839 if (ast_pthread_create_background(&devstate_collector.thread, NULL, run_devstate_collector, NULL) < 0) { 00840 ast_log(LOG_ERROR, "Unable to start device state collector thread.\n"); 00841 return -1; 00842 } 00843 00844 devstate_collector.enabled = 1; 00845 00846 return 0; 00847 }
| enum ast_device_state ast_parse_device_state | ( | const char * | device | ) |
Find out if device is active in a call or not.
Search the Channels by Name.
Definition at line 265 of file devicestate.c.
References ast_channel::_state, AST_CHANNEL_NAME, ast_channel_unlock, ast_copy_string(), AST_DEVICE_INUSE, AST_DEVICE_RINGING, AST_DEVICE_UNKNOWN, ast_get_channel_by_name_prefix_locked(), AST_STATE_RINGING, chan, and match().
Referenced by _ast_device_state(), and chanavail_exec().
00266 { 00267 struct ast_channel *chan; 00268 char match[AST_CHANNEL_NAME]; 00269 enum ast_device_state res; 00270 00271 ast_copy_string(match, device, sizeof(match)-1); 00272 strcat(match, "-"); 00273 chan = ast_get_channel_by_name_prefix_locked(match, strlen(match)); 00274 00275 if (!chan) 00276 return AST_DEVICE_UNKNOWN; 00277 00278 if (chan->_state == AST_STATE_RINGING) 00279 res = AST_DEVICE_RINGING; 00280 else 00281 res = AST_DEVICE_INUSE; 00282 00283 ast_channel_unlock(chan); 00284 00285 return res; 00286 }
| enum ast_device_state ast_state_chan2dev | ( | enum ast_channel_state | chanstate | ) |
Convert channel state to devicestate.
| 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 557 of file devicestate.c.
References ast_free.
Referenced by run_devstate_collector().
00558 { 00559 ast_free(sc); 00560 }
| const char* devstate2str | ( | enum ast_device_state | devstate | ) |
Convert device state to text string for output.
| devstate | Current device state |
Definition at line 215 of file devicestate.c.
00216 { 00217 return devstatestring[devstate][0]; 00218 }
| static void devstate_cache_cb | ( | const struct ast_event * | event, | |
| void * | data | |||
| ) | [static] |
Definition at line 568 of file devicestate.c.
References ARRAY_LEN, ast_event_get_ie_raw(), ast_event_get_ie_uint(), AST_EVENT_IE_EID, AST_EVENT_IE_STATE, ast_log(), devstate_change::eid, LOG_ERROR, MAX_SERVERS, change_collection::num_states, devstate_change::state, and change_collection::states.
Referenced by handle_devstate_change().
00569 { 00570 struct change_collection *collection = data; 00571 int i; 00572 const struct ast_eid *eid; 00573 00574 if (collection->num_states == ARRAY_LEN(collection->states)) { 00575 ast_log(LOG_ERROR, "More per-server state values than we have room for (MAX_SERVERS is %d)\n", 00576 MAX_SERVERS); 00577 return; 00578 } 00579 00580 if (!(eid = ast_event_get_ie_raw(event, AST_EVENT_IE_EID))) { 00581 ast_log(LOG_ERROR, "Device state change event with no EID\n"); 00582 return; 00583 } 00584 00585 i = collection->num_states; 00586 00587 collection->states[i].state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE); 00588 collection->states[i].eid = *eid; 00589 00590 collection->num_states++; 00591 }
| static enum ast_device_state devstate_cached | ( | const char * | device | ) | [static] |
Definition at line 288 of file devicestate.c.
References AST_DEVICE_UNKNOWN, ast_event_destroy(), AST_EVENT_DEVICE_STATE, ast_event_get_cached(), ast_event_get_ie_uint(), AST_EVENT_IE_DEVICE, AST_EVENT_IE_END, AST_EVENT_IE_PLTYPE_STR, and AST_EVENT_IE_STATE.
Referenced by _ast_device_state().
00289 { 00290 enum ast_device_state res = AST_DEVICE_UNKNOWN; 00291 struct ast_event *event; 00292 00293 event = ast_event_get_cached(AST_EVENT_DEVICE_STATE, 00294 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device, 00295 AST_EVENT_IE_END); 00296 00297 if (!event) 00298 return res; 00299 00300 res = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE); 00301 00302 ast_event_destroy(event); 00303 00304 return res; 00305 }
| static void devstate_change_collector_cb | ( | const struct ast_event * | event, | |
| void * | data | |||
| ) | [static] |
Definition at line 692 of file devicestate.c.
References ast_calloc, ast_cond_signal(), ast_event_get_ie_raw(), ast_event_get_ie_str(), ast_event_get_ie_uint(), AST_EVENT_IE_DEVICE, AST_EVENT_IE_EID, AST_EVENT_IE_STATE, AST_LIST_INSERT_TAIL, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), devstate_change::device, devstate_collector, devstate_change::eid, LOG_ERROR, and devstate_change::state.
Referenced by ast_enable_distributed_devstate().
00693 { 00694 struct devstate_change *sc; 00695 const char *device; 00696 const struct ast_eid *eid; 00697 uint32_t state; 00698 00699 device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE); 00700 eid = ast_event_get_ie_raw(event, AST_EVENT_IE_EID); 00701 state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE); 00702 00703 if (ast_strlen_zero(device) || !eid) { 00704 ast_log(LOG_ERROR, "Invalid device state change event received\n"); 00705 return; 00706 } 00707 00708 if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device)))) 00709 return; 00710 00711 strcpy(sc->device, device); 00712 sc->eid = *eid; 00713 sc->state = state; 00714 00715 ast_mutex_lock(&devstate_collector.lock); 00716 AST_LIST_INSERT_TAIL(&devstate_collector.devstate_change_q, sc, entry); 00717 ast_cond_signal(&devstate_collector.cond); 00718 ast_mutex_unlock(&devstate_collector.lock); 00719 }
| static void devstate_event | ( | const char * | device, | |
| enum ast_device_state | state | |||
| ) | [static] |
Definition at line 427 of file devicestate.c.
References ast_debug, AST_EVENT_DEVICE_STATE, AST_EVENT_DEVICE_STATE_CHANGE, AST_EVENT_IE_DEVICE, AST_EVENT_IE_END, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_IE_STATE, ast_event_new(), ast_event_queue_and_cache(), and devstate_collector.
Referenced by ast_devstate_changed_literal(), and do_state_change().
00428 { 00429 struct ast_event *event; 00430 enum ast_event_type event_type; 00431 00432 if (devstate_collector.enabled) { 00433 /* Distributed device state is enabled, so this state change is a change 00434 * for a single server, not the real state. */ 00435 event_type = AST_EVENT_DEVICE_STATE_CHANGE; 00436 } else { 00437 event_type = AST_EVENT_DEVICE_STATE; 00438 } 00439 00440 ast_debug(3, "device '%s' state '%d'\n", device, state); 00441 00442 if (!(event = ast_event_new(event_type, 00443 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device, 00444 AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_UINT, state, 00445 AST_EVENT_IE_END))) { 00446 return; 00447 } 00448 00449 ast_event_queue_and_cache(event); 00450 }
| static void* do_devstate_changes | ( | void * | data | ) | [static] |
Go through the dev state change queue and update changes in the dev state thread.
Definition at line 533 of file devicestate.c.
References ast_cond_wait(), ast_free, AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_LOCK, AST_LIST_NEXT, AST_LIST_UNLOCK, state_change::device, do_state_change(), and devstate_prov::next.
Referenced by ast_device_state_engine_init().
00534 { 00535 struct state_change *next, *current; 00536 00537 for (;;) { 00538 /* This basically pops off any state change entries, resets the list back to NULL, unlocks, and processes each state change */ 00539 AST_LIST_LOCK(&state_changes); 00540 if (AST_LIST_EMPTY(&state_changes)) 00541 ast_cond_wait(&change_pending, &state_changes.lock); 00542 next = AST_LIST_FIRST(&state_changes); 00543 AST_LIST_HEAD_INIT_NOLOCK(&state_changes); 00544 AST_LIST_UNLOCK(&state_changes); 00545 00546 /* Process each state change */ 00547 while ((current = next)) { 00548 next = AST_LIST_NEXT(current, list); 00549 do_state_change(current->device); 00550 ast_free(current); 00551 } 00552 } 00553 00554 return NULL; 00555 }
| static void do_state_change | ( | const char * | device | ) | [static] |
Called by the state change thread to find out what the state is, and then to queue up the state change event
Definition at line 454 of file devicestate.c.
References _ast_device_state(), ast_debug, ast_devstate2str(), and devstate_event().
Referenced by ast_devstate_changed_literal(), and do_devstate_changes().
00455 { 00456 enum ast_device_state state; 00457 00458 state = _ast_device_state(device, 0); 00459 00460 ast_debug(3, "Changing state for %s - state %d (%s)\n", device, state, ast_devstate2str(state)); 00461 00462 devstate_event(device, state); 00463 }
| static int getproviderstate | ( | const char * | provider, | |
| const char * | address | |||
| ) | [static] |
Get provider device state.
Definition at line 408 of file devicestate.c.
References ast_debug, AST_DEVICE_INVALID, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, devstate_prov::callback, and devstate_prov::label.
Referenced by _ast_device_state().
00409 { 00410 struct devstate_prov *devprov; 00411 int res = AST_DEVICE_INVALID; 00412 00413 AST_RWLIST_RDLOCK(&devstate_provs); 00414 AST_RWLIST_TRAVERSE(&devstate_provs, devprov, list) { 00415 ast_debug(5, "Checking provider %s with %s\n", devprov->label, provider); 00416 00417 if (!strcasecmp(devprov->label, provider)) { 00418 res = devprov->callback(address); 00419 break; 00420 } 00421 } 00422 AST_RWLIST_UNLOCK(&devstate_provs); 00423 00424 return res; 00425 }
| static void handle_devstate_change | ( | struct devstate_change * | sc | ) | [static] |
Definition at line 646 of file devicestate.c.
References ast_debug, AST_EVENT_DEVICE_STATE_CHANGE, ast_event_dump_cache(), AST_EVENT_IE_DEVICE, ast_event_sub_append_ie_str(), ast_event_sub_destroy(), ast_event_subscribe_new(), ast_log(), devstate_change::device, devstate_cache_cb(), LOG_ERROR, change_collection::num_states, and process_collection().
Referenced by run_devstate_collector().
00647 { 00648 struct ast_event_sub *tmp_sub; 00649 struct change_collection collection = { 00650 .num_states = 0, 00651 }; 00652 00653 ast_debug(1, "Processing device state change for '%s'\n", sc->device); 00654 00655 if (!(tmp_sub = ast_event_subscribe_new(AST_EVENT_DEVICE_STATE_CHANGE, devstate_cache_cb, &collection))) { 00656 ast_log(LOG_ERROR, "Failed to create subscription\n"); 00657 return; 00658 } 00659 00660 if (ast_event_sub_append_ie_str(tmp_sub, AST_EVENT_IE_DEVICE, sc->device)) { 00661 ast_log(LOG_ERROR, "Failed to append device IE\n"); 00662 ast_event_sub_destroy(tmp_sub); 00663 return; 00664 } 00665 00666 /* Populate the collection of device states from the cache */ 00667 ast_event_dump_cache(tmp_sub); 00668 00669 process_collection(sc->device, &collection); 00670 00671 ast_event_sub_destroy(tmp_sub); 00672 }
| static void process_collection | ( | const char * | device, | |
| struct change_collection * | collection | |||
| ) | [static] |
Definition at line 593 of file devicestate.c.
References ast_debug, ast_devstate2str(), ast_devstate_aggregate_add(), ast_devstate_aggregate_init(), ast_devstate_aggregate_result(), ast_event_destroy(), AST_EVENT_DEVICE_STATE, ast_event_get_cached(), ast_event_get_ie_uint(), AST_EVENT_IE_DEVICE, AST_EVENT_IE_END, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_IE_STATE, ast_event_new(), ast_event_queue_and_cache(), change_collection::num_states, devstate_change::state, and change_collection::states.
Referenced by handle_devstate_change().
00594 { 00595 int i; 00596 struct ast_devstate_aggregate agg; 00597 enum ast_device_state state; 00598 struct ast_event *event; 00599 00600 ast_devstate_aggregate_init(&agg); 00601 00602 for (i = 0; i < collection->num_states; i++) { 00603 ast_debug(1, "Adding per-server state of '%s' for '%s'\n", 00604 ast_devstate2str(collection->states[i].state), device); 00605 ast_devstate_aggregate_add(&agg, collection->states[i].state); 00606 } 00607 00608 state = ast_devstate_aggregate_result(&agg); 00609 00610 ast_debug(1, "Aggregate devstate result is %d\n", state); 00611 00612 event = ast_event_get_cached(AST_EVENT_DEVICE_STATE, 00613 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device, 00614 AST_EVENT_IE_END); 00615 00616 if (event) { 00617 enum ast_device_state old_state; 00618 00619 old_state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE); 00620 00621 ast_event_destroy(event); 00622 00623 if (state == old_state) { 00624 /* No change since last reported device state */ 00625 ast_debug(1, "Aggregate state for device '%s' has not changed from '%s'\n", 00626 device, ast_devstate2str(state)); 00627 return; 00628 } 00629 } 00630 00631 ast_debug(1, "Aggregate state for device '%s' has changed to '%s'\n", 00632 device, ast_devstate2str(state)); 00633 00634 event = ast_event_new(AST_EVENT_DEVICE_STATE, 00635 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device, 00636 AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_UINT, state, 00637 AST_EVENT_IE_END); 00638 00639 if (!event) { 00640 return; 00641 } 00642 00643 ast_event_queue_and_cache(event); 00644 }
| static void* run_devstate_collector | ( | void * | data | ) | [static] |
Definition at line 674 of file devicestate.c.
References ast_cond_wait(), AST_LIST_REMOVE_HEAD, ast_mutex_lock(), ast_mutex_unlock(), destroy_devstate_change(), devstate_collector, and handle_devstate_change().
Referenced by ast_enable_distributed_devstate().
00675 { 00676 for (;;) { 00677 struct devstate_change *sc; 00678 00679 ast_mutex_lock(&devstate_collector.lock); 00680 while (!(sc = AST_LIST_REMOVE_HEAD(&devstate_collector.devstate_change_q, entry))) 00681 ast_cond_wait(&devstate_collector.cond, &devstate_collector.lock); 00682 ast_mutex_unlock(&devstate_collector.lock); 00683 00684 handle_devstate_change(sc); 00685 00686 destroy_devstate_change(sc); 00687 } 00688 00689 return NULL; 00690 }
ast_cond_t change_pending [static] |
Flag for the queue.
Definition at line 184 of file devicestate.c.
pthread_t change_thread = AST_PTHREADT_NULL [static] |
The device state change notification thread.
Definition at line 181 of file devicestate.c.
Referenced by ast_device_state_engine_init(), and ast_devstate_changed_literal().
Definition at line 196 of file devicestate.c.
| struct { ... } devstate_change_q |
| struct { ... } devstate_collector |
const char* devstatestring[][2] [static] |
Device state strings for printing.
Definition at line 131 of file devicestate.c.
| unsigned int enabled |
Definition at line 199 of file devicestate.c.
Referenced by __ast_http_load(), load_odbc_config(), and osp_check_destination().
| struct ast_event_sub* event_sub |
Definition at line 195 of file devicestate.c.
Referenced by 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.
1.6.2