///////////////// Methods ////////////////////// /** * Starts the Overlord if we are active * * This method is called by the CheckState method * IF we have not seen any connections in a while * AND we still need some connections * */ public override void Activate() { #if POB_DEBUG Console.Error.WriteLine("In Activate: {0}", _node.Address); #endif if( IsActive == false ) { return; } DateTime now = DateTime.UtcNow; lock( _sync ) { if( now - _last_retry_time < _current_retry_interval ) { //Not time yet... return; } _last_retry_time = now; //Double the length of time we wait (resets to default on connections) _current_retry_interval += _current_retry_interval; _current_retry_interval = (_MAX_RETRY_INTERVAL < _current_retry_interval) ? _MAX_RETRY_INTERVAL : _current_retry_interval; } ConnectionTable tab = _node.ConnectionTable; //If we are going to connect to someone, this is how we //know who to use Address target = null; string contype = String.Empty; ISender sender = null; int desired_ctms = 1; ConnectionList structs = tab.GetConnections(ConnectionType.Structured); if( structs.Count < 2 ) { ConnectionList leafs = tab.GetConnections(ConnectionType.Leaf); if( leafs.Count == 0 ) { /* * We first need to get a Leaf connection */ return; } //We don't have enough connections to guarantee a connected //graph. Use a leaf connection to get another connection Connection leaf = null; //Make sure the following loop can't go on forever int attempts = 2 * leafs.Count; do { leaf = leafs[ _rand.Next( leafs.Count ) ]; attempts--; } while( leafs.Count > 1 && structs.Contains( leaf.Address ) && attempts > 0 ); //Now we have a random leaf that is not a //structured neighbor to try to get a new neighbor with: if( leaf != null ) { target = GetSelfTarget(); /* * This is the case of trying to find the nodes nearest * to ourselves, use the Annealing routing to get connected * more quickly */ sender = new ForwardingSender(_node, leaf.Address, target); //We are trying to connect to the two nearest nodes in one //one attempt, so wait for two distinct responses: desired_ctms = 2; //This is a near neighbor connection contype = STRUC_NEAR; } } if( structs.Count > 0 && sender == null ) { /** * We need left or right neighbors we send * a ConnectToMessage in the directons we * need. */ if( NeedLeftNeighbor ) { #if POB_DEBUG Console.Error.WriteLine("NeedLeftNeighbor: {0}", _node.Address); #endif target = new DirectionalAddress(DirectionalAddress.Direction.Left); short ttl = (short)DESIRED_NEIGHBORS; sender = new AHSender(_node, target, ttl, AHHeader.Options.Last); contype = STRUC_NEAR; } else if( NeedRightNeighbor ) { #if POB_DEBUG Console.Error.WriteLine("NeedRightNeighbor: {0}", _node.Address); #endif target = new DirectionalAddress(DirectionalAddress.Direction.Right); short ttl = (short)DESIRED_NEIGHBORS; sender = new AHSender(_node, target, ttl, AHHeader.Options.Last); contype = STRUC_NEAR; } } if( sender != null ) { ConnectTo(sender, target, contype, desired_ctms); } }
/** * This method is called when there is a Disconnection from * the ConnectionTable */ protected void DisconnectHandler(object connectiontable, EventArgs args) { ConnectionEventArgs ceargs = (ConnectionEventArgs)args; Connection c = ceargs.Connection; lock( _sync ) { _last_connection_time = DateTime.UtcNow; _need_left = -1; _need_right = -1; _current_retry_interval = _DEFAULT_RETRY_INTERVAL; } if( !IsActive ) { return; } if( c.MainType != ConnectionType.Structured ) { //Just activate and see what happens: Activate(); return; } ConnectionList cl = ceargs.CList; int right_pos = cl.RightInclusiveCount(_node.Address, c.Address); if( right_pos < DESIRED_NEIGHBORS ) { //We lost a close friend. Address target = new DirectionalAddress(DirectionalAddress.Direction.Right); short ttl = (short)DESIRED_NEIGHBORS; string contype = STRUC_NEAR; ISender send = new AHSender(_node, target, ttl, AHHeader.Options.Last); ConnectTo(send, target, contype, 1); } int left_pos = cl.LeftInclusiveCount(_node.Address, c.Address); if( left_pos < DESIRED_NEIGHBORS ) { //We lost a close friend. Address target = new DirectionalAddress(DirectionalAddress.Direction.Left); short ttl = (short)DESIRED_NEIGHBORS; string contype = STRUC_NEAR; ISender send = new AHSender(_node, target, ttl, AHHeader.Options.Last); ConnectTo(send, target, contype, 1); } }
public void TestWriteAndParse() { Address a = new DirectionalAddress(DirectionalAddress.Direction.Left); TransportAddress ta = TransportAddressFactory.CreateInstance("brunet.tcp://127.0.0.1:5000"); NodeInfo ni = NodeInfo.CreateInstance(a, ta); RoundTripHT(ni); RoundTrip(ni); //Test multiple tas: ArrayList tas = new ArrayList(); tas.Add(ta); for(int i = 5001; i < 5010; i++) tas.Add(TransportAddressFactory.CreateInstance("brunet.tcp://127.0.0.1:" + i.ToString())); NodeInfo ni3 = NodeInfo.CreateInstance(a, tas); RoundTripHT(ni3); RoundTrip(ni3); //Test null address: NodeInfo ni4 = NodeInfo.CreateInstance(null, ta); RoundTripHT(ni4); RoundTrip(ni4); //No TAs: NodeInfo ni5 = NodeInfo.CreateInstance( a ); RoundTripHT(ni5); RoundTrip(ni5); }
public void CacheTest() { Address a = new DirectionalAddress(DirectionalAddress.Direction.Left); Address a2 = new DirectionalAddress(DirectionalAddress.Direction.Left); TransportAddress ta = TransportAddressFactory.CreateInstance("brunet.tcp://127.0.0.1:5000"); TransportAddress ta2 = TransportAddressFactory.CreateInstance("brunet.tcp://127.0.0.1:5000"); NodeInfo ni = NodeInfo.CreateInstance(a, ta); NodeInfo ni2 = NodeInfo.CreateInstance(a2, ta2); Assert.AreSame( ni, ni2, "Reference equality of NodeInfo objects"); }
public void CTMSerializationTest() { Address a = new DirectionalAddress(DirectionalAddress.Direction.Left); TransportAddress ta = TransportAddressFactory.CreateInstance("brunet.tcp://127.0.0.1:5000"); NodeInfo ni = NodeInfo.CreateInstance(a, ta); RandomNumberGenerator rng = new RNGCryptoServiceProvider(); AHAddress tmp_add = new AHAddress(rng); ConnectToMessage ctm1 = new ConnectToMessage(ConnectionType.Unstructured, ni, tmp_add.ToString()); HTRoundTrip(ctm1); //Test multiple tas: ArrayList tas = new ArrayList(); tas.Add(ta); for(int i = 5001; i < 5010; i++) tas.Add(TransportAddressFactory.CreateInstance("brunet.tcp://127.0.0.1:" + i.ToString())); NodeInfo ni2 = NodeInfo.CreateInstance(a, tas); ConnectToMessage ctm2 = new ConnectToMessage(ConnectionType.Structured, ni2, tmp_add.ToString()); HTRoundTrip(ctm2); //Here is a ConnectTo message with a neighbor list: NodeInfo[] neighs = new NodeInfo[5]; for(int i = 0; i < 5; i++) { string ta_tmp = "brunet.tcp://127.0.0.1:" + (i+80).ToString(); NodeInfo tmp = NodeInfo.CreateInstance(new DirectionalAddress(DirectionalAddress.Direction.Left), TransportAddressFactory.CreateInstance(ta_tmp) ); neighs[i] = tmp; } ConnectToMessage ctm3 = new ConnectToMessage("structured", ni, neighs, tmp_add.ToString()); HTRoundTrip(ctm3); #if false Console.Error.WriteLine( ctm3.ToString() ); foreach(NodeInfo tni in ctm3a.Neighbors) { Console.Error.WriteLine(tni.ToString()); } #endif }
/** * This method is called when there is a Disconnection from * the ConnectionTable */ protected void DisconnectHandler(object connectiontable, EventArgs args) { ConnectionEventArgs ceargs = (ConnectionEventArgs)args; Connection c = ceargs.Connection; lock( _sync ) { _last_connection_time = DateTime.UtcNow; _need_left = -1; _need_right = -1; _need_short = -1; _need_bypass = -1; _current_retry_interval = _DEFAULT_RETRY_INTERVAL; _doubts_table.Remove(c.Address); } if( IsActive ) { if( c.MainType == ConnectionType.Structured ) { ConnectionList cl = ceargs.CList; int left_pos = cl.LeftInclusiveCount(_node.Address, c.Address); int right_pos = cl.RightInclusiveCount(_node.Address, c.Address); if( right_pos < DESIRED_NEIGHBORS ) { //We lost a close friend. Address target = new DirectionalAddress(DirectionalAddress.Direction.Right); short ttl = (short)DESIRED_NEIGHBORS; string contype = STRUC_NEAR; ISender send = new AHSender(_node, target, ttl, AHPacket.AHOptions.Last); ConnectTo(send, contype); } if( left_pos < DESIRED_NEIGHBORS ) { //We lost a close friend. Address target = new DirectionalAddress(DirectionalAddress.Direction.Left); short ttl = (short)DESIRED_NEIGHBORS; string contype = STRUC_NEAR; ISender send = new AHSender(_node, target, ttl, AHPacket.AHOptions.Last); ConnectTo(send, contype); } if( c.ConType == STRUC_SHORT ) { if( NeedShortcut ) { CreateShortcut(); } } if (c.ConType == STRUC_BYPASS) { if (NeedBypass) { CreateBypass(); } } } else { //Just activate and see what happens: Activate(); } } }
/** * Read the address out of the buffer This makes a copy * and calls Parse on the copy. This is a "convienience" method. * @throw ParseException if the buffer is not a valid address */ static public Address Parse(MemBlock mb) { //Read some of the least significant bytes out, //AHAddress all have last bit 0, so we skip the last byte which //will have less entropy ushort idx = (ushort)NumberSerializer.ReadShort(mb, Address.MemSize - 3); Address a = _mb_cache[idx]; if( a != null ) { if( a.ToMemBlock().Equals(mb) ) { return a; } } //Else we need to read the address and put it in the cache try { if( 2 * mb.Length < mb.ReferencedBufferLength ) { /* * This MemBlock is much smaller than the array * we are referencing, don't keep the big one * in scope, instead make a copy */ mb = MemBlock.Copy((ICopyable)mb); } int add_class = Address.ClassOf(mb); switch (add_class) { case 0: a = new AHAddress(mb); break; case 124: a = new DirectionalAddress(mb); break; default: a = null; throw new ParseException("Unknown Address Class: " + add_class + ", buffer:" + mb.ToString()); } //Cache this result: _mb_cache[ idx ] = a; return a; } catch(ArgumentOutOfRangeException ex) { throw new ParseException("Address too short: " + mb.ToString(), ex); } catch(ArgumentException ex) { throw new ParseException("Could not parse: " + mb.ToString(), ex); } }