Inheritance: Brunet.Messaging.ISender
Beispiel #1
0
 public ConnectionState GetReplacement(ConnectionTableState cts,
                              Connection c, ConnectionState c1,
                              ConnectionState c2) {
   if( (c1.Edge is RelayEdge) && (c2.Edge is RelayEdge) ) {
     return GetIdx(c1) <= GetIdx(c2) ? c1 : c2;
   }
   return _fallback.GetReplacement(cts,c,c1,c2);
 }
Beispiel #2
0
 public ConnectionEventArgs(Connection c, ConnectionState cs, int idx,
                            ConnectionTableState old, ConnectionTableState news) {
   Connection = c;
   ConnectionState = cs;
   Index = idx;
   OldState = old;
   NewState = news;
 }
 /**
  * This method is called when there is a change in a Connection's status
  */
 protected void StatusChangedHandler(Connection c,
                           Brunet.Collections.Pair<ConnectionState, ConnectionState> oldnew) {
   //Console.Error.WriteLine("Status Changed:\n{0}\n{1}\n{2}\n{3}",c, c.Status, nltarget, nrtarget);
   ConnectionList structs = _node.ConnectionTable.GetConnections(ConnectionType.Structured);
   ConnectToNearer(structs, c.Address,
                   oldnew.Second.StatusMessage.Neighbors);
 }
 /// <summary>Called when a connection has been lost.</summary>
 abstract protected void LostConnection(Connection con);
Beispiel #5
0
 public GreedyRouting(AHAddress local, ConnectionList structured_cons) {
   //Fake connection to ourselves:
   _local_con = new Connection(null, local, "structured.self", null, null);
   int local_idx;
   _structs = ConnectionList.InsertInto(structured_cons, _local_con, out local_idx);
   _NO_ONE = new Pair<Connection, bool>(null, false);
   _LOCAL = new Pair<Connection, bool>(null, true);
 }
    /**
     * Get a StatusMessage for this node
     */
    public IDictionary GetStatus(IDictionary status_message, ISender edge) {
      //we just got s status request
      if( 1 == _disconnecting ) {
        throw new AdrException((int)ErrorMessage.ErrorCode.Disconnecting, "disconnecting");
      }

      StatusMessage sm = new StatusMessage(status_message);
      Edge from = GetEdge(edge);

      if(ProtocolLog.LinkDebug.Enabled) {
        ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format(
          "{0} -start- sys:link.GetStatus({1},{2})", _node.Address, sm, edge));
      }

      CphState cphstate = null;
      if(from != null) {
        cphstate = _edge_to_cphstate[from] as CphState;
      }

     /**
      * StatusMessage objects are used to verify the completion
      * of the Link protocol.  If we receive a StatusMessage request
      * after we send a LinkMessage response, we know the other
      * Node got our LinkMessage response, and the connection
      * is active
      */
      StatusMessage response = null;
      ConnectionTable tab = _node.ConnectionTable;
      if (cphstate != null) {
        try {
          LinkMessage lm_to_add = cphstate.LM;
          //This is part of connection process:
          response = _node.GetStatus( sm.NeighborType, lm_to_add.Local.Address );
          Connection con = new Connection(from,
                                        lm_to_add.Local.Address,
                                        lm_to_add.ConTypeString,
                                        sm,
                                        lm_to_add);
          tab.Add(con);
        }
        finally {
          from.CloseEvent -= this.CloseHandler;
          CloseHandler(from, null);
        }
      } else {
        //This is just a "regular" status request
        //update our table:
        Address fadd = null;
        Connection c = tab.GetConnection(from);
        if( c != null ) {
          fadd = c.Address;
            tab.UpdateStatus(c, sm);
        }
        response = _node.GetStatus( sm.NeighborType, fadd );
      }
      
      if(ProtocolLog.LinkDebug.Enabled) {
        ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format(
          "{0} -end- sys:link.GetStatus()->{1}", _node.Address,response));
      }

      return response.ToDictionary();
    }
    protected void ConStateChange(Connection con,
        Pair<Connections.ConnectionState, Connections.ConnectionState> cs)
    {
      if(cs.First.Edge.Equals(cs.Second.Edge)) {
        return;
      }

      if(!_ondemand.ConnectionDesired(con.Address)) {
        return;
      }
      SecurityAssociation sa;
      GetSecureSender(con, out sa);
    }
    override protected void LostConnection(Connection con)
    {
      if(!ConnectionDesired(con.Address)) {
        if(con.ConType.Equals(Type)) {
        }
        return;
      }

      if(IsActive) {
        if(ProtocolLog.PolicyBasedCO.Enabled) {
          ProtocolLog.Write(ProtocolLog.PolicyBasedCO, String.Format(
                            "Disconnection: {0} at {1}", con, DateTime.UtcNow));
        }
        DelayedConnectTo(con.Address, true);
      }
    }
