Пример #1
0
 /**
  * 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);
   }
 }
Пример #2
0
 public ForwardingSender(Node n, Address forwarder, ushort init_option, Address destination, short ttl, ushort option) {
   _n = n;
   _dest = destination;
   _sender = new AHSender(n, forwarder, init_option);
   _f_ttl =  ttl;
   _f_option = option;
   byte[] f_buffer = new byte[4];
   NumberSerializer.WriteShort(ttl, f_buffer, 0);
   NumberSerializer.WriteUShort(option, f_buffer, 2);      
   _header = new CopyList(PType.Protocol.Forwarding,
                          MemBlock.Reference(new byte[]{0}),
                          destination,
                          MemBlock.Reference(f_buffer) 
                          );
 }
Пример #3
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());
    }
Пример #4
0
    /// <summary>This is the generic Put that is used by both the regular Put
    /// and Create methods.  The use of the unique variable differentiates the
    /// two.  This is asynchronous.  Results are stored in the Channel returns.
    /// Creates and Puts return true if successful or exception if there are
    /// network errors in adding the entry, creates also fail if a previous
    /// entry exists.  The work of determining success is handled in
    /// PutEnqueueHandler and PutCloseHandler.</summary>
    /// <param name="key">The index to store the value at.</param>
    /// <param name="value">The value to store.</param>
    /// <param name="ttl">The dht lease time for the key:value pair.</param>
    /// <param name="returns">The Channel where the result will be placed.</param>
    /// <param name="unique">True to do a create, false otherwise.</param>
    public void AsyncPut(MemBlock key, MemBlock value, int ttl, Channel returns, bool unique) {
      if(!_online) {
        throw new DhtException("The Node is (going) offline, DHT is offline.");
      }
      AsDhtPutState adps = new AsDhtPutState(returns);

      MemBlock[] brunet_address_for_key = MapToRing(key);
      Channel[] q = new Channel[DEGREE];
      lock(_adps_table.SyncRoot) {
        for (int k = 0; k < DEGREE; k++) {
          Channel queue = new Channel(1);
          queue.CloseEvent += this.PutCloseHandler;
          _adps_table[queue] = adps;
          q[k] = queue;
        }
      }

      for (int k = 0; k < DEGREE; k++) {
        Address target = new AHAddress(brunet_address_for_key[k]);
        AHSender s = new AHSender(Node, target, AHPacket.AHOptions.Greedy);
        _rpc.Invoke(s, q[k], "dht.Put", brunet_address_for_key[k], value, ttl, unique);
      }
    }
Пример #5
0
    /// <summary>Restores any of the Dht results that don't return all their
    /// values.  We only get here at the end of a Dht return operation.</summary>
    /// <remarks>This analyzes the holes and fills them in individually.  This only
    /// fills holes where there was a positive result (MAJORITY of results
    /// received).</remarks>
    /// <param name="adgs">The AsDhtGetState to analyze for follow up.</param>
    protected void GetFollowUp(AsDhtGetState adgs) {
      foreach (DictionaryEntry de in adgs.results) {
        if(de.Value == null || de.Key == null) {
          continue;
        }

        Hashtable res = (Hashtable) de.Value;
        if(res.Count < MAJORITY || res.Count == DEGREE) {
          if(res.Count < MAJORITY) {
            if(Dht.DhtLog.Enabled) {
              ProtocolLog.Write(Dht.DhtLog, String.Format(
                "Failed get count:total = {0}:{1}", res.Count, DEGREE));
            }
          }
          res.Clear();
          continue;
        }
        MemBlock value = (MemBlock) de.Key;

        int ttl = (int) adgs.ttls[value] / res.Count;
        if(Dht.DhtLog.Enabled) {
          ProtocolLog.Write(Dht.DhtLog, String.Format(
            "Doing follow up put count:total = {0}:{1}", res.Count, DEGREE));
        }
        for(int i = 0; i < DEGREE; i++) {
          if(!res.Contains(i)) {
            MemBlock key = adgs.brunet_address_for_key[i];
            Channel queue = new Channel();
            Address target = new AHAddress(key);
            AHSender s = new AHSender(Node, target, AHPacket.AHOptions.Greedy);
            try {
             _rpc.Invoke(s, queue, "dht.Put", key, value, ttl, false);
            }
            catch(Exception) {}
          }
        }
        res.Clear();
      }
      adgs.ttls.Clear();
      adgs.results.Clear();
    }
Пример #6
0
    /// <remarks>This starts the get process by sending dht.Get to all the remote
    /// end points that contain the key we're looking up.  The next step is
    /// is when the results are placed in the channel and GetEnqueueHandler is
    /// called or GetCloseHandler is called.  This means the get needs to be
    /// stateful, that information is stored in the _adgs_table.</remarks>
    public void AsyncGet(MemBlock key, Channel returns) {
      if(!_online) {
        throw new DhtException("The Node is (going) offline, DHT is offline.");
      }
      // create a GetState and map in our table map its queues to it
      // so when we get a GetHandler we know which state to load
      AsDhtGetState adgs = new AsDhtGetState(returns);
      Channel[] q = new Channel[DEGREE];
      lock(_adgs_table.SyncRoot) {
        for (int k = 0; k < DEGREE; k++) {
          Channel queue = new Channel(1);
          _adgs_table[queue] = adgs;
          q[k] = queue;
        }
      }

      // Setting up our Channels
      for (int k = 0; k < DEGREE; k++) {
        Channel queue = q[k];
        queue.EnqueueEvent += this.GetEnqueueHandler;
        queue.CloseEvent += this.GetCloseHandler;
        adgs.queueMapping[queue] = k;
      }

      // Sending off the request!
      adgs.brunet_address_for_key = MapToRing(key);
      for (int k = 0; k < DEGREE; k++) {
        Address target = new AHAddress(adgs.brunet_address_for_key[k]);
        AHSender s = new AHSender(Node, target, AHPacket.AHOptions.Greedy);
        // 1024 is in there for backwards compatibility
        _rpc.Invoke(s, q[k], "dht.Get", adgs.brunet_address_for_key[k], 1024, null);
      }
    }
    /**
     * This method is called when there is a Disconnection from
     * the ConnectionTable
     */
    protected void DisconnectHandler(object connectiontable, EventArgs args)
    { 
      ConnectionEventArgs ceargs = (ConnectionEventArgs)args;
      Connection c = ceargs.Connection;


      lock( _sync ) {
        _last_connection_time = DateTime.UtcNow;
        _need_left = -1;
        _need_right = -1;
        _current_retry_interval = _DEFAULT_RETRY_INTERVAL;
      }

      if( !IsActive ) {
        return;
      }


      if( c.MainType != ConnectionType.Structured ) {
        //Just activate and see what happens:
        Activate();
        return;
      }

      ConnectionList cl = ceargs.CList;
      int right_pos = cl.RightInclusiveCount(_node.Address, c.Address);
      if( right_pos < DESIRED_NEIGHBORS ) {
        //We lost a close friend.
        Address target = new DirectionalAddress(DirectionalAddress.Direction.Right);
        short ttl = (short)DESIRED_NEIGHBORS;
        string contype = STRUC_NEAR;
        ISender send = new AHSender(_node, target, ttl, AHHeader.Options.Last);
        ConnectTo(send, target, contype, 1);
      }

      int left_pos = cl.LeftInclusiveCount(_node.Address, c.Address);
      if( left_pos < DESIRED_NEIGHBORS ) {
        //We lost a close friend.
        Address target = new DirectionalAddress(DirectionalAddress.Direction.Left);
        short ttl = (short)DESIRED_NEIGHBORS;
        string contype = STRUC_NEAR;
        ISender send = new AHSender(_node, target, ttl, AHHeader.Options.Last);
        ConnectTo(send, target, contype, 1);
      }
    }
