diff --git a/lib/installer-exclude/ice4j.jar b/lib/installer-exclude/ice4j.jar index 6a2d8c0bb..972dc448e 100644 Binary files a/lib/installer-exclude/ice4j.jar and b/lib/installer-exclude/ice4j.jar differ diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/IceUdpTransportManager.java b/src/net/java/sip/communicator/impl/protocol/jabber/IceUdpTransportManager.java index 4e239e4d5..ccdeff9b3 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/IceUdpTransportManager.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/IceUdpTransportManager.java @@ -839,6 +839,11 @@ public synchronized boolean startConnectivityEstablishment( List candidates = transport.getChildExtensionsOfType( CandidatePacketExtension.class); + // Sorts the remote candidates (host < reflexive < relayed) in + // order to create first host, then reflexive, the relayed + // candidates, to be able to set the relative-candidate matching + // the rel-addr/rel-port attribute. + Collections.sort(candidates); if(candidates == null || candidates.size() == 0) { @@ -891,6 +896,17 @@ public synchronized boolean startConnectivityEstablishment( Component component = stream.getComponent(candidate.getComponent()); + TransportAddress relatedAddr = null; + if(candidate.getRelAddr() != null + && candidate.getRelPort() != -1) + { + relatedAddr = new TransportAddress( + candidate.getRelAddr(), + candidate.getRelPort(), + Transport.parse(candidate.getProtocol())); + } + RemoteCandidate relatedCandidate + = component.findRemoteCandidate(relatedAddr); component.addUpdateRemoteCandidate( new RemoteCandidate( new TransportAddress( @@ -902,7 +918,8 @@ public synchronized boolean startConnectivityEstablishment( org.ice4j.ice.CandidateType.parse( candidate.getType().toString()), Integer.toString(candidate.getFoundation()), - candidate.getPriority())); + candidate.getPriority(), + relatedCandidate)); } } @@ -930,6 +947,11 @@ public synchronized boolean startConnectivityEstablishment( List candidates = transport.getChildExtensionsOfType( CandidatePacketExtension.class); + // Sorts the remote candidates (host < reflexive < relayed) in order + // to create first host, then reflexive, the relayed candidates, to + // be able to set the relative-candidate matching the + // rel-addr/rel-port attribute. + Collections.sort(candidates); /* * If we cannot associate an IceMediaStream with the remote content, @@ -979,6 +1001,17 @@ public synchronized boolean startConnectivityEstablishment( Component component = stream.getComponent(candidate.getComponent()); + TransportAddress relatedAddr = null; + if(candidate.getRelAddr() != null + && candidate.getRelPort() != -1) + { + relatedAddr = new TransportAddress( + candidate.getRelAddr(), + candidate.getRelPort(), + Transport.parse(candidate.getProtocol())); + } + RemoteCandidate relatedCandidate + = component.findRemoteCandidate(relatedAddr); component.addRemoteCandidate( new RemoteCandidate( new TransportAddress( @@ -990,7 +1023,8 @@ public synchronized boolean startConnectivityEstablishment( org.ice4j.ice.CandidateType.parse( candidate.getType().toString()), Integer.toString(candidate.getFoundation()), - candidate.getPriority())); + candidate.getPriority(), + relatedCandidate)); startConnectivityEstablishment = true; } } diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/JingleNodesCandidate.java b/src/net/java/sip/communicator/impl/protocol/jabber/JingleNodesCandidate.java index 1241e107c..8e87e0ed9 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/JingleNodesCandidate.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/JingleNodesCandidate.java @@ -57,7 +57,8 @@ public JingleNodesCandidate(TransportAddress transportAddress, transportAddress, parentComponent, CandidateType.RELAYED_CANDIDATE, - CandidateExtendedType.JINGLE_NODE_CANDIDATE); + CandidateExtendedType.JINGLE_NODE_CANDIDATE, + null); setBase(this); setRelayServerAddress(localEndPoint); this.localEndPoint = localEndPoint; diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/P2PTransportManager.java b/src/net/java/sip/communicator/impl/protocol/jabber/P2PTransportManager.java index fbccca15e..d56660e93 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/P2PTransportManager.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/P2PTransportManager.java @@ -126,7 +126,7 @@ public PacketExtension createTransport(IceMediaStream stream) List candidates = component.getLocalCandidates(); - for(Candidate candidate : component.getLocalCandidates()) + for(LocalCandidate candidate : component.getLocalCandidates()) { if(candidate instanceof UPNPCandidate) { @@ -371,6 +371,8 @@ public synchronized boolean startConnectivityEstablishment( candidate.getType().toString()), "0", (long)(candidate.getPreference() * 1000), + // Gingle does not send rel-addr/rel-port infromation. + null, ufrag); component.addUpdateRemoteCandidate(remoteCandidate); @@ -460,6 +462,8 @@ public synchronized boolean startConnectivityEstablishment( candidate.getType().toString()), "0", (long)(candidate.getPreference() * 1000), + // Gingle does not send rel-addr/rel-port infromation. + null, ufrag); component.addRemoteCandidate(remoteCandidate); diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/TransportManagerGTalkImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/TransportManagerGTalkImpl.java index 104927b69..e12a90823 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/TransportManagerGTalkImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/TransportManagerGTalkImpl.java @@ -1074,6 +1074,8 @@ else if(name.equals("video_rtcp")) candidate.getType().toString()), "0", (long)(candidate.getPreference() * 1000), + // Gingle does not send rel-addr/rel-port infromation. + null, ufrag); component.addUpdateRemoteCandidate(remoteCandidate); } @@ -1162,6 +1164,8 @@ else if(name.equals("video_rtcp")) candidate.getType().toString()), "0", (long)(candidate.getPreference() * 1000), + // Gingle does not send rel-addr/rel-port infromation. + null, ufrag); component.addRemoteCandidate(remoteCandidate); startConnectivityEstablishment = true; diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/gtalk/GTalkPacketFactory.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/gtalk/GTalkPacketFactory.java index 19e0df8d8..968c05199 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/gtalk/GTalkPacketFactory.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/gtalk/GTalkPacketFactory.java @@ -285,7 +285,7 @@ else if(name.equals("video_rtp")) List candToRemove = new ArrayList(); List candidates = component.getLocalCandidates(); - for(Candidate candidate : component.getLocalCandidates()) + for(LocalCandidate candidate : component.getLocalCandidates()) { if(candidate instanceof UPNPCandidate) { diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/CandidatePacketExtension.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/CandidatePacketExtension.java index 0d4443677..53a2a70ea 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/CandidatePacketExtension.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/CandidatePacketExtension.java @@ -12,6 +12,7 @@ * @author Emil Ivov */ public class CandidatePacketExtension extends AbstractPacketExtension + implements Comparable { /** * The name of the "candidate" element. @@ -371,4 +372,42 @@ public CandidateType getType() { return CandidateType.valueOf(getAttributeAsString(TYPE_ATTR_NAME)); } + + /** + * Compares this instance with another CandidatePacketExtension by + * preference of type: host < local < prflx < srflx < stun < relay. + * + * @return 0 if the type are equal. -1 if this instance type is preferred. + * Otherwise 1. + */ + public int compareTo(CandidatePacketExtension candidatePacketExtension) + { + // If the types are differents. + if(this.getType() != candidatePacketExtension.getType()) + { + CandidateType[] types = { + CandidateType.host, + CandidateType.local, + CandidateType.prflx, + CandidateType.srflx, + CandidateType.stun, + CandidateType.relay + }; + for(int i = 0; i < types.length; ++i) + { + // this object is preferred. + if(types[i] == this.getType()) + { + return -1; + } + // the candidatePacketExtension is preferred. + else if(types[i] == candidatePacketExtension.getType()) + { + return 1; + } + } + } + // If the types are equal. + return 0; + } }