Beispiel #9
0
 public ConSenderWrapper(Connection con)
 {
   Con = con;
 }
Beispiel #10
0
 public UpdateNeighborAction(StructuredNode n,
                             string contype,
                             Connection neigh) {
   Node = n;
   ConType = contype;
   Neighbor = neigh;
 }
Beispiel #11
0
 virtual protected void ValidConnection(Connection con)
 {
   AddConnection(con.Address, new ConSenderWrapper(con));
 }
Beispiel #12
0
 virtual protected void ValidDisconnection(Connection con)
 {
   RemoveConnection(con.Address);
 }
 override protected void ObtainedConnection(Connection con)
 {
   if(ConnectionDesired(con.Address)) {
     if(ProtocolLog.PolicyBasedCO.Enabled) {
       ProtocolLog.Write(ProtocolLog.PolicyBasedCO, String.Format(
                         "Connection: {0} at {1}", con, DateTime.UtcNow));
     }
   } else if(con.ConType.Equals(Type)) {
     DelayedRemove(con.Address, "Undesired");
   }
 }
Beispiel #14
0
 public ConnectionEventArgs(Connection c, int idx, ConnectionList cl, int view) {
   Connection = c;
   Index = idx;
   CList = cl;
   View = view;
 }
 override protected void ValidConnection(Connection con)
 {
   con.StateChangeEvent += ConStateChange;
   SecurityAssociation sa;
   GetSecureSender(con, out sa);
 }
 /// <summary>Called when a connection has been formed.</summary>
 abstract protected void ObtainedConnection(Connection con);
Beispiel #17
0
    public void WrapperEdgeRegressionTest()
    {
      AHAddress addr = new AHAddress(new System.Security.Cryptography.RNGCryptoServiceProvider());
      TransportAddress ta = TransportAddressFactory.CreateInstance("brunet.tcp://169.0.5.1:5000");
      FakeEdge fe = new FakeEdge(ta, ta);
      WrapperEdge we_fe = new WrapperEdge(fe);
      Connection fcon = new Connection(we_fe, addr, "structured", null, null);

      List<Connection> overlap = new List<Connection>();
      overlap.Add(fcon);
      RelayTransportAddress tta = new RelayTransportAddress(addr, overlap);
      RelayEdge te1 = new RelayEdge(null, tta, tta, new SimpleForwarderSelector(), overlap);
      WrapperEdge we_te1 = new WrapperEdge(te1);
      Connection t1con = new Connection(we_te1, addr, "structured", null, null);

      overlap = new List<Connection>();
      overlap.Add(t1con);
      RelayEdge te2 = new RelayEdge(null, tta, tta, new SimpleForwarderSelector(), overlap);
      WrapperEdge we_te2 = new WrapperEdge(te2);
      Connection t2con = new Connection(we_te2, addr, "structured", null, null);

      overlap = new List<Connection>();
      overlap.Add(t2con);
      RelayEdge te3 = new RelayEdge(null, tta, tta, new SimpleForwarderSelector(), overlap);
      WrapperEdge we_te3 = new WrapperEdge(te3);
      Connection t3con = new Connection(we_te3, addr, "structured", null, null);

      overlap = new List<Connection>();
      overlap.Add(t3con);
      RelayEdge te4 = new RelayEdge(null, tta, tta, new SimpleForwarderSelector(), overlap);
      WrapperEdge we_te4 = new WrapperEdge(te4);
      Connection t4con = new Connection(we_te4, addr, "structured", null, null);

      overlap = new List<Connection>();
      overlap.Add(t4con);
      RelayEdge te5 = new RelayEdge(null, tta, tta, new SimpleForwarderSelector(), overlap);
      WrapperEdge we_te5 = new WrapperEdge(te5);
      Connection t5con = new Connection(we_te5, addr, "structured", null, null);

      Assert.AreEqual(te5.ShouldClose(), false, "Shouldn't close yet...");
      te1.DisconnectionHandler(fcon);
      Assert.AreEqual(te5.ShouldClose(), true, "Should close...");

      overlap.Add(t5con);
      overlap.Add(t3con);
      overlap.Add(t1con);
      te2.UpdateNeighborIntersection(overlap);
      Assert.AreEqual(te5.ShouldClose(), true, "Should close... 2");
    }