Пример #8
0
  public static int Main(string[] args) {

    /**
     * Get the arguments
     */
    if( args.Length < 2 ) {
      Console.Error.WriteLine("usage: SNodeExample.exe [tcp|udp] port remota_ta0 remote_ta1 ...");
      return 0;
    }

    /**
     * Make the edge listener:
     */
    Brunet.EdgeListener el = null;
    int port = Int32.Parse( args[1] );
    if( args[0].ToLower() == "tcp" ) {
      el = new Brunet.TcpEdgeListener(port);
    }
    else if( args[0].ToLower() == "udp" ) {
      el = new Brunet.UdpEdgeListener(port);
    }
    /**
     * Create a random address for our node.
     * Some other application might want to select the address
     * a particular way, or reuse a previously selected random
     * address.  If the addresses are not random (or the output
     * of secure hashes) the network might not behave correctly.
     */
    RandomNumberGenerator rng = new RNGCryptoServiceProvider();
    Brunet.AHAddress tmp_add = new Brunet.AHAddress(rng);
    Console.WriteLine("Address: {0}", tmp_add);
    /**
     * Make the node that lives in a particular
     * namespace (or realm) called "testspace"
     */
    Brunet.Node tmp_node = new Brunet.StructuredNode(tmp_add, "testspace");
    Brunet.ReqrepManager rrman = Brunet.ReqrepManager.GetInstance(tmp_node);
    ReqrepExample irh = new ReqrepExample();
    tmp_node.GetTypeSource(PType.Protocol.Chat).Subscribe(irh, tmp_node);
    /**
     * Add the EdgeListener
     */
    tmp_node.AddEdgeListener( el );
    /**
     * Tell the node who it can connect to:
     */
    for(int i = 2; i < args.Length; i++) {
      tmp_node.RemoteTAs.Add( TransportAddressFactory.CreateInstance( args[i] ) );
    }
    /**
     * Now we connect
     */
    tmp_node.Connect();
    Console.WriteLine("Connected");
    /**
     * In a real application, we would create some IAHPacketHandler
     * objects and do:
     * tmp_node.Subscribe( )
     * finally, we could send packets using tmp_node.Send( ) or
     * tmp_node.SendTo( )
     */
    string msg = "";
    System.Text.Encoding coder = new System.Text.ASCIIEncoding();
    while( true ) {
     Console.Write("To: ");
     msg = Console.ReadLine();
     if ( msg == "q" ) { break; }
     Address dest = AddressParser.Parse(msg);
     while( msg != "." ) {
      msg = Console.ReadLine();
      int length = coder.GetByteCount(msg);
      byte[] payload = new byte[length];
      coder.GetBytes(msg, 0, msg.Length, payload, 0);
      ISender sender = new AHSender(tmp_node, dest);
      rrman.SendRequest(sender, ReqrepManager.ReqrepType.Request,
                        new CopyList(PType.Protocol.Chat, MemBlock.Reference(payload)),
			irh , null);
     }
    }
	 
    return 1;
  }
