/**
     * Compute candidate scores for a shortcut connection.
     * @param start address computed by the SCO.
     * @param range nunber of candidate nodes.
     * @param cb callback function when candidate scores are available. 
     * @param current current selection of the optimal in the provided range.
     */
    public override void ComputeCandidates(Address start, int range, TargetSelectorDelegate cb, Address current) {
      Channel q = null;
      RequestState rs = null;
      lock(_sync) {
#if VTS_DEBUG
        Console.Error.WriteLine("VTS local: {0}, start: {1}, range: {2}, count: {3}", _node.Address, start, range, _num_requests);
#endif
        if (_num_requests == MAX_REQUESTS) {
          return; //do nothing and return;
        }
        _num_requests++;
        q = new Channel();
        rs = new RequestState(start, range, cb, current);
        _channel_to_state[q] = rs;        
      }
      
      //create a new request state
      ISender s = new ForwardingSender(_node, 
                                       start, 
                                       AHHeader.Options.Greedy, 
                                       new DirectionalAddress(DirectionalAddress.Direction.Left),
                                       (short) range,
                                       AHHeader.Options.Path
                                       );

      q.EnqueueEvent += new EventHandler(EnqueueHandler);
      q.CloseEvent += new EventHandler(CloseHandler);
      RpcManager rpc = RpcManager.GetInstance(_node);
      rpc.Invoke(s, q, "ncserver.EchoVivaldiState", new object[]{});
    }