Beispiel #18
0
    /**
     * When we're here, we have the status message
     */
    protected void StatusCloseHandler(object q, EventArgs args) {
      try {
        Channel resq = (Channel)q;
        //If we got no result
        RpcResult res = (RpcResult)resq.Dequeue();
        StatusMessage sm = new StatusMessage((IDictionary)res.Result);
        if(_node.EdgeVerifyMethod != null) {
          if(!_node.EdgeVerifyMethod(_node, _e, LinkMessageReply.Local.Address)) {
            throw new Exception("Edge verification failed!");
          }
        }

        Connection c = new Connection(_e, LinkMessageReply.Local.Address,
                                        _contype, sm, LinkMessageReply);
        _node.ConnectionTable.Add(c);
        _con.Value = c;
        Finish(Result.Success);
      }
      catch(InvalidOperationException) {
         /*
          * This is unexpected. 
          */
        string message = String.Format(
                           "No StatusMessage returned from open({1}) Edge: {0}",
                           _e, !_e.IsClosed);
        if(ProtocolLog.LinkDebug.Enabled) {
          ProtocolLog.Write(ProtocolLog.LinkDebug, message);
        }
        /*
         * We got a link message from this guy, but not a status response,
         * so let's try this TA again.
         */
        Finish(Result.RetryThisTA);
      }
      catch(Exception x) {
        /*
         * Clearly we got some response from this edge, but something
         * unexpected happened.  Let's try it this edge again if we
         * can
         */
        if(ProtocolLog.LinkDebug.Enabled) {
          ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format(
            "LPS.StatusResultHandler Exception: {0}", x));
        }
        Finish(Result.RetryThisTA);
      }
    }
Beispiel #19
0
 /**
  * Call the GetStatus method on the given connection
  */
 protected void CallGetStatus(string type, Connection c) {
   ConnectionTable tab = this.ConnectionTable;
   if( c != null ) {
     StatusMessage req = GetStatus(type, c.Address);
     Channel stat_res = new Channel(1);
     EventHandler handle_result = delegate(object q, EventArgs eargs) {
       try {
         RpcResult r = (RpcResult)stat_res.Dequeue();
         StatusMessage sm = new StatusMessage( (IDictionary)r.Result );
         tab.UpdateStatus(c, sm);
       }
       catch(Exception) {
         //Looks like lc disappeared before we could update it
       }
     };
     stat_res.CloseEvent += handle_result;
     _rpc.Invoke(c.Edge, stat_res, "sys:link.GetStatus", req.ToDictionary() );
   }
 }
Beispiel #20
0
    /// <summary>We don't want to send on disconnected edges.  So we remove said
    /// connections and edges!</summary>
    public void DisconnectionHandler(Connection con)
    {
      bool close = false;
      List<Connection> tunnels = null;
      lock(_sync) {
        tunnels = new List<Connection>(_tunnels.Count);
        foreach(Connection ccon in _tunnels) {
          if(con.Equals(ccon)){
            continue;
          }
          tunnels.Add(ccon);
        }

        if(tunnels.Count == _tunnels.Count) {
          return;
        }

        _tunnels = tunnels;
        close = _tunnels.Count == 0;
      }

      if(close || ShouldClose()) {
        Close();
      }

      //_tunnels is immutable and if we don't pass the latest _tunnels to _ias
      //he will go into an inconsistent state.
      _ias.Update(tunnels);
    }
    protected bool GetSecureSender(Connection con, out SecurityAssociation sa)
    {
      sa = _so.CreateSecurityAssociation(con.State.Edge);
      bool ready = false;
      lock(_address_to_sender) {
        if(!_registered.ContainsKey(sa)) {
          _registered[sa] = true;
          sa.StateChangeEvent += SAStateChange;
        }

        if(sa.State == SecurityAssociation.States.Active ||
            sa.State == SecurityAssociation.States.Updating)
        {
          Address addr = con.Address;
          if(_address_to_sender.ContainsKey(addr)) {
            SecurityAssociation to_fixup = _address_to_sender[addr] as SecurityAssociation;
            if(to_fixup != null && to_fixup != sa) {
              to_fixup.StateChangeEvent -= SAStateChange;
              _registered.Remove(to_fixup);
            }
          }
          AddConnection(con.Address, sa);
          ready = true;
        }
      }
      return ready;
    }
