/** * 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); } } }
/** * 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); } }