示例#2
0
    public void Test() {
      RandomNumberGenerator rng = new RNGCryptoServiceProvider();      
      AHAddress tmp_add = new AHAddress(rng);
      Node n = new StructuredNode(tmp_add, "unittest");
      AHSender ah = new AHSender(n, AddressParser.Parse("brunet:node:JOJZG7VO6RFOEZJ6CJJ2WOIJWTXRVRP4"));
      ForwardingSender fs = new ForwardingSender(n, 
                                                 AddressParser.Parse("brunet:node:JOJZG7VO6RFOEZJ6CJJ2WOIJWTXRVRP4"),
                                                 AddressParser.Parse("brunet:node:5FMQW3KKJWOOGVDO6QAQP65AWVZQ4VUQ"));
      
      string uri = "sender:ah?dest=JOJZG7VO6RFOEZJ6CJJ2WOIJWTXRVRP4&mode=exact";
      ISender s = SenderFactory.CreateInstance(n, uri);
      Assert.IsTrue(s is AHSender);
      Assert.AreEqual(uri, s.ToUri());
      uri = "sender:ah?dest=JOJZG7VO6RFOEZJ6CJJ2WOIJWTXRVRP4&mode=greedy";
      
      //Create the above programatically
      IDictionary<string, string> param_args = new Dictionary<string,string>();
      param_args["dest"] = "JOJZG7VO6RFOEZJ6CJJ2WOIJWTXRVRP4";
      param_args["mode"] = "greedy";
      string uri0 = SenderFactory.EncodeUri("ah", param_args); 
      Assert.AreEqual(uri, uri0, "EncodeUri works");
      //Check decode:
      string scheme;
      param_args = SenderFactory.DecodeUri(uri, out scheme);
      Assert.AreEqual(scheme, "ah", "Scheme decoded");
      Assert.AreEqual(param_args.Count, 2, "2 parameters in uri");
      Assert.AreEqual(param_args["dest"], "JOJZG7VO6RFOEZJ6CJJ2WOIJWTXRVRP4", "Extracted address");
      Assert.AreEqual(param_args["mode"], "greedy", "got mode");

      s = SenderFactory.CreateInstance(n, uri);
      Assert.IsTrue(s is AHSender);
      Assert.AreEqual(uri, s.ToUri());      
      string furi = "sender:fw?relay=JOJZG7VO6RFOEZJ6CJJ2WOIJWTXRVRP4&init_mode=greedy&dest=5FMQW3KKJWOOGVDO6QAQP65AWVZQ4VUQ&ttl=3&mode=path";
      s = SenderFactory.CreateInstance(n, furi);
      Assert.IsTrue(s is ForwardingSender);
      Assert.AreEqual(furi, s.ToUri());
    }
 /**
  * This handles the packet forwarding protocol
  */
 public void HandleData(MemBlock b, ISender ret_path, object state)
 {
   /*
    * Check it
    */
   AHSender ahs = ret_path as AHSender;
   if( ahs != null ) {
     //This was an AHSender:
     /*
      * This goes A -> B -> C
      */
     if( b[0] == 0 ) {
       int offset = 1;
       //This is the first leg, going from A->B
       Address add_c = AddressParser.Parse(b.Slice(offset, Address.MemSize));
       offset += Address.MemSize;
       //Since ahs a sender to return, we would be the source:
       Address add_a = ahs.Destination;
       short ttl = NumberSerializer.ReadShort(b, offset);//2 bytes
       offset += 2;
       ushort options = (ushort) NumberSerializer.ReadShort(b, offset);//2 bytes
       offset += 2;
       MemBlock payload = b.Slice(offset);
       MemBlock f_header = MemBlock.Reference( new byte[]{1} );
       /*
        * switch the packet from [A B f0 C] to [B C f 1 A]
        */
       ICopyable new_payload = new CopyList(PType.Protocol.Forwarding,
                                        f_header, add_a, payload);
       /*
        * ttl and options are present in the forwarding header.
        */
       AHSender next = new AHSender(_n, ahs.ReceivedFrom, add_c,
                                    ttl,
                                    options); 
       next.Send(new_payload);
     }
     else if ( b[0] == 1 ) {
       /*
        * This is the second leg: B->C
        * Make a Forwarding Sender, and unwrap the inside packet
        */
       Address add_a = AddressParser.Parse(b.Slice(1, Address.MemSize));
       Address add_b = ahs.Destination;
       MemBlock rest_of_payload = b.Slice(1 + Address.MemSize);
       //Here's the return path:
       ISender new_ret_path = new ForwardingSender(_n, add_b, add_a);
       _n.HandleData(rest_of_payload, new_ret_path, this);
     }
   }
   else {
     //This is not (currently) supported.
     Console.Error.WriteLine("Got a forwarding request from: {0}", ret_path);
   }
 }
    /**
     * @param structs the ConnectionList to work with
     * @param target_to_for a mapping of Address -> Address, if we want to
     * connect to the key, the value should be the forwarder
     * @param neighs an IEnumerable of NodeInfo objects.
     */
    protected void ConnectToNearer(ConnectionList structs, 
                                   IDictionary target_to_for, IEnumerable neighs) {
      Address nltarget;
      Address nrtarget;
      CheckForNearerNeighbors(structs, neighs, out nltarget, out nrtarget);
      
      if( nrtarget != null ) {
        Address forwarder = (Address)target_to_for[nrtarget];
        ISender send = new ForwardingSender(_node, forwarder, nrtarget);
        ConnectTo(send, nrtarget, STRUC_NEAR, 1);
      }

      if( nltarget != null && !nltarget.Equals(nrtarget) ) {
        Address forwarder = (Address)target_to_for[nltarget];
        ISender send = new ForwardingSender(_node, forwarder, nltarget);
        ConnectTo(send, nltarget, STRUC_NEAR, 1);
      }
    }
    /**
     * Similar to the above except the forwarder is the same for all targets
     * @param cl ConnectionList of structs
     * @param forwarder the Node to forward through
     * @param ni an IEnumerable of NodeInfo objects representing neighbors
     * forwarder
     */
    protected void ConnectToNearer(ConnectionList cl, Address forwarder, IEnumerable ni)
    {
      Address nltarget;
      Address nrtarget;
      CheckForNearerNeighbors(cl, ni, out nltarget, out nrtarget);
      
      if( nrtarget != null ) {
        ISender send = new ForwardingSender(_node, forwarder, nrtarget);
        ConnectTo(send, nrtarget, STRUC_NEAR, 1);
      }

      if( nltarget != null && !nltarget.Equals(nrtarget) ) {
        ISender send = new ForwardingSender(_node, forwarder, nltarget);
        ConnectTo(send, nltarget, STRUC_NEAR, 1);
      }
    }
    /**
     * This method is called when a new Connection is added
     * to the ConnectionTable
     */
    protected void ConnectHandler(object contab, EventArgs eargs)
    {
      lock( _sync ) {
        _last_connection_time = DateTime.UtcNow;
        _current_retry_interval = _DEFAULT_RETRY_INTERVAL;
        _need_left = -1;
        _need_right = -1;
      }

      if( IsActive == false ) {
        return;
      }

      ConnectionEventArgs args = (ConnectionEventArgs)eargs;
      Connection new_con = args.Connection;
      ConnectionList structs = null;

      if( new_con.MainType == ConnectionType.Structured ) {
        structs = args.CList;
      } else {
        if( new_con.MainType == ConnectionType.Leaf ) {
          /*
           * We just got a leaf.  Try to use it to get a shortcut.near
           * This leaf could be connecting a new part of the network
           * to us.  We try to connect to ourselves to make sure
           * the network is connected:
           */
          Address target = GetSelfTarget();
          //This is a near neighbor connection
          ISender send = new ForwardingSender(_node, new_con.Address, target);
          //Try to connect to the two nearest to us:
          ConnectTo(send, target, STRUC_NEAR, 2);
        }
        structs = _node.ConnectionTable.GetConnections(ConnectionType.Structured);
      }
      ConnectToNearer(structs, new_con.Address, new_con.Status.Neighbors);
    }
    ///////////////// Methods //////////////////////
    
    /**
     * Starts the Overlord if we are active
     *
     * This method is called by the CheckState method
     * IF we have not seen any connections in a while
     * AND we still need some connections
     *
     */
    public override void Activate()
    {
#if POB_DEBUG
      Console.Error.WriteLine("In Activate: {0}", _node.Address);
#endif
      if( IsActive == false ) {
        return;
      }

      DateTime now = DateTime.UtcNow;
      lock( _sync ) {
        if( now - _last_retry_time < _current_retry_interval ) {
          //Not time yet...
          return;
        }
        _last_retry_time = now;
        //Double the length of time we wait (resets to default on connections)
        _current_retry_interval += _current_retry_interval;
        _current_retry_interval = (_MAX_RETRY_INTERVAL < _current_retry_interval) ?
            _MAX_RETRY_INTERVAL : _current_retry_interval;
      }

      ConnectionTable tab = _node.ConnectionTable;
      //If we are going to connect to someone, this is how we
      //know who to use
      Address target = null;
      string contype = String.Empty;
      ISender sender = null;
      int desired_ctms = 1;
      
      ConnectionList structs = tab.GetConnections(ConnectionType.Structured);
      if( structs.Count < 2 ) {
        ConnectionList leafs = tab.GetConnections(ConnectionType.Leaf);
        if( leafs.Count == 0 )
        {
          /*
           * We first need to get a Leaf connection
           */
          return;
        }
        //We don't have enough connections to guarantee a connected
        //graph.  Use a leaf connection to get another connection
        Connection leaf = null;
        //Make sure the following loop can't go on forever
        int attempts = 2 * leafs.Count;
        do {
          leaf = leafs[ _rand.Next( leafs.Count ) ];
          attempts--;
        }
        while( leafs.Count > 1 && structs.Contains( leaf.Address ) &&
               attempts > 0 );
        //Now we have a random leaf that is not a
        //structured neighbor to try to get a new neighbor with:
        if( leaf != null ) {
          target = GetSelfTarget();
          /*
           * This is the case of trying to find the nodes nearest
           * to ourselves, use the Annealing routing to get connected
           * more quickly
           */
          sender = new ForwardingSender(_node, leaf.Address, target);
          //We are trying to connect to the two nearest nodes in one
          //one attempt, so wait for two distinct responses:
          desired_ctms = 2;
          //This is a near neighbor connection
          contype = STRUC_NEAR;
        }
      }
      
      if( structs.Count > 0 && sender == null ) {
        /**
         * We need left or right neighbors we send
         * a ConnectToMessage in the directons we
         * need.
         */
        if( NeedLeftNeighbor ) {
#if POB_DEBUG
          Console.Error.WriteLine("NeedLeftNeighbor: {0}", _node.Address);
#endif
          target = new DirectionalAddress(DirectionalAddress.Direction.Left);
          short ttl = (short)DESIRED_NEIGHBORS;
          sender = new AHSender(_node, target, ttl, AHHeader.Options.Last);
          contype = STRUC_NEAR;
        } else if( NeedRightNeighbor ) {
#if POB_DEBUG
          Console.Error.WriteLine("NeedRightNeighbor: {0}", _node.Address);
#endif
          target = new DirectionalAddress(DirectionalAddress.Direction.Right);
          short ttl = (short)DESIRED_NEIGHBORS;
          sender = new AHSender(_node, target, ttl, AHHeader.Options.Last);
          contype = STRUC_NEAR;
        }
      }

      if( sender != null ) {
        ConnectTo(sender, target, contype, desired_ctms);
      }
    }
    /**
     * This method is called when a new Connection is added
     * to the ConnectionTable
     */
    protected void ConnectHandler(object contab, EventArgs eargs)
    {
            
      lock( _sync ) {
        _last_connection_time = DateTime.UtcNow;
        _current_retry_interval = _DEFAULT_RETRY_INTERVAL;
        _need_left = -1;
        _need_right = -1;
        _need_short = -1;
        _need_bypass = -1;
      }
      if( IsActive == false ) {
        return;
      }
      ConnectionEventArgs args = (ConnectionEventArgs)eargs;
      Connection new_con = args.Connection;
#if SEND_DIRECTIONAL_TO_NEAR
      bool connect_left = false;
      bool connect_right = false;
#endif
      
      ConnectionList structs = null;
      if( new_con.MainType == ConnectionType.Leaf ) {
        /*
         * We just got a leaf.  Try to use it to get a shortcut.near
         * This leaf could be connecting a new part of the network
         * to us.  We try to connect to ourselves to make sure
         * the network is connected:
         */
        Address target = GetSelfTarget();
        //This is a near neighbor connection
        string contype = STRUC_NEAR;
        ISender send = new ForwardingSender(_node, new_con.Address, target);
        //Try to connect to the two nearest to us:
        ConnectTo(send, contype, 2);
      }
      else if( new_con.MainType == ConnectionType.Structured ) {
#if SEND_DIRECTIONAL_TO_NEAR
        int left_pos = cl.LeftInclusiveCount(_node.Address, new_con.Address);
        int right_pos = cl.RightInclusiveCount(_node.Address, new_con.Address);

        if( left_pos < DESIRED_NEIGHBORS ) {
        /*
         * This is a new left neighbor.  Always
         * connect to the right of a left neighbor,
         * this will make sure we are connected to
         * our local neighborhood.
         */
          connect_right = true;
          if( left_pos < DESIRED_NEIGHBORS - 1) { 
            /*
             * Don't connect to the left of our most
             * left neighbor.  If this is not our
             * most left neighbor, make sure we are
             * connected to his left
             */
            connect_left = true;
          }
        }
        if( right_pos < DESIRED_NEIGHBORS ) {
        /*
         * This is a new right neighbor.  Always
         * connect to the left of a right neighbor,
         * this will make sure we are connected to
         * our local neighborhood.
         */
          connect_left = true;
          if( right_pos < DESIRED_NEIGHBORS - 1) { 
            /*
             * Don't connect to the right of our most
             * right neighbor.  If this is not our
             * most right neighbor, make sure we are
             * connected to his right
             */
            connect_right = true;
          }
        }
        
        if( left_pos >= DESIRED_NEIGHBORS && right_pos >= DESIRED_NEIGHBORS ) {
        //This looks like a shortcut
          
        }
#endif
        structs = args.CList;
      }//Done handling the structured connection case
      /*
       * Now see if we need to connect to any of the neighbors of this guy
       */
      if( structs == null ) {
        structs = _node.ConnectionTable.GetConnections(ConnectionType.Structured);
      }
      ConnectToNearer(structs, new_con.Address, new_con.Status.Neighbors);
      
      //We also send directional messages.  In the future we may find this
      //to be unnecessary
      ///@todo evaluate the performance impact of this:
#if SEND_DIRECTIONAL_TO_NEAR
      if( nrtarget == null || nltarget == null ) {
      /**
       * Once we find nodes for which we can't get any closer, we
       * make sure we are connected to the right and left of that node.
       *
       * When we connect to a neighbor's neighbor with directional addresses
       * we need TTL = 2.  1 to get to the neighbor, 2 to get to the neighbor's
       * neighbor.
       */
        short nn_ttl = 2;
        if( connect_right ) {
          ConnectToOnEdge(new DirectionalAddress(DirectionalAddress.Direction.Right),
                        new_con.Edge, nn_ttl, STRUC_NEAR); 
        }
        if( connect_left ) {
          ConnectToOnEdge(new DirectionalAddress(DirectionalAddress.Direction.Left),
                        new_con.Edge, nn_ttl, STRUC_NEAR); 
        }
      }
#endif
    }
    /// <summary>Used to send data over the tunnel via forwarding senders
    /// using a randomly selected peer from our overlap list.</summary>
    public void HandleEdgeSend(Edge from, ICopyable data)
    {
      TunnelEdge te = from as TunnelEdge;
      Connection forwarder = te.NextForwarder;

      if(te.RemoteID == -1) {
        Address target = (te.RemoteTA as TunnelTransportAddress).Target;
        ISender sender = new ForwardingSender(_node, forwarder.Address, target);
        sender.Send(new CopyList(PType.Protocol.Tunneling, te.MId, data));
      } else {
        try {
          forwarder.Edge.Send(new CopyList(te.Header, te.MId, data));
        } catch {
          // We could be sending aon a closed edge... we could deal with this
          // better, but let's just let the system take its natural course.
        }
      }
    }
