summaryrefslogtreecommitdiff
path: root/channels
diff options
context:
space:
mode:
authorJoshua Colp <jcolp@digium.com>2006-09-27 01:39:39 +0000
committerJoshua Colp <jcolp@digium.com>2006-09-27 01:39:39 +0000
commit481265e3478a2c089b9d94597bd379f72538771c (patch)
tree12a54fafcd6eb1a803128399a7fe2bc0d3cf6467 /channels
parentee13556e3093967218c847d148d339822f24d343 (diff)
Clean up code and convert last two things (firmware/dialplan cache) to linked list macros.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@43733 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels')
-rw-r--r--channels/chan_iax2.c501
1 files changed, 227 insertions, 274 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index 8949714a1..08c4d0e6d 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -228,7 +228,6 @@ static struct ast_flags globalflags = { 0 };
static pthread_t netthreadid = AST_PTHREADT_NULL;
static pthread_t schedthreadid = AST_PTHREADT_NULL;
AST_MUTEX_DEFINE_STATIC(sched_lock);
-static int sched_halt = 0;
static ast_cond_t sched_cond;
enum {
@@ -382,7 +381,7 @@ static struct iax2_trunk_peer {
AST_MUTEX_DEFINE_STATIC(tpeerlock);
struct iax_firmware {
- struct iax_firmware *next;
+ AST_LIST_ENTRY(iax_firmware) list;
int fd;
int mmaplen;
int dead;
@@ -608,7 +607,7 @@ struct chan_iax2_pvt {
int calling_tns;
int calling_pres;
int amaflags;
- struct iax2_dpcache *dpentries;
+ AST_LIST_HEAD_NOLOCK(, iax2_dpcache) dpentries;
struct ast_variable *vars;
/*! last received remote rr */
struct iax_rr remote_rr;
@@ -631,10 +630,7 @@ static AST_LIST_HEAD_STATIC(users, iax2_user);
static AST_LIST_HEAD_STATIC(peers, iax2_peer);
-static struct ast_firmware_list {
- struct iax_firmware *wares;
- ast_mutex_t lock;
-} waresl;
+static AST_LIST_HEAD_STATIC(firmwares, iax_firmware);
/*! Extension exists */
#define CACHE_FLAG_EXISTS (1 << 0)
@@ -653,7 +649,7 @@ static struct ast_firmware_list {
/*! Matchmore */
#define CACHE_FLAG_MATCHMORE (1 << 7)
-static struct iax2_dpcache {
+struct iax2_dpcache {
char peercontext[AST_MAX_CONTEXT];
char exten[AST_MAX_EXTENSION];
struct timeval orig;
@@ -661,11 +657,11 @@ static struct iax2_dpcache {
int flags;
unsigned short callno;
int waiters[256];
- struct iax2_dpcache *next;
- struct iax2_dpcache *peer; /*!< For linking in peers */
-} *dpcache;
+ AST_LIST_ENTRY(iax2_dpcache) cache_list;
+ AST_LIST_ENTRY(iax2_dpcache) peer_list;
+};
-AST_MUTEX_DEFINE_STATIC(dpcache_lock);
+static AST_LIST_HEAD_STATIC(dpcache, iax2_dpcache);
static void reg_source_db(struct iax2_peer *p);
static struct iax2_peer *realtime_peer(const char *peername, struct sockaddr_in *sin);
@@ -693,7 +689,6 @@ struct iax2_thread {
char curfunc[80];
#endif
int actions;
- int halt;
pthread_t threadid;
int threadnum;
struct sockaddr_in iosin;
@@ -1069,6 +1064,8 @@ static struct chan_iax2_pvt *new_iax(struct sockaddr_in *sin, int lockpeer, cons
jbconf.max_contig_interp = maxjitterinterps;
jb_setconf(tmp->jb,&jbconf);
+ AST_LIST_HEAD_INIT_NOLOCK(&tmp->dpentries);
+
return tmp;
}
@@ -1304,34 +1301,31 @@ static void destroy_firmware(struct iax_firmware *cur)
static int try_firmware(char *s)
{
struct stat stbuf;
- struct iax_firmware *cur;
- int ifd;
- int fd;
- int res;
-
+ struct iax_firmware *cur = NULL;
+ int ifd, fd, res, len, chunk;
struct ast_iax2_firmware_header *fwh, fwh2;
struct MD5Context md5;
- unsigned char sum[16];
- unsigned char buf[1024];
- int len, chunk;
- char *s2;
- char *last;
- s2 = alloca(strlen(s) + 100);
- if (!s2) {
+ unsigned char sum[16], buf[1024];
+ char *s2, *last;
+
+ if (!(s2 = alloca(strlen(s) + 100))) {
ast_log(LOG_WARNING, "Alloca failed!\n");
return -1;
}
+
last = strrchr(s, '/');
if (last)
last++;
else
last = s;
+
snprintf(s2, strlen(s) + 100, "/var/tmp/%s-%ld", last, (unsigned long)ast_random());
- res = stat(s, &stbuf);
- if (res < 0) {
+
+ if ((res = stat(s, &stbuf) < 0)) {
ast_log(LOG_WARNING, "Failed to stat '%s': %s\n", s, strerror(errno));
return -1;
}
+
/* Make sure it's not a directory */
if (S_ISDIR(stbuf.st_mode))
return -1;
@@ -1409,8 +1403,8 @@ static int try_firmware(char *s)
close(fd);
return -1;
}
- cur = waresl.wares;
- while(cur) {
+
+ AST_LIST_TRAVERSE(&firmwares, cur, list) {
if (!strcmp((char *)cur->fwh->devname, (char *)fwh->devname)) {
/* Found a candidate */
if (cur->dead || (ntohs(cur->fwh->version) < ntohs(fwh->version)))
@@ -1422,20 +1416,16 @@ static int try_firmware(char *s)
close(fd);
return 0;
}
- cur = cur->next;
}
- if (!cur) {
- /* Allocate a new one and link it */
- if ((cur = ast_calloc(1, sizeof(*cur)))) {
- cur->fd = -1;
- cur->next = waresl.wares;
- waresl.wares = cur;
- }
+
+ if (!cur && ((cur = ast_calloc(1, sizeof(*cur))))) {
+ cur->fd = -1;
+ AST_LIST_INSERT_TAIL(&firmwares, cur, list);
}
+
if (cur) {
- if (cur->fwh) {
+ if (cur->fwh)
munmap(cur->fwh, cur->mmaplen);
- }
if (cur->fd > -1)
close(cur->fd);
cur->fwh = fwh;
@@ -1443,25 +1433,27 @@ static int try_firmware(char *s)
cur->mmaplen = stbuf.st_size;
cur->dead = 0;
}
+
return 0;
}
static int iax_check_version(char *dev)
{
int res = 0;
- struct iax_firmware *cur;
- if (!ast_strlen_zero(dev)) {
- ast_mutex_lock(&waresl.lock);
- cur = waresl.wares;
- while(cur) {
- if (!strcmp(dev, (char *)cur->fwh->devname)) {
- res = ntohs(cur->fwh->version);
- break;
- }
- cur = cur->next;
+ struct iax_firmware *cur = NULL;
+
+ if (ast_strlen_zero(dev))
+ return 0;
+
+ AST_LIST_LOCK(&firmwares);
+ AST_LIST_TRAVERSE(&firmwares, cur, list) {
+ if (!strcmp(dev, (char *)cur->fwh->devname)) {
+ res = ntohs(cur->fwh->version);
+ break;
}
- ast_mutex_unlock(&waresl.lock);
}
+ AST_LIST_UNLOCK(&firmwares);
+
return res;
}
@@ -1472,51 +1464,52 @@ static int iax_firmware_append(struct iax_ie_data *ied, const unsigned char *dev
unsigned int start = (desc >> 8) & 0xffffff;
unsigned int bytes;
struct iax_firmware *cur;
- if (!ast_strlen_zero((char *)dev) && bs) {
- start *= bs;
- ast_mutex_lock(&waresl.lock);
- cur = waresl.wares;
- while(cur) {
- if (!strcmp((char *)dev, (char *)cur->fwh->devname)) {
- iax_ie_append_int(ied, IAX_IE_FWBLOCKDESC, desc);
- if (start < ntohl(cur->fwh->datalen)) {
- bytes = ntohl(cur->fwh->datalen) - start;
- if (bytes > bs)
- bytes = bs;
- iax_ie_append_raw(ied, IAX_IE_FWBLOCKDATA, cur->fwh->data + start, bytes);
- } else {
- bytes = 0;
- iax_ie_append(ied, IAX_IE_FWBLOCKDATA);
- }
- if (bytes == bs)
- res = 0;
- else
- res = 1;
- break;
- }
- cur = cur->next;
+
+ if (ast_strlen_zero((char *)dev) || !bs)
+ return -1;
+
+ start *= bs;
+
+ AST_LIST_LOCK(&firmwares);
+ AST_LIST_TRAVERSE(&firmwares, cur, list) {
+ if (strcmp((char *)dev, (char *)cur->fwh->devname))
+ continue;
+ iax_ie_append_int(ied, IAX_IE_FWBLOCKDESC, desc);
+ if (start < ntohl(cur->fwh->datalen)) {
+ bytes = ntohl(cur->fwh->datalen) - start;
+ if (bytes > bs)
+ bytes = bs;
+ iax_ie_append_raw(ied, IAX_IE_FWBLOCKDATA, cur->fwh->data + start, bytes);
+ } else {
+ bytes = 0;
+ iax_ie_append(ied, IAX_IE_FWBLOCKDATA);
}
- ast_mutex_unlock(&waresl.lock);
+ if (bytes == bs)
+ res = 0;
+ else
+ res = 1;
+ break;
}
+ AST_LIST_UNLOCK(&firmwares);
+
return res;
}
static void reload_firmware(void)
{
- struct iax_firmware *cur, *curl, *curp;
+ struct iax_firmware *cur = NULL;
DIR *fwd;
struct dirent *de;
- char dir[256];
- char fn[256];
+ char dir[256], fn[256];
+
+ AST_LIST_LOCK(&firmwares);
+
/* Mark all as dead */
- ast_mutex_lock(&waresl.lock);
- cur = waresl.wares;
- while(cur) {
+ AST_LIST_TRAVERSE(&firmwares, cur, list)
cur->dead = 1;
- cur = cur->next;
- }
- /* Now that we've freed them, load the new ones */
+
+ /* Now that we have marked them dead... load new ones */
snprintf(dir, sizeof(dir), "%s/firmware/iax", (char *)ast_config_AST_DATA_DIR);
fwd = opendir(dir);
if (fwd) {
@@ -1534,23 +1527,13 @@ static void reload_firmware(void)
ast_log(LOG_WARNING, "Error opening firmware directory '%s': %s\n", dir, strerror(errno));
/* Clean up leftovers */
- cur = waresl.wares;
- curp = NULL;
- while(cur) {
- curl = cur;
- cur = cur->next;
- if (curl->dead) {
- if (curp) {
- curp->next = cur;
- } else {
- waresl.wares = cur;
- }
- destroy_firmware(curl);
- } else {
- curp = cur;
- }
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&firmwares, cur, list) {
+ if (!cur->dead)
+ continue;
+ AST_LIST_REMOVE_CURRENT(&firmwares, list);
+ destroy_firmware(cur);
}
- ast_mutex_unlock(&waresl.lock);
+ AST_LIST_TRAVERSE_SAFE_END
}
static int __do_deliver(void *data)
@@ -1687,20 +1670,22 @@ static void iax2_destroy_helper(struct chan_iax2_pvt *pvt)
static int iax2_predestroy(int callno)
{
- struct ast_channel *c;
- struct chan_iax2_pvt *pvt;
+ struct ast_channel *c = NULL;
+ struct chan_iax2_pvt *pvt = NULL;
+
ast_mutex_lock(&iaxsl[callno]);
- pvt = iaxs[callno];
- if (!pvt) {
+
+ if (!(pvt = iaxs[callno])) {
ast_mutex_unlock(&iaxsl[callno]);
return -1;
}
+
if (!ast_test_flag(pvt, IAX_ALREADYGONE)) {
iax2_destroy_helper(pvt);
ast_set_flag(pvt, IAX_ALREADYGONE);
}
- c = pvt->owner;
- if (c) {
+
+ if ((c = pvt->owner)) {
c->_softhangup |= AST_SOFTHANGUP_DEV;
c->tech_pvt = NULL;
ast_queue_hangup(c);
@@ -1708,7 +1693,9 @@ static int iax2_predestroy(int callno)
ast_atomic_fetchadd_int(&usecnt, -1);
ast_update_use_count();
}
+
ast_mutex_unlock(&iaxsl[callno]);
+
return 0;
}
@@ -1723,9 +1710,9 @@ static int iax2_predestroy_nolock(int callno)
static void iax2_destroy(int callno)
{
- struct chan_iax2_pvt *pvt;
- struct iax_frame *cur;
- struct ast_channel *owner;
+ struct chan_iax2_pvt *pvt = NULL;
+ struct iax_frame *cur = NULL;
+ struct ast_channel *owner = NULL;
retry:
ast_mutex_lock(&iaxsl[callno]);
@@ -2096,16 +2083,18 @@ static int iax2_show_stats(int fd, int argc, char *argv[])
static int iax2_show_cache(int fd, int argc, char *argv[])
{
- struct iax2_dpcache *dp;
- char tmp[1024], *pc;
- int s;
- int x,y;
+ struct iax2_dpcache *dp = NULL;
+ char tmp[1024], *pc = NULL;
+ int s, x, y;
struct timeval tv;
+
gettimeofday(&tv, NULL);
- ast_mutex_lock(&dpcache_lock);
- dp = dpcache;
+
+ AST_LIST_LOCK(&dpcache);
+
ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8.8s %s\n", "Peer/Context", "Exten", "Exp.", "Wait.", "Flags");
- while(dp) {
+
+ AST_LIST_TRAVERSE(&dpcache, dp, cache_list) {
s = dp->expiry.tv_sec - tv.tv_sec;
tmp[0] = '\0';
if (dp->flags & CACHE_FLAG_EXISTS)
@@ -2142,9 +2131,10 @@ static int iax2_show_cache(int fd, int argc, char *argv[])
ast_cli(fd, "%-20.20s %-12.12s %-9d %-8d %s\n", pc, dp->exten, s, y, tmp);
else
ast_cli(fd, "%-20.20s %-12.12s %-9.9s %-8d %s\n", pc, dp->exten, "(expired)", y, tmp);
- dp = dp->next;
}
- ast_mutex_unlock(&dpcache_lock);
+
+ AST_LIST_LOCK(&dpcache);
+
return RESULT_SUCCESS;
}
@@ -4198,18 +4188,21 @@ static int iax2_show_firmware(int fd, int argc, char *argv[])
#else /* __FreeBSD__ */
#define FORMAT "%-15.15s %-15d %-15d\n" /* XXX 2.95 ? */
#endif /* __FreeBSD__ */
- struct iax_firmware *cur;
+ struct iax_firmware *cur = NULL;
+
if ((argc != 3) && (argc != 4))
return RESULT_SHOWUSAGE;
- ast_mutex_lock(&waresl.lock);
+
+ AST_LIST_LOCK(&firmwares);
ast_cli(fd, FORMAT2, "Device", "Version", "Size");
- for (cur = waresl.wares;cur;cur = cur->next) {
+ AST_LIST_TRAVERSE(&firmwares, cur, list)
if ((argc == 3) || (!strcasecmp(argv[3], (char *)cur->fwh->devname)))
ast_cli(fd, FORMAT, cur->fwh->devname, ntohs(cur->fwh->version),
(int)ntohl(cur->fwh->datalen));
- }
- ast_mutex_unlock(&waresl.lock);
+
+ AST_LIST_UNLOCK(&firmwares);
+
return RESULT_SUCCESS;
#undef FORMAT
#undef FORMAT2
@@ -5231,15 +5224,12 @@ static int try_transfer(struct chan_iax2_pvt *pvt, struct iax_ies *ies)
static int complete_dpreply(struct chan_iax2_pvt *pvt, struct iax_ies *ies)
{
char exten[256] = "";
- int status = CACHE_FLAG_UNKNOWN;
- int expiry = iaxdefaultdpcache;
- int x;
- int matchmore = 0;
- struct iax2_dpcache *dp, *prev;
+ int status = CACHE_FLAG_UNKNOWN, expiry = iaxdefaultdpcache, x, matchmore = 0;
+ struct iax2_dpcache *dp = NULL;
if (ies->called_number)
ast_copy_string(exten, ies->called_number, sizeof(exten));
-
+
if (ies->dpstatus & IAX_DPSTATUS_EXISTS)
status = CACHE_FLAG_EXISTS;
else if (ies->dpstatus & IAX_DPSTATUS_CANEXIST)
@@ -5247,40 +5237,31 @@ static int complete_dpreply(struct chan_iax2_pvt *pvt, struct iax_ies *ies)
else if (ies->dpstatus & IAX_DPSTATUS_NONEXISTENT)
status = CACHE_FLAG_NONEXISTENT;
- if (ies->dpstatus & IAX_DPSTATUS_IGNOREPAT) {
- /* Don't really do anything with this */
- }
if (ies->refresh)
expiry = ies->refresh;
if (ies->dpstatus & IAX_DPSTATUS_MATCHMORE)
matchmore = CACHE_FLAG_MATCHMORE;
- ast_mutex_lock(&dpcache_lock);
- prev = NULL;
- dp = pvt->dpentries;
- while(dp) {
- if (!strcmp(dp->exten, exten)) {
- /* Let them go */
- if (prev)
- prev->peer = dp->peer;
- else
- pvt->dpentries = dp->peer;
- dp->peer = NULL;
- dp->callno = 0;
- dp->expiry.tv_sec = dp->orig.tv_sec + expiry;
- if (dp->flags & CACHE_FLAG_PENDING) {
- dp->flags &= ~CACHE_FLAG_PENDING;
- dp->flags |= status;
- dp->flags |= matchmore;
- }
- /* Wake up waiters */
- for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
- if (dp->waiters[x] > -1)
- write(dp->waiters[x], "asdf", 4);
- }
- prev = dp;
- dp = dp->peer;
+
+ AST_LIST_LOCK(&dpcache);
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&dpcache, dp, peer_list) {
+ if (strcmp(dp->exten, exten))
+ continue;
+ AST_LIST_REMOVE_CURRENT(&dpcache, peer_list);
+ dp->callno = 0;
+ dp->expiry.tv_sec = dp->orig.tv_sec + expiry;
+ if (dp->flags & CACHE_FLAG_PENDING) {
+ dp->flags &= ~CACHE_FLAG_PENDING;
+ dp->flags |= status;
+ dp->flags |= matchmore;
+ }
+ /* Wake up waiters */
+ for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
+ if (dp->waiters[x] > -1)
+ write(dp->waiters[x], "asdf", 4);
}
- ast_mutex_unlock(&dpcache_lock);
+ AST_LIST_TRAVERSE_SAFE_END
+ AST_LIST_UNLOCK(&dpcache);
+
return 0;
}
@@ -7024,15 +7005,11 @@ retryowner2:
}
}
}
- ast_mutex_lock(&dpcache_lock);
- dp = iaxs[fr->callno]->dpentries;
- while(dp) {
- if (!(dp->flags & CACHE_FLAG_TRANSMITTED)) {
+ AST_LIST_LOCK(&dpcache);
+ AST_LIST_TRAVERSE(&iaxs[fr->callno]->dpentries, dp, peer_list)
+ if (!(dp->flags & CACHE_FLAG_TRANSMITTED))
iax2_dprequest(dp, fr->callno);
- }
- dp = dp->peer;
- }
- ast_mutex_unlock(&dpcache_lock);
+ AST_LIST_UNLOCK(&dpcache);
break;
case IAX_COMMAND_POKE:
/* Send back a pong packet with the original timestamp */
@@ -7607,11 +7584,6 @@ static void *iax2_process_thread(void *data)
}
ast_mutex_unlock(&thread->lock);
- /* If we were signalled, then we are already out of both lists or we are shutting down */
- if (thread->halt) {
- break;
- }
-
/* Add ourselves to the active list now */
AST_LIST_LOCK(&active_list);
AST_LIST_INSERT_HEAD(&active_list, thread, list);
@@ -7655,11 +7627,6 @@ static void *iax2_process_thread(void *data)
}
}
- /* Free our own memory */
- ast_mutex_destroy(&thread->lock);
- ast_cond_destroy(&thread->cond);
- free(thread);
-
return NULL;
}
@@ -8015,17 +7982,17 @@ static void *sched_thread(void *ignore)
ts.tv_sec = tv.tv_sec;
ts.tv_nsec = tv.tv_usec * 1000;
+ pthread_testcancel();
ast_mutex_lock(&sched_lock);
ast_cond_timedwait(&sched_cond, &sched_lock, &ts);
- if (sched_halt == 1)
- break;
ast_mutex_unlock(&sched_lock);
+ pthread_testcancel();
count = ast_sched_runq(sched);
if (count >= 20)
ast_log(LOG_DEBUG, "chan_iax2: ast_sched_runq ran %d scheduled tasks all at once\n", count);
}
- ast_mutex_unlock(&sched_lock);
+
return NULL;
}
@@ -9211,48 +9178,32 @@ static int cache_get_callno_locked(const char *data)
static struct iax2_dpcache *find_cache(struct ast_channel *chan, const char *data, const char *context, const char *exten, int priority)
{
- struct iax2_dpcache *dp, *prev = NULL, *next;
+ struct iax2_dpcache *dp = NULL;
struct timeval tv;
- int x;
- int com[2];
- int timeout;
- int old=0;
- int outfd;
- int abort;
- int callno;
- struct ast_channel *c;
- struct ast_frame *f;
+ int x, com[2], timeout, old = 0, outfd, abort, callno;
+ struct ast_channel *c = NULL;
+ struct ast_frame *f = NULL;
+
gettimeofday(&tv, NULL);
- dp = dpcache;
- while(dp) {
- next = dp->next;
- /* Expire old caches */
+
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&dpcache, dp, cache_list) {
if (ast_tvcmp(tv, dp->expiry) > 0) {
- /* It's expired, let it disappear */
- if (prev)
- prev->next = dp->next;
- else
- dpcache = dp->next;
- if (!dp->peer && !(dp->flags & CACHE_FLAG_PENDING) && !dp->callno) {
- /* Free memory and go again */
- free(dp);
- } else {
- ast_log(LOG_WARNING, "DP still has peer field or pending or callno (flags = %d, peer = %p callno = %d)\n", dp->flags, dp->peer, dp->callno);
- }
- dp = next;
- continue;
+ AST_LIST_REMOVE_CURRENT(&dpcache, cache_list);
+ if ((dp->flags & CACHE_FLAG_PENDING) || dp->callno)
+ ast_log(LOG_WARNING, "DP still has peer field or pending or callno (flags = %d, peer = blah, callno = %d)\n", dp->flags, dp->callno);
+ else
+ free(dp);
+ continue;
}
- /* We found an entry that matches us! */
- if (!strcmp(dp->peercontext, data) && !strcmp(dp->exten, exten))
+ if (!strcmp(dp->peercontext, data) && !strcmp(dp->exten, exten))
break;
- prev = dp;
- dp = next;
}
+ AST_LIST_TRAVERSE_SAFE_END
+
if (!dp) {
/* No matching entry. Create a new one. */
/* First, can we make a callno? */
- callno = cache_get_callno_locked(data);
- if (callno < 0) {
+ if ((callno = cache_get_callno_locked(data)) < 0) {
ast_log(LOG_WARNING, "Unable to generate call for '%s'\n", data);
return NULL;
}
@@ -9266,18 +9217,18 @@ static struct iax2_dpcache *find_cache(struct ast_channel *chan, const char *dat
dp->orig = dp->expiry;
/* Expires in 30 mins by default */
dp->expiry.tv_sec += iaxdefaultdpcache;
- dp->next = dpcache;
dp->flags = CACHE_FLAG_PENDING;
for (x=0;x<sizeof(dp->waiters) / sizeof(dp->waiters[0]); x++)
dp->waiters[x] = -1;
- dpcache = dp;
- dp->peer = iaxs[callno]->dpentries;
- iaxs[callno]->dpentries = dp;
+ /* Insert into the lists */
+ AST_LIST_INSERT_TAIL(&dpcache, dp, cache_list);
+ AST_LIST_INSERT_TAIL(&iaxs[callno]->dpentries, dp, peer_list);
/* Send the request if we're already up */
if (ast_test_flag(&iaxs[callno]->state, IAX_STATE_STARTED))
iax2_dprequest(dp, callno);
ast_mutex_unlock(&iaxsl[callno]);
}
+
/* By here we must have a dp */
if (dp->flags & CACHE_FLAG_PENDING) {
/* Okay, here it starts to get nasty. We need a pipe now to wait
@@ -9299,31 +9250,27 @@ static struct iax2_dpcache *find_cache(struct ast_channel *chan, const char *dat
/* Okay, now we wait */
timeout = iaxdefaulttimeout * 1000;
/* Temporarily unlock */
- ast_mutex_unlock(&dpcache_lock);
+ AST_LIST_UNLOCK(&dpcache);
/* Defer any dtmf */
if (chan)
old = ast_channel_defer_dtmf(chan);
abort = 0;
while(timeout) {
c = ast_waitfor_nandfds(&chan, chan ? 1 : 0, &com[0], 1, NULL, &outfd, &timeout);
- if (outfd > -1) {
+ if (outfd > -1)
+ break;
+ if (!c)
+ continue;
+ if (!(f = ast_read(c))) {
+ abort = 1;
break;
}
- if (c) {
- f = ast_read(c);
- if (f)
- ast_frfree(f);
- else {
- /* Got hung up on, abort! */
- break;
- abort = 1;
- }
- }
+ ast_frfree(f);
}
if (!timeout) {
ast_log(LOG_WARNING, "Timeout waiting for %s exten %s\n", data, exten);
}
- ast_mutex_lock(&dpcache_lock);
+ AST_LIST_LOCK(&dpcache);
dp->waiters[x] = -1;
close(com[1]);
close(com[0]);
@@ -9359,23 +9306,23 @@ static struct iax2_dpcache *find_cache(struct ast_channel *chan, const char *dat
/*! \brief Part of the IAX2 switch interface */
static int iax2_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
{
- struct iax2_dpcache *dp;
int res = 0;
+ struct iax2_dpcache *dp = NULL;
#if 0
ast_log(LOG_NOTICE, "iax2_exists: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
#endif
if ((priority != 1) && (priority != 2))
return 0;
- ast_mutex_lock(&dpcache_lock);
- dp = find_cache(chan, data, context, exten, priority);
- if (dp) {
+
+ AST_LIST_LOCK(&dpcache);
+ if ((dp = find_cache(chan, data, context, exten, priority))) {
if (dp->flags & CACHE_FLAG_EXISTS)
- res= 1;
- }
- ast_mutex_unlock(&dpcache_lock);
- if (!dp) {
+ res = 1;
+ } else {
ast_log(LOG_WARNING, "Unable to make DP cache\n");
}
+ AST_LIST_UNLOCK(&dpcache);
+
return res;
}
@@ -9383,22 +9330,22 @@ static int iax2_exists(struct ast_channel *chan, const char *context, const char
static int iax2_canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
{
int res = 0;
- struct iax2_dpcache *dp;
+ struct iax2_dpcache *dp = NULL;
#if 0
ast_log(LOG_NOTICE, "iax2_canmatch: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
#endif
if ((priority != 1) && (priority != 2))
return 0;
- ast_mutex_lock(&dpcache_lock);
- dp = find_cache(chan, data, context, exten, priority);
- if (dp) {
+
+ AST_LIST_LOCK(&dpcache);
+ if ((dp = find_cache(chan, data, context, exten, priority))) {
if (dp->flags & CACHE_FLAG_CANEXIST)
- res= 1;
- }
- ast_mutex_unlock(&dpcache_lock);
- if (!dp) {
+ res = 1;
+ } else {
ast_log(LOG_WARNING, "Unable to make DP cache\n");
}
+ AST_LIST_UNLOCK(&dpcache);
+
return res;
}
@@ -9406,22 +9353,22 @@ static int iax2_canmatch(struct ast_channel *chan, const char *context, const ch
static int iax2_matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
{
int res = 0;
- struct iax2_dpcache *dp;
+ struct iax2_dpcache *dp = NULL;
#if 0
ast_log(LOG_NOTICE, "iax2_matchmore: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);
#endif
if ((priority != 1) && (priority != 2))
return 0;
- ast_mutex_lock(&dpcache_lock);
- dp = find_cache(chan, data, context, exten, priority);
- if (dp) {
+
+ AST_LIST_LOCK(&dpcache);
+ if ((dp = find_cache(chan, data, context, exten, priority))) {
if (dp->flags & CACHE_FLAG_MATCHMORE)
- res= 1;
- }
- ast_mutex_unlock(&dpcache_lock);
- if (!dp) {
+ res = 1;
+ } else {
ast_log(LOG_WARNING, "Unable to make DP cache\n");
}
+ AST_LIST_UNLOCK(&dpcache);
+
return res;
}
@@ -9431,8 +9378,8 @@ static int iax2_exec(struct ast_channel *chan, const char *context, const char *
char odata[256];
char req[256];
char *ncontext;
- struct iax2_dpcache *dp;
- struct ast_app *dial;
+ struct iax2_dpcache *dp = NULL;
+ struct ast_app *dial = NULL;
#if 0
ast_log(LOG_NOTICE, "iax2_exec: con: %s, exten: %s, pri: %d, cid: %s, data: %s, newstack: %d\n", context, exten, priority, callerid ? callerid : "<unknown>", data, newstack);
#endif
@@ -9447,9 +9394,9 @@ static int iax2_exec(struct ast_channel *chan, const char *context, const char *
return -1;
} else if (priority != 1)
return -1;
- ast_mutex_lock(&dpcache_lock);
- dp = find_cache(chan, data, context, exten, priority);
- if (dp) {
+
+ AST_LIST_LOCK(&dpcache);
+ if ((dp = find_cache(chan, data, context, exten, priority))) {
if (dp->flags & CACHE_FLAG_EXISTS) {
ast_copy_string(odata, data, sizeof(odata));
ncontext = strchr(odata, '/');
@@ -9463,18 +9410,18 @@ static int iax2_exec(struct ast_channel *chan, const char *context, const char *
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Executing Dial('%s')\n", req);
} else {
- ast_mutex_unlock(&dpcache_lock);
+ AST_LIST_UNLOCK(&dpcache);
ast_log(LOG_WARNING, "Can't execute nonexistent extension '%s[@%s]' in data '%s'\n", exten, context, data);
return -1;
}
}
- ast_mutex_unlock(&dpcache_lock);
- dial = pbx_findapp("Dial");
- if (dial) {
+ AST_LIST_UNLOCK(&dpcache);
+
+ if ((dial = pbx_findapp("Dial")))
return pbx_exec(chan, dial, req);
- } else {
+ else
ast_log(LOG_WARNING, "No dial application registered\n");
- }
+
return -1;
}
@@ -9810,6 +9757,13 @@ static struct ast_cli_entry cli_iax2[] = {
#endif /* IAXTESTS */
};
+static void thread_free(struct iax2_thread *thread)
+{
+ ast_mutex_destroy(&thread->lock);
+ ast_cond_destroy(&thread->cond);
+ free(thread);
+}
+
static int __unload_module(void)
{
pthread_t threadid = AST_PTHREADT_NULL;
@@ -9824,7 +9778,6 @@ static int __unload_module(void)
if (schedthreadid != AST_PTHREADT_NULL) {
pthread_cancel(schedthreadid);
ast_mutex_lock(&sched_lock);
- sched_halt = 1;
ast_cond_signal(&sched_cond);
ast_mutex_unlock(&sched_lock);
pthread_join(schedthreadid, NULL);
@@ -9835,9 +9788,10 @@ static int __unload_module(void)
AST_LIST_TRAVERSE_SAFE_BEGIN(&idle_list, thread, list) {
AST_LIST_REMOVE_CURRENT(&idle_list, list);
threadid = thread->threadid;
- thread->halt = 1;
+ pthread_cancel(threadid);
signal_condition(&thread->lock, &thread->cond);
pthread_join(threadid, NULL);
+ thread_free(thread);
}
AST_LIST_TRAVERSE_SAFE_END
AST_LIST_UNLOCK(&idle_list);
@@ -9846,23 +9800,25 @@ static int __unload_module(void)
AST_LIST_TRAVERSE_SAFE_BEGIN(&active_list, thread, list) {
AST_LIST_REMOVE_CURRENT(&active_list, list);
threadid = thread->threadid;
- thread->halt = 1;
+ pthread_cancel(threadid);
signal_condition(&thread->lock, &thread->cond);
pthread_join(threadid, NULL);
+ thread_free(thread);
}
AST_LIST_TRAVERSE_SAFE_END
AST_LIST_UNLOCK(&active_list);
AST_LIST_LOCK(&dynamic_list);
- AST_LIST_TRAVERSE_SAFE_BEGIN(&dynamic_list, thread, list) {
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&dynamic_list, thread, list) {
AST_LIST_REMOVE_CURRENT(&dynamic_list, list);
threadid = thread->threadid;
- thread->halt = 1;
- signal_condition(&thread->lock, &thread->cond);
+ pthread_cancel(threadid);
+ signal_condition(&thread->lock, &thread->cond);
pthread_join(threadid, NULL);
- }
+ thread_free(thread);
+ }
AST_LIST_TRAVERSE_SAFE_END
- AST_LIST_UNLOCK(&dynamic_list);
+ AST_LIST_UNLOCK(&dynamic_list);
ast_netsock_release(netsock);
for (x=0;x<IAX_MAX_CALLS;x++)
@@ -9882,7 +9838,6 @@ static int __unload_module(void)
static int unload_module(void)
{
- ast_mutex_destroy(&waresl.lock);
ast_custom_function_unregister(&iaxpeer_function);
return __unload_module();
}
@@ -9936,8 +9891,6 @@ static int load_module(void)
}
ast_netsock_init(netsock);
-
- ast_mutex_init(&waresl.lock);
ast_cli_register_multiple(cli_iax2, sizeof(cli_iax2) / sizeof(struct ast_cli_entry));