public ConnectionState GetReplacement(ConnectionTableState cts, Connection c, ConnectionState c1, ConnectionState c2) { if( (c1.Edge is RelayEdge) && (c2.Edge is RelayEdge) ) { return GetIdx(c1) <= GetIdx(c2) ? c1 : c2; } return _fallback.GetReplacement(cts,c,c1,c2); }
public ConnectionEventArgs(Connection c, ConnectionState cs, int idx, ConnectionTableState old, ConnectionTableState news) { Connection = c; ConnectionState = cs; Index = idx; OldState = old; NewState = news; }
/** * This method is called when there is a change in a Connection's status */ protected void StatusChangedHandler(Connection c, Brunet.Collections.Pair<ConnectionState, ConnectionState> oldnew) { //Console.Error.WriteLine("Status Changed:\n{0}\n{1}\n{2}\n{3}",c, c.Status, nltarget, nrtarget); ConnectionList structs = _node.ConnectionTable.GetConnections(ConnectionType.Structured); ConnectToNearer(structs, c.Address, oldnew.Second.StatusMessage.Neighbors); }
/// <summary>Called when a connection has been lost.</summary> abstract protected void LostConnection(Connection con);
public GreedyRouting(AHAddress local, ConnectionList structured_cons) { //Fake connection to ourselves: _local_con = new Connection(null, local, "structured.self", null, null); int local_idx; _structs = ConnectionList.InsertInto(structured_cons, _local_con, out local_idx); _NO_ONE = new Pair<Connection, bool>(null, false); _LOCAL = new Pair<Connection, bool>(null, true); }
/** * Get a StatusMessage for this node */ public IDictionary GetStatus(IDictionary status_message, ISender edge) { //we just got s status request if( 1 == _disconnecting ) { throw new AdrException((int)ErrorMessage.ErrorCode.Disconnecting, "disconnecting"); } StatusMessage sm = new StatusMessage(status_message); Edge from = GetEdge(edge); if(ProtocolLog.LinkDebug.Enabled) { ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format( "{0} -start- sys:link.GetStatus({1},{2})", _node.Address, sm, edge)); } CphState cphstate = null; if(from != null) { cphstate = _edge_to_cphstate[from] as CphState; } /** * StatusMessage objects are used to verify the completion * of the Link protocol. If we receive a StatusMessage request * after we send a LinkMessage response, we know the other * Node got our LinkMessage response, and the connection * is active */ StatusMessage response = null; ConnectionTable tab = _node.ConnectionTable; if (cphstate != null) { try { LinkMessage lm_to_add = cphstate.LM; //This is part of connection process: response = _node.GetStatus( sm.NeighborType, lm_to_add.Local.Address ); Connection con = new Connection(from, lm_to_add.Local.Address, lm_to_add.ConTypeString, sm, lm_to_add); tab.Add(con); } finally { from.CloseEvent -= this.CloseHandler; CloseHandler(from, null); } } else { //This is just a "regular" status request //update our table: Address fadd = null; Connection c = tab.GetConnection(from); if( c != null ) { fadd = c.Address; tab.UpdateStatus(c, sm); } response = _node.GetStatus( sm.NeighborType, fadd ); } if(ProtocolLog.LinkDebug.Enabled) { ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format( "{0} -end- sys:link.GetStatus()->{1}", _node.Address,response)); } return response.ToDictionary(); }
protected void ConStateChange(Connection con, Pair<Connections.ConnectionState, Connections.ConnectionState> cs) { if(cs.First.Edge.Equals(cs.Second.Edge)) { return; } if(!_ondemand.ConnectionDesired(con.Address)) { return; } SecurityAssociation sa; GetSecureSender(con, out sa); }
override protected void LostConnection(Connection con) { if(!ConnectionDesired(con.Address)) { if(con.ConType.Equals(Type)) { } return; } if(IsActive) { if(ProtocolLog.PolicyBasedCO.Enabled) { ProtocolLog.Write(ProtocolLog.PolicyBasedCO, String.Format( "Disconnection: {0} at {1}", con, DateTime.UtcNow)); } DelayedConnectTo(con.Address, true); } }
public ConSenderWrapper(Connection con) { Con = con; }
public UpdateNeighborAction(StructuredNode n, string contype, Connection neigh) { Node = n; ConType = contype; Neighbor = neigh; }
virtual protected void ValidConnection(Connection con) { AddConnection(con.Address, new ConSenderWrapper(con)); }
virtual protected void ValidDisconnection(Connection con) { RemoveConnection(con.Address); }
override protected void ObtainedConnection(Connection con) { if(ConnectionDesired(con.Address)) { if(ProtocolLog.PolicyBasedCO.Enabled) { ProtocolLog.Write(ProtocolLog.PolicyBasedCO, String.Format( "Connection: {0} at {1}", con, DateTime.UtcNow)); } } else if(con.ConType.Equals(Type)) { DelayedRemove(con.Address, "Undesired"); } }
public ConnectionEventArgs(Connection c, int idx, ConnectionList cl, int view) { Connection = c; Index = idx; CList = cl; View = view; }
override protected void ValidConnection(Connection con) { con.StateChangeEvent += ConStateChange; SecurityAssociation sa; GetSecureSender(con, out sa); }
/// <summary>Called when a connection has been formed.</summary> abstract protected void ObtainedConnection(Connection con);
public void WrapperEdgeRegressionTest() { AHAddress addr = new AHAddress(new System.Security.Cryptography.RNGCryptoServiceProvider()); TransportAddress ta = TransportAddressFactory.CreateInstance("brunet.tcp://169.0.5.1:5000"); FakeEdge fe = new FakeEdge(ta, ta); WrapperEdge we_fe = new WrapperEdge(fe); Connection fcon = new Connection(we_fe, addr, "structured", null, null); List<Connection> overlap = new List<Connection>(); overlap.Add(fcon); RelayTransportAddress tta = new RelayTransportAddress(addr, overlap); RelayEdge te1 = new RelayEdge(null, tta, tta, new SimpleForwarderSelector(), overlap); WrapperEdge we_te1 = new WrapperEdge(te1); Connection t1con = new Connection(we_te1, addr, "structured", null, null); overlap = new List<Connection>(); overlap.Add(t1con); RelayEdge te2 = new RelayEdge(null, tta, tta, new SimpleForwarderSelector(), overlap); WrapperEdge we_te2 = new WrapperEdge(te2); Connection t2con = new Connection(we_te2, addr, "structured", null, null); overlap = new List<Connection>(); overlap.Add(t2con); RelayEdge te3 = new RelayEdge(null, tta, tta, new SimpleForwarderSelector(), overlap); WrapperEdge we_te3 = new WrapperEdge(te3); Connection t3con = new Connection(we_te3, addr, "structured", null, null); overlap = new List<Connection>(); overlap.Add(t3con); RelayEdge te4 = new RelayEdge(null, tta, tta, new SimpleForwarderSelector(), overlap); WrapperEdge we_te4 = new WrapperEdge(te4); Connection t4con = new Connection(we_te4, addr, "structured", null, null); overlap = new List<Connection>(); overlap.Add(t4con); RelayEdge te5 = new RelayEdge(null, tta, tta, new SimpleForwarderSelector(), overlap); WrapperEdge we_te5 = new WrapperEdge(te5); Connection t5con = new Connection(we_te5, addr, "structured", null, null); Assert.AreEqual(te5.ShouldClose(), false, "Shouldn't close yet..."); te1.DisconnectionHandler(fcon); Assert.AreEqual(te5.ShouldClose(), true, "Should close..."); overlap.Add(t5con); overlap.Add(t3con); overlap.Add(t1con); te2.UpdateNeighborIntersection(overlap); Assert.AreEqual(te5.ShouldClose(), true, "Should close... 2"); }
/** * When we're here, we have the status message */ protected void StatusCloseHandler(object q, EventArgs args) { try { Channel resq = (Channel)q; //If we got no result RpcResult res = (RpcResult)resq.Dequeue(); StatusMessage sm = new StatusMessage((IDictionary)res.Result); if(_node.EdgeVerifyMethod != null) { if(!_node.EdgeVerifyMethod(_node, _e, LinkMessageReply.Local.Address)) { throw new Exception("Edge verification failed!"); } } Connection c = new Connection(_e, LinkMessageReply.Local.Address, _contype, sm, LinkMessageReply); _node.ConnectionTable.Add(c); _con.Value = c; Finish(Result.Success); } catch(InvalidOperationException) { /* * This is unexpected. */ string message = String.Format( "No StatusMessage returned from open({1}) Edge: {0}", _e, !_e.IsClosed); if(ProtocolLog.LinkDebug.Enabled) { ProtocolLog.Write(ProtocolLog.LinkDebug, message); } /* * We got a link message from this guy, but not a status response, * so let's try this TA again. */ Finish(Result.RetryThisTA); } catch(Exception x) { /* * Clearly we got some response from this edge, but something * unexpected happened. Let's try it this edge again if we * can */ if(ProtocolLog.LinkDebug.Enabled) { ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format( "LPS.StatusResultHandler Exception: {0}", x)); } Finish(Result.RetryThisTA); } }
/** * Call the GetStatus method on the given connection */ protected void CallGetStatus(string type, Connection c) { ConnectionTable tab = this.ConnectionTable; if( c != null ) { StatusMessage req = GetStatus(type, c.Address); Channel stat_res = new Channel(1); EventHandler handle_result = delegate(object q, EventArgs eargs) { try { RpcResult r = (RpcResult)stat_res.Dequeue(); StatusMessage sm = new StatusMessage( (IDictionary)r.Result ); tab.UpdateStatus(c, sm); } catch(Exception) { //Looks like lc disappeared before we could update it } }; stat_res.CloseEvent += handle_result; _rpc.Invoke(c.Edge, stat_res, "sys:link.GetStatus", req.ToDictionary() ); } }
/// <summary>We don't want to send on disconnected edges. So we remove said /// connections and edges!</summary> public void DisconnectionHandler(Connection con) { bool close = false; List<Connection> tunnels = null; lock(_sync) { tunnels = new List<Connection>(_tunnels.Count); foreach(Connection ccon in _tunnels) { if(con.Equals(ccon)){ continue; } tunnels.Add(ccon); } if(tunnels.Count == _tunnels.Count) { return; } _tunnels = tunnels; close = _tunnels.Count == 0; } if(close || ShouldClose()) { Close(); } //_tunnels is immutable and if we don't pass the latest _tunnels to _ias //he will go into an inconsistent state. _ias.Update(tunnels); }
protected bool GetSecureSender(Connection con, out SecurityAssociation sa) { sa = _so.CreateSecurityAssociation(con.State.Edge); bool ready = false; lock(_address_to_sender) { if(!_registered.ContainsKey(sa)) { _registered[sa] = true; sa.StateChangeEvent += SAStateChange; } if(sa.State == SecurityAssociation.States.Active || sa.State == SecurityAssociation.States.Updating) { Address addr = con.Address; if(_address_to_sender.ContainsKey(addr)) { SecurityAssociation to_fixup = _address_to_sender[addr] as SecurityAssociation; if(to_fixup != null && to_fixup != sa) { to_fixup.StateChangeEvent -= SAStateChange; _registered.Remove(to_fixup); } } AddConnection(con.Address, sa); ready = true; } } return ready; }
/** <summary>Begins a new transfer state to the neighbor connected via con. </summary> <param name="con">The connection to the neigbhor we will be transferring data to.</param> <param name="ts">The table server we're providing the transfer for. C# does not allow sub-class objects to have access to their parent objects member variables, so we pass it in like this.</param> <remarks> Step 1: Get all the keys between me and my new neighbor. Step 2: Get all values for those keys, we copy so that we don't worry about changes to the dht during this interaction. This is only a pointer copy and since we let the OS deal with removing the contents of an entry, we don't need to make copies of the actual entry. Step 3: Generate another list of keys of up to max parallel transfers and begin transferring, that way we do not need to lock access to the entry enumerator until non-constructor puts. Step 4: End constructor, results from puts, cause the next entry to be sent. */ public TransferState(Brunet.Connections.Connection con, TableServer ts) { this._ts = ts; this._con = con; // Get all keys between me and my new neighbor LinkedList<MemBlock> keys; lock(_ts._sync) { keys = _ts._data.GetKeysBetween((AHAddress) _ts._node.Address, (AHAddress) _con.Address); } if(Dht.DhtLog.Enabled) { ProtocolLog.Write(Dht.DhtLog, String.Format( "Starting transfer from {0} to {1}", _ts._node.Address, _con.Address)); } int total_entries = 0; /* Get all values for those keys, we copy so that we don't worry about * changes to the dht during this interaction. This is only a pointer * copy and since we let the OS deal with removing the contents of an * entry, we don't need to make copies of the actual entry. */ foreach(MemBlock key in keys) { Entry[] entries; lock(_ts._sync) { LinkedList<Entry> llentries = _ts._data.GetEntries(key); if(llentries == null) { continue; } entries = new Entry[llentries.Count]; total_entries += llentries.Count; llentries.CopyTo(entries, 0); } key_entries.AddLast(entries); } if(Dht.DhtLog.Enabled) { ProtocolLog.Write(Dht.DhtLog, String.Format( "Total keys: {0}, total entries: {1}.", key_entries.Count, total_entries)); } _entry_enumerator = GetEntryEnumerator(); /* Here we generate another list of keys that we would like to * this is done here, so that we can lock up the _entry_enumerator * only during this stage and not during the RpcManager.Invoke */ LinkedList<Entry> local_entries = new LinkedList<Entry>(); for(int i = 0; i < MAX_PARALLEL_TRANSFERS && _entry_enumerator.MoveNext(); i++) { local_entries.AddLast((Entry) _entry_enumerator.Current); } foreach(Entry ent in local_entries) { Channel queue = new Channel(); queue.CloseAfterEnqueue(); queue.CloseEvent += this.NextTransfer; int ttl = (int) (ent.EndTime - DateTime.UtcNow).TotalSeconds; try { _ts._rpc.Invoke(_con.Edge, queue, "dht.PutHandler", ent.Key, ent.Value, ttl, false); } catch { if(_con.Edge.IsClosed) { _interrupted = true; Done(); break; } } } }
/** * There are only four ways we can get here: * * 1) We got some exception in Start and never made the first request * 2) There was some problem in LinkCloseHandler * 3) We either got a response or had a problem in StatusCloseHandler * 4) The Edge closed, and the CloseHandler was called. * * The only possibility for a race is between the CloseHandler and * the others. * * When this state machine reaches an end point, it calls this method, * which fires the FinishEvent */ protected void Finish(Result res) { /* * No matter what, we are done here: */ if(ProtocolLog.LinkDebug.Enabled) { string message; Exception x; if (_x.TryGet(out x) ) { message = String.Format( "LPS: {0} finished: {2}, with exception: {1}", _node.Address, x, res); } else { message = String.Format("LPS: {0} finished: {1}", _node.Address, res); } ProtocolLog.Write(ProtocolLog.LinkDebug, message); } int already_finished = Interlocked.Exchange(ref _is_finished, 1); if(already_finished == 1) { //We already got here. //This is a barrier. Only one Finish call will make //it past this point. Only two could happen in a race: //Edge closing or some other failure/success. return; } //We don't care about close event's anymore _e.CloseEvent -= this.CloseHandler; //Set the result: _result = res; try { //Check to see if we need to close the edge if( _con.IsSet == false ) { /* * We didn't get a complete connection, * but we may have heard some response. If so * close the edge gracefully. */ if (LinkMessageReply != null) { //Let's be nice, send a Close message, but don't add this connection: Connection tmp_c = new Connection(_e, LinkMessageReply.Local.Address, _contype, null, LinkMessageReply); tmp_c.Close(_node.Rpc, "From LPS, did not complete a connection."); } else { /* * We never heard from the other side, so we will assume that further * packets will only waste bandwidth */ _e.Close(); } if(ProtocolLog.LinkDebug.Enabled) { ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format( "LPS: {0} got no connection", _node.Address)); } } else { if(ProtocolLog.LinkDebug.Enabled) { ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format( "LPS: {0} got connection: {1}", _node.Address, _con.Value)); } } //This could throw an exception, but make sure we unlock if it does. FireFinished(); } finally { /** * We have to make sure the lock is eventually released: */ this.Unlock(); } }
override protected void ObtainedConnection(Connection con) { bool con_desired = ConnectionDesired(con.Address); if(con_desired || con.ConType.Equals(Type)) { if(ProtocolLog.PolicyBasedCO.Enabled) { ProtocolLog.Write(ProtocolLog.PolicyBasedCO, String.Format( "Connection: {0} at {1}, Desired: {2}", con, DateTime.UtcNow, ConnectionDesired(con.Address))); } } if(!con_desired && con.ConType.Equals(Type)) { Set(con.Address); } }
///<summary>Creates an edge and a connection from node2 to node1 including ///the edge. Note: this is unidirectional, this must be called twice, ///swapping node1 with node2 for a connection to be complete.</summary> protected void AddConnection(GraphNode node1, GraphNode node2, int delay) { Edge edge = new GraphEdge(delay); Connection con = new Connection(edge, node2.Address, ConnectionType.Structured.ToString(), null, null); node1.ConnectionTable.Add(con); }
/** * <summary>Begins a new transfer state to the neighbor connected via con. * </summary> * <param name="con">The connection to the neigbhor we will be transferring * data to.</param> * <param name="ts">The table server we're providing the transfer for. C# * does not allow sub-class objects to have access to their parent objects * member variables, so we pass it in like this.</param> * <remarks> * Step 1: * * Get all the keys between me and my new neighbor. * * Step 2: * * Get all values for those keys, we copy so that we don't worry about * changes to the dht during this interaction. This is only a pointer * copy and since we let the OS deal with removing the contents of an * entry, we don't need to make copies of the actual entry. * * Step 3: * * Generate another list of keys of up to max parallel transfers and begin * transferring, that way we do not need to lock access to the entry * enumerator until non-constructor puts. * * Step 4: * * End constructor, results from puts, cause the next entry to be sent. */ public TransferState(Brunet.Connections.Connection con, TableServer ts) { this._ts = ts; this._con = con; // Get all keys between me and my new neighbor LinkedList <MemBlock> keys; lock (_ts._sync) { keys = _ts._data.GetKeysBetween((AHAddress)_ts._node.Address, (AHAddress)_con.Address); } if (Dht.DhtLog.Enabled) { ProtocolLog.Write(Dht.DhtLog, String.Format( "Starting transfer from {0} to {1}", _ts._node.Address, _con.Address)); } int total_entries = 0; /* Get all values for those keys, we copy so that we don't worry about * changes to the dht during this interaction. This is only a pointer * copy and since we let the OS deal with removing the contents of an * entry, we don't need to make copies of the actual entry. */ foreach (MemBlock key in keys) { Entry[] entries; lock (_ts._sync) { LinkedList <Entry> llentries = _ts._data.GetEntries(key); if (llentries == null) { continue; } entries = new Entry[llentries.Count]; total_entries += llentries.Count; llentries.CopyTo(entries, 0); } key_entries.AddLast(entries); } if (Dht.DhtLog.Enabled) { ProtocolLog.Write(Dht.DhtLog, String.Format( "Total keys: {0}, total entries: {1}.", key_entries.Count, total_entries)); } _entry_enumerator = GetEntryEnumerator(); /* Here we generate another list of keys that we would like to * this is done here, so that we can lock up the _entry_enumerator * only during this stage and not during the RpcManager.Invoke */ LinkedList <Entry> local_entries = new LinkedList <Entry>(); for (int i = 0; i < MAX_PARALLEL_TRANSFERS && _entry_enumerator.MoveNext(); i++) { local_entries.AddLast((Entry)_entry_enumerator.Current); } foreach (Entry ent in local_entries) { Channel queue = new Channel(); queue.CloseAfterEnqueue(); queue.CloseEvent += this.NextTransfer; int ttl = (int)(ent.EndTime - DateTime.UtcNow).TotalSeconds; try { _ts._rpc.Invoke(_con.Edge, queue, "dht.PutHandler", ent.Key, ent.Value, ttl, false); } catch { if (_con.Edge.IsClosed) { _interrupted = true; Done(); break; } } } }
override protected void ValidConnection(Connection con) { SecurityAssociation sa; GetSecureSender(con, out sa); }
public AnnealingRouting(AHAddress local, ConnectionList structured_cons) { //Fake connection to ourselves: _local_con = new Connection(null, local, "structured.self", null, null); int local_idx; _structs = ConnectionList.InsertInto(structured_cons, _local_con, out local_idx); }
override protected void ValidDisconnection(Connection con) { ISender sender; if(!_address_to_sender.TryGetValue(con.Address, out sender)) { return; } SecurityAssociation sa = sender as SecurityAssociation; if(sa != null) { sa.Close("Connection closed..."); } }
public void Test() { Address addr_x = new AHAddress(new RNGCryptoServiceProvider()); byte[] addrbuff = Address.ConvertToAddressBuffer(addr_x.ToBigInteger() + (Address.Full / 2)); Address.SetClass(addrbuff, AHAddress._class); Address addr_y = new AHAddress(addrbuff); List<Connection> connections = new List<Connection>(); ConnectionTable ct_x = new ConnectionTable(); ConnectionTable ct_y = new ConnectionTable(); ConnectionTable ct_empty = new ConnectionTable(); NCService ncservice = new NCService(); Connection fast_con = null; for(int i = 1; i <= 11; i++) { addrbuff = Address.ConvertToAddressBuffer(addr_x.ToBigInteger() + (i * Address.Full / 16)); Address.SetClass(addrbuff, AHAddress._class); Address addr = new AHAddress(addrbuff); Connection con = null; TransportAddress ta = TransportAddressFactory.CreateInstance("brunet.tcp://158.7.0.1:5000"); Edge fe = new FakeEdge(ta, ta, TransportAddress.TAType.Tcp); if(i <= 10) { con = new Connection(fe, addr, "structured", null, null); ct_x.Add(con); if(i % 2 == 0) { ncservice.ProcessSample(DateTime.UtcNow, String.Empty, addr, new Point(new double[] {0, 0}, 0), 0, i*10); } } else { fast_con = new Connection(fe, addr, "structured", null, null); ncservice.ProcessSample(DateTime.UtcNow, String.Empty, addr, new Point(new double[] {0, 0}, 0), 0, 5); } if(i == 10) { ct_y.Add(con); } connections.Add(con); } ITunnelOverlap sto = new SimpleTunnelOverlap(); ITunnelOverlap nto = new NCTunnelOverlap(ncservice); ConnectionType con_type = ConnectionType.Structured; List<Connection> pre_cons = new List<Connection>(); pre_cons.Add(connections[9]); IDictionary id = nto.GetSyncMessage(pre_cons, addr_x, ct_x.GetConnections(con_type)); // We do have some pre-existing overlap Assert.AreEqual(nto.EvaluateOverlap(ct_y.GetConnections(con_type), id)[0], connections[9], "NC: Have an overlap!"); Assert.AreEqual(sto.EvaluateOverlap(ct_y.GetConnections(con_type), id)[0], connections[9], "Simple: Have an overlap!"); // We have no overlap with an empty connection table Assert.AreEqual(nto.EvaluateOverlap(ct_empty.GetConnections(con_type), id).Count, 0, "No overlap!"); Assert.AreEqual(sto.EvaluateOverlap(ct_empty.GetConnections(con_type), id).Count, 0, "No overlap!"); // latency[0] == -1 Assert.AreEqual(connections[1].Address.Equals(nto.EvaluatePotentialOverlap(id)), true, "NC: EvaluatePotentialOverlap returns expected!"); Assert.AreEqual(ct_x.Contains(con_type, sto.EvaluatePotentialOverlap(id)), true, "Simple: EvaluatePotentialOverlap returns valid!"); ct_y.Add(fast_con); ct_x.Add(fast_con); id = nto.GetSyncMessage(pre_cons, addr_x, ct_x.GetConnections(con_type)); Assert.AreEqual(fast_con.Address.Equals(nto.EvaluatePotentialOverlap(id)), true, "NC: EvaluatePotentialOverlap returns expected!"); Assert.AreEqual(nto.EvaluateOverlap(ct_y.GetConnections(con_type), id)[0], fast_con, "NC: Have better overlap!"); }
protected bool GetSecureSender(Connection con, out SecurityAssociation sa) { sa = _so.GetSecureSender(con.Address); bool ready = false; lock(_address_to_sender) { if(!_registered.ContainsKey(sa)) { _registered[sa] = true; sa.StateChangeEvent += SAStateChange; } if(sa.State == SecurityAssociation.States.Active || sa.State == SecurityAssociation.States.Updating) { AddConnection(con.Address, sa); ready = true; } } return ready; }