示例#10
0
 public void Test() {
   RandomNumberGenerator rng = new RNGCryptoServiceProvider();      
   AHAddress tmp_add = new AHAddress(rng);
   Node n = new StructuredNode(tmp_add, "unittest");
   AHSender ah = new AHSender(n, AddressParser.Parse("brunet:node:JOJZG7VO6RFOEZJ6CJJ2WOIJWTXRVRP4"));
   ForwardingSender fs = new ForwardingSender(n, 
                                              AddressParser.Parse("brunet:node:JOJZG7VO6RFOEZJ6CJJ2WOIJWTXRVRP4"),
                                              AddressParser.Parse("brunet:node:5FMQW3KKJWOOGVDO6QAQP65AWVZQ4VUQ"));
   
   string uri = "sender:ah?dest=brunet:node:JOJZG7VO6RFOEZJ6CJJ2WOIJWTXRVRP4&mode=exact";
   ISender s = SenderFactory.CreateInstance(n, uri);
   Assert.IsTrue(s is AHSender);
   Assert.AreEqual(uri, s.ToUri());
   uri = "sender:ah?dest=brunet:node:JOJZG7VO6RFOEZJ6CJJ2WOIJWTXRVRP4&mode=greedy";
   s = SenderFactory.CreateInstance(n, uri);
   Assert.IsTrue(s is AHSender);
   Assert.AreEqual(uri, s.ToUri());      
   uri = "sender:fw?relay=brunet:node:JOJZG7VO6RFOEZJ6CJJ2WOIJWTXRVRP4&init_mode=greedy&dest=brunet:node:5FMQW3KKJWOOGVDO6QAQP65AWVZQ4VUQ&ttl=3&mode=path";
   s = SenderFactory.CreateInstance(n, uri);
   Assert.IsTrue(s is ForwardingSender);
   Assert.AreEqual(uri, s.ToUri());
 }