#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "asterisk.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/options.h"
Go to the source code of this file.
Data Structures | |
struct | devstate_cb |
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,...) |
int | ast_device_state_changed_literal (const char *dev) |
Tells Asterisk the State for Device is changed. | |
int | ast_device_state_engine_init (void) |
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) |
static | AST_LIST_HEAD_STATIC (state_changes, state_change) |
static | AST_LIST_HEAD_STATIC (devstate_cbs, devstate_cb) |
int | ast_parse_device_state (const char *device) |
Search the Channels by Name. | |
const char * | devstate2str (int devstate) |
Convert device state to text string for output. | |
static void * | do_devstate_changes (void *data) |
static void | do_state_change (const char *device) |
Variables | |
static ast_cond_t | change_pending |
static pthread_t | change_thread = AST_PTHREADT_NULL |
static const char * | devstatestring [] |
Definition in file devicestate.c.
static int __ast_device_state_changed_literal | ( | char * | buf | ) | [static] |
Definition at line 197 of file devicestate.c.
References ast_cond_signal(), AST_LIST_FIRST, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, AST_PTHREADT_NULL, calloc, change_pending, change_thread, do_state_change(), and list.
Referenced by ast_device_state_changed(), and ast_device_state_changed_literal().
00198 { 00199 char *device, *tmp; 00200 struct state_change *change = NULL; 00201 00202 device = buf; 00203 tmp = strrchr(device, '-'); 00204 if (tmp) 00205 *tmp = '\0'; 00206 if (change_thread != AST_PTHREADT_NULL) 00207 change = calloc(1, sizeof(*change) + strlen(device)); 00208 00209 if (!change) { 00210 /* we could not allocate a change struct, or */ 00211 /* there is no background thread, so process the change now */ 00212 do_state_change(device); 00213 } else { 00214 /* queue the change */ 00215 strcpy(change->device, device); 00216 AST_LIST_LOCK(&state_changes); 00217 AST_LIST_INSERT_TAIL(&state_changes, change, list); 00218 if (AST_LIST_FIRST(&state_changes) == change) 00219 /* the list was empty, signal the thread */ 00220 ast_cond_signal(&change_pending); 00221 AST_LIST_UNLOCK(&state_changes); 00222 } 00223 00224 return 1; 00225 }
int ast_device_state | ( | const char * | device | ) |
Asks a channel for device state.
device | like a dialstring Asks a channel for device state, data is normaly a number from dialstring used by the low level module Trys the channel devicestate callback if not supported search in the active channels list for the device. Returns an AST_DEVICE_??? state -1 on failure |
Definition at line 104 of file devicestate.c.
References AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_UNKNOWN, ast_get_channel_tech(), ast_parse_device_state(), ast_strdupa, ast_channel_tech::devicestate, strsep(), and ast_channel::tech.
Referenced by ast_extension_state2(), chanavail_exec(), create_queue_member(), do_state_change(), reload_queues(), and transmit_state_notify().
00105 { 00106 char *buf; 00107 char *tech; 00108 char *number; 00109 const struct ast_channel_tech *chan_tech; 00110 int res = 0; 00111 00112 buf = ast_strdupa(device); 00113 tech = strsep(&buf, "/"); 00114 number = buf; 00115 if (!number) 00116 return AST_DEVICE_INVALID; 00117 00118 chan_tech = ast_get_channel_tech(tech); 00119 if (!chan_tech) 00120 return AST_DEVICE_INVALID; 00121 00122 if (!chan_tech->devicestate) /* Does the channel driver support device state notification? */ 00123 return ast_parse_device_state(device); /* No, try the generic function */ 00124 else { 00125 res = chan_tech->devicestate(number); /* Ask the channel driver for device state */ 00126 if (res == AST_DEVICE_UNKNOWN) { 00127 res = ast_parse_device_state(device); 00128 /* at this point we know the device exists, but the channel driver 00129 could not give us a state; if there is no channel state available, 00130 it must be 'not in use' 00131 */ 00132 if (res == AST_DEVICE_UNKNOWN) 00133 res = AST_DEVICE_NOT_INUSE; 00134 return res; 00135 } else 00136 return res; 00137 } 00138 }
int ast_device_state_changed | ( | const char * | fmt, | |
... | ||||
) |
Definition at line 235 of file devicestate.c.
References __ast_device_state_changed_literal(), and AST_MAX_EXTENSION.
Referenced by __login_exec(), action_agent_callback_login(), agent_hangup(), expire_register(), expire_registry(), handle_response_peerpoke(), iax2_poke_noanswer(), local_watcher(), reg_source_db(), register_verify(), reload_agents(), sip_poke_noanswer(), socket_read(), and update_registry().
00236 { 00237 char buf[AST_MAX_EXTENSION]; 00238 va_list ap; 00239 00240 va_start(ap, fmt); 00241 vsnprintf(buf, sizeof(buf), fmt, ap); 00242 va_end(ap); 00243 return __ast_device_state_changed_literal(buf); 00244 }
int ast_device_state_changed_literal | ( | const char * | device | ) |
Tells Asterisk the State for Device is changed.
device | devicename like a dialstrin Asterisk polls the new extensionstates and calls the registered callbacks for the changed extensions Returns 0 on success, -1 on failure |
Definition at line 227 of file devicestate.c.
References __ast_device_state_changed_literal(), and ast_strdupa.
Referenced by ast_channel_free(), and ast_setstate().
00228 { 00229 char *buf; 00230 buf = ast_strdupa(dev); 00231 return __ast_device_state_changed_literal(buf); 00232 }
int ast_device_state_engine_init | ( | void | ) |
Definition at line 272 of file devicestate.c.
References ast_cond_init(), ast_log(), ast_pthread_create, change_pending, change_thread, do_devstate_changes(), and LOG_ERROR.
Referenced by main().
00273 { 00274 ast_cond_init(&change_pending, NULL); 00275 if (ast_pthread_create(&change_thread, NULL, do_devstate_changes, NULL) < 0) { 00276 ast_log(LOG_ERROR, "Unable to start device state change thread.\n"); 00277 return -1; 00278 } 00279 00280 return 0; 00281 }
int ast_devstate_add | ( | ast_devstate_cb_type | callback, | |
void * | data | |||
) |
Registers a device state change callback.
callback | Callback | |
data | to pass to callback The callback is called if the state for extension is changed Return -1 on failure, ID on success |
Definition at line 141 of file devicestate.c.
References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, calloc, and list.
Referenced by load_module().
00142 { 00143 struct devstate_cb *devcb; 00144 00145 if (!callback) 00146 return -1; 00147 00148 devcb = calloc(1, sizeof(*devcb)); 00149 if (!devcb) 00150 return -1; 00151 00152 devcb->data = data; 00153 devcb->callback = callback; 00154 00155 AST_LIST_LOCK(&devstate_cbs); 00156 AST_LIST_INSERT_HEAD(&devstate_cbs, devcb, list); 00157 AST_LIST_UNLOCK(&devstate_cbs); 00158 00159 return 0; 00160 }
void ast_devstate_del | ( | ast_devstate_cb_type | callback, | |
void * | data | |||
) |
Definition at line 163 of file devicestate.c.
References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, devstate_cb::callback, devstate_cb::data, free, and list.
Referenced by unload_module().
00164 { 00165 struct devstate_cb *devcb; 00166 00167 AST_LIST_LOCK(&devstate_cbs); 00168 AST_LIST_TRAVERSE_SAFE_BEGIN(&devstate_cbs, devcb, list) { 00169 if ((devcb->callback == callback) && (devcb->data == data)) { 00170 AST_LIST_REMOVE_CURRENT(&devstate_cbs, list); 00171 free(devcb); 00172 break; 00173 } 00174 } 00175 AST_LIST_TRAVERSE_SAFE_END; 00176 AST_LIST_UNLOCK(&devstate_cbs); 00177 }
static AST_LIST_HEAD_STATIC | ( | state_changes | , | |
state_change | ||||
) | [static] |
static AST_LIST_HEAD_STATIC | ( | devstate_cbs | , | |
devstate_cb | ||||
) | [static] |
int ast_parse_device_state | ( | const char * | device | ) |
Search the Channels by Name.
device | like a dialstring Search the Device in active channels by compare the channelname against the devicename. Compared are only the first chars to the first '-' char. Returns an AST_DEVICE_UNKNOWN if no channel found or AST_DEVICE_INUSE if a channel is found |
Definition at line 80 of file devicestate.c.
References ast_channel::_state, AST_CHANNEL_NAME, AST_DEVICE_INUSE, AST_DEVICE_RINGING, AST_DEVICE_UNKNOWN, ast_get_channel_by_name_prefix_locked(), ast_mutex_unlock(), AST_STATE_RINGING, ast_channel::lock, and match().
Referenced by ast_device_state().
00081 { 00082 struct ast_channel *chan; 00083 char match[AST_CHANNEL_NAME]; 00084 int res; 00085 00086 ast_copy_string(match, device, sizeof(match)-1); 00087 strcat(match, "-"); 00088 chan = ast_get_channel_by_name_prefix_locked(match, strlen(match)); 00089 00090 if (!chan) 00091 return AST_DEVICE_UNKNOWN; 00092 00093 if (chan->_state == AST_STATE_RINGING) 00094 res = AST_DEVICE_RINGING; 00095 else 00096 res = AST_DEVICE_INUSE; 00097 00098 ast_mutex_unlock(&chan->lock); 00099 00100 return res; 00101 }
const char* devstate2str | ( | int | devstate | ) |
Convert device state to text string for output.
devstate | Current device state |
Definition at line 74 of file devicestate.c.
Referenced by __queues_show(), changethread(), and do_state_change().
00075 { 00076 return devstatestring[devstate]; 00077 }
static void* do_devstate_changes | ( | void * | data | ) | [static] |
Definition at line 247 of file devicestate.c.
References ast_cond_wait(), AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, change_pending, do_state_change(), free, and list.
Referenced by ast_device_state_engine_init().
00248 { 00249 struct state_change *cur; 00250 00251 AST_LIST_LOCK(&state_changes); 00252 for(;;) { 00253 /* the list lock will _always_ be held at this point in the loop */ 00254 cur = AST_LIST_REMOVE_HEAD(&state_changes, list); 00255 if (cur) { 00256 /* we got an entry, so unlock the list while we process it */ 00257 AST_LIST_UNLOCK(&state_changes); 00258 do_state_change(cur->device); 00259 free(cur); 00260 AST_LIST_LOCK(&state_changes); 00261 } else { 00262 /* there was no entry, so atomically unlock the list and wait for 00263 the condition to be signalled (returns with the lock held) */ 00264 ast_cond_wait(&change_pending, &state_changes.lock); 00265 } 00266 } 00267 00268 return NULL; 00269 }
static void do_state_change | ( | const char * | device | ) | [static] |
Definition at line 180 of file devicestate.c.
References ast_device_state(), ast_hint_state_changed(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), devstate_cb::callback, devstate_cb::data, devstate2str(), list, LOG_DEBUG, and option_debug.
Referenced by __ast_device_state_changed_literal(), and do_devstate_changes().
00181 { 00182 int state; 00183 struct devstate_cb *devcb; 00184 00185 state = ast_device_state(device); 00186 if (option_debug > 2) 00187 ast_log(LOG_DEBUG, "Changing state for %s - state %d (%s)\n", device, state, devstate2str(state)); 00188 00189 AST_LIST_LOCK(&devstate_cbs); 00190 AST_LIST_TRAVERSE(&devstate_cbs, devcb, list) 00191 devcb->callback(device, state, devcb->data); 00192 AST_LIST_UNLOCK(&devstate_cbs); 00193 00194 ast_hint_state_changed(device); 00195 }
ast_cond_t change_pending [static] |
Definition at line 71 of file devicestate.c.
Referenced by __ast_device_state_changed_literal(), ast_device_state_engine_init(), and do_devstate_changes().
pthread_t change_thread = AST_PTHREADT_NULL [static] |
Definition at line 70 of file devicestate.c.
Referenced by __ast_device_state_changed_literal(), and ast_device_state_engine_init().
const char* devstatestring[] [static] |
Definition at line 44 of file devicestate.c.