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 d3280cbf5..318241931 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/IceUdpTransportManager.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/IceUdpTransportManager.java @@ -65,16 +65,6 @@ public class IceUdpTransportManager */ protected final Agent iceAgent; - /** - * Default STUN server address. - */ - protected static final String DEFAULT_STUN_SERVER_ADDRESS = "stun.jitsi.net"; - - /** - * Default STUN server port. - */ - protected static final int DEFAULT_STUN_SERVER_PORT = 3478; - /** * Creates a new instance of this transport manager, binding it to the * specified peer. @@ -86,187 +76,85 @@ public IceUdpTransportManager(CallPeerJabberImpl callPeer) { super(callPeer); iceAgent = createIceAgent(); + + //FIXME: initiator == controlling is only true the first time in a call + //and not for ice restarts. ICE is smart so this isn't breaking anything + //but it still sucks. + iceAgent.setControlling(!callPeer.isInitiator()); + iceAgent.addStateChangeListener(this); } + /** - * Creates the ICE agent that we would be using in this transport manager - * for all negotiation. + * Discovers and returns a list of dynamically obtained (as opposed to + * statically configured) STUN/TURN servers for use with this account. This + * specific implementation would only implement DNS-based discovery on the + * domain of the service that is currently in use. + *
+ * It is meant to later provide additional discovery methods.
+ * XEP-0215 for example.
*
- * @return the ICE agent to use for all the ICE negotiation that this
- * transport manager would be going through
+ * @return
*/
- protected Agent createIceAgent()
+ protected StunCandidateHarvester discoverStunServerForAccount()
{
- long startGatheringHarvesterTime = System.currentTimeMillis();
CallPeerJabberImpl peer = getCallPeer();
ProtocolProviderServiceJabberImpl provider = peer.getProtocolProvider();
NetworkAddressManagerService namSer = getNetAddrMgr();
- boolean atLeastOneStunServer = false;
- Agent agent = namSer.createIceAgent();
-
- /*
- * XEP-0176: the initiator MUST include the ICE-CONTROLLING attribute,
- * the responder MUST include the ICE-CONTROLLED attribute.
- */
- agent.setControlling(!peer.isInitiator());
-
- //we will now create the harvesters
JabberAccountIDImpl accID
= (JabberAccountIDImpl) provider.getAccountID();
- if (accID.isStunServerDiscoveryEnabled())
+ //the default server is supposed to use the same user name and
+ //password as the account itself.
+ String username
+ = org.jivesoftware.smack.util.StringUtils.parseName(
+ provider.getOurJID());
+ String password
+ = JabberActivator.getProtocolProviderFactory().loadPassword(
+ accID);
+ UserCredentials credentials = provider.getUserCredentials();
+
+ if(credentials != null)
+ password = credentials.getPasswordAsString();
+
+ // ask for password if not saved
+ if (password == null)
{
- //the default server is supposed to use the same user name and
- //password as the account itself.
- String username
- = org.jivesoftware.smack.util.StringUtils.parseName(
- provider.getOurJID());
- String password
- = JabberActivator.getProtocolProviderFactory().loadPassword(
- accID);
- UserCredentials credentials = provider.getUserCredentials();
-
- if(credentials != null)
- password = credentials.getPasswordAsString();
-
- // ask for password if not saved
- if (password == null)
+ //create a default credentials object
+ credentials = new UserCredentials();
+ credentials.setUserName(accID.getUserID());
+ //request a password from the user
+ credentials
+ = provider.getAuthority().obtainCredentials(
+ accID.getDisplayName(),
+ credentials,
+ SecurityAuthority.AUTHENTICATION_REQUIRED);
+
+ // in case user has canceled the login window
+ if(credentials == null)
+ return null;
+
+ //extract the password the user passed us.
+ char[] pass = credentials.getPassword();
+
+ // the user didn't provide us a password (i.e. canceled the
+ // operation)
+ if(pass == null)
+ return null;
+ password = new String(pass);
+
+ if (credentials.isPasswordPersistent())
{
- //create a default credentials object
- credentials = new UserCredentials();
- credentials.setUserName(accID.getUserID());
- //request a password from the user
- credentials
- = provider.getAuthority().obtainCredentials(
- accID.getDisplayName(),
- credentials,
- SecurityAuthority.AUTHENTICATION_REQUIRED);
-
- // in case user has canceled the login window
- if(credentials == null)
- return null;
-
- //extract the password the user passed us.
- char[] pass = credentials.getPassword();
-
- // the user didn't provide us a password (i.e. canceled the
- // operation)
- if(pass == null)
- return null;
- password = new String(pass);
-
- if (credentials.isPasswordPersistent())
- {
- JabberActivator.getProtocolProviderFactory()
- .storePassword(accID, password);
- }
- }
-
- StunCandidateHarvester autoHarvester
- = namSer.discoverStunServer(
- accID.getService(),
- StringUtils.getUTF8Bytes(username),
- StringUtils.getUTF8Bytes(password));
-
- if (logger.isInfoEnabled())
- logger.info("Auto discovered harvester is " + autoHarvester);
-
- if (autoHarvester != null)
- {
- atLeastOneStunServer = true;
- agent.addCandidateHarvester(autoHarvester);
+ JabberActivator.getProtocolProviderFactory()
+ .storePassword(accID, password);
}
}
- //now create stun server descriptors for whatever other STUN/TURN
- //servers the user may have set.
- for(StunServerDescriptor desc : accID.getStunServers())
- {
- TransportAddress addr
- = new TransportAddress(
- desc.getAddress(),
- desc.getPort(),
- Transport.UDP);
-
- // if we get STUN server from automatic discovery, it may just
- // be server name (i.e. stun.domain.org) and it may be possible that
- // it cannot be resolved
- if(addr.getAddress() == null)
- {
- logger.info("Unresolved address for " + addr);
- continue;
- }
-
- StunCandidateHarvester harvester;
-
- if(desc.isTurnSupported())
- {
- //Yay! a TURN server
- harvester
- = new TurnCandidateHarvester(
- addr,
- new LongTermCredential(
- desc.getUsername(),
- desc.getPassword()));
- }
- else
- {
- //this is a STUN only server
- harvester = new StunCandidateHarvester(addr);
- }
-
- if (logger.isInfoEnabled())
- logger.info("Adding pre-configured harvester " + harvester);
-
- atLeastOneStunServer = true;
- agent.addCandidateHarvester(harvester);
- }
-
- if(!atLeastOneStunServer && accID.isUseDefaultStunServer())
- {
- /* we have no configured or discovered STUN server so takes the
- * default provided by us if user allows it
- */
- TransportAddress addr
- = new TransportAddress(
- DEFAULT_STUN_SERVER_ADDRESS,
- DEFAULT_STUN_SERVER_PORT,
- Transport.UDP);
-
- agent.addCandidateHarvester(new StunCandidateHarvester(addr));
- }
-
- /* Jingle nodes candidate */
- if(accID.isJingleNodesRelayEnabled())
- {
- /* this method is blocking until Jingle Nodes auto-discovery (if
- * enabled) finished
- */
- SmackServiceNode serviceNode = provider.getJingleNodesServiceNode();
-
- if(serviceNode != null)
- {
- agent.addCandidateHarvester(
- new JingleNodesHarvester(serviceNode));
- }
- }
-
- if(accID.isUPNPEnabled())
- agent.addCandidateHarvester(new UPNPHarvester());
-
- long stopGatheringHarvesterTime = System.currentTimeMillis();
-
- if (logger.isInfoEnabled())
- {
- long gatheringHarvesterTime
- = stopGatheringHarvesterTime - startGatheringHarvesterTime;
-
- logger.info(
- "End gathering harvester within " + gatheringHarvesterTime
- + " ms");
- }
- return agent;
+ return namSer.discoverStunServer(
+ accID.getService(),
+ StringUtils.getUTF8Bytes(username),
+ StringUtils.getUTF8Bytes(password));
}
/**
@@ -603,7 +491,6 @@ public void startCandidateHarvest(
throws OperationFailedException
{
this.cpeList = ourAnswer;
-
super.startCandidateHarvest(theirOffer, ourAnswer, transportInfoSender);
}
@@ -769,19 +656,6 @@ public List
@@ -783,6 +798,22 @@ public static String getICECandidateExtendedType(
return null;
}
+ /**
+ * Discovers and returns a list of dynamically obtained (as opposed to
+ * statically configured) STUN/TURN servers for use with this account. This
+ * specific implementation would only implement DNS-based discovery on the
+ * domain of the service that is currently in use. Protocol-specific
+ * implementations can provide additional discovery methods, such as
+ * XEP-0215 for example.
+ *
+ * @return
+ */
+ protected StunCandidateHarvester discoverStunServerForAccount()
+ {
+ //TODO: add a default implementation here.
+ return null;
+ }
+
/**
* Creates the ICE agent that we would be using in this transport manager
@@ -793,10 +824,98 @@ public static String getICECandidateExtendedType(
*/
protected Agent createIceAgent()
{
- //work in progress
- return null;
+ ProtocolProviderService provider = getCallPeer().getProtocolProvider();
+ NetworkAddressManagerService namSer = getNetAddrMgr();
+ boolean atLeastOneStunServer = false;
+ Agent agent = namSer.createIceAgent();
+
+ //we will now create the harvesters
+ AccountID accID = provider.getAccountID();
+
+ if (accID.isStunServerDiscoveryEnabled())
+ {
+ StunCandidateHarvester autoHarvester
+ = discoverStunServerForAccount();
+
+ if(autoHarvester != null)
+ {
+
+ if (logger.isInfoEnabled())
+ logger.info("Auto discovered harvester: " + autoHarvester);
+
+ if (autoHarvester != null)
+ {
+ atLeastOneStunServer = true;
+ agent.addCandidateHarvester(autoHarvester);
+ }
+ }
+ }
+
+ //now create stun server descriptors for whatever other STUN/TURN
+ //servers the user may have set.
+ for(StunServerDescriptor desc : accID.getStunServers())
+ {
+ TransportAddress addr
+ = new TransportAddress(
+ desc.getAddress(),
+ desc.getPort(),
+ Transport.UDP);
+
+ // if we get STUN server from automatic discovery, it may just
+ // be server name (i.e. stun.domain.org) and it may be possible that
+ // it cannot be resolved
+ if(addr.getAddress() == null)
+ {
+ logger.info("Unresolved address for " + addr);
+ continue;
+ }
+
+ StunCandidateHarvester harvester;
+
+ if(desc.isTurnSupported())
+ {
+ //Yay! a TURN server
+ harvester
+ = new TurnCandidateHarvester(
+ addr,
+ new LongTermCredential(
+ desc.getUsername(),
+ desc.getPassword()));
+ }
+ else
+ {
+ //this is a STUN only server
+ harvester = new StunCandidateHarvester(addr);
+ }
+
+ if (logger.isInfoEnabled())
+ logger.info("Adding pre-configured harvester " + harvester);
+
+ atLeastOneStunServer = true;
+ agent.addCandidateHarvester(harvester);
+ }
+
+ if(!atLeastOneStunServer && accID.isUseDefaultStunServer())
+ {
+ /* we have no configured or discovered STUN server so takes the
+ * default provided by us if user allows it
+ */
+ TransportAddress addr
+ = new TransportAddress(
+ DEFAULT_STUN_SERVER_ADDRESS,
+ DEFAULT_STUN_SERVER_PORT,
+ Transport.UDP);
+
+ agent.addCandidateHarvester(new StunCandidateHarvester(addr));
+ }
+
+ if(accID.isUPNPEnabled())
+ agent.addCandidateHarvester(new UPNPHarvester());
+
+ return agent;
}
+
/**
* Creates an {@link IceMediaStream} with the specified media
* name.
@@ -815,4 +934,16 @@ protected IceMediaStream createIceStream(String media, Agent agent)
{
return null;
}
+
+ /**
+ * Returns a reference to the {@link NetworkAddressManagerService}. This is
+ * only a convenience method.
+ *
+ * @return a reference to the {@link NetworkAddressManagerService}
+ * currently in use in our environment.
+ */
+ public static NetworkAddressManagerService getNetAddrMgr()
+ {
+ return ProtocolMediaActivator.getNetworkAddressManagerService();
+ }
}