Пример #9
0
  /**
   * Here we handle routing AHPackets
   */
  public void HandleData(MemBlock data, ISender ret_path, object state) {
    /*
     * Unfortunately, the old code needs the full header intact, and
     * we have already eaten a byte of it, put it back:
     */
    MemBlock full_packet = data.ExtendHead(1);
    AHPacket p = new AHPacket(full_packet);
    //Route avoiding the edge we got the packet from:
    IRouter router = null;
    if( p.Destination.Class == 0 ) {
      router = _ah_router;
    }
    else {
      router = _d_router;
    }
    Edge edge_rec_from = ret_path as Edge;
    bool deliver_locally;
    router.Route(edge_rec_from, p, out deliver_locally);
    if( deliver_locally ) {
      //Send a response exactly back to the node that sent to us
      ISender resp_send = new AHSender(_n, ret_path, p.Source,
                                       _n.DefaultTTLFor(p.Source),
                                       AHPacket.AHOptions.Exact);
      //data:
      _n.HandleData( data.Slice(AHPacket.HeaderLength), resp_send, this); 
    }

  }
Пример #10
0
    /**
    <summary>This is the generic Put that is used by both the regular Put and
    Create methods.  The use of the unique variable differentiates the two.
    This is asynchronous.  Results are stored in the Channel returns.
    Creates and Puts return true if successful or exception if there are
    network errors in adding the entry, creates also fail if a previous
    entry exists.  The work of determining success is handled in
    PutEnqueueHandler and PutCloseHandler.</summary>
    <param name="key">The index to store the value at.</param>
    <param name="value">The value to store.</param>
    <param name="ttl">The dht lease time for the key:value pair.</param>
    <param name="returns">The Channel where the result will be placed.</param>
    <param name="unique">True to do a create, false otherwise.</param>
    */
    public void AsPut(MemBlock key, MemBlock value, int ttl, Channel returns, bool unique) {
      if (!Activated) {
        throw new Exception("DhtClient: Not yet activated.");
      }

      returns.CloseAfterEnqueue();
      AsDhtPutState adps = new AsDhtPutState(returns);

      MemBlock[] brunet_address_for_key = MapToRing(key);
      Channel[] q = new Channel[DEGREE];
      lock(_adps_table.SyncRoot) {
        for (int k = 0; k < DEGREE; k++) {
          Channel queue = new Channel();
          queue.CloseAfterEnqueue();
          queue.CloseEvent += this.PutCloseHandler;
          _adps_table[queue] = adps;
          q[k] = queue;
        }
      }

      for (int k = 0; k < DEGREE; k++) {
        Address target = new AHAddress(brunet_address_for_key[k]);
        AHSender s = new AHSender(node, target, AHPacket.AHOptions.Greedy);
        _rpc.Invoke(s, q[k], "dht.Put", brunet_address_for_key[k], value, ttl, unique);
      }
    }