Beispiel #22
0
      /**
      <summary>Begins a new transfer state to the neighbor connected via con.
      </summary>
      <param name="con">The connection to the neigbhor we will be transferring
      data to.</param>
      <param name="ts">The table server we're providing the transfer for.  C#
      does not allow sub-class objects to have access to their parent objects
      member variables, so we pass it in like this.</param>
      <remarks>
      Step 1:

      Get all the keys between me and my new neighbor.

      Step 2:

      Get all values for those keys, we copy so that we don't worry about
      changes to the dht during this interaction.  This is only a pointer
      copy and since we let the OS deal with removing the contents of an
      entry, we don't need to make copies of the actual entry.

      Step 3:

      Generate another list of keys of up to max parallel transfers and begin
      transferring, that way we do not need to lock access to the entry
      enumerator until non-constructor puts.

      Step 4:

      End constructor, results from puts, cause the next entry to be sent.
      */
      public TransferState(Brunet.Connections.Connection con, TableServer ts) {
        this._ts = ts;
        this._con = con;
        // Get all keys between me and my new neighbor
        LinkedList<MemBlock> keys;
        lock(_ts._sync) {
          keys = _ts._data.GetKeysBetween((AHAddress) _ts._node.Address,
                                      (AHAddress) _con.Address);
        }
        if(Dht.DhtLog.Enabled) {
          ProtocolLog.Write(Dht.DhtLog, String.Format(
                            "Starting transfer from {0} to {1}", 
                            _ts._node.Address, _con.Address));
        }
        int total_entries = 0;
        /* Get all values for those keys, we copy so that we don't worry about
         * changes to the dht during this interaction.  This is only a pointer
         * copy and since we let the OS deal with removing the contents of an
         * entry, we don't need to make copies of the actual entry.
         */
        foreach(MemBlock key in keys) {
          Entry[] entries;
          lock(_ts._sync) {
            LinkedList<Entry> llentries = _ts._data.GetEntries(key);
            if(llentries == null) {
              continue;
            }
            entries = new Entry[llentries.Count];
            total_entries += llentries.Count;
            llentries.CopyTo(entries, 0);
          }
          key_entries.AddLast(entries);
        }
        if(Dht.DhtLog.Enabled) {
          ProtocolLog.Write(Dht.DhtLog, String.Format(
                            "Total keys: {0}, total entries: {1}.", 
                            key_entries.Count, total_entries));
        }
        _entry_enumerator = GetEntryEnumerator();

        /* Here we generate another list of keys that we would like to 
         * this is done here, so that we can lock up the _entry_enumerator
         * only during this stage and not during the RpcManager.Invoke
         */
        LinkedList<Entry> local_entries = new LinkedList<Entry>();
        for(int i = 0; i < MAX_PARALLEL_TRANSFERS && _entry_enumerator.MoveNext(); i++) {
          local_entries.AddLast((Entry) _entry_enumerator.Current);
        }

        foreach(Entry ent in local_entries) {
          Channel queue = new Channel();
          queue.CloseAfterEnqueue();
          queue.CloseEvent += this.NextTransfer;
          int ttl = (int) (ent.EndTime - DateTime.UtcNow).TotalSeconds;
          try {
            _ts._rpc.Invoke(_con.Edge, queue, "dht.PutHandler", ent.Key, ent.Value, ttl, false);
          }
          catch {
            if(_con.Edge.IsClosed) {
              _interrupted = true;
              Done();
              break;
            }
          }
        }
      }
