Exemplo n.º 1
0
    /**
     * When we get an EdgeRequest message, this is where we handle it.
     * @param remoteid remote id for the edge. 
     * @param localid local id for the edge. 
     * @param rest_of_payload control message.
     * @param return_path return path for the packet
     */
    protected void HandleEdgeRequest(int remoteid, int localid, MemBlock rest_of_payload, ISender return_path)
    {
#if TUNNEL_DEBUG
        Console.Error.WriteLine("Receiving edge request");
#endif
        //probably a new incoming edge
        bool is_new_edge = true;
        bool send_edge_event = false;
        TunnelEdge e = null;

        ArrayList args = (ArrayList) AdrConverter.Deserialize(rest_of_payload);
        Address target = AddressParser.Parse(MemBlock.Reference((byte[]) args[0]));
        //list of packet forwarders
        ArrayList forwarders = new ArrayList();
        for (int i = 1; i < args.Count; i++) {
          forwarders.Add(AddressParser.Parse(MemBlock.Reference((byte[]) args[i])));
        }
        //it is however possible that we have already created the edge locally

        lock( _sync ) {
        TunnelEdge e_dup = (TunnelEdge) _remote_id_ht[remoteid];
        if (e_dup != null) {
          TunnelTransportAddress remote_ta = new TunnelTransportAddress(target, forwarders);          
          //compare TAs
          TunnelTransportAddress e_rta = e_dup.RemoteTA as TunnelTransportAddress;
            if (e_rta != null && e_rta.Target.Equals( remote_ta.Target ) ) {
            //the fellow sent a duplicate edge request
            is_new_edge = false;
#if TUNNEL_DEBUG
            Console.Error.WriteLine("Duplicate edge request: from {0}", remote_ta);
#endif
            //but do send a response back
            //we also have to send a response back now
          } else {
            //someone else guessed the same id on its side
            //still okay, we can generate a unqiue id locally
          }
        } else {
          //this is the first edge request from a node and also
          //has a unique id on its side
          
        }
        if(is_new_edge) {
          do {
            localid = _rand.Next();
            //Make sure not to use negative ids
            if( localid < 0 ) { localid = ~localid; }
          } while( _id_ht.Contains(localid) || localid == 0 );
          
          //create an edge
          e = new TunnelEdge(this, true, _node, target, forwarders, localid, remoteid); 
#if TUNNEL_DEBUG
          Console.Error.WriteLine("Creating an instance of TunnelEdge: {0}", e);
          Console.Error.WriteLine("remoteid: {0}, localid: {1}", remoteid, localid);
#endif      

          _id_ht[localid] = e;
          _remote_id_ht[remoteid] = e;
          try {
            e.CloseEvent += this.CloseHandler;
          }
          catch {
            CloseHandler(e, null);
            throw;
          }
#if TUNNEL_DEBUG
          Console.Error.WriteLine("announcing tunnel edge (incoming): {0}", e);
#endif 
          send_edge_event = true;
        }
      }//Drop the lock

      /*
       * No matter what, we send a response back now
       */
        Packet p = null;
        using(MemoryStream ms = new MemoryStream()) {
          ms.WriteByte((byte) MessageType.EdgeResponse);
          NumberSerializer.WriteInt(localid, ms);
          NumberSerializer.WriteInt(remoteid, ms);
        
          //overwrite the first address in the edge response
          args[0] = _node.Address.ToMemBlock();

          AdrConverter.Serialize(args, ms);
          p = new AHPacket(1, 2, _node.Address, target, AHPacket.AHOptions.Exact, 
                                AHPacket.Protocol.Tunneling, ms.ToArray());
        }
        //send using the edge we received data on
#if TUNNEL_DEBUG
        Console.Error.WriteLine("Sending edge response: {0}", p);
#endif
        try {
          AHSender ahs = (AHSender)return_path;
          Edge from = (Edge)ahs.ReceivedFrom;
          from.Send(p);
#if TUNNEL_DEBUG
        } catch (Exception ex) {

          Console.Error.WriteLine(ex);
#else
        } catch (Exception) {
#endif
        }
        finally {
          if( send_edge_event ) {
            SendEdgeEvent(e);
          }
        }
    }