Пример #11
0
    public BlockingQueue[] PrimitiveGet(MemBlock key, int maxbytes, MemBlock token) {
      if (!Activated) {
        throw new Exception("DhtClient: Not yet activated.");
      }

      BlockingQueue[] q = new BlockingQueue[DEGREE];
      MemBlock[] b = MapToRing(key);

      for(int i = 0; i < DEGREE; i++) {
        Address target = new AHAddress(b[i]);
        AHSender s = new AHSender(node, target);
        q[i] = new BlockingQueue();
        _rpc.Invoke(s, q[i], "dht.Get", b[i], maxbytes, token);
      }
      return q;
    }
Пример #12
0
    public BlockingQueue[] PrimitivePut(MemBlock key, int ttl, MemBlock data, bool unique) {
      if (!Activated) {
        throw new Exception("DhtClient: Not yet activated.");
      }

      BlockingQueue[] q = new BlockingQueue[DEGREE];
      MemBlock[] b = MapToRing(key);

      for(int i = 0; i < DEGREE; i++) {
        Address target = new AHAddress(b[i]);
        AHSender s = new AHSender(node , target);
        q[i] = new BlockingQueue();
        _rpc.Invoke(s, q[i], "dht.Put", b[i], data, ttl, unique);
      }
      return q;
    }
