[ice4j] r158 committed - Adds methods for discovering a local candidate based on a TransportAdd...

ice4j at googlecode.com ice4j at googlecode.com
Thu Apr 29 00:35:36 CEST 2010


Revision: 158
Author: emcho at sip-communicator.org
Date: Wed Apr 28 15:30:53 2010
Log: Adds methods for discovering a local candidate based on a  
TransportAddress
http://code.google.com/p/ice4j/source/detail?r=158

Deleted:
  /trunk/src/org/ice4j/ice/ConnectivityCheckClient.java
  /trunk/src/org/ice4j/ice/ConnectivityCheckServer.java
Modified:
  /trunk/src/org/ice4j/ice/Agent.java
  /trunk/src/org/ice4j/ice/CheckList.java
  /trunk/src/org/ice4j/ice/Component.java
  /trunk/src/org/ice4j/ice/IceMediaStream.java
  /trunk/src/org/ice4j/ice/checks/RemoteAddressHandler.java

=======================================
--- /trunk/src/org/ice4j/ice/ConnectivityCheckClient.java	Tue Apr 27  
16:32:34 2010
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * ice4j, the OpenSource Java Solution for NAT and Firewall Traversal.
- * Maintained by the SIP Communicator community  
(http://sip-communicator.org).
- *
- * Distributable under LGPL license. See terms of license at gnu.org.
- */
-package org.ice4j.ice;
-
-import java.net.*;
-import java.util.logging.*;
-
-import org.ice4j.*;
-import org.ice4j.attribute.*;
-import org.ice4j.message.*;
-import org.ice4j.stack.*;
-
-/**
- * @author Emil Ivov
- */
-public class ConnectivityCheckClient
-    implements ResponseCollector
-{
-    /**
-     * The <tt>Logger</tt> used by the <tt>ConnectivityCheckClient</tt>
-     * class and its instances for logging output.
-     */
-    private static final Logger logger = Logger
-                    .getLogger(ConnectivityCheckClient.class.getName());
-
-    /**
-     * The agent that created us.
-     */
-    private final Agent parentAgent;
-
-    /**
-     * The stun stack that we will use for connectivity checks.
-     */
-    StunStack stunStack = StunStack.getInstance();
-
-    /**
-     * Creates a new <tt>ConnectivityCheckHandler</tt> setting
-     * <tt>parentAgent</tt> as the agent that will be used for retrieving
-     * information such as user fragments for example.
-     *
-     * @param parentAgent the <tt>Agent</tt> that is creating this  
instance.
-     */
-    public ConnectivityCheckClient(Agent parentAgent)
-    {
-        this.parentAgent = parentAgent;
-    }
-
-    public void startChecks(CheckList checkList)
-    {
-        for(CandidatePair pair : checkList)
-        {
-            startCheckForPair(pair);
-        }
-    }
-
-
-    private void startCheckForPair(CandidatePair pair)
-    {
-        //we don't need to do a canReach() verification here as it has been
-        //already verified during the gathering process.
-        DatagramSocket stunSocket =  
((HostCandidate)pair.getLocalCandidate())
-            .getStunSocket(null);
-
-        Request request = MessageFactory.createBindingRequest();
-
-        //priority
-        PriorityAttribute priority =  
AttributeFactory.createPriorityAttribute(
-            pair.getLocalCandidate().computePriorityForType(
-                            CandidateType.PEER_REFLEXIVE_CANDIDATE));
-
-        request.addAttribute(priority);
-
-        //controlling controlled
-        if (parentAgent.isControlling())
-        {
-            request.addAttribute(AttributeFactory
-                            .createIceControllingAttribute(parentAgent
-                                            .getTieBreaker()));
-        }
-        else
-        {
-            request.addAttribute(AttributeFactory
-                            .createIceControlledAttribute(parentAgent
-                                            .getTieBreaker()));
-        }
-
-        //credentials
-        String localUserName = parentAgent.generateLocalUserName();
-        UsernameAttribute unameAttr =  
AttributeFactory.createUsernameAttribute(
-                        localUserName);
-
-        request.addAttribute(unameAttr);
-
-        //todo: do this in the stun stack so that we could do the
-        //calculation once the request is ready (we'd need the transaction  
id
-        //for example.
-        //todo: also implement SASL prepare
-        MessageIntegrityAttribute msgIntegrity = AttributeFactory
-            .createMessageIntegrityAttribute(localUserName);
-
-
-        request.addAttribute(msgIntegrity);
-
-        TransactionID tran;
-
-        try
-        {
-            tran = stunStack.sendRequest(request,
-                    pair.getRemoteCandidate().getTransportAddress(),  
stunSocket,
-                    this);
-System.out.println("checking pair " + pair + " with tran=" +  
tran.toString());
-        }
-        catch (Exception exception)
-        {
-            logger.log( Level.INFO,
-                        "Failed to send " + request + " through "
-                        + stunSocket.getLocalSocketAddress(),
-                        exception);
-            return;
-        }
-    }
-
-    public void processResponse(StunMessageEvent response)
-    {
-    }
-
-    public void processTimeout(StunTimeoutEvent event)
-    {
-        System.out.println("timeout event=" + event);
-    }
-
-    public void processUnreachable(StunFailureEvent event)
-    {
-        System.out.println("failure event=" + event);
-    }
-
-
-}
=======================================
--- /trunk/src/org/ice4j/ice/ConnectivityCheckServer.java	Tue Apr 27  
16:32:34 2010
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * ice4j, the OpenSource Java Solution for NAT and Firewall Traversal.
- * Maintained by the SIP Communicator community  
(http://sip-communicator.org).
- *
- * Distributable under LGPL license. See terms of license at gnu.org.
- */
-package org.ice4j.ice;
-
-import java.util.logging.*;
-
-import org.ice4j.*;
-import org.ice4j.attribute.*;
-import org.ice4j.message.*;
-import org.ice4j.security.*;
-import org.ice4j.stack.*;
-/**
- * @author Emil Ivov
- */
-public class ConnectivityCheckServer
-    implements RequestListener,
-               CredentialsAuthority
-{
-    /**
-     * The <tt>Logger</tt> used by the <tt>ConnectivityCheckServer</tt>
-     * class and its instances for logging output.
-     */
-    private static final Logger logger = Logger
-                    .getLogger(ConnectivityCheckServer.class.getName());
-
-    /**
-     * The agent that created us.
-     */
-    private final Agent parentAgent;
-
-    /**
-     * The stun stack that we will use for connectivity checks.
-     */
-    StunStack stunStack = StunStack.getInstance();
-
-    /**
-     * Creates a new <tt>ConnectivityCheckServer</tt> setting
-     * <tt>parentAgent</tt> as the agent that will be used for retrieving
-     * information such as user fragments for example.
-     *
-     * @param parentAgent the <tt>Agent</tt> that is creating this  
instance.
-     */
-    public ConnectivityCheckServer(Agent parentAgent)
-    {
-        this.parentAgent = parentAgent;
-        stunStack.addRequestListener(this);
-        stunStack.getCredentialsManager().registerAuthority(this);
-    }
-
-    public void requestReceived(StunMessageEvent evt)
-    {
-        Request request = (Request)evt.getMessage();
-
-        //ignore incoming requests that are not meant for the local user.
-        //normally the stack will get rid of faulty user names but we could
-        //still see messages not meant for this server if both peers or  
running
-        //on this same instance of the stack.
-        UsernameAttribute uname = (UsernameAttribute)request
-            .getAttribute(Attribute.USERNAME);
-
-        if(uname == null
-           || !checkLocalUserName(new String(uname.getUsername())))
-        {
-            return;
-        }
-
-        //check message integrity.
-        Response response = MessageFactory.createBindingResponse(
-                        request, evt.getRemoteAddress());
-        try
-        {
-             
stunStack.sendResponse(evt.getTransactionID().getTransactionID(),
-                response, evt.getLocalAddress(), evt.getRemoteAddress());
-        }
-        catch (Exception e)
-        {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
-        }
-    }
-
-    /**
-     * Verifies whether <tt>username</tt> is currently known to this server
-     * and returns <tt>true</tt> if so. Returns <tt>false</tt> otherwise.
-     *
-     * @param username the user name whose validity we'd like to check.
-     *
-     * @return <tt>true</tt> if <tt>username</tt> is known to this
-     * <tt>ConnectivityCheckServer</tt> and <tt>false</tt> otherwise.
-     */
-    public boolean checkLocalUserName(String username)
-    {
-        boolean accept = false;
-        int colon = username.indexOf(":");
-        if( colon < 0)
-        {
-            //caller gave us a ufrag
-            if(username.equals(parentAgent.getLocalUfrag()))
-                accept = true;
-        }
-        else
-        {
-            //caller gave us the entire username.
-            if(username.substring(0,  
colon).equals(parentAgent.getLocalUfrag()))
-                accept = true;
-        }
-        return accept;
-    }
-
-    /**
-     * Implements the {@link CredentialsAuthority#getLocalKey(String)}  
method in a
-     * way that would return this handler's parent agent password if
-     * <tt>username</tt> is either the local ufrag or the username that the
-     * agent's remote peer was expected to use.
-     *
-     * @param username the local ufrag that we should return a password  
for.
-     *
-     * @return this handler's parent agent local password if  
<tt>username</tt>
-     * equals the local ufrag and <tt>null</tt> otherwise.
-     */
-    public byte[] getLocalKey(String username)
-    {
-        //support both the case where username is the local fragment or the
-        //entire user name.
-        int colon = username.indexOf(":");
-        if( colon < 0)
-        {
-            //caller gave us a ufrag
-            if (username.equals(parentAgent.getLocalUfrag()))
-                return parentAgent.getLocalPassword().getBytes();
-        }
-        else
-        {
-            //caller gave us the entire username.
-            if(username.substring(0,  
colon).equals(parentAgent.getLocalUfrag()))
-                return parentAgent.getLocalPassword().getBytes();
-        }
-
-        return null;
-    }
-
-    /**
-     * Implements the {@link CredentialsAuthority#getRemoteKey(String)}  
method
-     * in a way that would return this handler's parent agent remote  
password if
-     * <tt>username</tt> is either the remote ufrag or the username that we
-     * are expected to use when querying the remote peer.
-     *
-     * @param username the remote ufrag that we should return a password  
for.
-     *
-     * @return this handler's parent agent remote password if  
<tt>username</tt>
-     * equals the remote ufrag and <tt>null</tt> otherwise.
-     */
-    public byte[] getRemoteKey(String username)
-    {
-        //support both the case where username is the local fragment or the
-        //entire user name.
-        int colon = username.indexOf(":");
-        if( colon < 0)
-        {
-            //caller gave us a ufrag
-            if (username.equals(parentAgent.getRemoteUfrag()))
-                return parentAgent.getRemotePassword().getBytes();
-        }
-        else
-        {
-            //caller gave us the entire username.
-            if (username.equals(parentAgent.generateLocalUserName()))
-                return parentAgent.getRemotePassword().getBytes();
-        }
-
-        return null;
-    }
-}
=======================================
--- /trunk/src/org/ice4j/ice/Agent.java	Tue Apr 27 16:32:34 2010
+++ /trunk/src/org/ice4j/ice/Agent.java	Wed Apr 28 15:30:53 2010
@@ -15,10 +15,11 @@
  import java.util.logging.*;

  import org.ice4j.*;
+import org.ice4j.ice.checks.*;
  import org.ice4j.ice.harvest.*;

  /**
- * An IceAgent could be described as the main class (i.e. the chef  
d'orchestre)
+ * An <tt>Agent</tt> could be described as the main class (i.e. the chef  
d'orchestre)
   * of an ICE implementation.
   * <p>
   * As defined in RFC 3264, an agent is the protocol implementation  
involved in
@@ -27,9 +28,9 @@
   * <p>
   *
   * @author Emil Ivov
- * @author Namal Senarathne
   */
  public class Agent
+    implements RemoteAddressHandler
  {
      /**
       * Our class logger.
@@ -68,7 +69,29 @@
       * we assign within a session (i.e. the entire life time of an
       * <tt>Agent</tt>)
       */
-    private FoundationsRegistry foundationsRegistry = new  
FoundationsRegistry();
+    private final FoundationsRegistry foundationsRegistry
+                                          = new FoundationsRegistry();
+
+    /**
+     * The <tt>triggeredCheckQueue</tt> is a FIFO queue containing  
candidate
+     * pairs for which checks are to be sent at the next available  
opportunity.
+     * A pair would get into a triggered check queue as soon as we receive
+     * a check on its local candidate.
+     */
+    private final List<CandidatePair> triggeredCheckQueue
+                                          = new Vector<CandidatePair>();
+
+    /**
+     * The <tt>List</tt> of remote addresses that we have discovered  
through
+     * incoming connectivity checks, before actually receiving a session
+     * description from the peer and that may potentially contain peer  
reflexive
+     * addresses. This list is stored and only if and while connectivity  
checks
+     * are not running. Once they start, we are able to determine whether  
the
+     * addresses in here are actually peer-reflexive or not, and schedule
+     * the necessary triggered checks.
+     */
+    private final List<RemoteCandidate> preDiscoveredRemoteCandidatesQueue
+        = new Vector<RemoteCandidate>();

      /**
       * The user fragment that we should use for the ice-ufrag attribute.
@@ -105,14 +128,25 @@
      /**
       * The entity that will be taking care of outgoing connectivity checks.
       */
-    private final ConnectivityCheckClient connCheckHandler
+    private final ConnectivityCheckClient connCheckClient
                                  = new ConnectivityCheckClient(this);

      /**
       * The entity that will be taking care of incoming connectivity checks.
       */
      private final ConnectivityCheckServer connCheckServer
-                                = new ConnectivityCheckServer(this);
+                                = new ConnectivityCheckServer(this, this);
+
+    /**
+     * Indicates whether this agent has both sent and received candidate  
lists
+     * and started connectivity establishment. This is important in cases  
like
+     * determining whether a remote address we've just discovered is peer
+     * reflexive or not. If iceStarted is true and we don't know about the
+     * address then we should add it to the list of candidates. Otherwise
+     * we should wait for the remote party to send their media description
+     * before being able to determine.
+     */
+    private boolean iceStarted = false;

      /**
       * Creates an empty <tt>Agent</tt> with no streams, and no address
@@ -253,19 +287,52 @@
      /**
       * Initializes all stream check lists and begins the checks.
       */
-    public void startChecks()
-    {
-        initCheckLists();
-
-        List<IceMediaStream> streams = getStreams();
-
-        for(IceMediaStream stream : streams)
-        {
-            CheckList list = stream.getCheckList();
-
-            connCheckHandler.startChecks(list);
+    public void startConnectivityEstablishment()
+    {
+        synchronized(this)
+        {
+            initCheckLists();
+
+            List<IceMediaStream> streams = getStreams();
+
+            for(IceMediaStream stream : streams)
+            {
+                CheckList list = stream.getCheckList();
+
+                connCheckClient.startChecks(list);
+            }
+
+            iceStarted = true;
          }
      }
+
+    /**
+     * Indicates whether this {@link Agent} is currently in the process of
+     * running connectivity checks and establishing connectivity.  
Connectivity
+     * establishment is considered to have started after both {@link  
Agent}s
+     * have exchanged their media descriptions. Determining whether the  
actual
+     * process has started is important, for example, when determining  
whether
+     * a remote address we've just discovered is peer reflexive or not.
+     * If CE has started and we don't know about the address then we should
+     * add it to the list of candidates. Otherwise we should hold to it  
until
+     * it does and check later.
+     * <p>
+     * Note that an {@link Agent} would be ready to and will send  
responses to
+     * connectivity checks as soon as it streams get created, which is well
+     * before we actually start the checks.
+     *
+     * @return <tt>true</tt> after media descriptions have been exchanged  
both
+     * ways and connectivity checks have started (regardless of their  
current
+     * state) and <tt>false</tt> otherwise.
+     */
+    public boolean isStarted()
+    {
+        synchronized(this)
+        {
+            return iceStarted;
+        }
+
+    }

      /**
       * Creates, initializes and orders the list of candidate pairs that  
would
@@ -582,4 +649,72 @@
      {
          return isControlling;
      }
-}
+
+    /**
+     * Returns the local <tt>LocalCandidate</tt> with the specified
+     * <tt>localAddress</tt> if it belongs to any of this {@link Agent}'s
+     * streams or <tt>null</tt> if it doesn't.
+     *
+     * @param localAddress the {@link TransportAddress} we are looking for.
+     *
+     * @return the local <tt>LocalCandidate</tt> with the specified
+     * <tt>localAddress</tt> if it belongs to any of this {@link Agent}'s
+     * streams or <tt>null</tt> if it doesn't.
+     */
+    public LocalCandidate findLocalCandidate(TransportAddress localAddress)
+    {
+        Collection<IceMediaStream> streamsCollection =  
mediaStreams.values();
+
+        for( IceMediaStream cmp : streamsCollection)
+        {
+            LocalCandidate cnd = cmp.findLocalCandidate(localAddress);
+
+            if(cnd != null)
+                return cnd;
+        }
+
+        return null;
+    }
+
+    /**
+     * Notifies the implementation that the {@link  
ConnectivityCheckServer} has
+     * just received a message on <tt>localAddress</tt> originating at
+     * <tt>remoteAddress</tt> carrying the specified <tt>priority</tt>.  
This
+     * will cause us to schedule a triggered check for the corresponding
+     * remote candidate and potentially to the discovery of a  
PEER-REFLEXIVE
+     * candidate.
+     *
+     * @param remoteAddress the address that we've just seen, and that is
+     * potentially a peer-reflexive address.
+     * @param localAddress the address that we were contacted on.
+     * @param priority the priority that the remote party assigned to
+     * @param remoteUFrag the user fragment that we should be using when  
and if
+     * we decide to send a check to <tt>remoteAddress</tt>.
+     *
+     */
+    public void handleRemoteAddress(TransportAddress remoteAddress,
+                                    TransportAddress localAddress,
+                                    long             priority,
+                                    String           remoteUFrag)
+    {
+        this.createMediaStream(null).createComponent(null).
+
+        if(iceStarted)
+        {
+            /*
+            if remoteAddress is not known
+            {
+                create peer reflexive candidate
+            }
+
+            schedule triggered check
+            */
+        }
+        else
+        {
+            RemoteCandidate remoteCand = new RemoteCandidate(
+                remoteAddres, );
+        }
+
+    }
+}
=======================================
--- /trunk/src/org/ice4j/ice/CheckList.java	Sun Apr 25 07:40:11 2010
+++ /trunk/src/org/ice4j/ice/CheckList.java	Wed Apr 28 15:30:53 2010
@@ -13,11 +13,13 @@
   * <tt>CheckListState</tt>). The pairs in a check list are those that an  
ICE
   * agent will run STUN connectivity checks for. There is one check list per
   * in-use media stream resulting from the offer/answer exchange.
- *
+ * <p>
+ * Given the asynchronous nature of ice, a check list may be accessed from
+ * different locations. This class therefore stores pairs in a  
<tt>Vector</tt>
   * @author Emil Ivov
   */
  public class CheckList
-    extends LinkedList<CandidatePair>
+    extends Vector<CandidatePair>
  {
      /**
       * A dummy serialization id.
=======================================
--- /trunk/src/org/ice4j/ice/Component.java	Sat Mar  6 08:05:26 2010
+++ /trunk/src/org/ice4j/ice/Component.java	Wed Apr 28 15:30:53 2010
@@ -576,4 +576,27 @@
              }
          }
      }
-}
+
+    /**
+     * Returns the local <tt>LocalCandidate</tt> with the specified
+     * <tt>localAddress</tt> if it belongs to this component or  
<tt>null</tt>
+     * if it doesn't.
+     *
+     * @param localAddress the {@link TransportAddress} we are looking for.
+     *
+     * @return  the local <tt>LocalCandidate</tt> with the specified
+     * <tt>localAddress</tt> if it belongs to this component or  
<tt>null</tt>
+     * if it doesn't.
+     */
+    public LocalCandidate findLocalCandidate(TransportAddress localAddress)
+    {
+
+        for( LocalCandidate localCnd : localCandidates)
+        {
+            if(localCnd.getTransportAddress().equals(localAddress))
+                return localCnd;
+        }
+
+        return null;
+    }
+}
=======================================
--- /trunk/src/org/ice4j/ice/IceMediaStream.java	Sun Apr 25 07:40:11 2010
+++ /trunk/src/org/ice4j/ice/IceMediaStream.java	Wed Apr 28 15:30:53 2010
@@ -467,4 +467,30 @@
      {
          this.maxCheckListSize = nSize;
      }
-}
+
+    /**
+     * Returns the local <tt>LocalCandidate</tt> with the specified
+     * <tt>localAddress</tt> if it belongs to any of this stream's  
components
+     * or <tt>null</tt> otherwise.
+     *
+     * @param localAddress the {@link TransportAddress} we are looking for.
+     *
+     * @return  the local <tt>LocalCandidate</tt> with the specified
+     * <tt>localAddress</tt> if it belongs to any of this stream's  
components
+     * or <tt>null</tt> otherwise.
+     */
+    public LocalCandidate findLocalCandidate(TransportAddress localAddress)
+    {
+        Collection<Component> cmpCol = components.values();
+
+        for( Component cmp : cmpCol)
+        {
+            LocalCandidate cnd = cmp.findLocalCandidate(localAddress);
+
+            if(cnd != null)
+                return cnd;
+        }
+
+        return null;
+    }
+}
=======================================
--- /trunk/src/org/ice4j/ice/checks/RemoteAddressHandler.java	Wed Apr 28  
15:30:42 2010
+++ /trunk/src/org/ice4j/ice/checks/RemoteAddressHandler.java	Wed Apr 28  
15:30:53 2010
@@ -22,7 +22,10 @@
      /**
       * Notifies the implementation that the {@link  
ConnectivityCheckServer} has
       * just received a message on <tt>localAddress</tt> originating at
-     * <tt>remoteAddress</tt> carrying the specified <tt>priority</tt>.
+     * <tt>remoteAddress</tt> carrying the specified <tt>priority</tt>.  
This
+     * will cause us to schedule a triggered check for the corresponding
+     * remote candidate and potentially to the discovery of a  
PEER-REFLEXIVE
+     * candidate.
       *
       * @param remoteAddress the address that we've just seen, and that is
       * potentially a peer-reflexive address.

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe at sip-communicator.dev.java.net
For additional commands, e-mail: commits-help at sip-communicator.dev.java.net





More information about the commits mailing list