Inheritance: ICopyable
Example #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);
   }
 }
Example #2
0
 /**
 <summary>Sends the data over the multicast socket.</summary>
 <param name="data">The data to send.</summary>
 */
 public override void Send(ICopyable data) {
   IPAddress[] ips = LocalIPAddresses;
   if(ips == null) {
     ips = IPHandler.GetLocalIPAddresses();
   }
   // Silly users can trigger a handful of exceptions here...
   try {
     data = new CopyList(IPHandler.MagicCookie, data);
     byte[] buffer = new byte[data.Length];
     int length = data.CopyTo(buffer, 0);
     // I REALLY HATE THIS but we can't be setting this option in more than one thread!
     lock(_s) {
       foreach(IPAddress ip in ips) {
         /*
          * This can throw an exception on an invalid address, we need to skip it and move on!
          * Never showed to be an issue in Linux, but Windows does some weird things.
          */
         try {
           _s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface,
                             IPHandler.IPAddressToInt(ip));
         }
         catch {
           continue;
         }
         _s.SendTo(buffer, 0, length, 0, EndPoint);
       }
     }
   }
   catch(System.Net.Sockets.SocketException sx) {
     throw new SendException(true, "SocketException", sx);
   }
   // Can't pass the fact that the IPHandler is not running :-/
   catch (ObjectDisposedException odx) {
     throw new SendException(false, "Socket appears to be disposed", odx);
   }
   catch (Exception e) {
     ProtocolLog.WriteIf(ProtocolLog.Exceptions, "ERROR: " + e);
     throw new SendException(true, "Socket appears to be disposed", e);
   }
 }
Example #3
0
    /**
    <summary>Sends the data over the unicast socket.</summary>
    <param name="data">The data to send.</summary>
    */
    public virtual void Send(ICopyable data) {
      // Silly users can trigger a handful of exceptions here...
      try {
        data = new CopyList(IPHandler.MagicCookie, data);
        byte[] buffer = new byte[data.Length];
        int length = data.CopyTo(buffer, 0);

        _s.SendTo(buffer, 0, length, 0, EndPoint);
      }
      catch(System.Net.Sockets.SocketException sx) {
        throw new SendException(true, "SocketException", sx);
      }
      catch (ObjectDisposedException odx) {
        throw new SendException(false, "Socket appears to be disposed", odx);
      }
      catch (Exception e) {
        ProtocolLog.WriteIf(ProtocolLog.Exceptions, "ERROR: " + e);
        throw new SendException(true, "Socket appears to be disposed", e);
      }
    }
Example #4
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...
      }
    }
  }
Example #5
0
    override protected bool HandleOutgoing(ICopyable app_data, out ICopyable data)
    {
      MemBlock buffer = null;
      data = null;
      int written = 1;
      lock(_buffer_sync) {
        if(app_data != null) {
          int count = app_data.CopyTo(_buffer, 0);
          written = _ssl.Write(_buffer, count);
        }

        if(written > 0) {
          int count = _write.Read(_buffer, _buffer.Length);
          if(count <= 0) {
            // This really shouldn't ever happen
            ProtocolLog.WriteIf(ProtocolLog.SecurityExceptions, this + " error");
            data = null;
            return false;
          }

          buffer = MemBlock.Copy(_buffer, 0, count);
        }
      }

      if(written > 0) {
        // Timer becomes -1 when there are no more control messages
        long to = _ssl.GetTimeout();
        if(to >= 0) {
          HandleWouldBlock();
        }

        if(buffer != null) {
          data = new CopyList(PType, Header, buffer);
          return true;
        }
      }

      // If the write failed, then Dtls is either waiting for a control message
      // or has a control message to send
      var error = _ssl.GetError(written);
      if(error == SslError.SSL_ERROR_WANT_READ) {
        HandleWouldBlock();
      } else if(error == SslError.SSL_ERROR_SSL) {
        var ose = new OpenSslException();
        Close("Received unrecoverable error: " + ose.ToString());
        throw ose;
      } else {
        ProtocolLog.WriteIf(ProtocolLog.SecurityExceptions, "Send other");
      }
      data = null;
      return false;
    }
