Fixes issues with DTLS-SRTP.

cusax-fix 4857
Lyubomir Marinov 12 years ago
parent bc8c31a2a5
commit 1d1a2b116a

@ -750,7 +750,7 @@ private void appendStreamEncryptionMethod(
}
else
{
info = "SDES";
info = srtpControl.getSrtpControlType().toString();
}
rtpType = resources.getI18NString(

@ -150,9 +150,9 @@ protected void conferenceFocusChanged(boolean oldValue, boolean newValue)
* @param rdpes the <tt>RtpDescriptionPacketExtension</tt>s which specify
* the <tt>MediaType</tt>s for which colibri (conference) channels are to be
* allocated
* @return a <tt>ColibriConferenceIQ</tt> which describes the allocated colibri
* (conference) channels for the specified <tt>mediaTypes</tt> which are to
* be used by the specified <tt>peer</tt>; otherwise, <tt>null</tt>
* @return a <tt>ColibriConferenceIQ</tt> which describes the allocated
* colibri (conference) channels for the specified <tt>mediaTypes</tt> which
* are to be used by the specified <tt>peer</tt>; otherwise, <tt>null</tt>
*/
public ColibriConferenceIQ createColibriChannels(
CallPeerJabberImpl peer,
@ -172,8 +172,10 @@ public ColibriConferenceIQ createColibriChannels(
if (peerMediaHandler.getMediaHandler() != colibriMediaHandler)
{
for (MediaType mediaType : MediaType.values())
{
if (peerMediaHandler.getStream(mediaType) != null)
return null;
}
}
ProtocolProviderServiceJabberImpl protocolProvider
@ -186,8 +188,11 @@ public ColibriConferenceIQ createColibriChannels(
if ((jitsiVideoBridge == null) || (jitsiVideoBridge.length() == 0))
{
if (logger.isInfoEnabled())
logger.info("Failed to allocate colibri channels: no " +
" videobridge found.");
{
logger.info(
"Failed to allocate colibri channels: no videobridge"
+ " found.");
}
return null;
}
@ -251,22 +256,31 @@ public ColibriConferenceIQ createColibriChannels(
if (response == null)
{
if (logger.isInfoEnabled())
logger.info("Failed to allocate colibri channels: response " +
"is null. Maybe the response timeouted.");
{
logger.info(
"Failed to allocate colibri channels: response is null."
+ " Maybe the response timeouted.");
}
return null;
}
else if (response.getError() != null)
{
if (logger.isInfoEnabled())
logger.info("Failed to allocate colibri channels: " +
response.getError());
{
logger.info(
"Failed to allocate colibri channels: "
+ response.getError());
}
return null;
}
else if (!(response instanceof ColibriConferenceIQ))
{
if (logger.isInfoEnabled())
logger.info("Failed to allocate colibri channels: response is" +
"not a colibri conference");
{
logger.info(
"Failed to allocate colibri channels: response is not a"
+ " colibri conference");
}
return null;
}

@ -2114,10 +2114,10 @@ private ColibriConferenceIQ.Channel getColibriChannel(MediaType mediaType)
if (getPeer().isJitsiVideoBridge()
&& (transportManager instanceof RawUdpTransportManager))
{
channel = ((RawUdpTransportManager) transportManager)
channel
= ((RawUdpTransportManager) transportManager)
.getColibriChannel(mediaType, false /* remote */);
}
return channel;
}
@ -2144,36 +2144,39 @@ public boolean isRemotelyOnHold()
@Override
public void setLocallyOnHold(boolean locallyOnHold)
{
if (!getPeer().isJitsiVideoBridge())
{
super.setLocallyOnHold(locallyOnHold);
}
else
CallPeerJabberImpl peer = getPeer();
if (peer.isJitsiVideoBridge())
{
this.locallyOnHold = locallyOnHold;
if (!locallyOnHold
&& CallPeerState.ON_HOLD_MUTUALLY.equals(getPeer().getState()))
return;
for (MediaType mediaType : MediaType.values())
if (locallyOnHold
|| !CallPeerState.ON_HOLD_MUTUALLY.equals(peer.getState()))
{
ColibriConferenceIQ.Channel channel
for (MediaType mediaType : MediaType.values())
{
ColibriConferenceIQ.Channel channel
= getColibriChannel(mediaType);
if (channel == null)
continue;
MediaDirection direction
= locallyOnHold
? MediaDirection.INACTIVE
: MediaDirection.SENDRECV;
if (channel != null)
{
MediaDirection direction
= locallyOnHold
? MediaDirection.INACTIVE
: MediaDirection.SENDRECV;
getPeer().getCall().setChannelDirection(
channel.getID(),
mediaType,
direction);
peer.getCall().setChannelDirection(
channel.getID(),
mediaType,
direction);
}
}
}
}
else
{
super.setLocallyOnHold(locallyOnHold);
}
}
/**

@ -664,20 +664,20 @@ public void startCandidateHarvest(
*/
protected PacketExtension createTransport(IceMediaStream stream)
{
IceUdpTransportPacketExtension trans
IceUdpTransportPacketExtension transport
= new IceUdpTransportPacketExtension();
Agent iceAgent = stream.getParentAgent();
trans.setUfrag(iceAgent.getLocalUfrag());
trans.setPassword(iceAgent.getLocalPassword());
transport.setUfrag(iceAgent.getLocalUfrag());
transport.setPassword(iceAgent.getLocalPassword());
for(Component component : stream.getComponents())
{
for(Candidate<?> candidate : component.getLocalCandidates())
trans.addCandidate(createCandidate(candidate));
transport.addCandidate(createCandidate(candidate));
}
return trans;
return transport;
}
/**

@ -355,14 +355,14 @@ public MediaStreamTarget getStreamTarget(MediaType mediaType)
* @param local <tt>true</tt> if the <tt>ColibriConferenceIQ.Channel</tt>
* which is to be used locally is to be returned or <tt>false</tt> for the
* one which is to be used remotely
* @return the <tt>ColibriConferenceIQ.Channel</tt> which belongs to a content
* associated with the specified <tt>mediaType</tt> and which is to be used
* in accord with the specified <tt>local</tt> indicator if such a channel
* exists; otherwise, <tt>null</tt>
* @return the <tt>ColibriConferenceIQ.Channel</tt> which belongs to a
* content associated with the specified <tt>mediaType</tt> and which is to
* be used in accord with the specified <tt>local</tt> indicator if such a
* channel exists; otherwise, <tt>null</tt>
*/
ColibriConferenceIQ.Channel getColibriChannel(
MediaType mediaType,
boolean local)
MediaType mediaType,
boolean local)
{
ColibriConferenceIQ.Channel channel = null;
@ -380,7 +380,6 @@ ColibriConferenceIQ.Channel getColibriChannel(
channel = channels.get(local ? 0 : 1);
}
}
return channel;
}
@ -520,15 +519,15 @@ public void startCandidateHarvest(
*/
if (call.getConference().isJitsiVideoBridge())
{
List<RtpDescriptionPacketExtension> descriptions
List<RtpDescriptionPacketExtension> rdpes
= new ArrayList<RtpDescriptionPacketExtension>();
for (ContentPacketExtension cpe : cpes)
{
RtpDescriptionPacketExtension rtpDesc
RtpDescriptionPacketExtension rdpe
= cpe.getFirstChildOfType(
RtpDescriptionPacketExtension.class);
MediaType mediaType = MediaType.parseString(rtpDesc.getMedia());
MediaType mediaType = MediaType.parseString(rdpe.getMedia());
/*
* The existence of a content for the mediaType and regardless
@ -538,24 +537,24 @@ public void startCandidateHarvest(
if ((colibri == null)
|| (colibri.getContent(mediaType.toString()) == null))
{
if (!descriptions.contains(rtpDesc))
descriptions.add(rtpDesc);
if (!rdpes.contains(rdpe))
rdpes.add(rdpe);
}
}
if (!descriptions.isEmpty())
if (!rdpes.isEmpty())
{
/*
* We are about to request the channel allocations for the
* media types found in 'descriptions'. Regardless of the
* response, we do not want to repeat these requests.
* We are about to request the channel allocations for the media
* types found in 'rdpes'. Regardless of the response, we do not
* want to repeat these requests.
*/
if (colibri == null)
colibri = new ColibriConferenceIQ();
for (RtpDescriptionPacketExtension description : descriptions)
colibri.getOrCreateContent(description.getMedia());
for (RtpDescriptionPacketExtension rdpe : rdpes)
colibri.getOrCreateContent(rdpe.getMedia());
ColibriConferenceIQ conferenceResult
= call.createColibriChannels(peer, descriptions);
= call.createColibriChannels(peer, rdpes);
if (conferenceResult != null)
{
@ -579,24 +578,25 @@ else if (!videoBridgeID.equals(conferenceResultID))
{
if (content.getChannel(channelResult.getID())
== null)
{
content.addChannel(channelResult);
}
}
}
}
else
{
/*
* The call fails if createColibriChannels method fails
* this can happen if the conference packet timeouts or
* it can't be build.
* The call fails if the createColibriChannels method fails
* which may happen if the conference packet times out or it
* can't be built.
*/
ProtocolProviderServiceJabberImpl
.throwOperationFailedException(
"Failed to allocate colibri channel.",
OperationFailedException.GENERAL_ERROR,
null,
Logger.getLogger(
RawUdpTransportManager.class));
Logger.getLogger(RawUdpTransportManager.class));
}
}
}

@ -110,17 +110,16 @@ public String toXML()
bldr.append("<").append(getElementName()).append(" ");
if(getNamespace() != null)
bldr.append("xmlns='").append(getNamespace()).append("'");
String namespace = getNamespace();
if(namespace != null)
bldr.append("xmlns='").append(namespace).append("'");
//add the rest of the attributes if any
for(Map.Entry<String, String> entry : attributes.entrySet())
{
bldr.append(" ")
.append(entry.getKey())
.append("='")
.append(entry.getValue())
.append("'");
bldr.append(" ").append(entry.getKey()).append("='")
.append(entry.getValue()).append("'");
}
//add child elements if any

@ -18,6 +18,7 @@
* COnferencing with LIghtweight BRIdging.
*
* @author Lyubomir Marinov
* @author Boris Grozev
*/
public class ColibriConferenceIQ
extends IQ
@ -224,6 +225,12 @@ public void setID(String id)
*/
public static class Channel
{
/**
* The name of the XML attribute of a <tt>channel</tt> which represents
* its direction.
*/
public static final String DIRECTION_ATTR_NAME = "direction";
/**
* The XML element name of a <tt>channel</tt> of a <tt>content</tt> of a
* Jitsi VideoBridge <tt>conference</tt> IQ.
@ -285,10 +292,9 @@ public static class Channel
public static final String SSRC_ELEMENT_NAME = "ssrc";
/**
* The name of the XML attribute of a <tt>channel</tt> which represents
* its direction.
* The direction of the <tt>channel</tt> represented by this instance.
*/
public static final String DIRECTION_ATTR_NAME = "direction";
private MediaDirection direction;
/**
* The number of seconds of inactivity after which the <tt>channel</tt>
@ -330,10 +336,7 @@ public static class Channel
*/
private long[] ssrcs = NO_SSRCS;
/**
* The direction of the <tt>channel</tt> represented by this instance.
*/
private MediaDirection direction;
private IceUdpTransportPacketExtension transport;
/**
* Adds a <tt>payload-type</tt> element defined by XEP-0167: Jingle RTP
@ -390,6 +393,18 @@ public synchronized boolean addSSRC(long ssrc)
return true;
}
/**
* Gets the <tt>direction</tt> of this <tt>Channel</tt>.
*
* @return the <tt>direction</tt> of this <tt>Channel</tt>.
*/
public MediaDirection getDirection()
{
return direction == null
? MediaDirection.SENDRECV
: direction;
}
/**
* Gets the number of seconds of inactivity after which the
* <tt>channel</tt> represented by this instance expires.
@ -474,16 +489,9 @@ public synchronized long[] getSSRCs()
return (ssrcs.length == 0) ? NO_SSRCS : ssrcs.clone();
}
/**
* Gets the <tt>direction</tt> of this <tt>Channel</tt>.
*
* @return the <tt>direction</tt> of this <tt>Channel</tt>.
*/
public MediaDirection getDirection()
public IceUdpTransportPacketExtension getTransport()
{
return direction == null
? MediaDirection.SENDRECV
: direction;
return transport;
}
/**
@ -549,6 +557,17 @@ public synchronized boolean removeSSRC(long ssrc)
}
}
/**
* Sets the <tt>direction</tt> of this <tt>Channel</tt>
*
* @param direction the <tt>MediaDirection</tt> to set the
* <tt>direction</tt> of this <tt>Channel</tt> to.
*/
public void setDirection(MediaDirection direction)
{
this.direction = direction;
}
/**
* Sets the number of seconds of inactivity after which the
* <tt>channel</tt> represented by this instance expires.
@ -632,15 +651,9 @@ public void setSSRCs(long[] ssrcs)
: ssrcs.clone();
}
/**
* Sets the <tt>direction</tt> of this <tt>Channel</tt>
*
* @param direction the <tt>MediaDirection</tt> to set the
* <tt>direction</tt> of this <tt>Channel</tt> to.
*/
public void setDirection(MediaDirection direction)
public void setTransport(IceUdpTransportPacketExtension transport)
{
this.direction = direction;
this.transport = transport;
}
/**
@ -696,7 +709,8 @@ public void toXML(StringBuilder xml)
}
MediaDirection direction = getDirection();
if (direction != null && direction != MediaDirection.SENDRECV)
if ((direction != null) && (direction != MediaDirection.SENDRECV))
{
xml.append(' ').append(DIRECTION_ATTR_NAME).append("='")
.append(direction.toString()).append('\'');
@ -706,8 +720,10 @@ public void toXML(StringBuilder xml)
boolean hasPayloadTypes = (payloadTypes.size() != 0);
long[] ssrcs = getSSRCs();
boolean hasSSRCs = (ssrcs.length != 0);
IceUdpTransportPacketExtension transport = getTransport();
boolean hasTransport = (transport != null);
if (hasPayloadTypes || hasSSRCs)
if (hasPayloadTypes || hasSSRCs || hasTransport)
{
xml.append('>');
if (hasPayloadTypes)
@ -724,6 +740,8 @@ public void toXML(StringBuilder xml)
.append(SSRC_ELEMENT_NAME).append('>');
}
}
if (hasTransport)
xml.append(transport.toXML());
xml.append("</").append(ELEMENT_NAME).append('>');
}
else

@ -18,10 +18,71 @@
* Jitsi VideoBridge extension <tt>ColibriConferenceIQ</tt>.
*
* @author Lyubomir Marinov
* @author Boris Grozev
*/
public class ColibriIQProvider
implements IQProvider
{
private void addChildExtension(
ColibriConferenceIQ.Channel channel,
PacketExtension childExtension)
{
if (childExtension instanceof PayloadTypePacketExtension)
{
PayloadTypePacketExtension payloadType
= (PayloadTypePacketExtension) childExtension;
if ("opus".equals(payloadType.getName())
&& (payloadType.getChannels() != 2))
{
/*
* We only have a Format for opus with 2 channels, because it
* MUST be advertised with 2 channels. Fixing the number of
* channels here allows us to be compatible with agents who
* advertise it with 1 channel.
*/
payloadType.setChannels(2);
}
channel.addPayloadType(payloadType);
}
else if (childExtension instanceof IceUdpTransportPacketExtension)
{
IceUdpTransportPacketExtension transport
= (IceUdpTransportPacketExtension) childExtension;
channel.setTransport(transport);
}
}
private PacketExtension parseExtension(
XmlPullParser parser,
String name,
String namespace)
throws Exception
{
PacketExtensionProvider extensionProvider
= (PacketExtensionProvider)
ProviderManager.getInstance().getExtensionProvider(
name,
namespace);
PacketExtension extension;
if (extensionProvider == null)
{
/*
* No PacketExtensionProvider for the specified name and namespace
* has been registered. Throw away the element.
*/
throwAway(parser, name);
extension = null;
}
else
{
extension = extensionProvider.parseExtension(parser);
}
return extension;
}
/**
* Parses an IQ sub-document and creates an
* <tt>org.jivesoftware.smack.packet.IQ</tt> instance.
@ -51,7 +112,6 @@ public IQ parseIQ(XmlPullParser parser)
boolean done = false;
ColibriConferenceIQ.Channel channel = null;
ColibriConferenceIQ.Content content = null;
PacketExtensionProvider payloadTypePacketExtensionProvider = null;
StringBuilder ssrc = null;
while (!done)
@ -129,19 +189,23 @@ else if (ColibriConferenceIQ.Content.ELEMENT_NAME.equals(
if ((rtcpPort != null) && (rtcpPort.length() != 0))
channel.setRTCPPort(Integer.parseInt(rtcpPort));
String directionStr
String direction
= parser.getAttributeValue(
"" ,
ColibriConferenceIQ.Channel
.DIRECTION_ATTR_NAME);
if (directionStr != null)
if ((direction != null) && (direction.length() != 0))
{
channel.setDirection(
MediaDirection.parseString(directionStr));
MediaDirection.parseString(direction));
}
String expire
= parser.getAttributeValue(
"",
ColibriConferenceIQ.Channel.EXPIRE_ATTR_NAME);
ColibriConferenceIQ.Channel
.EXPIRE_ATTR_NAME);
if ((expire != null) && (expire.length() != 0))
channel.setExpire(Integer.parseInt(expire));
@ -165,55 +229,52 @@ else if (ColibriConferenceIQ.Content.ELEMENT_NAME.equals(
&& (contentName.length() != 0))
content.setName(contentName);
}
else if (PayloadTypePacketExtension.ELEMENT_NAME.equals(
name))
else if (channel != null)
{
/*
* The channel element of the Jitsi VideoBridge protocol
* reuses the payload-type element defined in XEP-0167:
* Jingle RTP Sessions.
*/
if (payloadTypePacketExtensionProvider == null)
{
payloadTypePacketExtensionProvider
= (PacketExtensionProvider)
ProviderManager.getInstance()
.getExtensionProvider(name, namespace);
}
if (payloadTypePacketExtensionProvider == null)
String peName = null;
String peNamespace = null;
if (PayloadTypePacketExtension.ELEMENT_NAME.equals(
name))
{
/*
* Well, the PacketExtensionProvider appears to have
* not been registered. Throw away the payload-type
* element.
* The channel element of the Jitsi VideoBridge
* protocol reuses the payload-type element defined
* in XEP-0167: Jingle RTP Sessions.
*/
while ((XmlPullParser.END_TAG != parser.next())
|| !name.equals(parser.getName()));
peName = name;
peNamespace = namespace;
}
else if (IceUdpTransportPacketExtension.ELEMENT_NAME
.equals(name)
&& IceUdpTransportPacketExtension.NAMESPACE
.equals(parser.getNamespace()))
{
peName = name;
peNamespace
= IceUdpTransportPacketExtension.NAMESPACE;
}
else if (RawUdpTransportPacketExtension.ELEMENT_NAME
.equals(name)
&& RawUdpTransportPacketExtension.NAMESPACE
.equals(parser.getNamespace()))
{
peName = name;
peNamespace
= RawUdpTransportPacketExtension.NAMESPACE;
}
if (peName == null)
{
throwAway(parser, name);
}
else
{
PayloadTypePacketExtension payloadType
= (PayloadTypePacketExtension)
payloadTypePacketExtensionProvider
.parseExtension(parser);
if (payloadType != null)
{
if("opus".equals(payloadType.getName())
&& payloadType.getChannels() != 2)
{
/*
* We only have a Format for opus with 2
* channels, because it MUST be advertised
* with 2 channels.
* Fixing the number of channels here allows
* us to be compatible with agents who
* advertise it with 1 channel.
*/
payloadType.setChannels(2);
}
channel.addPayloadType(payloadType);
}
PacketExtension extension
= parseExtension(parser, peName, peNamespace);
if (extension != null)
addChildExtension(channel, extension);
}
}
break;
@ -235,4 +296,11 @@ else if (PayloadTypePacketExtension.ELEMENT_NAME.equals(
return iq;
}
private void throwAway(XmlPullParser parser, String name)
throws Exception
{
while ((XmlPullParser.END_TAG != parser.next())
|| !name.equals(parser.getName()));
}
}

Loading…
Cancel
Save