aboutsummaryrefslogtreecommitdiffstats
path: root/channels
diff options
context:
space:
mode:
authorfile <file@f38db490-d61c-443f-a65b-d21fe96a405b>2006-05-03 16:07:03 +0000
committerfile <file@f38db490-d61c-443f-a65b-d21fe96a405b>2006-05-03 16:07:03 +0000
commit30cebe45f2ba83d26df3186e4fb388a0ced000bc (patch)
tree46a5f6da4d34f877284da59ebf849ee61494ba1d /channels
parentf2f9525d91c31184795fdf709a6694c25f39ef00 (diff)
Update chan_iax2 to use linkedlists.h for users and peers. Modify the way get_from_jb and expire_registry works to get rid of certain crash scenarios. Finally - change the way expire_registry works when realtime autoclear is enabled to be a bit more efficient.
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@24422 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels')
-rw-r--r--channels/chan_iax2.c488
1 files changed, 238 insertions, 250 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index f0fab7ab9..960db235b 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -308,8 +308,8 @@ struct iax2_user {
struct ast_codec_pref prefs;
struct ast_ha *ha;
struct iax2_context *contexts;
- struct iax2_user *next;
struct ast_variable *vars;
+ AST_LIST_ENTRY(iax2_user) entry;
};
struct iax2_peer {
@@ -357,7 +357,7 @@ struct iax2_peer {
int smoothing; /*!< Sample over how many units to determine historic ms */
struct ast_ha *ha;
- struct iax2_peer *next;
+ AST_LIST_ENTRY(iax2_peer) entry;
};
#define IAX2_TRUNK_PREFACE (sizeof(struct iax_frame) + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr))
@@ -628,15 +628,9 @@ static struct ast_iax2_queue {
ast_mutex_t lock;
} iaxq;
-static struct ast_user_list {
- struct iax2_user *users;
- ast_mutex_t lock;
-} userl;
+static AST_LIST_HEAD_STATIC(users, iax2_user);
-static struct ast_peer_list {
- struct iax2_peer *peers;
- ast_mutex_t lock;
-} peerl;
+static AST_LIST_HEAD_STATIC(peers, iax2_peer);
static struct ast_firmware_list {
struct iax_firmware *wares;
@@ -1009,14 +1003,18 @@ static int uncompress_subclass(unsigned char csub)
static struct iax2_peer *find_peer(const char *name, int realtime)
{
- struct iax2_peer *peer;
- ast_mutex_lock(&peerl.lock);
- for(peer = peerl.peers; peer; peer = peer->next) {
+ struct iax2_peer *peer = NULL;
+
+ /* Grab peer from linked list */
+ AST_LIST_LOCK(&peers);
+ AST_LIST_TRAVERSE(&peers, peer, entry) {
if (!strcasecmp(peer->name, name)) {
break;
}
}
- ast_mutex_unlock(&peerl.lock);
+ AST_LIST_UNLOCK(&peers);
+
+ /* Now go for realtime if applicable */
if(!peer && realtime)
peer = realtime_peer(name, NULL);
return peer;
@@ -1024,23 +1022,21 @@ static struct iax2_peer *find_peer(const char *name, int realtime)
static int iax2_getpeername(struct sockaddr_in sin, char *host, int len, int lockpeer)
{
- struct iax2_peer *peer;
+ struct iax2_peer *peer = NULL;
int res = 0;
if (lockpeer)
- ast_mutex_lock(&peerl.lock);
- peer = peerl.peers;
- while (peer) {
+ AST_LIST_LOCK(&peers);
+ AST_LIST_TRAVERSE(&peers, peer, entry) {
if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) &&
- (peer->addr.sin_port == sin.sin_port)) {
- ast_copy_string(host, peer->name, len);
- res = 1;
- break;
+ (peer->addr.sin_port == sin.sin_port)) {
+ ast_copy_string(host, peer->name, len);
+ res = 1;
+ break;
}
- peer = peer->next;
}
if (lockpeer)
- ast_mutex_unlock(&peerl.lock);
+ AST_LIST_UNLOCK(&peers);
if (!peer) {
peer = realtime_peer(NULL, &sin);
if (peer) {
@@ -2134,20 +2130,20 @@ static int iax2_show_peer(int fd, int argc, char *argv[])
static char *complete_iax2_show_peer(const char *line, const char *word, int pos, int state)
{
int which = 0;
- struct iax2_peer *p;
+ struct iax2_peer *p = NULL;
char *res = NULL;
int wordlen = strlen(word);
/* 0 - iax2; 1 - show; 2 - peer; 3 - <peername> */
if (pos == 3) {
- ast_mutex_lock(&peerl.lock);
- for (p = peerl.peers ; p ; p = p->next) {
+ AST_LIST_LOCK(&peers);
+ AST_LIST_TRAVERSE(&peers, p, entry) {
if (!strncasecmp(p->name, word, wordlen) && ++which > state) {
res = ast_strdup(p->name);
break;
}
}
- ast_mutex_unlock(&peerl.lock);
+ AST_LIST_UNLOCK(&peers);
}
return res;
@@ -2304,66 +2300,75 @@ static void unwrap_timestamp(struct iax_frame *fr)
#ifdef NEWJB
static int get_from_jb(void *p);
-static void update_jbsched(struct chan_iax2_pvt *pvt) {
- int when;
-
- when = ast_tvdiff_ms(ast_tvnow(), pvt->rxcore);
-
- /* fprintf(stderr, "now = %d, next=%d\n", when, jb_next(pvt->jb)); */
-
- when = jb_next(pvt->jb) - when;
- /* fprintf(stderr, "when = %d\n", when); */
-
- if(pvt->jbid > -1) ast_sched_del(sched, pvt->jbid);
-
- if(when <= 0) {
- /* XXX should really just empty until when > 0.. */
- when = 1;
- }
-
- pvt->jbid = ast_sched_add(sched, when, get_from_jb, (void *)pvt);
-
- /* Signal scheduler thread */
- signal_condition(&sched_lock, &sched_cond);
+static void update_jbsched(struct chan_iax2_pvt *pvt)
+{
+ int when;
+
+ when = ast_tvdiff_ms(ast_tvnow(), pvt->rxcore);
+
+ /* fprintf(stderr, "now = %d, next=%d\n", when, jb_next(pvt->jb)); */
+
+ when = jb_next(pvt->jb) - when;
+ /* fprintf(stderr, "when = %d\n", when); */
+
+ if(pvt->jbid > -1) ast_sched_del(sched, pvt->jbid);
+
+ if(when <= 0) {
+ /* XXX should really just empty until when > 0.. */
+ when = 1;
+ }
+
+ pvt->jbid = ast_sched_add(sched, when, get_from_jb, CALLNO_TO_PTR(pvt->callno));
+
+ /* Signal scheduler thread */
+ signal_condition(&sched_lock, &sched_cond);
}
static void __get_from_jb(void *p)
{
- /* make sure pvt is valid! */
- struct chan_iax2_pvt *pvt = p;
- struct iax_frame *fr;
- jb_frame frame;
- int ret;
- long now;
- long next;
- struct timeval tv;
-
- ast_mutex_lock(&iaxsl[pvt->callno]);
- /* fprintf(stderr, "get_from_jb called\n"); */
- pvt->jbid = -1;
-
- gettimeofday(&tv,NULL);
- /* round up a millisecond since ast_sched_runq does; */
- /* prevents us from spinning while waiting for our now */
- /* to catch up with runq's now */
- tv.tv_usec += 1000;
-
- now = ast_tvdiff_ms(tv, pvt->rxcore);
+ int callno = PTR_TO_CALLNO(p);
+ struct chan_iax2_pvt *pvt = iaxs[callno];
+ struct iax_frame *fr;
+ jb_frame frame;
+ int ret;
+ long now;
+ long next;
+ struct timeval tv;
+
+ /* Make sure we have a valid private structure before going on */
+ ast_mutex_lock(&iaxsl[callno]);
+ pvt = iaxs[callno];
+ if (!pvt) {
+ /* No go! */
+ ast_mutex_unlock(&iaxsl[callno]);
+ return;
+ }
- if(now >= (next = jb_next(pvt->jb))) {
+ /* fprintf(stderr, "get_from_jb called\n"); */
+ pvt->jbid = -1;
+
+ gettimeofday(&tv,NULL);
+ /* round up a millisecond since ast_sched_runq does; */
+ /* prevents us from spinning while waiting for our now */
+ /* to catch up with runq's now */
+ tv.tv_usec += 1000;
+
+ now = ast_tvdiff_ms(tv, pvt->rxcore);
+
+ if(now >= (next = jb_next(pvt->jb))) {
ret = jb_get(pvt->jb,&frame,now,ast_codec_interp_len(pvt->voiceformat));
switch(ret) {
case JB_OK:
/*if(frame.type == JB_TYPE_VOICE && next + 20 != jb_next(pvt->jb)) fprintf(stderr, "NEXT %ld is not %ld+20!\n", jb_next(pvt->jb), next); */
fr = frame.data;
__do_deliver(fr);
- break;
+ break;
case JB_INTERP:
- {
+ {
struct ast_frame af;
-
+
/*if(next + 20 != jb_next(pvt->jb)) fprintf(stderr, "NEXT %ld is not %ld+20!\n", jb_next(pvt->jb), next); */
-
+
/* create an interpolation frame */
/*fprintf(stderr, "Making Interpolation frame\n"); */
af.frametype = AST_FRAME_VOICE;
@@ -2375,28 +2380,28 @@ static void __get_from_jb(void *p)
af.data = NULL;
af.delivery = ast_tvadd(pvt->rxcore, ast_samp2tv(next, 1000));
af.offset=AST_FRIENDLY_OFFSET;
-
+
/* queue the frame: For consistency, we would call __do_deliver here, but __do_deliver wants an iax_frame,
* which we'd need to malloc, and then it would free it. That seems like a drag */
- if (iaxs[pvt->callno] && !ast_test_flag(iaxs[pvt->callno], IAX_ALREADYGONE))
- iax2_queue_frame(pvt->callno, &af);
- }
- break;
+ if (!ast_test_flag(iaxs[callno], IAX_ALREADYGONE))
+ iax2_queue_frame(callno, &af);
+ }
+ break;
case JB_DROP:
/*if(next != jb_next(pvt->jb)) fprintf(stderr, "NEXT %ld is not next %ld!\n", jb_next(pvt->jb), next); */
iax2_frame_free(frame.data);
- break;
+ break;
case JB_NOFRAME:
case JB_EMPTY:
/* do nothing */
- break;
+ break;
default:
/* shouldn't happen */
- break;
+ break;
}
- }
- update_jbsched(pvt);
- ast_mutex_unlock(&iaxsl[pvt->callno]);
+ }
+ update_jbsched(pvt);
+ ast_mutex_unlock(&iaxsl[callno]);
}
static int get_from_jb(void *data)
@@ -2803,10 +2808,9 @@ static struct iax2_peer *realtime_peer(const char *peername, struct sockaddr_in
ast_sched_del(sched, peer->expire);
peer->expire = ast_sched_add(sched, (global_rtautoclear) * 1000, expire_registry, peer);
}
- ast_mutex_lock(&peerl.lock);
- peer->next = peerl.peers;
- peerl.peers = peer;
- ast_mutex_unlock(&peerl.lock);
+ AST_LIST_LOCK(&peers);
+ AST_LIST_INSERT_HEAD(&peers, peer, entry);
+ AST_LIST_UNLOCK(&peers);
if (ast_test_flag(peer, IAX_DYNAMIC))
reg_source_db(peer);
} else {
@@ -2861,10 +2865,9 @@ static struct iax2_user *realtime_user(const char *username)
if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) {
ast_set_flag(user, IAX_RTCACHEFRIENDS);
- ast_mutex_lock(&userl.lock);
- user->next = userl.users;
- userl.users = user;
- ast_mutex_unlock(&userl.lock);
+ AST_LIST_LOCK(&users);
+ AST_LIST_INSERT_HEAD(&users, user, entry);
+ AST_LIST_UNLOCK(&users);
} else {
ast_set_flag(user, IAX_TEMPONLY);
}
@@ -3520,19 +3523,19 @@ static int iax2_write(struct ast_channel *c, struct ast_frame *f);
static int iax2_getpeertrunk(struct sockaddr_in sin)
{
- struct iax2_peer *peer;
+ struct iax2_peer *peer = NULL;
int res = 0;
- ast_mutex_lock(&peerl.lock);
- peer = peerl.peers;
- while(peer) {
+
+ AST_LIST_LOCK(&peers);
+ AST_LIST_TRAVERSE(&peers, peer, entry) {
if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) &&
- (peer->addr.sin_port == sin.sin_port)) {
- res = ast_test_flag(peer, IAX_TRUNK);
- break;
+ (peer->addr.sin_port == sin.sin_port)) {
+ res = ast_test_flag(peer, IAX_TRUNK);
+ break;
}
- peer = peer->next;
}
- ast_mutex_unlock(&peerl.lock);
+ AST_LIST_UNLOCK(&peers);
+
return res;
}
@@ -4270,7 +4273,7 @@ static int iax2_show_users(int fd, int argc, char *argv[])
#define FORMAT "%-15.15s %-20.20s %-15.15s %-15.15s %-5.5s %-5.10s\n"
#define FORMAT2 "%-15.15s %-20.20s %-15.15d %-15.15s %-5.5s %-5.10s\n"
- struct iax2_user *user;
+ struct iax2_user *user = NULL;
char auth[90];
char *pstr = "";
@@ -4288,32 +4291,32 @@ static int iax2_show_users(int fd, int argc, char *argv[])
return RESULT_SHOWUSAGE;
}
- ast_mutex_lock(&userl.lock);
ast_cli(fd, FORMAT, "Username", "Secret", "Authen", "Def.Context", "A/C","Codec Pref");
- for(user=userl.users;user;user=user->next) {
+ AST_LIST_LOCK(&users);
+ AST_LIST_TRAVERSE(&users, user, entry) {
if (havepattern && regexec(&regexbuf, user->name, 0, NULL, 0))
continue;
-
+
if (!ast_strlen_zero(user->secret)) {
ast_copy_string(auth,user->secret,sizeof(auth));
} else if (!ast_strlen_zero(user->inkeys)) {
snprintf(auth, sizeof(auth), "Key: %-15.15s ", user->inkeys);
} else
ast_copy_string(auth, "-no secret-", sizeof(auth));
-
+
if(ast_test_flag(user,IAX_CODEC_NOCAP))
pstr = "REQ Only";
else if(ast_test_flag(user,IAX_CODEC_NOPREFS))
pstr = "Disabled";
else
pstr = ast_test_flag(user,IAX_CODEC_USER_FIRST) ? "Caller" : "Host";
-
+
ast_cli(fd, FORMAT2, user->name, auth, user->authmethods,
- user->contexts ? user->contexts->context : context,
- user->ha ? "Yes" : "No", pstr);
-
+ user->contexts ? user->contexts->context : context,
+ user->ha ? "Yes" : "No", pstr);
+
}
- ast_mutex_unlock(&userl.lock);
+ AST_LIST_UNLOCK(&users);
if (havepattern)
regfree(&regexbuf);
@@ -4335,7 +4338,7 @@ static int __iax2_show_peers(int manager, int fd, struct mansession *s, int argc
#define FORMAT2 "%-15.15s %-15.15s %s %-15.15s %-8s %s %-10s%s"
#define FORMAT "%-15.15s %-15.15s %s %-15.15s %-5d%s %s %-10s%s"
- struct iax2_peer *peer;
+ struct iax2_peer *peer = NULL;
char name[256];
char iabuf[INET_ADDRSTRLEN];
int registeredonly=0;
@@ -4374,12 +4377,14 @@ static int __iax2_show_peers(int manager, int fd, struct mansession *s, int argc
return RESULT_SHOWUSAGE;
}
- ast_mutex_lock(&peerl.lock);
+
if (s)
astman_append(s, FORMAT2, "Name/Username", "Host", " ", "Mask", "Port", " ", "Status", term);
else
ast_cli(fd, FORMAT2, "Name/Username", "Host", " ", "Mask", "Port", " ", "Status", term);
- for (peer = peerl.peers;peer;peer = peer->next) {
+
+ AST_LIST_LOCK(&peers);
+ AST_LIST_TRAVERSE(&peers, peer, entry) {
char nm[20];
char status[20];
char srch[2000];
@@ -4404,31 +4409,31 @@ static int __iax2_show_peers(int manager, int fd, struct mansession *s, int argc
unmonitored_peers++;
ast_copy_string(nm, ast_inet_ntoa(iabuf, sizeof(iabuf), peer->mask), sizeof(nm));
-
+
snprintf(srch, sizeof(srch), FORMAT, name,
- peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)",
- ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
- nm,
- ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ",
- peer->encmethods ? "(E)" : " ", status, term);
-
+ peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)",
+ ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
+ nm,
+ ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ",
+ peer->encmethods ? "(E)" : " ", status, term);
+
if (s)
astman_append(s, FORMAT, name,
- peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)",
- ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
- nm,
- ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ",
- peer->encmethods ? "(E)" : " ", status, term);
+ peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)",
+ ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
+ nm,
+ ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ",
+ peer->encmethods ? "(E)" : " ", status, term);
else
ast_cli(fd, FORMAT, name,
- peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)",
- ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
- nm,
- ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ",
- peer->encmethods ? "(E)" : " ", status, term);
+ peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)",
+ ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
+ nm,
+ ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : " ",
+ peer->encmethods ? "(E)" : " ", status, term);
total_peers++;
}
- ast_mutex_unlock(&peerl.lock);
+ AST_LIST_UNLOCK(&peers);
if (s)
astman_append(s,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term);
@@ -4578,13 +4583,14 @@ static int iax2_show_registry(int fd, int argc, char *argv[])
{
#define FORMAT2 "%-20.20s %-10.10s %-20.20s %8.8s %s\n"
#define FORMAT "%-20.20s %-10.10s %-20.20s %8d %s\n"
- struct iax2_registry *reg;
+ struct iax2_registry *reg = NULL;
+
char host[80];
char perceived[80];
char iabuf[INET_ADDRSTRLEN];
if (argc != 3)
return RESULT_SHOWUSAGE;
- ast_mutex_lock(&peerl.lock);
+ AST_LIST_LOCK(&peers);
ast_cli(fd, FORMAT2, "Host", "Username", "Perceived", "Refresh", "State");
for (reg = registrations;reg;reg = reg->next) {
snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(iabuf, sizeof(iabuf), reg->addr.sin_addr), ntohs(reg->addr.sin_port));
@@ -4595,7 +4601,7 @@ static int iax2_show_registry(int fd, int argc, char *argv[])
ast_cli(fd, FORMAT, host,
reg->username, perceived, reg->refresh, regstate2str(reg->regstate));
}
- ast_mutex_unlock(&peerl.lock);
+ AST_LIST_UNLOCK(&peers);
return RESULT_SUCCESS;
#undef FORMAT
#undef FORMAT2
@@ -4959,7 +4965,7 @@ static int check_access(int callno, struct sockaddr_in *sin, struct iax_ies *ies
/* Start pessimistic */
int res = -1;
int version = 2;
- struct iax2_user *user, *best = NULL;
+ struct iax2_user *user = NULL, *best = NULL;
int bestscore = 0;
int gotcapability=0;
char iabuf[INET_ADDRSTRLEN];
@@ -5014,10 +5020,9 @@ static int check_access(int callno, struct sockaddr_in *sin, struct iax_ies *ies
ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr), version);
return res;
}
- ast_mutex_lock(&userl.lock);
/* Search the userlist for a compatible entry, and fill in the rest */
- user = userl.users;
- while(user) {
+ AST_LIST_LOCK(&users);
+ AST_LIST_TRAVERSE(&users, user, entry) {
if ((ast_strlen_zero(iaxs[callno]->username) || /* No username specified */
!strcmp(iaxs[callno]->username, user->name)) /* Or this username specified */
&& ast_apply_ha(user->ha, sin) /* Access is permitted from this IP */
@@ -5058,9 +5063,8 @@ static int check_access(int callno, struct sockaddr_in *sin, struct iax_ies *ies
}
}
}
- user = user->next;
}
- ast_mutex_unlock(&userl.lock);
+ AST_LIST_UNLOCK(&users);
user = best;
if (!user && !ast_strlen_zero(iaxs[callno]->username)) {
user = realtime_user(iaxs[callno]->username);
@@ -5473,7 +5477,7 @@ static int authenticate(char *challenge, char *secret, char *keyn, int authmetho
static int authenticate_reply(struct chan_iax2_pvt *p, struct sockaddr_in *sin, struct iax_ies *ies, char *override, char *okey)
{
- struct iax2_peer *peer;
+ struct iax2_peer *peer = NULL;
/* Start pessimistic */
int res = -1;
int authmethods = 0;
@@ -5497,23 +5501,21 @@ static int authenticate_reply(struct chan_iax2_pvt *p, struct sockaddr_in *sin,
/* Normal password authentication */
res = authenticate(p->challenge, override, okey, authmethods, &ied, sin, &p->ecx, &p->dcx);
} else {
- ast_mutex_lock(&peerl.lock);
- peer = peerl.peers;
- while(peer) {
+ AST_LIST_LOCK(&peers);
+ AST_LIST_TRAVERSE(&peers, peer, entry) {
if ((ast_strlen_zero(p->peer) || !strcmp(p->peer, peer->name))
- /* No peer specified at our end, or this is the peer */
- && (ast_strlen_zero(peer->username) || (!strcmp(peer->username, p->username)))
- /* No username specified in peer rule, or this is the right username */
- && (!peer->addr.sin_addr.s_addr || ((sin->sin_addr.s_addr & peer->mask.s_addr) == (peer->addr.sin_addr.s_addr & peer->mask.s_addr)))
- /* No specified host, or this is our host */
- ) {
+ /* No peer specified at our end, or this is the peer */
+ && (ast_strlen_zero(peer->username) || (!strcmp(peer->username, p->username)))
+ /* No username specified in peer rule, or this is the right username */
+ && (!peer->addr.sin_addr.s_addr || ((sin->sin_addr.s_addr & peer->mask.s_addr) == (peer->addr.sin_addr.s_addr & peer->mask.s_addr)))
+ /* No specified host, or this is our host */
+ ) {
res = authenticate(p->challenge, peer->secret, peer->outkey, authmethods, &ied, sin, &p->ecx, &p->dcx);
if (!res)
break;
}
- peer = peer->next;
}
- ast_mutex_unlock(&peerl.lock);
+ AST_LIST_UNLOCK(&peers);
if (!peer) {
/* We checked our list and didn't find one. It's unlikely, but possible,
that we're trying to authenticate *to* a realtime peer */
@@ -5830,7 +5832,25 @@ static void prune_peers(void);
static void __expire_registry(void *data)
{
- struct iax2_peer *p = data;
+ char *name = data;
+ struct iax2_peer *p = NULL;
+
+ /* Go through and grab this peer... and if it needs to be removed... then do it */
+ AST_LIST_LOCK(&peers);
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&peers, p, entry) {
+ if (!strcasecmp(p->name, name)) {
+ /* If we are set to auto clear then remove ourselves */
+ if (ast_test_flag(p, IAX_RTAUTOCLEAR))
+ AST_LIST_REMOVE_CURRENT(&peers, entry);
+ break;
+ }
+ }
+ AST_LIST_TRAVERSE_SAFE_END
+ AST_LIST_UNLOCK(&peers);
+
+ /* Peer is already gone for whatever reason */
+ if (!p)
+ return;
ast_log(LOG_DEBUG, "Expiring registration for peer '%s'\n", p->name);
manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", p->name);
@@ -5846,8 +5866,8 @@ static void __expire_registry(void *data)
iax2_regfunk(p->name, 0);
if (ast_test_flag(p, IAX_RTAUTOCLEAR)) {
- ast_set_flag(p, IAX_DELME);
- prune_peers();
+ /* We are already gone from the list, so we can just destroy ourselves */
+ destroy_peer(p);
}
}
@@ -5893,7 +5913,7 @@ static void reg_source_db(struct iax2_peer *p)
if (p->expire > -1)
ast_sched_del(sched, p->expire);
ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
- p->expire = ast_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, (void *)p);
+ p->expire = ast_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, (void *)p->name);
if (iax2_regfunk)
iax2_regfunk(p->name, 1);
register_peer_exten(p, 1);
@@ -5971,7 +5991,7 @@ static int update_registry(char *name, struct sockaddr_in *sin, int callno, char
p->expiry = refresh;
}
if (p->expiry && sin->sin_addr.s_addr)
- p->expire = ast_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, (void *)p);
+ p->expire = ast_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, (void *)p->name);
iax_ie_append_str(&ied, IAX_IE_USERNAME, p->name);
iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(p->zonetag));
if (sin->sin_addr.s_addr) {
@@ -6289,7 +6309,6 @@ static int timing_read(int *id, int fd, short events, void *cbdata)
res = read(fd, buf, sizeof(buf));
if (res < 1) {
ast_log(LOG_WARNING, "Unable to read from timing fd\n");
- ast_mutex_unlock(&peerl.lock);
return 1;
}
}
@@ -6553,7 +6572,7 @@ static int socket_read(int *id, int fd, short events, void *cbdata)
thread->iofd = fd;
thread->iores = recvfrom(fd, thread->buf, sizeof(thread->buf), 0,(struct sockaddr *) &thread->iosin, &len);
if (thread->iores < 0) {
- if (errno != ECONNREFUSED)
+ if (errno != ECONNREFUSED && errno != EAGAIN)
ast_log(LOG_WARNING, "Error: %s\n", strerror(errno));
handle_error();
AST_LIST_LOCK(&idle_list);
@@ -8554,21 +8573,17 @@ static int peer_set_srcaddr(struct iax2_peer *peer, const char *srcaddr)
/*! \brief Create peer structure based on configuration */
static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, int temponly)
{
- struct iax2_peer *peer;
- struct iax2_peer *prev;
+ struct iax2_peer *peer = NULL;
struct ast_ha *oldha = NULL;
int maskfound=0;
int found=0;
- prev = NULL;
- ast_mutex_lock(&peerl.lock);
+
+ AST_LIST_LOCK(&peers);
if (!temponly) {
- peer = peerl.peers;
- while(peer) {
+ AST_LIST_TRAVERSE(&peers, peer, entry) {
if (!strcmp(peer->name, name)) {
break;
}
- prev = peer;
- peer = peer->next;
}
} else
peer = NULL;
@@ -8576,15 +8591,10 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, in
found++;
oldha = peer->ha;
peer->ha = NULL;
- /* Already in the list, remove it and it will be added back (or FREE'd) */
- if (prev) {
- prev->next = peer->next;
- } else {
- peerl.peers = peer->next;
- }
- ast_mutex_unlock(&peerl.lock);
+ AST_LIST_REMOVE(&peers, peer, entry);
+ AST_LIST_UNLOCK(&peers);
} else {
- ast_mutex_unlock(&peerl.lock);
+ AST_LIST_UNLOCK(&peers);
if ((peer = ast_calloc(1, sizeof(*peer)))) {
peer->expire = -1;
peer->pokeexpire = -1;
@@ -8744,7 +8754,7 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, in
/*! \brief Create in-memory user structure from configuration */
static struct iax2_user *build_user(const char *name, struct ast_variable *v, int temponly)
{
- struct iax2_user *prev, *user;
+ struct iax2_user *user = NULL;
struct iax2_context *con, *conl = NULL;
struct ast_ha *oldha = NULL;
struct iax2_context *oldcon = NULL;
@@ -8752,16 +8762,12 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v, in
char *varname = NULL, *varval = NULL;
struct ast_variable *tmpvar = NULL;
- prev = NULL;
- ast_mutex_lock(&userl.lock);
+ AST_LIST_LOCK(&users);
if (!temponly) {
- user = userl.users;
- while(user) {
+ AST_LIST_TRAVERSE(&users, user, entry) {
if (!strcmp(user->name, name)) {
break;
}
- prev = user;
- user = user->next;
}
} else
user = NULL;
@@ -8772,14 +8778,10 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v, in
user->ha = NULL;
user->contexts = NULL;
/* Already in the list, remove it and it will be added back (or FREE'd) */
- if (prev) {
- prev->next = user->next;
- } else {
- userl.users = user->next;
- }
- ast_mutex_unlock(&userl.lock);
+ AST_LIST_REMOVE(&users, user, entry);
+ AST_LIST_UNLOCK(&users);
} else {
- ast_mutex_unlock(&userl.lock);
+ AST_LIST_UNLOCK(&users);
/* This is going to memset'd to 0 in the next block */
user = ast_malloc(sizeof(*user));
}
@@ -8894,16 +8896,15 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v, in
static void delete_users(void)
{
- struct iax2_user *user;
- struct iax2_peer *peer;
+ struct iax2_user *user = NULL;
+ struct iax2_peer *peer = NULL;
struct iax2_registry *reg, *regl;
- ast_mutex_lock(&userl.lock);
- for (user=userl.users;user;) {
+ AST_LIST_LOCK(&users);
+ AST_LIST_TRAVERSE(&users, user, entry)
ast_set_flag(user, IAX_DELME);
- user = user->next;
- }
- ast_mutex_unlock(&userl.lock);
+ AST_LIST_UNLOCK(&users);
+
for (reg = registrations;reg;) {
regl = reg;
reg = reg->next;
@@ -8922,13 +8923,12 @@ static void delete_users(void)
free(regl);
}
registrations = NULL;
- ast_mutex_lock(&peerl.lock);
- for (peer=peerl.peers;peer;) {
- /* Assume all will be deleted, and we'll find out for sure later */
+
+ AST_LIST_LOCK(&peers);
+ AST_LIST_TRAVERSE(&peers, peer, entry)
ast_set_flag(peer, IAX_DELME);
- peer = peer->next;
- }
- ast_mutex_unlock(&peerl.lock);
+ AST_LIST_UNLOCK(&peers);
+
}
static void destroy_user(struct iax2_user *user)
@@ -8944,21 +8944,18 @@ static void destroy_user(struct iax2_user *user)
static void prune_users(void)
{
- struct iax2_user *user, *usernext, *userlast = NULL;
- ast_mutex_lock(&userl.lock);
- for (user=userl.users;user;) {
- usernext = user->next;
+ struct iax2_user *user = NULL;
+
+ AST_LIST_LOCK(&users);
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&users, user, entry) {
if (ast_test_flag(user, IAX_DELME)) {
destroy_user(user);
- if (userlast)
- userlast->next = usernext;
- else
- userl.users = usernext;
- } else
- userlast = user;
- user = usernext;
+ AST_LIST_REMOVE_CURRENT(&users, entry);
+ }
}
- ast_mutex_unlock(&userl.lock);
+ AST_LIST_TRAVERSE_SAFE_END
+ AST_LIST_UNLOCK(&users);
+
}
static void destroy_peer(struct iax2_peer *peer)
@@ -8987,22 +8984,17 @@ static void destroy_peer(struct iax2_peer *peer)
static void prune_peers(void){
/* Prune peers who still are supposed to be deleted */
- struct iax2_peer *peer, *peerlast, *peernext;
- ast_mutex_lock(&peerl.lock);
- peerlast = NULL;
- for (peer=peerl.peers;peer;) {
- peernext = peer->next;
+ struct iax2_peer *peer = NULL;
+
+ AST_LIST_LOCK(&peers);
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&peers, peer, entry) {
if (ast_test_flag(peer, IAX_DELME)) {
destroy_peer(peer);
- if (peerlast)
- peerlast->next = peernext;
- else
- peerl.peers = peernext;
- } else
- peerlast = peer;
- peer=peernext;
+ AST_LIST_REMOVE_CURRENT(&peers, entry);
+ }
}
- ast_mutex_unlock(&peerl.lock);
+ AST_LIST_TRAVERSE_SAFE_END
+ AST_LIST_UNLOCK(&peers);
}
static void set_timing(void)
@@ -9274,19 +9266,17 @@ static int set_config(char *config_file, int reload)
if (!strcasecmp(utype, "user") || !strcasecmp(utype, "friend")) {
user = build_user(cat, ast_variable_browse(cfg, cat), 0);
if (user) {
- ast_mutex_lock(&userl.lock);
- user->next = userl.users;
- userl.users = user;
- ast_mutex_unlock(&userl.lock);
+ AST_LIST_LOCK(&users);
+ AST_LIST_INSERT_HEAD(&users, user, entry);
+ AST_LIST_UNLOCK(&users);
}
}
if (!strcasecmp(utype, "peer") || !strcasecmp(utype, "friend")) {
peer = build_peer(cat, ast_variable_browse(cfg, cat), 0);
if (peer) {
- ast_mutex_lock(&peerl.lock);
- peer->next = peerl.peers;
- peerl.peers = peer;
- ast_mutex_unlock(&peerl.lock);
+ AST_LIST_LOCK(&peers);
+ AST_LIST_INSERT_HEAD(&peers, peer, entry);
+ AST_LIST_UNLOCK(&peers);
if (ast_test_flag(peer, IAX_DYNAMIC))
reg_source_db(peer);
}
@@ -9307,7 +9297,8 @@ static int reload_config(void)
{
char *config = "iax.conf";
struct iax2_registry *reg;
- struct iax2_peer *peer;
+ struct iax2_peer *peer = NULL;
+
ast_copy_string(accountcode, "", sizeof(accountcode));
ast_copy_string(language, "", sizeof(language));
amaflags = 0;
@@ -9322,12 +9313,13 @@ static int reload_config(void)
for (reg = registrations; reg; reg = reg->next)
iax2_do_register(reg);
/* Qualify hosts, too */
- ast_mutex_lock(&peerl.lock);
- for (peer = peerl.peers; peer; peer = peer->next)
+ AST_LIST_LOCK(&peers);
+ AST_LIST_TRAVERSE(&peers, peer, entry)
iax2_poke_peer(peer, 0);
- ast_mutex_unlock(&peerl.lock);
+ AST_LIST_UNLOCK(&peers);
reload_firmware();
iax_provision_reload();
+
return 0;
}
@@ -10035,8 +10027,6 @@ static int __unload_module(void)
static int unload_module(void *mod)
{
ast_mutex_destroy(&iaxq.lock);
- ast_mutex_destroy(&userl.lock);
- ast_mutex_destroy(&peerl.lock);
ast_mutex_destroy(&waresl.lock);
ast_custom_function_unregister(&iaxpeer_function);
return __unload_module();
@@ -10049,8 +10039,8 @@ static int load_module(void *mod)
char *config = "iax.conf";
int res = 0;
int x;
- struct iax2_registry *reg;
- struct iax2_peer *peer;
+ struct iax2_registry *reg = NULL;
+ struct iax2_peer *peer = NULL;
ast_custom_function_register(&iaxpeer_function);
@@ -10091,8 +10081,6 @@ static int load_module(void *mod)
ast_netsock_init(netsock);
ast_mutex_init(&iaxq.lock);
- ast_mutex_init(&userl.lock);
- ast_mutex_init(&peerl.lock);
ast_mutex_init(&waresl.lock);
ast_cli_register_multiple(iax2_cli, sizeof(iax2_cli) / sizeof(iax2_cli[0]));
@@ -10124,13 +10112,13 @@ static int load_module(void *mod)
for (reg = registrations; reg; reg = reg->next)
iax2_do_register(reg);
- ast_mutex_lock(&peerl.lock);
- for (peer = peerl.peers; peer; peer = peer->next) {
+ AST_LIST_LOCK(&peers);
+ AST_LIST_TRAVERSE(&peers, peer, entry) {
if (peer->sockfd < 0)
peer->sockfd = defaultsockfd;
iax2_poke_peer(peer, 0);
}
- ast_mutex_unlock(&peerl.lock);
+ AST_LIST_UNLOCK(&peers);
reload_firmware();
iax_provision_reload();
return res;