Example #6
0
 /**
  * Abandon any attempts to get requests for the given ID.
  * @throw Exception if handler is not the original handler for this Request
  */
 public void StopRequest(int request_id, IReplyHandler handler) {
   RequestState rs = null;
   lock( _sync ) {
     if( !_req_state_table.TryTake(request_id, out rs)) {
       rs = null;
     }
   }
   if( rs != null ) {
      /*
       * Send an ack for this reply:
       */
      byte[] ack_payload = new byte[5];
      ack_payload[0] = (byte)ReqrepType.ReplyAck;
      NumberSerializer.WriteInt(request_id, ack_payload, 1);
      ICopyable data = new CopyList(_prefix, MemBlock.Reference(ack_payload));
      foreach(ISender ret_path in rs.Repliers) {
        try {
          //Try to send an ack, but if we can't, oh well...
          ret_path.Send(data);
        }
        catch { }
      }
   }
 }
Example #7
0
    /// <summary>Constructor for a RelayEdge, RemoteID == -1 for out bound.</summary>
    public RelayEdge(IEdgeSendHandler send_handler, RelayTransportAddress local_ta,
        RelayTransportAddress remote_ta, IForwarderSelector ias, List<Connection> overlap,
        int remote_id) : base(send_handler, remote_id != -1)
    {
      _remote_id = remote_id;
      lock(_rand) {
        LocalID = _rand.Next();
      }
      byte[] bid = new byte[8];
      NumberSerializer.WriteInt(LocalID, bid, 0);
      NumberSerializer.WriteInt(_remote_id, bid, 4);
      _mid = MemBlock.Reference(bid);
      _local_ta = local_ta;
      _remote_ta = remote_ta;
      _tunnels = new List<Connection>(overlap);
      _ias = ias;
      _ias.Update(_tunnels);

      AHHeader ahh = new AHHeader(1, 20, local_ta.Target, remote_ta.Target,
          AHHeader.Options.Exact);
      ICopyable header = new CopyList(PType.Protocol.AH, ahh,
          PType.Protocol.Relaying);
      Header = MemBlock.Copy(header);
    }
Example #8
0
  /**
   * This is how you invoke a method on a remote host.
   * Results are put into the Channel.
   * 
   * If you want to have an Event based approach, listen to the EnqueueEvent
   * on the Channel you pass for the results.  That will be fired
   * immediately from the thread that gets the result.
   *
   * When a result comes back, we put and RpcResult into the Channel.
   * When you have enough responses, Close the queue (please).  The code
   * will stop sending requests after the queue is closed.  If you never close
   * the queue, this will be wasteful of resources.
   *
   * @param target the sender to use when making the RPC call
   * @param q the Channel into which the RpcResult objects will be placed.
   *            q may be null if you don't care about the response.
   * @param method the Rpc method to call
   *
   * @throw Exception if we cannot send the request for some reason.
   */
  virtual public void Invoke(ISender target, Channel q, string method,
                              params object[] args)
  {
    //build state for the RPC call
    RpcRequestState rs = new RpcRequestState();
    rs.Results = q;
    rs.RpcTarget = target;

    object[] rpc_call = new object[2];
    rpc_call[0] = method;
    if( args != null ) {
      rpc_call[1] = args;
    }
    else {
      //There are no args, which we represent as a zero length list
      rpc_call[1] = new object[0];
    }
    
    AdrCopyable req_copy = new AdrCopyable(rpc_call);
#if RPC_DEBUG
    Console.Error.WriteLine("[RpcClient: {0}] Invoking method: {1} on target: {2}",
                     _rrman.Info, method, target);
#endif
    ICopyable rrpayload = new CopyList( PType.Protocol.Rpc, req_copy ); 
    int reqid = _rrman.SendRequest(target, ReqrepManager.ReqrepType.Request,
                                   rrpayload, this, rs);
  
    //Make sure we stop this request when the queue is closed.
    if( q != null ) {
      try {
        q.CloseEvent += delegate(object qu, EventArgs eargs) {
          _rrman.StopRequest(reqid, this);
       };
      }
      catch {
        if(q.Closed) {
          _rrman.StopRequest(reqid, this);
        }
        else {
          throw;
        }
      }
    }
  }
Example #9
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...
     }
   }
 }