summaryrefslogtreecommitdiff
path: root/channels/chan_iax2.c
diff options
context:
space:
mode:
authorRichard Mudgett <rmudgett@digium.com>2015-01-20 16:59:30 +0000
committerRichard Mudgett <rmudgett@digium.com>2015-01-20 16:59:30 +0000
commite4738a59eb7c3b55b096902967cea31e8f842057 (patch)
tree931d3d3f9292a7cc38bc5245c16d94e13178e215 /channels/chan_iax2.c
parent14b8e03dad718a638f50f9de928b85951cb1e0bc (diff)
CHANNEL(peer), chan_iax2, res_fax, SNMP agent: Fix deadlock from reaching across a bridge.
Calling ast_channel_bridge_peer() cannot be done while holding any channel locks. The reported issue hit the deadlock in chan_iax2, but an audit of the ast_channel_bridge_peer() calls found three more locations where the same deadlock can occur. * Made CHANNEL(peer), res_fax, and the SNMP agent not call ast_channel_bridge_peer() with any channel locked. For CHANNEL(peer) I had to rework the logic to not hold the channel lock. * Made chan_iax2 no longer call ast_channel_bridge_peer(). It was done for legacy reasons that no longer apply. * Removed the iax.conf forcejitterbuffer option. It is now always enabled when the jitterbuffer option is enabled. If you put a jitter buffer on a channel it will be on the channel. ASTERISK-24600 #close Reported by: Jeff Collell Review: https://reviewboard.asterisk.org/r/4342/ ........ Merged revisions 430817 from http://svn.asterisk.org/svn/asterisk/branches/13 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@430819 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels/chan_iax2.c')
-rw-r--r--channels/chan_iax2.c64
1 files changed, 8 insertions, 56 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index bb65df460..cc70bfd3a 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -455,7 +455,6 @@ struct iax2_context {
#define IAX_RTCACHEFRIENDS (uint64_t)(1 << 17) /*!< let realtime stay till your reload */
#define IAX_RTUPDATE (uint64_t)(1 << 18) /*!< Send a realtime update */
#define IAX_RTAUTOCLEAR (uint64_t)(1 << 19) /*!< erase me on expire */
-#define IAX_FORCEJITTERBUF (uint64_t)(1 << 20) /*!< Force jitterbuffer, even when bridged to a channel that can take jitter */
#define IAX_RTIGNOREREGEXPIRE (uint64_t)(1 << 21) /*!< When using realtime, ignore registration expiration */
#define IAX_TRUNKTIMESTAMPS (uint64_t)(1 << 22) /*!< Send trunk timestamps */
#define IAX_TRANSFERMEDIA (uint64_t)(1 << 23) /*!< When doing IAX2 transfers, transfer media only */
@@ -3180,7 +3179,7 @@ static int __find_callno(unsigned short callno, unsigned short dcallno, struct a
iaxs[x]->pingid = iax2_sched_add(sched, ping_time * 1000, send_ping, (void *)(long)x);
iaxs[x]->lagid = iax2_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)(long)x);
iaxs[x]->amaflags = amaflags;
- ast_copy_flags64(iaxs[x], &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT);
+ ast_copy_flags64(iaxs[x], &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT);
ast_string_field_set(iaxs[x], accountcode, accountcode);
ast_string_field_set(iaxs[x], mohinterpret, mohinterpret);
ast_string_field_set(iaxs[x], mohsuggest, mohsuggest);
@@ -4191,8 +4190,6 @@ static int schedule_delivery(struct iax_frame *fr, int updatehistory, int fromtr
int type, len;
int ret;
int needfree = 0;
- struct ast_channel *owner = NULL;
- RAII_VAR(struct ast_channel *, bridge, NULL, ast_channel_cleanup);
/*
* Clear fr->af.data if there is no data in the buffer. Things
@@ -4233,45 +4230,6 @@ static int schedule_delivery(struct iax_frame *fr, int updatehistory, int fromtr
return -1;
}
- iax2_lock_owner(fr->callno);
- if (!iaxs[fr->callno]) {
- /* The call dissappeared so discard this frame that we could not send. */
- iax2_frame_free(fr);
- return -1;
- }
- if ((owner = iaxs[fr->callno]->owner)) {
- bridge = ast_channel_bridge_peer(owner);
- }
-
- /* if the user hasn't requested we force the use of the jitterbuffer, and we're bridged to
- * a channel that can accept jitter, then flush and suspend the jb, and send this frame straight through */
- if ( (!ast_test_flag64(iaxs[fr->callno], IAX_FORCEJITTERBUF)) && owner && bridge && (ast_channel_tech(bridge)->properties & AST_CHAN_TP_WANTSJITTER) ) {
- jb_frame frame;
-
- ast_channel_unlock(owner);
-
- /* deliver any frames in the jb */
- while (jb_getall(iaxs[fr->callno]->jb, &frame) == JB_OK) {
- __do_deliver(frame.data);
- /* __do_deliver() can make the call disappear */
- if (!iaxs[fr->callno])
- return -1;
- }
-
- jb_reset(iaxs[fr->callno]->jb);
-
- AST_SCHED_DEL(sched, iaxs[fr->callno]->jbid);
-
- /* deliver this frame now */
- if (tsout)
- *tsout = fr->ts;
- __do_deliver(fr);
- return -1;
- }
- if (owner) {
- ast_channel_unlock(owner);
- }
-
/* insert into jitterbuffer */
/* TODO: Perhaps we could act immediately if it's not droppable and late */
ret = jb_put(iaxs[fr->callno]->jb, fr, type, len, fr->ts,
@@ -4670,7 +4628,7 @@ static int create_addr(const char *peername, struct ast_channel *c, struct ast_s
if (peer->maxms && ((peer->lastms > peer->maxms) || (peer->lastms < 0)))
goto return_unref;
- ast_copy_flags64(cai, peer, IAX_SENDANI | IAX_TRUNK | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT);
+ ast_copy_flags64(cai, peer, IAX_SENDANI | IAX_TRUNK | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT);
cai->maxtime = peer->maxms;
cai->capability = peer->capability;
cai->encmethods = peer->encmethods;
@@ -7977,7 +7935,7 @@ static int check_access(int callno, struct ast_sockaddr *addr, struct iax_ies *i
iaxs[callno]->amaflags = user->amaflags;
if (!ast_strlen_zero(user->language))
ast_string_field_set(iaxs[callno], language, user->language);
- ast_copy_flags64(iaxs[callno], user, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
+ ast_copy_flags64(iaxs[callno], user, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
/* Keep this check last */
if (!ast_strlen_zero(user->dbsecret)) {
char *family, *key=NULL;
@@ -12460,7 +12418,7 @@ static struct ast_channel *iax2_request(const char *type, struct ast_format_cap
memset(&cai, 0, sizeof(cai));
cai.capability = iax2_capability;
- ast_copy_flags64(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
+ ast_copy_flags64(&cai, &globalflags, IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
/* Populate our address from the given */
if (create_addr(pds.peer, NULL, &addr, &cai)) {
@@ -12482,7 +12440,7 @@ static struct ast_channel *iax2_request(const char *type, struct ast_format_cap
}
/* If this is a trunk, update it now */
- ast_copy_flags64(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
+ ast_copy_flags64(iaxs[callno], &cai, IAX_TRUNK | IAX_SENDANI | IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
if (ast_test_flag64(&cai, IAX_TRUNK)) {
int new_callno;
if ((new_callno = make_trunk(callno, 1)) != -1)
@@ -12800,7 +12758,7 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, st
if (peer) {
if (firstpass) {
- ast_copy_flags64(peer, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT);
+ ast_copy_flags64(peer, &globalflags, IAX_USEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT);
peer->encmethods = iax2_encryption;
peer->adsi = adsi;
ast_string_field_set(peer, secret, "");
@@ -12887,8 +12845,6 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, st
ast_set_flags_to64(peer, IAX_NOTRANSFER|IAX_TRANSFERMEDIA, IAX_NOTRANSFER);
} else if (!strcasecmp(v->name, "jitterbuffer")) {
ast_set2_flag64(peer, ast_true(v->value), IAX_USEJITTERBUF);
- } else if (!strcasecmp(v->name, "forcejitterbuffer")) {
- ast_set2_flag64(peer, ast_true(v->value), IAX_FORCEJITTERBUF);
} else if (!strcasecmp(v->name, "host")) {
if (!strcasecmp(v->value, "dynamic")) {
/* They'll register with us */
@@ -13134,7 +13090,7 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v, st
user->calltoken_required = CALLTOKEN_DEFAULT;
ast_string_field_set(user, name, name);
ast_string_field_set(user, language, language);
- ast_copy_flags64(user, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF | IAX_CODEC_USER_FIRST | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT);
+ ast_copy_flags64(user, &globalflags, IAX_USEJITTERBUF | IAX_CODEC_USER_FIRST | IAX_CODEC_NOPREFS | IAX_CODEC_NOCAP | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT);
ast_clear_flag64(user, IAX_HASCALLERID);
ast_string_field_set(user, cid_name, "");
ast_string_field_set(user, cid_num, "");
@@ -13216,8 +13172,6 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v, st
ast_set2_flag64(user, ast_true(v->value), IAX_IMMEDIATE);
} else if (!strcasecmp(v->name, "jitterbuffer")) {
ast_set2_flag64(user, ast_true(v->value), IAX_USEJITTERBUF);
- } else if (!strcasecmp(v->name, "forcejitterbuffer")) {
- ast_set2_flag64(user, ast_true(v->value), IAX_FORCEJITTERBUF);
} else if (!strcasecmp(v->name, "dbsecret")) {
ast_string_field_set(user, dbsecret, v->value);
} else if (!strcasecmp(v->name, "secret")) {
@@ -13430,7 +13384,7 @@ static void set_config_destroy(void)
amaflags = 0;
delayreject = 0;
ast_clear_flag64((&globalflags), IAX_NOTRANSFER | IAX_TRANSFERMEDIA | IAX_USEJITTERBUF |
- IAX_FORCEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
+ IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE);
delete_users();
ao2_callback(callno_limits, OBJ_NODATA, addr_range_delme_cb, NULL);
ao2_callback(calltoken_ignores, OBJ_NODATA, addr_range_delme_cb, NULL);
@@ -13661,8 +13615,6 @@ static int set_config(const char *config_file, int reload, int forced)
}
} else if (!strcasecmp(v->name, "jitterbuffer"))
ast_set2_flag64((&globalflags), ast_true(v->value), IAX_USEJITTERBUF);
- else if (!strcasecmp(v->name, "forcejitterbuffer"))
- ast_set2_flag64((&globalflags), ast_true(v->value), IAX_FORCEJITTERBUF);
else if (!strcasecmp(v->name, "delayreject"))
delayreject = ast_true(v->value);
else if (!strcasecmp(v->name, "allowfwdownload"))