aboutsummaryrefslogtreecommitdiffstats
path: root/channels/chan_iax2.c
diff options
context:
space:
mode:
authorrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2008-12-01 17:45:52 +0000
committerrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2008-12-01 17:45:52 +0000
commit0e6e2a1ffdac811c224ca87dc30ba2e0e9950d9b (patch)
tree7d722bc511bf4277e53ff49dc02352a9ccca341a /channels/chan_iax2.c
parentfa6ffcfebec48156e557e10dde8ff7662f37b153 (diff)
Merged revisions 160004 via svnmerge from
https://origsvn.digium.com/svn/asterisk/trunk ................ r160004 | russell | 2008-12-01 11:34:31 -0600 (Mon, 01 Dec 2008) | 14 lines 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: http://svn.digium.com/svn/asterisk/branches/1.6.1@160006 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels/chan_iax2.c')
-rw-r--r--channels/chan_iax2.c54
1 files changed, 42 insertions, 12 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index db6fab255..c89d18e1d 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -3851,6 +3851,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;
@@ -3863,8 +3885,23 @@ static int iax2_setoption(struct ast_channel *c, int option, void *data, int dat
errno = ENOSYS;
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);
@@ -3875,6 +3912,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)
@@ -4161,17 +4199,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) {