Пример #13
0
    /**
     * This method is called when there is a Disconnection from
     * the ConnectionTable
     */
    protected void DisconnectHandler(object connectiontable, EventArgs args)
    { 
      ConnectionEventArgs ceargs = (ConnectionEventArgs)args;
      Connection c = ceargs.Connection;


      lock( _sync ) {
        _last_connection_time = DateTime.UtcNow;
        _need_left = -1;
        _need_right = -1;
        _need_short = -1;
        _need_bypass = -1;
        _current_retry_interval = _DEFAULT_RETRY_INTERVAL;
        _doubts_table.Remove(c.Address);
      }

      if( IsActive ) {
        if( c.MainType == ConnectionType.Structured ) {
          ConnectionList cl = ceargs.CList;
          int left_pos = cl.LeftInclusiveCount(_node.Address, c.Address);
          int right_pos = cl.RightInclusiveCount(_node.Address, c.Address);
          if( right_pos < DESIRED_NEIGHBORS ) {
            //We lost a close friend.
            Address target = new DirectionalAddress(DirectionalAddress.Direction.Right);
            short ttl = (short)DESIRED_NEIGHBORS;
            string contype = STRUC_NEAR;
            ISender send = new AHSender(_node, target, ttl, AHPacket.AHOptions.Last);
            ConnectTo(send, contype);
          }
          if( left_pos < DESIRED_NEIGHBORS ) {
            //We lost a close friend.
            Address target = new DirectionalAddress(DirectionalAddress.Direction.Left);
            short ttl = (short)DESIRED_NEIGHBORS;
            string contype = STRUC_NEAR;
            ISender send = new AHSender(_node, target, ttl, AHPacket.AHOptions.Last);
            ConnectTo(send, contype);
          }
          if( c.ConType == STRUC_SHORT ) {
            if( NeedShortcut ) {
              CreateShortcut();
            }
          }
          if (c.ConType == STRUC_BYPASS) {
            if (NeedBypass) {
              CreateBypass();
            }
          }
        }
        else {
          //Just activate and see what happens:
          Activate();
        }
      }
    }
Пример #14
0
  /**
   * Here we handle routing AHPackets
   */
  public void HandleData(MemBlock data, ISender ret_path, object st) {
    AHState state = _state; //Read the state, it can't change after the read
    var header = new AHHeader(data);
    var payload = data.Slice(header.Length);

    Connection next_con;
    //Check to see if we can use a Leaf connection:
    int dest_idx = state.Leafs.IndexOf(header.Destination);
    if( dest_idx >= 0 ) {
      next_con = state.Leafs[dest_idx];
    }
    else {
      var alg = state.GetRoutingAlgo(header);
      Pair<Connection, bool> result = alg.NextConnection(ret_path as Edge, header);
      if( result.Second ) {
        //Send a response exactly back to the node that sent to us
        var resp_send = new AHSender(_n, ret_path, header.Source,
                                       _n.DefaultTTLFor(header.Source),
                                       AHHeader.Options.Exact);
        _n.HandleData( payload, resp_send, this); 
      }
      next_con = result.First;
    }
    //Send it on:
    if( next_con != null ) {
      //Now we do the sending:
      var new_packet = new CopyList(PType.Protocol.AH,
                                    header.IncrementHops(),
                                    payload);
      try {
        next_con.Edge.Send(new_packet);
      }
      catch(EdgeException) {
        //Just drop the packet...
      }
    }
  }
    ///////////////// 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);
      }
    }
Пример #16
0
    virtual protected void ConnectTo(Address target, string ConnectionType) {
      ConnectionType mt = Connection.StringToMainType(ConnectionType);
      /*
       * This is an anonymous delegate which is called before
       * the Connector starts.  If it returns true, the Connector
       * will finish immediately without sending an ConnectToMessage
       */
      Linker l = new Linker(_node, target, null, ConnectionType,
          _node.Address.ToString());
      object link_task = l.Task;
      Connector.AbortCheck abort = delegate(Connector c) {
        bool stop = false;
        stop = _node.ConnectionTable.Contains( mt, target );
        if (!stop ) {
          /*
           * Make a linker to get the task.  We won't use
           * this linker.
           * No need in sending a ConnectToMessage if we
           * already have a linker going.
           */
          stop = _node.TaskQueue.HasTask( link_task );
        }
        return stop;
      };
      if (abort(null)) {
        return;
      }

      ConnectToMessage  ctm = new ConnectToMessage(ConnectionType, _node.GetNodeInfo(8),
          _node.Address.ToString());
      ISender send = new AHSender(_node, target, AHPacket.AHOptions.Exact);
      Connector con = new Connector(_node, send, ctm, this);
      con.FinishEvent += ConnectorEndHandler;
      con.AbortIf = abort;
      _node.TaskQueue.Enqueue(con);
    }
Пример #17
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());
 }