Exemplo n.º 2
0
    /**
     * This method creates an instance of a tunnel edge to a remote node, given its 
     * tunnel transport URI.
     * @param ta TransportAddress to create an edge to
     * @param ecb the EdgeCreationCallback to call when done
     * @throw EdgeException if we try to call this before calling
     * Start.
     */
    public override void CreateEdgeTo(TransportAddress ta, EdgeCreationCallback ecb) 
    {
      try {
      if (!IsStarted) {
        throw new EdgeException("TunnelEdgeListener not started");
      }
      else if (0 == _running) {
        throw new EdgeException("TunnelEdgeListener not running");
      }
      else if (ta.TransportAddressType != this.TAType) {
	throw new EdgeException(ta.TransportAddressType.ToString()
				+ " is not my type: " + this.TAType.ToString());
      }
      else {
#if TUNNEL_DEBUG
        Console.Error.WriteLine("CreateEdgeTo TunnelEdge to: {0}", ta);
#endif  
        TunnelTransportAddress tun_ta = ta as TunnelTransportAddress;
        ArrayList forwarders = new ArrayList();
        ArrayList forwarding_edges = new ArrayList();
#if TUNNEL_DEBUG
        Console.Error.WriteLine("TunnelEdgeListener: Finding structured connections to tunnel over");
#endif
        IEnumerable struc_cons = _node.ConnectionTable.GetConnections(ConnectionType.Structured);
        if (struc_cons ==  null) {
#if TUNNEL_DEBUG
          Console.Error.WriteLine("List of structured connections is null");
#endif 
        }
#if TUNNEL_DEBUG
        Console.Error.WriteLine("TunnelEdgeListener: Browsing list of structured connections");
#endif
        foreach (Connection con in struc_cons) {
#if TUNNEL_DEBUG
          Console.Error.WriteLine("TunnelEdgeListener: Testing : {0}", con.Address);
#endif
          if (con.Edge.TAType == TransportAddress.TAType.Tunnel) {
#if TUNNEL_DEBUG
            Console.Error.WriteLine("Cannot tunnel over tunnel: " + con.Address.ToString());
#endif
            continue;
          }
          if (!tun_ta.ContainsForwarder(con.Address)) {
#if TUNNEL_DEBUG
            Console.Error.WriteLine("Cannot tunnel over connection: " + con.Address.ToString());
#endif
            continue;
          }
#if TUNNEL_DEBUG
          Console.Error.WriteLine("Can tunnel over connection: " + con.Address.ToString());
#endif
          forwarders.Add(con.Address);
          forwarding_edges.Add(con.Edge);
        }

        if (forwarders.Count < MIN_FORWARDERS) {
          ecb(false, null, new EdgeException("Cannot create edge over TA: " + tun_ta + ", not many forwarders"));
          return;
        }
        tun_ta = new TunnelTransportAddress(tun_ta.Target, forwarders);
        
        //choose a locally unique id
        lock( _sync ) {
          //Get a random ID for this edge:
          int localid;
          int remoteid = 0;
          do {
            localid = _rand.Next();
            //Make sure we don't have negative ids
            if( localid < 0 ) { localid = ~localid; }
          } while( _id_ht.Contains(localid) || localid == 0 );      
          //looks like the new edge is ready
          TunnelEdge e = new TunnelEdge(this, false, _node, tun_ta.Target, forwarders, localid, remoteid);
#if TUNNEL_DEBUG
          Console.Error.WriteLine("Creating an instance of TunnelEdge: {0}", e);
          Console.Error.WriteLine("remoteid: {0}, localid: {1}", remoteid, localid);
#endif      
          _id_ht[localid] = e;
          //we will defer the new edge event for later
          //when we actually get a response
          
          //now build the packet payload
          Packet p = null;
          using(MemoryStream ms = new MemoryStream()) {
            ms.WriteByte((byte) MessageType.EdgeRequest);
            NumberSerializer.WriteInt(localid, ms);
            NumberSerializer.WriteInt(remoteid, ms);
    #if TUNNEL_DEBUG
            Console.Error.WriteLine("Written off type, localid, remoteid");
    #endif
            
            ArrayList args = new ArrayList();
            //add the target address
            byte[] addr_bytes = new byte[Address.MemSize];
            _node.Address.CopyTo(addr_bytes);
            args.Add(addr_bytes.Clone());
    #if TUNNEL_DEBUG
            Console.Error.WriteLine("Added target address");
    #endif
            
            foreach (Address fwd in  forwarders) {
              //add forwarding addresses
              fwd.CopyTo(addr_bytes);
              args.Add(addr_bytes.Clone());
    #if TUNNEL_DEBUG
              Console.Error.WriteLine("Added a forwarding address");
    #endif
    
            }
    #if TUNNEL_DEBUG
            Console.Error.WriteLine("Creating a memory stream holding the payload");
    #endif
            AdrConverter.Serialize(args, ms);
            p = new AHPacket(1, 2, _node.Address, tun_ta.Target, AHPacket.AHOptions.Exact, 
                                 AHPacket.Protocol.Tunneling, ms.ToArray());
          }
#if TUNNEL_DEBUG
          Console.Error.WriteLine("Created a request packet.");
#endif
          EdgeCreationState ecs = new EdgeCreationState(localid, forwarding_edges, p, ecb);
          _ecs_ht[localid] = ecs;

#if TUNNEL_DEBUG
          Console.Error.WriteLine("Created an edge creation state for the tunnel edge: {0}", e);
#endif
        }
      }
      //we will defer this sending to next heartbeat; an artificial delay from out own side
      } catch(Exception e) {
	ecb(false, null, e);
      }
    }