Beispiel #23
0
    /**
     * There are only four ways we can get here:
     * 
     * 1) We got some exception in Start and never made the first request
     * 2) There was some problem in LinkCloseHandler
     * 3) We either got a response or had a problem in StatusCloseHandler
     * 4) The Edge closed, and the CloseHandler was called.
     * 
     * The only possibility for a race is between the CloseHandler and
     * the others.
     *
     * When this state machine reaches an end point, it calls this method,
     * which fires the FinishEvent
     */
    protected void Finish(Result res) {
      /*
       * No matter what, we are done here:
       */
      if(ProtocolLog.LinkDebug.Enabled) {
        string message;
        Exception x;
        if (_x.TryGet(out x) ) {
          message = String.Format(
                      "LPS: {0} finished: {2}, with exception: {1}",
                      _node.Address, x, res);
        }
        else {
          message = String.Format("LPS: {0} finished: {1}",
                                  _node.Address, res);
        }
        ProtocolLog.Write(ProtocolLog.LinkDebug, message);
      }

      int already_finished = Interlocked.Exchange(ref _is_finished, 1);
      if(already_finished == 1) {
        //We already got here.
        //This is a barrier.  Only one Finish call will make
        //it past this point.  Only two could happen in a race:
        //Edge closing or some other failure/success.
        return;
      }
      //We don't care about close event's anymore
      _e.CloseEvent -= this.CloseHandler;

      //Set the result:
      _result = res;
      
      try {
        //Check to see if we need to close the edge
        if( _con.IsSet == false ) {
          /*
           * We didn't get a complete connection,
           * but we may have heard some response.  If so
           * close the edge gracefully.
           */
          if (LinkMessageReply != null) {
            //Let's be nice, send a Close message, but don't add this connection:
            Connection tmp_c = new Connection(_e, LinkMessageReply.Local.Address,
                                        _contype, null, LinkMessageReply);
            tmp_c.Close(_node.Rpc, "From LPS, did not complete a connection.");
          }
          else {
            /*
             * We never heard from the other side, so we will assume that further
             * packets will only waste bandwidth
             */
            _e.Close();
          }
          if(ProtocolLog.LinkDebug.Enabled) {
            ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format(
              "LPS: {0} got no connection", _node.Address));
          }
        }
        else {
          if(ProtocolLog.LinkDebug.Enabled) {
            ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format(
              "LPS: {0} got connection: {1}", _node.Address, _con.Value));
          }
        }
        //This could throw an exception, but make sure we unlock if it does.
        FireFinished();
      }
      finally {
        /**
         * We have to make sure the lock is eventually released:
         */
        this.Unlock();
      }
    }
    override protected void ObtainedConnection(Connection con)
    {
      bool con_desired = ConnectionDesired(con.Address);

      if(con_desired || con.ConType.Equals(Type)) {
        if(ProtocolLog.PolicyBasedCO.Enabled) {
          ProtocolLog.Write(ProtocolLog.PolicyBasedCO, String.Format(
                            "Connection: {0} at {1}, Desired: {2}",
                            con, DateTime.UtcNow, ConnectionDesired(con.Address)));
        }
      }

      if(!con_desired && con.ConType.Equals(Type)) {
        Set(con.Address);
      }
    }
Beispiel #25
0
 ///<summary>Creates an edge and a connection from node2 to node1 including
 ///the edge.  Note:  this is unidirectional, this must be called twice,
 ///swapping node1 with node2 for a connection to be complete.</summary>
 protected void AddConnection(GraphNode node1, GraphNode node2, int delay)
 {
   Edge edge = new GraphEdge(delay);
   Connection con = new Connection(edge, node2.Address, ConnectionType.Structured.ToString(), null, null);
   node1.ConnectionTable.Add(con);
 }
