|
|
|
@ -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));
|
|
|
|
|
|
|
|
|
|