/** * @returns an enumerator for the local tunnel TAs. */ public IEnumerator GetEnumerator() { ArrayList nearest = _node.ConnectionTable.GetNearestTo( (AHAddress) _node.Address, 6); ArrayList forwarders = new ArrayList(); foreach(Connection cons in nearest) { #if TUNNEL_DEBUG Console.Error.WriteLine("TunnelEdgeListener: testing if we can tunnel using node: {0}", cons.Address); #endif if (cons.Edge.TAType != TransportAddress.TAType.Tunnel) { forwarders.Add(cons.Address); #if TUNNEL_DEBUG Console.Error.WriteLine("TunnelEdgeListener: added node: {0} to tunnel TA", cons.Address); #endif } } if (forwarders.Count >= MIN_FORWARDERS ) { TransportAddress tun_ta = new TunnelTransportAddress(_node.Address, forwarders); #if TUNNEL_DEBUG Console.Error.WriteLine("TunnelEdgeListener: built tunnel TA: {0}", tun_ta); #endif yield return tun_ta; } }
/** * 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); } } }
/** * When we get an a response to an EdgeRequest, we handle it here. * @param remoteid remote id for the edge. * @param localid local id for the edge. * @param rest_of_payload control message. */ protected void HandleEdgeResponse(int remoteid, int localid, MemBlock rest_of_payload) { //assert (localid > 0) #if TUNNEL_DEBUG Console.Error.WriteLine("Receiving edge response"); #endif //possible response to our create edge request, make sure this //is the case by verifying the remote TA 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]))); } TunnelEdge e; EdgeCreationState ecs = null; lock( _sync ) { //This gets the edge with the matching ids: e = GetTunnelEdge(localid, 0); if (e != null) { #if TUNNEL_DEBUG Console.Error.WriteLine("Must verify the remoteTA for the response"); #endif TunnelTransportAddress remote_ta = new TunnelTransportAddress(target, forwarders); #if TUNNEL_DEBUG Console.Error.WriteLine("response.RemoteTA: {0}", remote_ta); Console.Error.WriteLine("edge.RemoteTA: {0}", e.RemoteTA); #endif TunnelTransportAddress e_rta = e.RemoteTA as TunnelTransportAddress; if (e_rta != null && e_rta.Target.Equals( remote_ta.Target ) ) { //Make sure they are trying to talk to us by checking //that the TA points to the same node e.RemoteID = remoteid; #if TUNNEL_DEBUG Console.Error.WriteLine("Edge protocol complete: {0}", e); #endif //raise an edge creation event //this was an outgoing edge ecs = (EdgeCreationState) _ecs_ht[localid]; _ecs_ht.Remove(localid); } else { //remote TAs do not match (ignore) } } else { //We had no matching edge, or already handled this response } } //End of the lock if( ecs != null ) { try { e.CloseEvent += this.CloseHandler; //this would be an outgoing edge #if TUNNEL_DEBUG Console.Error.WriteLine("remoteid: {0}, localid: {1}", remoteid, localid); Console.Error.WriteLine("announcing tunnel edge (outgoing): {0}", e); #endif ecs.CallECB(true, e, null); } catch(EdgeException) { /* * This edge has already closed so we need to handle it. * Note that we don't need to do CallECB which is handled * by the TimeoutChecker function. */ CloseHandler(e, null); } } else { //This must have already been handled, we don't want to create //more than one edge, just ignore it. } }
/** * 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); } }
protected static TransportAddress NoCacheCreateInstance(string s) { string scheme = s.Substring(0, s.IndexOf(":")); string t = scheme.Substring(scheme.IndexOf('.') + 1); //Console.Error.WriteLine(t); TransportAddress result = null; TransportAddress.TAType ta_type = StringToType(t); if (ta_type == TransportAddress.TAType.Tcp) { result = new IPTransportAddress(s); } if (ta_type == TransportAddress.TAType.Udp) { result = new IPTransportAddress(s); } if (ta_type == TransportAddress.TAType.Function) { result = new IPTransportAddress(s); } if (ta_type == TransportAddress.TAType.Tls) { result = new IPTransportAddress(s); } if (ta_type == TransportAddress.TAType.TlsTest) { result = new IPTransportAddress(s); } if (ta_type == TransportAddress.TAType.Tunnel) { result = new TunnelTransportAddress(s); } return result; }
public void Test() { TransportAddress ta1 = TransportAddressFactory.CreateInstance("brunet.udp://10.5.144.69:5000"); Assert.AreEqual(ta1.ToString(), "brunet.udp://10.5.144.69:5000", "Testing TA parsing"); TransportAddress ta2 = TransportAddressFactory.CreateInstance("brunet.udp://10.5.144.69:5000"); Assert.AreEqual(ta1, ta2, "Testing TA Equals"); string ta_string = "brunet.tunnel://UBU72YLHU5C3SY7JMYMJRTKK4D5BGW22/FE4QWASN+FE4QWASM"; TransportAddress ta = TransportAddressFactory.CreateInstance("brunet.tunnel://UBU72YLHU5C3SY7JMYMJRTKK4D5BGW22/FE4QWASN+FE4QWASM"); Assert.AreEqual(ta.ToString(), ta_string, "testing tunnel TA parsing"); //Console.WriteLine(ta); TunnelTransportAddress tun_ta = (TunnelTransportAddress) TransportAddressFactory.CreateInstance("brunet.tunnel://OIHZCNNUAXTLLARQIOBNCUWXYNAS62LO/CADSL6GV+CADSL6GU"); ArrayList fwd = new ArrayList(); fwd.Add(new AHAddress(Base32.Decode("CADSL6GVVBM6V442CETP4JTEAWACLC5A"))); fwd.Add(new AHAddress(Base32.Decode("CADSL6GUVBM6V442CETP4JTEAWACLC5A"))); TunnelTransportAddress test_ta = new TunnelTransportAddress(tun_ta.Target, fwd); Assert.AreEqual(tun_ta, test_ta, "testing tunnel TA compression enhancements"); //Console.WriteLine(tun_ta.ToString()); //Console.WriteLine(test_ta.ToString()); Assert.AreEqual(tun_ta.ToString(), test_ta.ToString(), "testing tunnel TA compression enhancements (toString)"); Assert.AreEqual(tun_ta.ContainsForwarder(new AHAddress(Base32.Decode("CADSL6GVVBM6V442CETP4JTEAWACLC5A"))), true, "testing tunnel TA contains forwarder (1)"); Assert.AreEqual(tun_ta.ContainsForwarder(new AHAddress(Base32.Decode("CADSL6GUVBM6V442CETP4JTEAWACLC5A"))), true, "testing tunnel TA contains forwarder (2)"); string StrLocalHost = Dns.GetHostName(); IPHostEntry IPEntry = Dns.GetHostEntry(StrLocalHost); TransportAddress local_ta = TransportAddressFactory.CreateInstance("brunet.udp://" + IPEntry.AddressList[0].ToString() + ":" + 5000); IEnumerable locals = TransportAddressFactory.CreateForLocalHost(TransportAddress.TAType.Udp, 5000); bool match = false; foreach (TransportAddress test_ta1 in locals) { //Console.WriteLine("test_ta: {0}", test_ta1); if (test_ta1.Equals(local_ta)) { match = true; } } Assert.AreEqual(match, true, "testing local TA matches"); //testing function TA TransportAddress func_ta = TransportAddressFactory.CreateInstance("brunet.function://localhost:3000"); TransportAddress func_ta2 = TransportAddressFactory.CreateInstance("brunet.function://localhost:3000"); Assert.AreEqual(func_ta, func_ta2, "equality of instances"); Assert.IsTrue(func_ta == func_ta2, "reference equality, test of caching"); Assert.AreEqual(func_ta.ToString(), "brunet.function://localhost:3000", "Testing function TA parsing"); }
protected static TransportAddress NoCacheCreateInstance(string s) { string scheme = s.Substring(0, s.IndexOf(":")); string t = scheme.Substring(scheme.IndexOf('.') + 1); //Console.Error.WriteLine(t); TransportAddress result = null; TransportAddress.TAType ta_type = StringToType(t); switch(ta_type) { case TransportAddress.TAType.Tcp: result = new IPTransportAddress(s); break; case TransportAddress.TAType.Udp: result = new IPTransportAddress(s); break; case TransportAddress.TAType.Function: result = new IPTransportAddress(s); break; case TransportAddress.TAType.S: result = new SimulationTransportAddress(s); break; case TransportAddress.TAType.Tls: result = new IPTransportAddress(s); break; case TransportAddress.TAType.TlsTest: result = new IPTransportAddress(s); break; case TransportAddress.TAType.Tunnel: result = new TunnelTransportAddress(s); break; } return result; }
/** * Handle a synchornization packet from tunnel edge target. * @param forwarders list of forwarding addresses the target is * using. */ public void HandleSyncPacket(ArrayList forwarders) { //This does not require a lock, and stuct_cons can't change after this call IEnumerable struct_cons = _node.ConnectionTable.GetConnections(ConnectionType.Structured); ArrayList temp_forwarders = new ArrayList(); ArrayList temp_senders = new ArrayList(); foreach(Connection c in struct_cons) { if(forwarders.Contains(c.Address)) { if(c.Edge.TAType != TAType) { temp_forwarders.Add(c.Address); temp_senders.Add(c.Edge); } } } TransportAddress new_local = new TunnelTransportAddress(_node.Address, temp_forwarders); TransportAddress new_remote = new TunnelTransportAddress(_target, temp_forwarders); /* * We are clearly only holding on lock in the below code * since we are only writing to memory and not calling any * functions */ lock(_sync) { _forwarders = temp_forwarders; _packet_senders = temp_senders; _localta = new_local; _remoteta = new_remote; } #if TUNNEL_DEBUG Console.Error.WriteLine("Synchronized edge: {0}.", this); #endif if (temp_forwarders.Count == 0) { //Now we have no forwarders, so close the edge Close(); } }