[asterisk-commits] file: branch file/chan_jingle2 r365690 - /team/file/chan_jingle2/channels/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue May 8 14:38:05 CDT 2012
Author: file
Date: Tue May 8 14:38:01 2012
New Revision: 365690
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=365690
Log:
Add locking to protect the owner channel since it can be changed during masquerades.
Modified:
team/file/chan_jingle2/channels/chan_jingle2.c
Modified: team/file/chan_jingle2/channels/chan_jingle2.c
URL: http://svnview.digium.com/svn/asterisk/team/file/chan_jingle2/channels/chan_jingle2.c?view=diff&rev=365690&r1=365689&r2=365690
==============================================================================
--- team/file/chan_jingle2/channels/chan_jingle2.c (original)
+++ team/file/chan_jingle2/channels/chan_jingle2.c Tue May 8 14:38:01 2012
@@ -816,6 +816,31 @@
iks_delete(iq);
}
+/*! \brief Helper function which gets the session lock and ultimately channel lock if present */
+static void jingle_get_owner_lock(struct jingle_session *session)
+{
+ while (session->owner && ast_channel_trylock(session->owner)) {
+ ao2_unlock(session);
+ usleep(1);
+ ao2_lock(session);
+ }
+}
+
+/*! \brief Helper function which queues a hangup frame with cause code */
+static void jingle_queue_hangup_with_cause(struct jingle_session *session, int cause)
+{
+ ao2_lock(session);
+
+ jingle_get_owner_lock(session);
+
+ if (session->owner) {
+ ast_queue_hangup_with_cause(session->owner, cause);
+ ast_channel_unlock(session->owner);
+ }
+
+ ao2_unlock(session);
+}
+
/*! \brief Internal function which sends a transport-info message */
static void jingle_send_transport_info(struct jingle_session *session, const char *from)
{
@@ -826,7 +851,7 @@
if (!(iq = iks_new("iq")) ||
!(jingle = iks_new(session->transport == JINGLE_TRANSPORT_GOOGLE_V1 ? "session" : "jingle"))) {
iks_delete(iq);
- ast_queue_hangup_with_cause(session->owner, AST_CAUSE_SWITCH_CONGESTION);
+ jingle_queue_hangup_with_cause(session, AST_CAUSE_SWITCH_CONGESTION);
return;
}
@@ -888,7 +913,7 @@
if (!res) {
ast_aji_send(session->connection, iq);
} else {
- ast_queue_hangup_with_cause(session->owner, AST_CAUSE_SWITCH_CONGESTION);
+ jingle_queue_hangup_with_cause(session, AST_CAUSE_SWITCH_CONGESTION);
}
/* Clean up after ourselves */
@@ -975,7 +1000,7 @@
if (!(iq = iks_new("iq")) ||
!(jingle = iks_new(session->transport == JINGLE_TRANSPORT_GOOGLE_V1 ? "session" : "jingle"))) {
- ast_queue_hangup_with_cause(session->owner, AST_CAUSE_SWITCH_CONGESTION);
+ jingle_queue_hangup_with_cause(session, AST_CAUSE_SWITCH_CONGESTION);
iks_delete(iq);
return;
}
@@ -1057,7 +1082,7 @@
if (!res) {
ast_aji_send(session->connection, iq);
} else {
- ast_queue_hangup_with_cause(session->owner, AST_CAUSE_SWITCH_CONGESTION);
+ jingle_queue_hangup_with_cause(session, AST_CAUSE_SWITCH_CONGESTION);
}
iks_delete(video_transport);
@@ -1100,7 +1125,17 @@
/* If no error occurred they accepted our session-initiate message happily */
if (!error) {
- ast_queue_control(session->owner, AST_CONTROL_PROCEEDING);
+ ao2_lock(session);
+
+ jingle_get_owner_lock(session);
+
+ if (session->owner) {
+ ast_queue_control(session->owner, AST_CONTROL_PROCEEDING);
+ ast_channel_unlock(session->owner);
+ }
+
+ ao2_unlock(session);
+
jingle_send_transport_info(session, iks_find_attrib(pak->x, "from"));
return IKS_FILTER_EAT;
}
@@ -1130,16 +1165,16 @@
session->gone = 0;
} else {
- ast_queue_hangup_with_cause(session->owner, AST_CAUSE_PROTOCOL_ERROR);
+ jingle_queue_hangup_with_cause(session, AST_CAUSE_PROTOCOL_ERROR);
}
} else if (iks_find_with_attrib(error, "service-unavailable", "xmlns", XMPP_STANZAS_NS)) {
- ast_queue_hangup_with_cause(session->owner, AST_CAUSE_CONGESTION);
+ jingle_queue_hangup_with_cause(session, AST_CAUSE_CONGESTION);
} else if (iks_find_with_attrib(error, "resource-constraint", "xmlns", XMPP_STANZAS_NS)) {
- ast_queue_hangup_with_cause(session->owner, AST_CAUSE_REQUESTED_CHAN_UNAVAIL);
+ jingle_queue_hangup_with_cause(session, AST_CAUSE_REQUESTED_CHAN_UNAVAIL);
} else if (iks_find_with_attrib(error, "bad-request", "xmlns", XMPP_STANZAS_NS)) {
- ast_queue_hangup_with_cause(session->owner, AST_CAUSE_PROTOCOL_ERROR);
+ jingle_queue_hangup_with_cause(session, AST_CAUSE_PROTOCOL_ERROR);
} else if (iks_find_with_attrib(error, "remote-server-not-found", "xmlns", XMPP_STANZAS_NS)) {
- ast_queue_hangup_with_cause(session->owner, AST_CAUSE_NO_ROUTE_DESTINATION);
+ jingle_queue_hangup_with_cause(session, AST_CAUSE_NO_ROUTE_DESTINATION);
} else if (iks_find_with_attrib(error, "feature-not-implemented", "xmlns", XMPP_STANZAS_NS)) {
/* Assume that this occurred because the remote side does not support our transport, so drop it down one and try again */
session->transport--;
@@ -1166,10 +1201,10 @@
session->gone = 0;
} else {
/* Otherwise we have exhausted all transports */
- ast_queue_hangup_with_cause(session->owner, AST_CAUSE_FACILITY_NOT_IMPLEMENTED);
+ jingle_queue_hangup_with_cause(session, AST_CAUSE_FACILITY_NOT_IMPLEMENTED);
}
} else {
- ast_queue_hangup_with_cause(session->owner, AST_CAUSE_PROTOCOL_ERROR);
+ jingle_queue_hangup_with_cause(session, AST_CAUSE_PROTOCOL_ERROR);
}
return IKS_FILTER_EAT;
@@ -1222,21 +1257,30 @@
break;
}
- if (session->owner && frame && frame->frametype == AST_FRAME_VOICE &&
- !ast_format_cap_iscompatible(ast_channel_nativeformats(session->owner), &frame->subclass.format)) {
- if (!ast_format_cap_iscompatible(session->jointcap, &frame->subclass.format)) {
- ast_debug(1, "Bogus frame of format '%s' received from '%s'!\n",
- ast_getformatname(&frame->subclass.format), ast_channel_name(session->owner));
- frame = &ast_null_frame;
- } else {
- ast_debug(1, "Oooh, format changed to %s\n",
- ast_getformatname(&frame->subclass.format));
- ast_format_cap_remove_bytype(ast_channel_nativeformats(session->owner), AST_FORMAT_TYPE_AUDIO);
- ast_format_cap_add(ast_channel_nativeformats(session->owner), &frame->subclass.format);
- ast_set_read_format(session->owner, ast_channel_readformat(session->owner));
- ast_set_write_format(session->owner, ast_channel_writeformat(session->owner));
- }
- }
+ ao2_lock(session);
+
+ jingle_get_owner_lock(session);
+
+ if (session->owner) {
+ if (frame && frame->frametype == AST_FRAME_VOICE &&
+ !ast_format_cap_iscompatible(ast_channel_nativeformats(session->owner), &frame->subclass.format)) {
+ if (!ast_format_cap_iscompatible(session->jointcap, &frame->subclass.format)) {
+ ast_debug(1, "Bogus frame of format '%s' received from '%s'!\n",
+ ast_getformatname(&frame->subclass.format), ast_channel_name(session->owner));
+ frame = &ast_null_frame;
+ } else {
+ ast_debug(1, "Oooh, format changed to %s\n",
+ ast_getformatname(&frame->subclass.format));
+ ast_format_cap_remove_bytype(ast_channel_nativeformats(session->owner), AST_FORMAT_TYPE_AUDIO);
+ ast_format_cap_add(ast_channel_nativeformats(session->owner), &frame->subclass.format);
+ ast_set_read_format(session->owner, ast_channel_readformat(session->owner));
+ ast_set_write_format(session->owner, ast_channel_writeformat(session->owner));
+ }
+ }
+ ast_channel_unlock(session->owner);
+ }
+
+ ao2_unlock(session);
return frame;
}
@@ -1282,7 +1326,11 @@
{
struct jingle_session *session = ast_channel_tech_pvt(newchan);
+ ao2_lock(session);
+
session->owner = newchan;
+
+ ao2_unlock(session);
return 0;
}
@@ -1303,7 +1351,7 @@
break;
case AST_CONTROL_BUSY:
if (ast_channel_state(ast) != AST_STATE_UP) {
- ast_channel_hangupcause_set(session->owner, AST_CAUSE_BUSY);
+ ast_channel_hangupcause_set(ast, AST_CAUSE_BUSY);
ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
} else {
res = -1;
@@ -1311,7 +1359,7 @@
break;
case AST_CONTROL_CONGESTION:
if (ast_channel_state(ast) != AST_STATE_UP) {
- ast_channel_hangupcause_set(session->owner, AST_CAUSE_CONGESTION);
+ ast_channel_hangupcause_set(ast, AST_CAUSE_CONGESTION);
ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
} else {
res = -1;
@@ -1319,7 +1367,7 @@
break;
case AST_CONTROL_INCOMPLETE:
if (ast_channel_state(ast) != AST_STATE_UP) {
- ast_channel_hangupcause_set(session->owner, AST_CAUSE_CONGESTION);
+ ast_channel_hangupcause_set(ast, AST_CAUSE_CONGESTION);
ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
}
break;
@@ -1549,7 +1597,6 @@
}
/* We purposely don't decrement the session here as there is a reference on the channel */
-
ao2_link(endpoint->sessions, session);
ao2_ref(endpoint, -1);
@@ -1571,7 +1618,7 @@
if (session->transport != JINGLE_TRANSPORT_GOOGLE_V1) {
/* If this content stanza has no name consider it invalid and move on */
if (ast_strlen_zero(name) && !(name = iks_find_attrib(content, "jin:name"))) {
- ast_queue_hangup_with_cause(session->owner, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
+ jingle_queue_hangup_with_cause(session, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
return;
}
@@ -1600,7 +1647,7 @@
if (session->transport == JINGLE_TRANSPORT_GOOGLE_V1) {
media = "audio";
} else if (ast_strlen_zero(media)) {
- ast_queue_hangup_with_cause(session->owner, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
+ jingle_queue_hangup_with_cause(session, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
return;
}
@@ -1622,7 +1669,7 @@
/* If video is not present cancel this session */
if (!session->vrtp) {
- ast_queue_hangup_with_cause(session->owner, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
+ jingle_queue_hangup_with_cause(session, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
return;
}
@@ -1630,7 +1677,7 @@
ast_format_cap_remove_bytype(session->jointcap, AST_FORMAT_TYPE_VIDEO);
} else {
/* Unknown media type */
- ast_queue_hangup_with_cause(session->owner, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
+ jingle_queue_hangup_with_cause(session, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
return;
}
@@ -1658,7 +1705,7 @@
if (ast_format_cap_is_empty(session->jointcap)) {
/* We have no compatible codecs, so terminate the session appropriately */
- ast_queue_hangup_with_cause(session->owner, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
+ jingle_queue_hangup_with_cause(session, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL);
return;
}
@@ -1669,7 +1716,7 @@
/* If we get past the description handling and we still don't know what RTP instance this is for... it is unknown content */
if (!rtp) {
- ast_queue_hangup_with_cause(session->owner, AST_CAUSE_SWITCH_CONGESTION);
+ jingle_queue_hangup_with_cause(session, AST_CAUSE_SWITCH_CONGESTION);
return;
}
@@ -1680,12 +1727,12 @@
iks *candidate;
if (!ice) {
- ast_queue_hangup_with_cause(session->owner, AST_CAUSE_SWITCH_CONGESTION);
+ jingle_queue_hangup_with_cause(session, AST_CAUSE_SWITCH_CONGESTION);
return;
}
if (ast_strlen_zero(ufrag) || ast_strlen_zero(pwd)) {
- ast_queue_hangup_with_cause(session->owner, AST_CAUSE_PROTOCOL_ERROR);
+ jingle_queue_hangup_with_cause(session, AST_CAUSE_PROTOCOL_ERROR);
return;
}
@@ -1705,14 +1752,14 @@
if (ast_strlen_zero(component) || ast_strlen_zero(foundation) || ast_strlen_zero(generation) || ast_strlen_zero(id) ||
ast_strlen_zero(ip) || ast_strlen_zero(network) || ast_strlen_zero(port) || ast_strlen_zero(priority) ||
ast_strlen_zero(protocol) || ast_strlen_zero(type)) {
- ast_queue_hangup_with_cause(session->owner, AST_CAUSE_PROTOCOL_ERROR);
+ jingle_queue_hangup_with_cause(session, AST_CAUSE_PROTOCOL_ERROR);
return;
}
if ((sscanf(component, "%30u", &local_candidate.id) != 1) ||
(sscanf(priority, "%30u", &local_candidate.priority) != 1) ||
(sscanf(port, "%30d", &real_port) != 1)) {
- ast_queue_hangup_with_cause(session->owner, AST_CAUSE_PROTOCOL_ERROR);
+ jingle_queue_hangup_with_cause(session, AST_CAUSE_PROTOCOL_ERROR);
return;
}
@@ -1758,7 +1805,7 @@
iks *candidate;
if (!ice) {
- ast_queue_hangup_with_cause(session->owner, AST_CAUSE_SWITCH_CONGESTION);
+ jingle_queue_hangup_with_cause(session, AST_CAUSE_SWITCH_CONGESTION);
return;
}
@@ -1790,7 +1837,7 @@
/* If this candidate is incomplete skip it */
if (ast_strlen_zero(address) || ast_strlen_zero(port) || ast_strlen_zero(username) ||
ast_strlen_zero(name)) {
- ast_queue_hangup_with_cause(session->owner, AST_CAUSE_PROTOCOL_ERROR);
+ jingle_queue_hangup_with_cause(session, AST_CAUSE_PROTOCOL_ERROR);
return;
}
@@ -1801,7 +1848,7 @@
/* Parse the target information so we can send a STUN request to the candidate */
if (sscanf(port, "%30d", &real_port) != 1) {
- ast_queue_hangup_with_cause(session->owner, AST_CAUSE_PROTOCOL_ERROR);
+ jingle_queue_hangup_with_cause(session, AST_CAUSE_PROTOCOL_ERROR);
return;
}
ast_sockaddr_parse(&target, address, PARSE_PORT_FORBID);
@@ -1815,7 +1862,7 @@
}
} else if (iks_find(content, "transport")) {
/* If this is a transport we do not support terminate the session as it probably won't work out in the end */
- ast_queue_hangup_with_cause(session->owner, AST_CAUSE_FACILITY_NOT_IMPLEMENTED);
+ jingle_queue_hangup_with_cause(session, AST_CAUSE_FACILITY_NOT_IMPLEMENTED);
changed = 0;
break;
}
@@ -1823,12 +1870,22 @@
/* Update the channel if the formats have changed */
if (changed) {
- struct ast_format fmt;
-
- ast_format_cap_copy(ast_channel_nativeformats(session->owner), session->jointcap);
- ast_codec_choose(&session->prefs, session->jointcap, 1, &fmt);
- ast_set_read_format(session->owner, &fmt);
- ast_set_write_format(session->owner, &fmt);
+ ao2_lock(session);
+
+ jingle_get_owner_lock(session);
+
+ if (session->owner) {
+ struct ast_format fmt;
+
+ ast_format_cap_copy(ast_channel_nativeformats(session->owner), session->jointcap);
+ ast_codec_choose(&session->prefs, session->jointcap, 1, &fmt);
+ ast_set_read_format(session->owner, &fmt);
+ ast_set_write_format(session->owner, &fmt);
+
+ ast_channel_unlock(session->owner);
+ }
+
+ ao2_unlock(session);
}
}
@@ -1894,8 +1951,6 @@
jingle_interpret_content(session, pak);
jingle_send_transport_info(session, iks_find_attrib(pak->x, "from"));
-
- /* Session reference count is purposely not decremented here due to having a reference on the channel */
}
/*! \brief Handler function for the 'transport-info' action */
@@ -1923,9 +1978,16 @@
jingle_interpret_content(session, pak);
+ ao2_lock(session);
+
+ jingle_get_owner_lock(session);
+
if (session->owner) {
ast_queue_control(session->owner, AST_CONTROL_ANSWER);
- }
+ ast_channel_unlock(session->owner);
+ }
+
+ ao2_unlock(session);
jingle_send_response(endpoint->connection, pak);
}
@@ -1938,6 +2000,10 @@
"unknown-session xmlns='urn:xmpp:jingle:errors:1'");
return;
}
+
+ ao2_lock(session);
+
+ jingle_get_owner_lock(session);
if (session->owner) {
if (iks_find_with_attrib(pak->query, "ringing", "xmlns", JINGLE_RTP_INFO_NS)) {
@@ -1950,7 +2016,10 @@
} else if (iks_find_with_attrib(pak->query, "unhold", "xmlns", JINGLE_RTP_INFO_NS)) {
ast_queue_control(session->owner, AST_CONTROL_UNHOLD);
}
+ ast_channel_unlock(session->owner);
}
+
+ ao2_unlock(session);
jingle_send_response(endpoint->connection, pak);
}
@@ -1963,6 +2032,10 @@
"unknown-session xmlns='urn:xmpp:jingle:errors:1'");
return;
}
+
+ ao2_lock(session);
+
+ jingle_get_owner_lock(session);
if (session->owner) {
iks *reason, *text;
@@ -1983,7 +2056,11 @@
ast_queue_hangup_with_cause(session->owner, cause);
session->gone = 1;
- }
+
+ ast_channel_unlock(session->owner);
+ }
+
+ ao2_unlock(session);
jingle_send_response(endpoint->connection, pak);
}
More information about the asterisk-commits
mailing list