Exemple #1
0
 protected AHHeader(short hops, AHHeader head) {
   //Set a new number of hops:
   Hops = hops;
   //Copy the rest:
   Ttl = head.Ttl;
   Opts = head.Opts;
   _src = head._src; 
   _dest = head._dest; 
   _data = head._data;
 }
  public void Send(ICopyable data) {
    /*
     * Assemble an AHPacket:
     */
    if( _header == null ) {
      AHHeader ahh = new AHHeader(_hops, _ttl, _source, _dest, _options);
      _header = MemBlock.Copy(new CopyList( PType.Protocol.AH, ahh));
      _header_length = _header.Length;
    }
    byte[] ah_packet;
    int packet_length;
    int packet_offset;

    //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 _buf_alloc, null);
    if( ba != null ) {
      try {
        ah_packet = ba.Buffer;
        packet_offset = ba.Offset;
        int tmp_off = packet_offset;
        tmp_off += _header.CopyTo(ah_packet, packet_offset);
        tmp_off += data.CopyTo(ah_packet, tmp_off);
        packet_length = tmp_off - packet_offset;
        ba.AdvanceBuffer(packet_length);
      }
      catch(System.Exception x) {
        throw new SendException(false, "could not write the packet, is it too big?", x);
      }
      finally {
        //Put the BA back
        Interlocked.Exchange<BufferAllocator>(ref _buf_alloc, ba);
      }
    }
    else {
      //Oh well, someone else is using the buffer, just go ahead
      //and allocate new memory:
      packet_offset = 0;
      packet_length = _header_length + data.Length;
      ah_packet = new byte[ packet_length ];
      int off_to_data = _header.CopyTo(ah_packet, 0);
      data.CopyTo(ah_packet, off_to_data);
    }
    MemBlock mb_packet = MemBlock.Reference(ah_packet, packet_offset, packet_length);
    /*
     * Now we announce this packet, the AHHandler will
     * handle routing it for us
     */
    _n.HandleData(mb_packet, _from, this);
  }
Exemple #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,
                                       _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...
      }
    }
  }
Exemple #4
0
 public AHRoutingAlgorithm GetRoutingAlgo(AHHeader head) {
   int addclass = head.Destination.Class;
   if( addclass == AHAddress.ClassValue ) {
     ushort opts = head.Opts;
     if( opts == AHHeader.Options.Last
      || opts == AHHeader.Options.Greedy ) {
       return _greedy;
     }
     else {
       return _annealing;
     }
   }
   else if( addclass == DirectionalAddress.ClassValue ) {
     return _directional;
   }
   else {
     throw new Exception(
     String.Format("No router for class: {0}", addclass));
   }
 }
Exemple #5
0
 public override Pair<Connection, bool> NextConnection(Edge from, AHHeader h) {
   DirectionalAddress dest = (DirectionalAddress)h.Destination;
   if( h.Ttl <= h.Hops ) {
     //Deliver it to us but stop it here:
     return _NULL_TRUE;
   }
   if ( dest.Bearing == DirectionalAddress.Direction.Left ) {
     if( h.Opts == AHHeader.Options.Path ) {
       return _LEFT_TRUE;    
     }
     else {
       return _LEFT_FALSE;
     }
   }
   else if (dest.Bearing == DirectionalAddress.Direction.Right) {
     if( h.Opts == AHHeader.Options.Path ) {
       return _RIGHT_TRUE;    
     }
     else {
       return _RIGHT_FALSE;
     }
   }
   else {
     throw new System.Exception(
         System.String.Format("Unrecognized direction: {0}", dest.Bearing));
   }
 }
Exemple #6
0
  public override Pair<Connection, bool> NextConnection(Edge from, AHHeader head) {
    Address dest = head.Destination;
    int d_idx = _structs.IndexOf(dest);
    if( d_idx >= 0 ) {
      //We have a direct connection:
      Connection next = _structs[d_idx];
      if( next != _local_con ) {
        return new Pair<Connection,bool>(next, false);
      }
      else {
        return new Pair<Connection, bool>(null, true);
      }
    }
    else {
      var ah_dest = (AHAddress)dest;
      int left_idx = ~d_idx;
      Connection l_c = _structs[left_idx];
      int right_idx = left_idx - 1;
      Connection r_c = _structs[right_idx];

      Connection next_con;
      Connection other_con;
      if( ah_dest.IsCloserToFirst((AHAddress)l_c.Address, (AHAddress)r_c.Address) ) {
        next_con = l_c;
        other_con = r_c;
      }
      else {
        next_con = r_c;
        other_con = l_c;
      }
      //See if we need to get it:
      /* everyone gets "path" packets,
       * if it's exact, only the destination gets it, handled above
       * otherwise, only the two nodes on either side of the destination get
       * it
       */
      bool local = head.Opts == AHHeader.Options.Path ||
                   ((next_con == _local_con || other_con == _local_con)
                    && head.Opts != AHHeader.Options.Exact);

      Connection to_send;
      //Check not to send it back the way it came:
      if(from == null) {
        /*
         * This packet is from us, so just send it to the closest
         * node, other than us.
         */
        to_send = _local_con != next_con ? next_con : other_con;
      }
      else if(next_con.Edge == from) {
        //Don't send it back the way it came:
        to_send = other_con;
      }
      else {
        //Great, the closest has not yet been visited:
        to_send = next_con;
      }
      //Now, make sure not to send it to ourselves:
      to_send = to_send == _local_con ? null : to_send;
      return new Pair<Connection, bool>(to_send, local);
    }
  }
Exemple #7
0
  public override Pair<Connection, bool> NextConnection(Edge from, AHHeader head) {
    Address dest = head.Destination;
    int d_idx = _structs.IndexOf(dest);
    Connection next_con;
    if( d_idx >= 0 ) {
      //We have a direct connection:
      next_con = _structs[d_idx];
    }
    else {
      //We have to check the right and the left:
      var ah_dest = (AHAddress)dest;
      int left_idx = ~d_idx;
      Connection l_c = _structs[left_idx];
      int right_idx = left_idx - 1;
      Connection r_c = _structs[right_idx];

      if( ah_dest.IsCloserToFirst((AHAddress)l_c.Address, (AHAddress)r_c.Address) ) {
        next_con = l_c;
      }
      else {
        next_con = r_c;
      }
      /*
       * Note, DO NOT DO COMPARISONS WITH INDEX VALUES!!!!!
       * do the the wrap around, _structs[x] == _structs[y]
       * when x = y + k * _structs.Count for all k, so equality
       * of Connection is not the same as equality of index
       */
      if( head.Hops >= head.Ttl ) {
        //Only deliver if we are the closest or last mode:
        bool local = next_con == _local_con || head.Opts == AHHeader.Options.Last;
        if( local ) {
          return _LOCAL;
        }
        else {
          return _NO_ONE;
        }
      }
    }
    return next_con == _local_con ? _LOCAL : new Pair<Connection, bool>(next_con, false);
  }
Exemple #8
0
 /** compute the next step in the route
  * @param from the Edge the packet came in on
  * @param head the header to route
  * @return next connection and bool indicating if local node should get
  * packet.  If there is no next connection, the connection will be null
  */
 public abstract Pair<Connection, bool> NextConnection(Edge from, AHHeader head);