diff options
author | kpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b> | 2005-07-08 21:14:34 +0000 |
---|---|---|
committer | kpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b> | 2005-07-08 21:14:34 +0000 |
commit | 1945cc0f8179b17589095af3550c8969d7790eed (patch) | |
tree | 0991463e1dac7d5f44a2be634d9a79b713a86521 /channel.c | |
parent | 4f868cef84f239a71b4f93b58aeb4852b3f0a0d3 (diff) |
queue device state changes and handle them serially in a background thread
optimize device state related functions
add ast_get_channel_by_name_prefix to allow searching for matching channels in O(1) operation
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@6062 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channel.c')
-rwxr-xr-x | channel.c | 170 |
1 files changed, 70 insertions, 100 deletions
@@ -57,6 +57,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/lock.h" #include "asterisk/app.h" #include "asterisk/transcap.h" +#include "asterisk/devicestate.h" /* uncomment if you have problems with 'monitoring' synchronized files */ #if 0 @@ -295,6 +296,58 @@ int ast_channel_register(const struct ast_channel_tech *tech) return 0; } +void ast_channel_unregister(const struct ast_channel_tech *tech) +{ + struct chanlist *chan, *last=NULL; + + if (option_debug) + ast_log(LOG_DEBUG, "Unregistering channel type '%s'\n", tech->type); + + ast_mutex_lock(&chlock); + + chan = backends; + while (chan) { + if (chan->tech == tech) { + if (last) + last->next = chan->next; + else + backends = backends->next; + free(chan); + ast_mutex_unlock(&chlock); + + if (option_verbose > 1) + ast_verbose( VERBOSE_PREFIX_2 "Unregistered channel type '%s'\n", tech->type); + + return; + } + last = chan; + chan = chan->next; + } + + ast_mutex_unlock(&chlock); +} + +const struct ast_channel_tech *ast_get_channel_tech(const char *name) +{ + struct chanlist *chanls; + + if (ast_mutex_lock(&chlock)) { + ast_log(LOG_WARNING, "Unable to lock channel tech list\n"); + return NULL; + } + + for (chanls = backends; chanls; chanls = chanls->next) { + if (strcasecmp(name, chanls->tech->type)) + continue; + + ast_mutex_unlock(&chlock); + return chanls->tech; + } + + ast_mutex_unlock(&chlock); + return NULL; +} + /*--- ast_cause2str: Gives the string form of a given hangup cause */ const char *ast_cause2str(int cause) { @@ -605,7 +658,7 @@ void ast_channel_undefer_dtmf(struct ast_channel *chan) * We should definitely go for a better scheme that is deadlock-free. */ static struct ast_channel *channel_find_locked(const struct ast_channel *prev, - const char *name) + const char *name, const int namelen) { const char *msg = prev ? "deadlock" : "initial deadlock"; int retries, done; @@ -615,8 +668,14 @@ static struct ast_channel *channel_find_locked(const struct ast_channel *prev, ast_mutex_lock(&chlock); for (c = channels; c; c = c->next) { if (prev == NULL) { - /* want either head of list or match by name */ - if (name == NULL || !strcasecmp(name, c->name)) + /* want head of list */ + if (!name) + break; + /* want match by full name */ + if (!namelen && !strcasecmp(c->name, name)) + break; + /* want match by name prefix */ + if (!strncasecmp(c->name, name, namelen)) break; } else if (c == prev) { /* found, return c->next */ c = c->next; @@ -646,13 +705,19 @@ static struct ast_channel *channel_find_locked(const struct ast_channel *prev, /*--- ast_channel_walk_locked: Browse channels in use */ struct ast_channel *ast_channel_walk_locked(const struct ast_channel *prev) { - return channel_find_locked(prev, NULL); + return channel_find_locked(prev, NULL, 0); } /*--- ast_get_channel_by_name_locked: Get channel by name and lock it */ struct ast_channel *ast_get_channel_by_name_locked(const char *name) { - return channel_find_locked(NULL, name); + return channel_find_locked(NULL, name, 0); +} + +/*--- ast_get_channel_by_name_prefix_locked: Get channel by name prefix and lock it */ +struct ast_channel *ast_get_channel_by_name_prefix_locked(const char *name, const int namelen) +{ + return channel_find_locked(NULL, name, namelen); } /*--- ast_safe_sleep_conditional: Wait, look for hangups and condition arg */ @@ -964,37 +1029,6 @@ int ast_hangup(struct ast_channel *chan) return res; } -void ast_channel_unregister(const struct ast_channel_tech *tech) -{ - struct chanlist *chan, *last=NULL; - - if (option_debug) - ast_log(LOG_DEBUG, "Unregistering channel type '%s'\n", tech->type); - - ast_mutex_lock(&chlock); - - chan = backends; - while (chan) { - if (chan->tech == tech) { - if (last) - last->next = chan->next; - else - backends = backends->next; - free(chan); - ast_mutex_unlock(&chlock); - - if (option_verbose > 1) - ast_verbose( VERBOSE_PREFIX_2 "Unregistered channel type '%s'\n", tech->type); - - return; - } - last = chan; - chan = chan->next; - } - - ast_mutex_unlock(&chlock); -} - int ast_answer(struct ast_channel *chan) { int res = 0; @@ -2167,70 +2201,6 @@ struct ast_channel *ast_request(const char *type, int format, void *data, int *c return c; } -int ast_parse_device_state(char *device) -{ - char name[AST_CHANNEL_NAME] = ""; - char *cut; - struct ast_channel *chan; - - chan = ast_channel_walk_locked(NULL); - while (chan) { - ast_copy_string(name, chan->name, sizeof(name)); - ast_mutex_unlock(&chan->lock); - cut = strchr(name,'-'); - if (cut) - *cut = 0; - if (!strcmp(name, device)) { - if (chan->_state == AST_STATE_RINGING) { - return AST_DEVICE_RINGING; - } else { - return AST_DEVICE_INUSE; - } - } - chan = ast_channel_walk_locked(chan); - } - return AST_DEVICE_UNKNOWN; -} - -int ast_device_state(char *device) -{ - char tech[AST_MAX_EXTENSION] = ""; - char *number; - struct chanlist *chanls; - int res = 0; - - ast_copy_string(tech, device, sizeof(tech)); - number = strchr(tech, '/'); - if (!number) { - return AST_DEVICE_INVALID; - } - *number = 0; - number++; - - if (ast_mutex_lock(&chlock)) { - ast_log(LOG_WARNING, "Unable to lock channel list\n"); - return -1; - } - chanls = backends; - while(chanls) { - if (!strcasecmp(tech, chanls->tech->type)) { - ast_mutex_unlock(&chlock); - if (!chanls->tech->devicestate) - return ast_parse_device_state(device); - else { - res = chanls->tech->devicestate(number); - if (res == AST_DEVICE_UNKNOWN) - return ast_parse_device_state(device); - else - return res; - } - } - chanls = chanls->next; - } - ast_mutex_unlock(&chlock); - return AST_DEVICE_INVALID; -} - int ast_call(struct ast_channel *chan, char *addr, int timeout) { /* Place an outgoing call, but don't wait any longer than timeout ms before returning. |