Inheritance: ISender
Example #1
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());
    }
 public ForwardingSender(Node n, Address forwarder, Address destination)
     : this(n, forwarder, AHHeader.Options.Exact, destination,
            AHSender.DefaultTTLFor(n.NetworkSize), AHHeader.Options.Annealing)
 {
 }
Example #3
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,
                                       AHSender.DefaultTTLFor(_n.NetworkSize),
                                       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);
      }
    }
    /**
     * 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);
      }
    }
        ///////////////// 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);
            }
        }
Example #7
0
 public void HandleData(AHHeader header, ICopyable payload, ISender ret_path, object st) {
   AHState state = _state; //Read the state, it can't change after the read
   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, 
                                      AHSender.DefaultTTLFor(_n.NetworkSize),
                                      AHHeader.Options.Exact, header.Hops);
       MemBlock data = payload as MemBlock;
       if(data == null) {
         // Try to get the shared BufferAllocator, useful when we don't know
         // how big the data is, which in general is just as expensive as
         // doing a CopyTo...
         BufferAllocator ba = Interlocked.Exchange<BufferAllocator>(ref _ba, null);
         if( ba != null ) {
           try {
             int length = payload.CopyTo(ba.Buffer, ba.Offset);
             data = MemBlock.Reference(ba.Buffer, ba.Offset, length);
             ba.AdvanceBuffer(length);
           } catch(System.Exception x) {
             throw new SendException(false, "could not write the packet, is it too big?", x);
           } finally {
             Interlocked.Exchange<BufferAllocator>(ref _ba, ba);
           }
         } else {
           data = MemBlock.Copy(payload);
         }
       }
       _n.HandleData( data, 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.State.Edge.Send(new_packet);
     }
     catch(SendException) {
       //Just drop the packet...
     }
   }
 }
Example #8
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);
            }
        }
Example #9
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);
   }
 }
Example #10
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) 
                          );
 }
Example #11
0
 public object[] proxy(string node, int ahOptions, int maxResultsToWait, 
     string method, params object[] args) {
   Address target = AddressParser.Parse(node);
   AHSender s = new AHSender(_node, target, (ushort)ahOptions);
   return this.Proxy(s, maxResultsToWait, method, args);
 }
Example #12
0
        public void HandleData(AHHeader header, ICopyable payload, ISender ret_path, object st)
        {
            AHState    state = _state; //Read the state, it can't change after the read
            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,
                                                 AHSender.DefaultTTLFor(_n.NetworkSize),
                                                 AHHeader.Options.Exact, header.Hops);
                    MemBlock data = payload as MemBlock;
                    if (data == null)
                    {
                        // Try to get the shared BufferAllocator, useful when we don't know
                        // how big the data is, which in general is just as expensive as
                        // doing a CopyTo...
                        BufferAllocator ba = Interlocked.Exchange <BufferAllocator>(ref _ba, null);
                        if (ba != null)
                        {
                            try {
                                int length = payload.CopyTo(ba.Buffer, ba.Offset);
                                data = MemBlock.Reference(ba.Buffer, ba.Offset, length);
                                ba.AdvanceBuffer(length);
                            } catch (System.Exception x) {
                                throw new SendException(false, "could not write the packet, is it too big?", x);
                            } finally {
                                Interlocked.Exchange <BufferAllocator>(ref _ba, ba);
                            }
                        }
                        else
                        {
                            data = MemBlock.Copy(payload);
                        }
                    }
                    _n.HandleData(data, 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.State.Edge.Send(new_packet);
                }
                catch (SendException) {
                    //Just drop the packet...
                }
            }
        }