#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 | 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... | |
Enumerations | |
enum | devstate_cache { CACHE_ON, CACHE_OFF } |
Whether or not to cache this device state value. More... | |
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. | |
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. | |
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. | |
enum ast_device_state | ast_parse_device_state (const char *device) |
Search the Channels by Name. | |
const char * | devstate2str (enum ast_device_state devstate) |
Convert device state to text string for output. | |
static enum ast_device_state | devstate_cached (const char *device) |
static void | devstate_event (const char *device, enum ast_device_state state, enum devstate_cache cache) |
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. | |
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. | |
static const char * | devstatestring [] |
Device state strings for printing. |
Definition in file devicestate.c.
enum devstate_cache |
Whether or not to cache this device state value.
Definition at line 164 of file devicestate.c.
00164 { 00165 /*! Cache this value as it is coming from a device state provider which is 00166 * pushing up state change events to us as they happen */ 00167 CACHE_ON, 00168 /*! Don't cache this result, since it was pulled from the device state provider. 00169 * We only want to cache results from device state providers that are being nice 00170 * and pushing state change events up to us as they happen. */ 00171 CACHE_OFF, 00172 };
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 289 of file devicestate.c.
References ast_debug, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, ast_device_state(), 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().
00290 { 00291 char *buf; 00292 char *number; 00293 const struct ast_channel_tech *chan_tech; 00294 enum ast_device_state res; 00295 /*! \brief Channel driver that provides device state */ 00296 char *tech; 00297 /*! \brief Another provider of device state */ 00298 char *provider = NULL; 00299 00300 /* If the last known state is cached, just return that */ 00301 if (check_cache) { 00302 res = devstate_cached(device); 00303 if (res != AST_DEVICE_UNKNOWN) { 00304 return res; 00305 } 00306 } 00307 00308 buf = ast_strdupa(device); 00309 tech = strsep(&buf, "/"); 00310 if (!(number = buf)) { 00311 if (!(provider = strsep(&tech, ":"))) 00312 return AST_DEVICE_INVALID; 00313 /* We have a provider */ 00314 number = tech; 00315 tech = NULL; 00316 } 00317 00318 if (provider) { 00319 ast_debug(3, "Checking if I can find provider for \"%s\" - number: %s\n", provider, number); 00320 return getproviderstate(provider, number); 00321 } 00322 00323 ast_debug(4, "No provider found, checking channel drivers for %s - %s\n", tech, number); 00324 00325 if (!(chan_tech = ast_get_channel_tech(tech))) 00326 return AST_DEVICE_INVALID; 00327 00328 if (!(chan_tech->devicestate)) /* Does the channel driver support device state notification? */ 00329 return ast_parse_device_state(device); /* No, try the generic function */ 00330 00331 res = chan_tech->devicestate(number); 00332 00333 if (res != AST_DEVICE_UNKNOWN) 00334 return res; 00335 00336 res = ast_parse_device_state(device); 00337 00338 if (res == AST_DEVICE_UNKNOWN) 00339 return AST_DEVICE_NOT_INUSE; 00340 00341 return res; 00342 }
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 344 of file devicestate.c.
References _ast_device_state().
Referenced by _ast_device_state(), ast_extension_state2(), ast_parse_device_state(), chanavail_exec(), create_queue_member(), device_state_cb(), devstate_cached(), devstate_read(), devstate_write(), do_state_change(), handle_cli_devstate_change(), page_exec(), ring_entry(), skinny_extensionstate_cb(), sla_state(), and transmit_state_notify().
00345 { 00346 /* This function is called from elsewhere in the code to find out the 00347 * current state of a device. Check the cache, first. */ 00348 00349 return _ast_device_state(device, 1); 00350 }
int ast_device_state_changed | ( | const char * | fmt, | |
... | ||||
) |
Tells Asterisk the State for Device is changed.
fmt | device name like a dial string with format parameters |
0 | on success | |
-1 | on failure |
Definition at line 488 of file devicestate.c.
References AST_DEVICE_UNKNOWN, 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(), expire_register(), handle_offhook_message(), handle_onhook_message(), handle_response_peerpoke(), handle_soft_key_event_message(), handle_stimulus_message(), login_exec(), reg_source_db(), register_verify(), reload_agents(), sip_peer_hold(), sip_poke_noanswer(), skinny_unregister(), socket_process(), update_call_counter(), and update_registry().
00489 { 00490 char buf[AST_MAX_EXTENSION]; 00491 va_list ap; 00492 00493 va_start(ap, fmt); 00494 vsnprintf(buf, sizeof(buf), fmt, ap); 00495 va_end(ap); 00496 00497 return ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, buf); 00498 }
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 470 of file devicestate.c.
References AST_DEVICE_UNKNOWN, and ast_devstate_changed_literal().
Referenced by ast_channel_free(), ast_setstate(), and dahdi_new().
00471 { 00472 return ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, dev); 00473 }
int ast_device_state_engine_init | ( | void | ) |
Initialize the device state engine in separate thread.
Provided by devicestate.c
Definition at line 526 of file devicestate.c.
References ast_cond_init(), ast_log(), ast_pthread_create_background, change_pending, change_thread, do_devstate_changes(), and LOG_ERROR.
Referenced by main().
00527 { 00528 ast_cond_init(&change_pending, NULL); 00529 if (ast_pthread_create_background(&change_thread, NULL, do_devstate_changes, NULL) < 0) { 00530 ast_log(LOG_ERROR, "Unable to start device state change thread.\n"); 00531 return -1; 00532 } 00533 00534 return 0; 00535 }
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 475 of file devicestate.c.
References ast_devstate_changed_literal(), AST_MAX_EXTENSION, and buf.
Referenced by conf_run(), devstate_write(), handle_cli_devstate_change(), load_module(), notify_metermaids(), sla_change_trunk_state(), sla_handle_hold_event(), and sla_station_exec().
00476 { 00477 char buf[AST_MAX_EXTENSION]; 00478 va_list ap; 00479 00480 va_start(ap, fmt); 00481 vsnprintf(buf, sizeof(buf), fmt, ap); 00482 va_end(ap); 00483 00484 return ast_devstate_changed_literal(state, buf); 00485 }
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 446 of file devicestate.c.
References ast_calloc, ast_cond_signal(), ast_debug, AST_DEVICE_UNKNOWN, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, AST_PTHREADT_NULL, CACHE_ON, change_pending, change_thread, devstate_event(), do_state_change(), and devstate_prov::list.
Referenced by ast_device_state_changed(), ast_device_state_changed_literal(), and ast_devstate_changed().
00447 { 00448 struct state_change *change; 00449 00450 ast_debug(3, "Notification of state change to be queued on device/channel %s\n", device); 00451 00452 if (state != AST_DEVICE_UNKNOWN) { 00453 devstate_event(device, state, CACHE_ON); 00454 } else if (change_thread == AST_PTHREADT_NULL || !(change = ast_calloc(1, sizeof(*change) + strlen(device)))) { 00455 /* we could not allocate a change struct, or */ 00456 /* there is no background thread, so process the change now */ 00457 do_state_change(device); 00458 } else { 00459 /* queue the change */ 00460 strcpy(change->device, device); 00461 AST_LIST_LOCK(&state_changes); 00462 AST_LIST_INSERT_TAIL(&state_changes, change, list); 00463 ast_cond_signal(&change_pending); 00464 AST_LIST_UNLOCK(&state_changes); 00465 } 00466 00467 return 1; 00468 }
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 353 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().
00354 { 00355 struct devstate_prov *devprov; 00356 00357 if (!callback || !(devprov = ast_calloc(1, sizeof(*devprov)))) 00358 return -1; 00359 00360 devprov->callback = callback; 00361 ast_copy_string(devprov->label, label, sizeof(devprov->label)); 00362 00363 AST_RWLIST_WRLOCK(&devstate_provs); 00364 AST_RWLIST_INSERT_HEAD(&devstate_provs, devprov, list); 00365 AST_RWLIST_UNLOCK(&devstate_provs); 00366 00367 return 0; 00368 }
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 371 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().
00372 { 00373 struct devstate_prov *devcb; 00374 int res = -1; 00375 00376 AST_RWLIST_WRLOCK(&devstate_provs); 00377 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&devstate_provs, devcb, list) { 00378 if (!strcasecmp(devcb->label, label)) { 00379 AST_RWLIST_REMOVE_CURRENT(list); 00380 ast_free(devcb); 00381 res = 0; 00382 break; 00383 } 00384 } 00385 AST_RWLIST_TRAVERSE_SAFE_END; 00386 AST_RWLIST_UNLOCK(&devstate_provs); 00387 00388 return res; 00389 }
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 183 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 devstate_read().
00184 { 00185 const char *res = "UNKNOWN"; 00186 00187 switch (state) { 00188 case AST_DEVICE_UNKNOWN: 00189 break; 00190 case AST_DEVICE_NOT_INUSE: 00191 res = "NOT_INUSE"; 00192 break; 00193 case AST_DEVICE_INUSE: 00194 res = "INUSE"; 00195 break; 00196 case AST_DEVICE_BUSY: 00197 res = "BUSY"; 00198 break; 00199 case AST_DEVICE_INVALID: 00200 res = "INVALID"; 00201 break; 00202 case AST_DEVICE_UNAVAILABLE: 00203 res = "UNAVAILABLE"; 00204 break; 00205 case AST_DEVICE_RINGING: 00206 res = "RINGING"; 00207 break; 00208 case AST_DEVICE_RINGINUSE: 00209 res = "RINGINUSE"; 00210 break; 00211 case AST_DEVICE_ONHOLD: 00212 res = "ONHOLD"; 00213 break; 00214 } 00215 00216 return res; 00217 }
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 219 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().
00220 { 00221 if (!strcasecmp(val, "NOT_INUSE")) 00222 return AST_DEVICE_NOT_INUSE; 00223 else if (!strcasecmp(val, "INUSE")) 00224 return AST_DEVICE_INUSE; 00225 else if (!strcasecmp(val, "BUSY")) 00226 return AST_DEVICE_BUSY; 00227 else if (!strcasecmp(val, "INVALID")) 00228 return AST_DEVICE_INVALID; 00229 else if (!strcasecmp(val, "UNAVAILABLE")) 00230 return AST_DEVICE_UNAVAILABLE; 00231 else if (!strcasecmp(val, "RINGING")) 00232 return AST_DEVICE_RINGING; 00233 else if (!strcasecmp(val, "RINGINUSE")) 00234 return AST_DEVICE_RINGINUSE; 00235 else if (!strcasecmp(val, "ONHOLD")) 00236 return AST_DEVICE_ONHOLD; 00237 00238 return AST_DEVICE_UNKNOWN; 00239 }
enum ast_device_state ast_parse_device_state | ( | const char * | device | ) |
Search the Channels by Name.
Definition at line 246 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_state(), AST_DEVICE_UNKNOWN, ast_get_channel_by_name_prefix_locked(), AST_STATE_RINGING, chan, and match().
Referenced by _ast_device_state(), and chanavail_exec().
00247 { 00248 struct ast_channel *chan; 00249 char match[AST_CHANNEL_NAME]; 00250 enum ast_device_state res; 00251 00252 ast_copy_string(match, device, sizeof(match)-1); 00253 strcat(match, "-"); 00254 chan = ast_get_channel_by_name_prefix_locked(match, strlen(match)); 00255 00256 if (!chan) 00257 return AST_DEVICE_UNKNOWN; 00258 00259 if (chan->_state == AST_STATE_RINGING) 00260 res = AST_DEVICE_RINGING; 00261 else 00262 res = AST_DEVICE_INUSE; 00263 00264 ast_channel_unlock(chan); 00265 00266 return res; 00267 }
const char* devstate2str | ( | enum ast_device_state | devstate | ) |
Convert device state to text string for output.
devstate | Current device state |
Definition at line 178 of file devicestate.c.
Referenced by __queues_show(), do_state_change(), handle_statechange(), notify_metermaids(), and page_exec().
00179 { 00180 return devstatestring[devstate]; 00181 }
static enum ast_device_state devstate_cached | ( | const char * | device | ) | [static] |
Definition at line 269 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().
00270 { 00271 enum ast_device_state res = AST_DEVICE_UNKNOWN; 00272 struct ast_event *event; 00273 00274 event = ast_event_get_cached(AST_EVENT_DEVICE_STATE, 00275 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device, 00276 AST_EVENT_IE_END); 00277 00278 if (!event) 00279 return res; 00280 00281 res = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE); 00282 00283 ast_event_destroy(event); 00284 00285 return res; 00286 }
static void devstate_event | ( | const char * | device, | |
enum ast_device_state | state, | |||
enum devstate_cache | cache | |||
) | [static] |
Definition at line 411 of file devicestate.c.
References AST_EVENT_DEVICE_STATE, AST_EVENT_IE_DEVICE, AST_EVENT_IE_END, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_IE_STATE, ast_event_new(), ast_event_queue(), ast_event_queue_and_cache(), and CACHE_ON.
Referenced by ast_devstate_changed_literal(), and do_state_change().
00412 { 00413 struct ast_event *event; 00414 00415 if (!(event = ast_event_new(AST_EVENT_DEVICE_STATE, 00416 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device, 00417 AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_UINT, state, 00418 AST_EVENT_IE_END))) { 00419 return; 00420 } 00421 00422 if (cache == CACHE_ON) { 00423 /* Cache this event, replacing an event in the cache with the same 00424 * device name if it exists. */ 00425 ast_event_queue_and_cache(event, 00426 AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, 00427 AST_EVENT_IE_END); 00428 } else { 00429 ast_event_queue(event); 00430 } 00431 }
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 501 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, change_pending, state_change::device, do_state_change(), devstate_prov::list, state_changes::lock, and devstate_prov::next.
Referenced by ast_device_state_engine_init().
00502 { 00503 struct state_change *next, *current; 00504 00505 for (;;) { 00506 /* This basically pops off any state change entries, resets the list back to NULL, unlocks, and processes each state change */ 00507 AST_LIST_LOCK(&state_changes); 00508 if (AST_LIST_EMPTY(&state_changes)) 00509 ast_cond_wait(&change_pending, &state_changes.lock); 00510 next = AST_LIST_FIRST(&state_changes); 00511 AST_LIST_HEAD_INIT_NOLOCK(&state_changes); 00512 AST_LIST_UNLOCK(&state_changes); 00513 00514 /* Process each state change */ 00515 while ((current = next)) { 00516 next = AST_LIST_NEXT(current, list); 00517 do_state_change(current->device); 00518 ast_free(current); 00519 } 00520 } 00521 00522 return NULL; 00523 }
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 435 of file devicestate.c.
References _ast_device_state(), ast_debug, ast_device_state(), CACHE_OFF, devstate2str(), and devstate_event().
Referenced by ast_devstate_changed_literal(), and do_devstate_changes().
00436 { 00437 enum ast_device_state state; 00438 00439 state = _ast_device_state(device, 0); 00440 00441 ast_debug(3, "Changing state for %s - state %d (%s)\n", device, state, devstate2str(state)); 00442 00443 devstate_event(device, state, CACHE_OFF); 00444 }
static int getproviderstate | ( | const char * | provider, | |
const char * | address | |||
) | [static] |
Get provider device state.
Definition at line 392 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().
00393 { 00394 struct devstate_prov *devprov; 00395 int res = AST_DEVICE_INVALID; 00396 00397 00398 AST_RWLIST_RDLOCK(&devstate_provs); 00399 AST_RWLIST_TRAVERSE(&devstate_provs, devprov, list) { 00400 ast_debug(5, "Checking provider %s with %s\n", devprov->label, provider); 00401 00402 if (!strcasecmp(devprov->label, provider)) { 00403 res = devprov->callback(address); 00404 break; 00405 } 00406 } 00407 AST_RWLIST_UNLOCK(&devstate_provs); 00408 return res; 00409 }
ast_cond_t change_pending [static] |
Flag for the queue.
Definition at line 161 of file devicestate.c.
Referenced by ast_device_state_engine_init(), ast_devstate_changed_literal(), and do_devstate_changes().
pthread_t change_thread = AST_PTHREADT_NULL [static] |
The device state change notification thread.
Definition at line 158 of file devicestate.c.
Referenced by ast_device_state_engine_init(), and ast_devstate_changed_literal().
const char* devstatestring[] [static] |