Beispiel #26
0
            /**
             * <summary>Begins a new transfer state to the neighbor connected via con.
             * </summary>
             * <param name="con">The connection to the neigbhor we will be transferring
             * data to.</param>
             * <param name="ts">The table server we're providing the transfer for.  C#
             * does not allow sub-class objects to have access to their parent objects
             * member variables, so we pass it in like this.</param>
             * <remarks>
             * Step 1:
             *
             * Get all the keys between me and my new neighbor.
             *
             * Step 2:
             *
             * Get all values for those keys, we copy so that we don't worry about
             * changes to the dht during this interaction.  This is only a pointer
             * copy and since we let the OS deal with removing the contents of an
             * entry, we don't need to make copies of the actual entry.
             *
             * Step 3:
             *
             * Generate another list of keys of up to max parallel transfers and begin
             * transferring, that way we do not need to lock access to the entry
             * enumerator until non-constructor puts.
             *
             * Step 4:
             *
             * End constructor, results from puts, cause the next entry to be sent.
             */
            public TransferState(Brunet.Connections.Connection con, TableServer ts)
            {
                this._ts  = ts;
                this._con = con;
                // Get all keys between me and my new neighbor
                LinkedList <MemBlock> keys;

                lock (_ts._sync) {
                    keys = _ts._data.GetKeysBetween((AHAddress)_ts._node.Address,
                                                    (AHAddress)_con.Address);
                }
                if (Dht.DhtLog.Enabled)
                {
                    ProtocolLog.Write(Dht.DhtLog, String.Format(
                                          "Starting transfer from {0} to {1}",
                                          _ts._node.Address, _con.Address));
                }
                int total_entries = 0;

                /* Get all values for those keys, we copy so that we don't worry about
                 * changes to the dht during this interaction.  This is only a pointer
                 * copy and since we let the OS deal with removing the contents of an
                 * entry, we don't need to make copies of the actual entry.
                 */
                foreach (MemBlock key in keys)
                {
                    Entry[] entries;
                    lock (_ts._sync) {
                        LinkedList <Entry> llentries = _ts._data.GetEntries(key);
                        if (llentries == null)
                        {
                            continue;
                        }
                        entries        = new Entry[llentries.Count];
                        total_entries += llentries.Count;
                        llentries.CopyTo(entries, 0);
                    }
                    key_entries.AddLast(entries);
                }
                if (Dht.DhtLog.Enabled)
                {
                    ProtocolLog.Write(Dht.DhtLog, String.Format(
                                          "Total keys: {0}, total entries: {1}.",
                                          key_entries.Count, total_entries));
                }
                _entry_enumerator = GetEntryEnumerator();

                /* Here we generate another list of keys that we would like to
                 * this is done here, so that we can lock up the _entry_enumerator
                 * only during this stage and not during the RpcManager.Invoke
                 */
                LinkedList <Entry> local_entries = new LinkedList <Entry>();

                for (int i = 0; i < MAX_PARALLEL_TRANSFERS && _entry_enumerator.MoveNext(); i++)
                {
                    local_entries.AddLast((Entry)_entry_enumerator.Current);
                }

                foreach (Entry ent in local_entries)
                {
                    Channel queue = new Channel();
                    queue.CloseAfterEnqueue();
                    queue.CloseEvent += this.NextTransfer;
                    int ttl = (int)(ent.EndTime - DateTime.UtcNow).TotalSeconds;
                    try {
                        _ts._rpc.Invoke(_con.Edge, queue, "dht.PutHandler", ent.Key, ent.Value, ttl, false);
                    }
                    catch {
                        if (_con.Edge.IsClosed)
                        {
                            _interrupted = true;
                            Done();
                            break;
                        }
                    }
                }
            }
 override protected void ValidConnection(Connection con)
 {
   SecurityAssociation sa;
   GetSecureSender(con, out sa);
 }
Beispiel #28
0
 public AnnealingRouting(AHAddress local, ConnectionList structured_cons) {
   //Fake connection to ourselves:
   _local_con = new Connection(null, local, "structured.self", null, null);
   int local_idx;
   _structs = ConnectionList.InsertInto(structured_cons, _local_con, out local_idx);
 }
 override protected void ValidDisconnection(Connection con)
 {
   ISender sender;
   if(!_address_to_sender.TryGetValue(con.Address, out sender)) {
     return;
   }
   SecurityAssociation sa = sender as SecurityAssociation;
   if(sa != null) {
     sa.Close("Connection closed...");
   }
 }
