![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
devicestate.c File Reference
Definition in file devicestate.c.
#include "asterisk.h"
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "asterisk/channel.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/linkedlists.h"
#include "asterisk/logger.h"
#include "asterisk/devicestate.h"
#include "asterisk/pbx.h"
#include "asterisk/app.h"
#include "asterisk/options.h"
Include dependency graph for devicestate.c:

Go to the source code of this file.
Data Structures | |
| struct | devstate_cb |
| A device state watcher (callback). More... | |
| struct | devstate_prov |
| A device state provider (not a channel). More... | |
| struct | state_change |
Functions | |
| static int | __ast_device_state_changed_literal (char *buf) |
| int | ast_device_state (const char *device) |
| Asks a channel for device state. | |
| int | ast_device_state_changed (const char *fmt,...) |
| 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. | |
| int | ast_devstate_add (ast_devstate_cb_type callback, void *data) |
| Registers a device state change callback. | |
| void | ast_devstate_del (ast_devstate_cb_type callback, void *data) |
| Unregisters a device state change callback. | |
| int | ast_devstate_prov_add (const char *label, ast_devstate_prov_cb_type callback) |
| Add device state provider. | |
| void | ast_devstate_prov_del (const char *label) |
| Remove device state provider. | |
| static | AST_LIST_HEAD_STATIC (state_changes, state_change) |
| The state change queue. State changes are queued for processing by a separate thread. | |
| int | ast_parse_device_state (const char *device) |
| Search the Channels by Name. | |
| static | AST_RWLIST_HEAD_STATIC (devstate_cbs, devstate_cb) |
| A device state watcher list. | |
| static | AST_RWLIST_HEAD_STATIC (devstate_provs, devstate_prov) |
| A list of providers. | |
| const char * | devstate2str (int devstate) |
| Convert device state to text string for output. | |
| 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) |
| Notify callback watchers of change, and notify PBX core for hint updates Normally executed within a separate thread. | |
| 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 at line 376 of file devicestate.c. References ast_calloc, ast_cond_signal(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), AST_PTHREADT_NULL, do_state_change(), LOG_DEBUG, and option_debug. Referenced by ast_device_state_changed(), and ast_device_state_changed_literal(). 00377 { 00378 char *device, *tmp; 00379 struct state_change *change; 00380 00381 if (option_debug > 2) 00382 ast_log(LOG_DEBUG, "Notification of state change to be queued on device/channel %s\n", buf); 00383 00384 device = buf; 00385 if ((tmp = strrchr(device, '-'))) 00386 *tmp = '\0'; 00387 00388 if (change_thread == AST_PTHREADT_NULL || !(change = ast_calloc(1, sizeof(*change) + strlen(device)))) { 00389 /* we could not allocate a change struct, or */ 00390 /* there is no background thread, so process the change now */ 00391 do_state_change(device); 00392 } else { 00393 /* queue the change */ 00394 strcpy(change->device, device); 00395 AST_LIST_LOCK(&state_changes); 00396 AST_LIST_INSERT_TAIL(&state_changes, change, list); 00397 ast_cond_signal(&change_pending); 00398 AST_LIST_UNLOCK(&state_changes); 00399 } 00400 00401 return 1; 00402 }
|
|
|
Asks a channel for device state.
Definition at line 216 of file devicestate.c. References AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_UNKNOWN, ast_get_channel_tech(), ast_log(), ast_parse_device_state(), ast_strdupa, ast_channel_tech::devicestate, getproviderstate(), LOG_DEBUG, option_debug, and strsep(). Referenced by ast_extension_state2(), do_state_change(), and transmit_state_notify(). 00217 { 00218 char *buf; 00219 char *number; 00220 const struct ast_channel_tech *chan_tech; 00221 int res = 0; 00222 /*! \brief Channel driver that provides device state */ 00223 char *tech; 00224 /*! \brief Another provider of device state */ 00225 char *provider = NULL; 00226 00227 buf = ast_strdupa(device); 00228 tech = strsep(&buf, "/"); 00229 if (!(number = buf)) { 00230 if (!(provider = strsep(&tech, ":"))) 00231 return AST_DEVICE_INVALID; 00232 /* We have a provider */ 00233 number = tech; 00234 tech = NULL; 00235 } 00236 00237 if (provider) { 00238 if (option_debug > 2) 00239 ast_log(LOG_DEBUG, "Checking if I can find provider for \"%s\" - number: %s\n", provider, number); 00240 return getproviderstate(provider, number); 00241 } 00242 00243 if (option_debug > 3) 00244 ast_log(LOG_DEBUG, "No provider found, checking channel drivers for %s - %s\n", tech, number); 00245 00246 if (!(chan_tech = ast_get_channel_tech(tech))) 00247 return AST_DEVICE_INVALID; 00248 00249 if (!(chan_tech->devicestate)) /* Does the channel driver support device state notification? */ 00250 return ast_parse_device_state(device); /* No, try the generic function */ 00251 00252 res = chan_tech->devicestate(number); 00253 00254 if (res != AST_DEVICE_UNKNOWN) 00255 return res; 00256 00257 res = ast_parse_device_state(device); 00258 00259 if (res == AST_DEVICE_UNKNOWN) 00260 return AST_DEVICE_NOT_INUSE; 00261 00262 return res; 00263 }
|
|
||||||||||||
|
Accept change notification, add it to change queue.
Definition at line 412 of file devicestate.c. References __ast_device_state_changed_literal(), and AST_MAX_EXTENSION. Referenced by __expire_registry(), __iax2_poke_noanswer(), __login_exec(), agent_hangup(), agent_logoff_maintenance(), expire_register(), handle_response_peerpoke(), notify_metermaids(), reg_source_db(), register_verify(), reload_agents(), sip_peer_hold(), sip_poke_noanswer(), socket_process(), update_call_counter(), and update_registry(). 00413 { 00414 char buf[AST_MAX_EXTENSION]; 00415 va_list ap; 00416 00417 va_start(ap, fmt); 00418 vsnprintf(buf, sizeof(buf), fmt, ap); 00419 va_end(ap); 00420 return __ast_device_state_changed_literal(buf); 00421 }
|
|
|
Tells Asterisk the State for Device is changed.
Definition at line 404 of file devicestate.c. References __ast_device_state_changed_literal(), and ast_strdupa. Referenced by ast_channel_free(), and ast_setstate(). 00405 { 00406 char *buf; 00407 buf = ast_strdupa(dev); 00408 return __ast_device_state_changed_literal(buf); 00409 }
|
|
|
Initialize the device state engine in separate thread.
Definition at line 449 of file devicestate.c. References ast_cond_init(), ast_log(), ast_pthread_create_background, change_pending, change_thread, do_devstate_changes(), and LOG_ERROR. 00450 { 00451 ast_cond_init(&change_pending, NULL); 00452 if (ast_pthread_create_background(&change_thread, NULL, do_devstate_changes, NULL) < 0) { 00453 ast_log(LOG_ERROR, "Unable to start device state change thread.\n"); 00454 return -1; 00455 } 00456 00457 return 0; 00458 }
|
|
||||||||||||
|
Registers a device state change callback.
Definition at line 322 of file devicestate.c. References ast_calloc, AST_RWLIST_INSERT_HEAD, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK. 00323 { 00324 struct devstate_cb *devcb; 00325 00326 if (!callback || !(devcb = ast_calloc(1, sizeof(*devcb)))) 00327 return -1; 00328 00329 devcb->data = data; 00330 devcb->callback = callback; 00331 00332 AST_RWLIST_WRLOCK(&devstate_cbs); 00333 AST_RWLIST_INSERT_HEAD(&devstate_cbs, devcb, list); 00334 AST_RWLIST_UNLOCK(&devstate_cbs); 00335 00336 return 0; 00337 }
|
|
||||||||||||
|
Unregisters a device state change callback.
Definition at line 340 of file devicestate.c. References AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, devstate_cb::callback, devstate_cb::data, and free. 00341 { 00342 struct devstate_cb *devcb; 00343 00344 AST_RWLIST_WRLOCK(&devstate_cbs); 00345 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&devstate_cbs, devcb, list) { 00346 if ((devcb->callback == callback) && (devcb->data == data)) { 00347 AST_RWLIST_REMOVE_CURRENT(&devstate_cbs, list); 00348 free(devcb); 00349 break; 00350 } 00351 } 00352 AST_RWLIST_TRAVERSE_SAFE_END; 00353 AST_RWLIST_UNLOCK(&devstate_cbs); 00354 }
|
|
||||||||||||
|
Add device state provider.
Definition at line 266 of file devicestate.c. References ast_calloc, AST_RWLIST_INSERT_HEAD, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK. Referenced by load_module(). 00267 { 00268 struct devstate_prov *devprov; 00269 00270 if (!callback || !(devprov = ast_calloc(1, sizeof(*devprov)))) 00271 return -1; 00272 00273 devprov->callback = callback; 00274 ast_copy_string(devprov->label, label, sizeof(devprov->label)); 00275 00276 AST_RWLIST_WRLOCK(&devstate_provs); 00277 AST_RWLIST_INSERT_HEAD(&devstate_provs, devprov, list); 00278 AST_RWLIST_UNLOCK(&devstate_provs); 00279 00280 return 0; 00281 }
|
|
|
Remove device state provider.
Definition at line 284 of file devicestate.c. References AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, free, and devstate_prov::label. Referenced by unload_module(). 00285 { 00286 struct devstate_prov *devcb; 00287 00288 AST_RWLIST_WRLOCK(&devstate_provs); 00289 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&devstate_provs, devcb, list) { 00290 if (!strcasecmp(devcb->label, label)) { 00291 AST_RWLIST_REMOVE_CURRENT(&devstate_provs, list); 00292 free(devcb); 00293 break; 00294 } 00295 } 00296 AST_RWLIST_TRAVERSE_SAFE_END; 00297 AST_RWLIST_UNLOCK(&devstate_provs); 00298 }
|
|
||||||||||||
|
The state change queue. State changes are queued for processing by a separate thread.
|
|
|
Search the Channels by Name.
Definition at line 192 of file devicestate.c. References ast_channel::_state, AST_CHANNEL_NAME, ast_channel_unlock, AST_DEVICE_INUSE, AST_DEVICE_RINGING, AST_DEVICE_UNKNOWN, ast_get_channel_by_name_prefix_locked(), AST_STATE_RINGING, and match(). Referenced by ast_device_state(). 00193 { 00194 struct ast_channel *chan; 00195 char match[AST_CHANNEL_NAME]; 00196 int res; 00197 00198 ast_copy_string(match, device, sizeof(match)-1); 00199 strcat(match, "-"); 00200 chan = ast_get_channel_by_name_prefix_locked(match, strlen(match)); 00201 00202 if (!chan) 00203 return AST_DEVICE_UNKNOWN; 00204 00205 if (chan->_state == AST_STATE_RINGING) 00206 res = AST_DEVICE_RINGING; 00207 else 00208 res = AST_DEVICE_INUSE; 00209 00210 ast_channel_unlock(chan); 00211 00212 return res; 00213 }
|
|
||||||||||||
|
A device state watcher list.
|
|
||||||||||||
|
A list of providers.
|
|
|
Convert device state to text string for output.
Definition at line 182 of file devicestate.c. Referenced by do_state_change(). 00183 { 00184 return devstatestring[devstate]; 00185 }
|
|
|
Go through the dev state change queue and update changes in the dev state thread.
Definition at line 424 of file devicestate.c. References ast_cond_wait(), AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_LOCK, AST_LIST_NEXT, AST_LIST_UNLOCK, do_state_change(), and free. Referenced by ast_device_state_engine_init(). 00425 { 00426 struct state_change *next, *current; 00427 00428 for (;;) { 00429 /* This basically pops off any state change entries, resets the list back to NULL, unlocks, and processes each state change */ 00430 AST_LIST_LOCK(&state_changes); 00431 if (AST_LIST_EMPTY(&state_changes)) 00432 ast_cond_wait(&change_pending, &state_changes.lock); 00433 next = AST_LIST_FIRST(&state_changes); 00434 AST_LIST_HEAD_INIT_NOLOCK(&state_changes); 00435 AST_LIST_UNLOCK(&state_changes); 00436 00437 /* Process each state change */ 00438 while ((current = next)) { 00439 next = AST_LIST_NEXT(current, list); 00440 do_state_change(current->device); 00441 free(current); 00442 } 00443 } 00444 00445 return NULL; 00446 }
|
|
|
Notify callback watchers of change, and notify PBX core for hint updates Normally executed within a separate thread.
Definition at line 359 of file devicestate.c. References ast_device_state(), ast_hint_state_changed(), ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, devstate_cb::callback, devstate_cb::data, devstate2str(), LOG_DEBUG, and option_debug. Referenced by __ast_device_state_changed_literal(), and do_devstate_changes(). 00360 { 00361 int state; 00362 struct devstate_cb *devcb; 00363 00364 state = ast_device_state(device); 00365 if (option_debug > 2) 00366 ast_log(LOG_DEBUG, "Changing state for %s - state %d (%s)\n", device, state, devstate2str(state)); 00367 00368 AST_RWLIST_RDLOCK(&devstate_cbs); 00369 AST_RWLIST_TRAVERSE(&devstate_cbs, devcb, list) 00370 devcb->callback(device, state, devcb->data); 00371 AST_RWLIST_UNLOCK(&devstate_cbs); 00372 00373 ast_hint_state_changed(device); 00374 }
|
|
||||||||||||
|
Get provider device state.
Definition at line 301 of file devicestate.c. References AST_DEVICE_INVALID, ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, devstate_prov::callback, devstate_prov::label, LOG_DEBUG, and option_debug. Referenced by ast_device_state(). 00302 { 00303 struct devstate_prov *devprov; 00304 int res = AST_DEVICE_INVALID; 00305 00306 00307 AST_RWLIST_RDLOCK(&devstate_provs); 00308 AST_RWLIST_TRAVERSE(&devstate_provs, devprov, list) { 00309 if (option_debug > 4) 00310 ast_log(LOG_DEBUG, "Checking provider %s with %s\n", devprov->label, provider); 00311 00312 if (!strcasecmp(devprov->label, provider)) { 00313 res = devprov->callback(address); 00314 break; 00315 } 00316 } 00317 AST_RWLIST_UNLOCK(&devstate_provs); 00318 return res; 00319 }
|
|
|
Flag for the queue.
Definition at line 176 of file devicestate.c. Referenced by ast_device_state_engine_init(). |
|
|
The device state change notification thread.
Definition at line 173 of file devicestate.c. Referenced by ast_device_state_engine_init(). |
|
|
Device state strings for printing.
Definition at line 131 of file devicestate.c. |