aboutsummaryrefslogtreecommitdiffstats
path: root/channel.c
diff options
context:
space:
mode:
authorkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2005-07-08 21:14:34 +0000
committerkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2005-07-08 21:14:34 +0000
commit1945cc0f8179b17589095af3550c8969d7790eed (patch)
tree0991463e1dac7d5f44a2be634d9a79b713a86521 /channel.c
parent4f868cef84f239a71b4f93b58aeb4852b3f0a0d3 (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-xchannel.c170
1 files changed, 70 insertions, 100 deletions
diff --git a/channel.c b/channel.c
index 04b77af27..6ec2ff044 100755
--- a/channel.c
+++ b/channel.c
@@ -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.