Beispiel #30
0
    public void Test()
    {
      Address addr_x = new AHAddress(new RNGCryptoServiceProvider());
      byte[] addrbuff = Address.ConvertToAddressBuffer(addr_x.ToBigInteger() + (Address.Full / 2));
      Address.SetClass(addrbuff, AHAddress._class);
      Address addr_y = new AHAddress(addrbuff);

      List<Connection> connections = new List<Connection>();
      ConnectionTable ct_x = new ConnectionTable();
      ConnectionTable ct_y = new ConnectionTable();
      ConnectionTable ct_empty = new ConnectionTable();
      NCService ncservice = new NCService();

      Connection fast_con = null;
      for(int i = 1; i <= 11; i++) {
        addrbuff = Address.ConvertToAddressBuffer(addr_x.ToBigInteger() + (i * Address.Full / 16));
        Address.SetClass(addrbuff, AHAddress._class);
        Address addr = new AHAddress(addrbuff);
        Connection con = null;

        TransportAddress ta = TransportAddressFactory.CreateInstance("brunet.tcp://158.7.0.1:5000");
        Edge fe = new FakeEdge(ta, ta, TransportAddress.TAType.Tcp);
        if(i <= 10) {
          con = new Connection(fe, addr, "structured", null, null);
          ct_x.Add(con);
          if(i % 2 == 0) {
            ncservice.ProcessSample(DateTime.UtcNow, String.Empty, addr,
                new Point(new double[] {0, 0}, 0), 0, i*10);
          }
        } else {
          fast_con = new Connection(fe, addr, "structured", null, null);
          ncservice.ProcessSample(DateTime.UtcNow, String.Empty, addr,
              new Point(new double[] {0, 0}, 0), 0, 5);
        }

        if(i == 10) {
          ct_y.Add(con);
        }
        connections.Add(con);
      }

      ITunnelOverlap sto = new SimpleTunnelOverlap();
      ITunnelOverlap nto = new NCTunnelOverlap(ncservice);

      ConnectionType con_type = ConnectionType.Structured;
      List<Connection> pre_cons = new List<Connection>();
      pre_cons.Add(connections[9]);
      IDictionary id = nto.GetSyncMessage(pre_cons, addr_x, ct_x.GetConnections(con_type));

      // We do have some pre-existing overlap
      Assert.AreEqual(nto.EvaluateOverlap(ct_y.GetConnections(con_type), id)[0], connections[9], "NC: Have an overlap!");
      Assert.AreEqual(sto.EvaluateOverlap(ct_y.GetConnections(con_type), id)[0], connections[9], "Simple: Have an overlap!");

      // We have no overlap with an empty connection table
      Assert.AreEqual(nto.EvaluateOverlap(ct_empty.GetConnections(con_type), id).Count, 0, "No overlap!");
      Assert.AreEqual(sto.EvaluateOverlap(ct_empty.GetConnections(con_type), id).Count, 0, "No overlap!");

      // latency[0] == -1
      Assert.AreEqual(connections[1].Address.Equals(nto.EvaluatePotentialOverlap(id)), true,
          "NC: EvaluatePotentialOverlap returns expected!");
      Assert.AreEqual(ct_x.Contains(con_type, sto.EvaluatePotentialOverlap(id)), true,
          "Simple: EvaluatePotentialOverlap returns valid!");

      ct_y.Add(fast_con);
      ct_x.Add(fast_con);
      id = nto.GetSyncMessage(pre_cons, addr_x, ct_x.GetConnections(con_type));
      Assert.AreEqual(fast_con.Address.Equals(nto.EvaluatePotentialOverlap(id)), true,
          "NC: EvaluatePotentialOverlap returns expected!");
      Assert.AreEqual(nto.EvaluateOverlap(ct_y.GetConnections(con_type), id)[0], fast_con, "NC: Have better overlap!");
    }
    protected bool GetSecureSender(Connection con, out SecurityAssociation sa)
    {
      sa = _so.GetSecureSender(con.Address);
      bool ready = false;
      lock(_address_to_sender) {
        if(!_registered.ContainsKey(sa)) {
          _registered[sa] = true;
          sa.StateChangeEvent += SAStateChange;
        }

        if(sa.State == SecurityAssociation.States.Active ||
            sa.State == SecurityAssociation.States.Updating)
        {
          AddConnection(con.Address, sa);
          ready = true;
        }
      }
      return ready;
    }