mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-22 04:43:50 +00:00
Merged revisions 160003 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r160003 | russell | 2008-12-01 11:27:30 -0600 (Mon, 01 Dec 2008) | 6 lines Apply some logic used in iax2_indicate() to iax2_setoption(), as well, since they both have the potential to send control frames in the middle of call setup. We have to wait until we have received a message back from the remote end before we try to send any more frames. Otherwise, the remote end will consider it invalid, and we'll get stuck in an INVAL/VNAK storm. ........ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@160004 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -3939,6 +3939,28 @@ static int iax2_hangup(struct ast_channel *c)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \note expects the pvt to be locked
|
||||
*/
|
||||
static int wait_for_peercallno(struct chan_iax2_pvt *pvt)
|
||||
{
|
||||
unsigned short callno = pvt->callno;
|
||||
|
||||
if (!pvt->peercallno) {
|
||||
/* We don't know the remote side's call number, yet. :( */
|
||||
int count = 10;
|
||||
while (count-- && pvt && !pvt->peercallno) {
|
||||
DEADLOCK_AVOIDANCE(&iaxsl[callno]);
|
||||
pvt = iaxs[callno];
|
||||
}
|
||||
if (!pvt->peercallno) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iax2_setoption(struct ast_channel *c, int option, void *data, int datalen)
|
||||
{
|
||||
struct ast_option_header *h;
|
||||
@@ -3954,8 +3976,23 @@ static int iax2_setoption(struct ast_channel *c, int option, void *data, int dat
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
default:
|
||||
if (!(h = ast_malloc(datalen + sizeof(*h))))
|
||||
{
|
||||
unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
|
||||
struct chan_iax2_pvt *pvt;
|
||||
|
||||
ast_mutex_lock(&iaxsl[callno]);
|
||||
pvt = iaxs[callno];
|
||||
|
||||
if (wait_for_peercallno(pvt)) {
|
||||
ast_mutex_unlock(&iaxsl[callno]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ast_mutex_unlock(&iaxsl[callno]);
|
||||
|
||||
if (!(h = ast_malloc(datalen + sizeof(*h)))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
h->flag = AST_OPTION_FLAG_REQUEST;
|
||||
h->option = htons(option);
|
||||
@@ -3966,6 +4003,7 @@ static int iax2_setoption(struct ast_channel *c, int option, void *data, int dat
|
||||
ast_free(h);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct ast_frame *iax2_read(struct ast_channel *c)
|
||||
@@ -4252,17 +4290,9 @@ static int iax2_indicate(struct ast_channel *c, int condition, const void *data,
|
||||
ast_mutex_lock(&iaxsl[callno]);
|
||||
pvt = iaxs[callno];
|
||||
|
||||
if (!pvt->peercallno) {
|
||||
/* We don't know the remote side's call number, yet. :( */
|
||||
int count = 10;
|
||||
while (count-- && pvt && !pvt->peercallno) {
|
||||
DEADLOCK_AVOIDANCE(&iaxsl[callno]);
|
||||
pvt = iaxs[callno];
|
||||
}
|
||||
if (!pvt->peercallno) {
|
||||
res = -1;
|
||||
goto done;
|
||||
}
|
||||
if (wait_for_peercallno(pvt)) {
|
||||
res = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
switch (condition) {
|
||||
|
Reference in New Issue
Block a user