internal Node(NetworkAddress peer, NetworkInfo network, NodeConnectionParameters parameters, Socket socket, VersionPayload peerVersion) { _RemoteSocketAddress = ((IPEndPoint)socket.RemoteEndPoint).Address; _RemoteSocketPort = ((IPEndPoint)socket.RemoteEndPoint).Port; Inbound = true; _Behaviors = new NodeBehaviorsCollection(this); _MyVersion = parameters.CreateVersion(peer.Endpoint, network); Network = network; _Peer = peer; _Connection = new NodeConnection(this, socket); _PeerVersion = peerVersion; LastSeen = peer.Time; ConnectedAt = DateTimeOffset.UtcNow; TraceCorrelation.LogInside(() => { NodeServerTrace.Information("Connected to advertised node " + _Peer.Endpoint); State = NodeState.Connected; }); InitDefaultBehaviors(parameters); _Connection.BeginListen(); }
public void CanUseAddrManager() { AddressManager addrman = new AddressManager(); addrman.DebugMode = true; var localhost = new NetworkAddress(IPAddress.Parse("127.0.0.1"), 8333); addrman.Add(localhost, localhost.Endpoint.Address); Assert.NotNull(addrman.nKey); Assert.True(addrman.nKey != new uint256(0)); Assert.True(addrman.nNew == 1); addrman.Good(localhost); Assert.True(addrman.nNew == 0); Assert.True(addrman.nTried == 1); addrman.Attempt(localhost); var addr = addrman.Select(); Assert.False(addr.Ago < TimeSpan.FromSeconds(10.0)); addrman.Connected(localhost); addr = addrman.Select(); Assert.True(addr.Ago < TimeSpan.FromSeconds(10.0)); }
private void Attempt_(NetworkAddress addr, DateTimeOffset nTime) { AddressInfo pinfo = Find(addr.Endpoint.Address); // if not found, bail out if (pinfo == null) { return; } AddressInfo info = pinfo; // check whether we are talking about the exact same CService (including same port) if (!info.Match(addr)) { return; } // update info info.LastTry = nTime; info.nAttempts++; }
//! Mark an entry as connection attempted to. public void Attempt(NetworkAddress addr) { Attempt(addr, DateTimeOffset.UtcNow); }
//! Add a single address. public bool Add(NetworkAddress addr, IPAddress source) { return Add(addr, source, TimeSpan.Zero); }
private AddressInfo Create(NetworkAddress addr, object addrSource, out int pnId) { pnId = 0; return(null); }
public void Good(NetworkAddress addr) { Good(addr, DateTimeOffset.UtcNow); }
public Peer(PeerOrigin origin, NetworkAddress address) { _Origin = origin; _NetworkAddress = address; }
void Connected_(NetworkAddress addr, DateTimeOffset nTime) { int unused; AddressInfo pinfo = Find(addr, out unused); // if not found, bail out if(pinfo == null) return; AddressInfo info = pinfo; // check whether we are talking about the exact same CService (including same port) if(!info.Match(addr)) return; // update info var nUpdateInterval = TimeSpan.FromSeconds(20 * 60); if(nTime - info.nTime > nUpdateInterval) info.nTime = nTime; }
private bool Add_(NetworkAddress addr, IPAddress source, TimeSpan nTimePenalty) { if (!addr.Endpoint.Address.IsRoutable(true)) { return(false); } bool fNew = false; int nId; AddressInfo pinfo = Find(addr, out nId); if (pinfo != null) { // periodically update nTime bool fCurrentlyOnline = (DateTimeOffset.UtcNow - addr.Time < TimeSpan.FromSeconds(24 * 60 * 60)); var nUpdateInterval = TimeSpan.FromSeconds(fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60); if (addr.ntime != 0 && (pinfo.Address.ntime == 0 || pinfo.Address.Time < addr.Time - nUpdateInterval - nTimePenalty)) { pinfo.Address.ntime = (uint)Math.Max(0L, (long)Utils.DateTimeToUnixTime(addr.Time - nTimePenalty)); } // add services pinfo.Address.Service |= addr.Service; // do not update if no new information is present if (addr.ntime == 0 || (pinfo.Address.ntime != 0 && addr.Time <= pinfo.Address.Time)) { return(false); } // do not update if the entry was already in the "tried" table if (pinfo.fInTried) { return(false); } // do not update if the max reference count is reached if (pinfo.nRefCount == ADDRMAN_NEW_BUCKETS_PER_ADDRESS) { return(false); } // stochastic test: previous nRefCount == N: 2^N times harder to increase it int nFactor = 1; for (int n = 0; n < pinfo.nRefCount; n++) { nFactor *= 2; } if (nFactor > 1 && (GetRandInt(nFactor) != 0)) { return(false); } } else { pinfo = Create(addr, source, out nId); pinfo.Address.ntime = (uint)Math.Max((long)0, (long)Utils.DateTimeToUnixTime(pinfo.Address.Time - nTimePenalty)); nNew++; fNew = true; } int nUBucket = pinfo.GetNewBucket(nKey, source); int nUBucketPos = pinfo.GetBucketPosition(nKey, true, nUBucket); if (vvNew[nUBucket, nUBucketPos] != nId) { bool fInsert = vvNew[nUBucket, nUBucketPos] == -1; if (!fInsert) { AddressInfo infoExisting = mapInfo[vvNew[nUBucket, nUBucketPos]]; if (infoExisting.IsTerrible || (infoExisting.nRefCount > 1 && pinfo.nRefCount == 0)) { // Overwrite the existing new table entry. fInsert = true; } } if (fInsert) { ClearNew(nUBucket, nUBucketPos); pinfo.nRefCount++; vvNew[nUBucket, nUBucketPos] = nId; } else { if (pinfo.nRefCount == 0) { Delete(nId); } } } return(fNew); }
public AddrPayload(NetworkAddress[] addresses) { addr_list = addresses.ToArray(); }
public static Node Connect(NetworkInfo network, NetworkAddress endpoint, NodeConnectionParameters parameters) { return(new Node(endpoint, network, parameters)); }
public AddrV2Payload(NetworkAddress address) : base(address) { }
public AddrPayload(NetworkAddress address) { addr_list = new NetworkAddress[] { address }; }
public void NodeToStringTest() { NetworkAddress address = new NetworkAddress(IPAddress.Parse("192.168.0.1"), 8333); Node node = new Node(address, Network.Main, null); String actual = node.ToString(); Assert.Equal("", actual); }
private void Attempt_(NetworkAddress addr, DateTimeOffset nTime) { }
private AddressInfo Find(NetworkAddress addr, out int nId) { nId = 0; return(null); }
private void Attempt_(NetworkAddress addr, DateTimeOffset nTime) { AddressInfo pinfo = Find(addr.Endpoint.Address); // if not found, bail out if(pinfo == null) return; AddressInfo info = pinfo; // check whether we are talking about the exact same CService (including same port) if(!info.Match(addr)) return; // update info info.LastTry = nTime; info.nAttempts++; }
internal Node(NetworkAddress peer, NetworkInfo network, NodeConnectionParameters parameters) { parameters = parameters ?? new NodeConnectionParameters(); var addrman = AddressManagerBehavior.GetAddrman(parameters); Inbound = false; _Behaviors = new NodeBehaviorsCollection(this); _MyVersion = parameters.CreateVersion(peer.Endpoint, network); Network = network; _Peer = peer; LastSeen = peer.Time; var socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp); socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, false); _Connection = new NodeConnection(this, socket); socket.ReceiveBufferSize = parameters.ReceiveBufferSize; socket.SendBufferSize = parameters.SendBufferSize; using (TraceCorrelation.Open()) { try { var completed = new ManualResetEvent(false); var args = new SocketAsyncEventArgs(); args.RemoteEndPoint = peer.Endpoint; args.Completed += (s, a) => { Utils.SafeSet(completed); }; if (!socket.ConnectAsync(args)) { completed.Set(); } WaitHandle.WaitAny(new WaitHandle[] { completed, parameters.ConnectCancellation.WaitHandle }); parameters.ConnectCancellation.ThrowIfCancellationRequested(); if (args.SocketError != SocketError.Success) { throw new SocketException((int)args.SocketError); } var remoteEndpoint = (IPEndPoint)(socket.RemoteEndPoint ?? args.RemoteEndPoint); _RemoteSocketAddress = remoteEndpoint.Address; _RemoteSocketPort = remoteEndpoint.Port; State = NodeState.Connected; ConnectedAt = DateTimeOffset.UtcNow; NodeServerTrace.Information("Outbound connection successfull"); if (addrman != null) { addrman.Attempt(Peer); } } catch (OperationCanceledException) { Utils.SafeCloseSocket(socket); NodeServerTrace.Information("Connection to node cancelled"); State = NodeState.Offline; if (addrman != null) { addrman.Attempt(Peer); } throw; } catch (Exception ex) { Utils.SafeCloseSocket(socket); NodeServerTrace.Error("Error connecting to the remote endpoint ", ex); DisconnectReason = new NodeDisconnectReason() { Reason = "Unexpected exception while connecting to socket", Exception = ex }; State = NodeState.Failed; if (addrman != null) { addrman.Attempt(Peer); } throw; } InitDefaultBehaviors(parameters); _Connection.BeginListen(); } }
public AddressInfo(NetworkAddress addr, IPAddress addrSource) { Address = addr; Source = addrSource; }
public bool Add(NetworkAddress addr) { return(false); }
internal bool Match(NetworkAddress addr) { return(false); }
public AddrPayload(NetworkAddress address) { addr_list = new NetworkAddress[] { address }; }
private AddressInfo Find(NetworkAddress addr, out int nId) { return(Find(addr.Endpoint.Address, out nId)); }
private bool Add_(NetworkAddress addr, IPAddress source, TimeSpan nTimePenalty) { if(!addr.Endpoint.Address.IsRoutable(true)) return false; bool fNew = false; int nId; AddressInfo pinfo = Find(addr, out nId); if(pinfo != null) { // periodically update nTime bool fCurrentlyOnline = (DateTimeOffset.UtcNow - addr.Time < TimeSpan.FromSeconds(24 * 60 * 60)); var nUpdateInterval = TimeSpan.FromSeconds(fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60); if(addr.ntime != 0 && (pinfo.Address.ntime == 0 || pinfo.Address.Time < addr.Time - nUpdateInterval - nTimePenalty)) pinfo.Address.ntime = (uint)Math.Max(0L, (long)Utils.DateTimeToUnixTime(addr.Time - nTimePenalty)); // add services pinfo.Address.Service |= addr.Service; // do not update if no new information is present if(addr.ntime == 0 || (pinfo.Address.ntime != 0 && addr.Time <= pinfo.Address.Time)) return false; // do not update if the entry was already in the "tried" table if(pinfo.fInTried) return false; // do not update if the max reference count is reached if(pinfo.nRefCount == ADDRMAN_NEW_BUCKETS_PER_ADDRESS) return false; // stochastic test: previous nRefCount == N: 2^N times harder to increase it int nFactor = 1; for(int n = 0 ; n < pinfo.nRefCount ; n++) nFactor *= 2; if(nFactor > 1 && (GetRandInt(nFactor) != 0)) return false; } else { pinfo = Create(addr, source, out nId); pinfo.Address.ntime = (uint)Math.Max((long)0, (long)Utils.DateTimeToUnixTime(pinfo.Address.Time - nTimePenalty)); nNew++; fNew = true; } int nUBucket = pinfo.GetNewBucket(nKey, source); int nUBucketPos = pinfo.GetBucketPosition(nKey, true, nUBucket); if(vvNew[nUBucket, nUBucketPos] != nId) { bool fInsert = vvNew[nUBucket, nUBucketPos] == -1; if(!fInsert) { AddressInfo infoExisting = mapInfo[vvNew[nUBucket, nUBucketPos]]; if(infoExisting.IsTerrible || (infoExisting.nRefCount > 1 && pinfo.nRefCount == 0)) { // Overwrite the existing new table entry. fInsert = true; } } if(fInsert) { ClearNew(nUBucket, nUBucketPos); pinfo.nRefCount++; vvNew[nUBucket, nUBucketPos] = nId; } else { if(pinfo.nRefCount == 0) { Delete(nId); } } } return fNew; }
private void ProcessMessageCore(IncomingMessage message) { if(message.Message.Payload is VersionPayload) { var version = message.AssertPayload<VersionPayload>(); var connectedToSelf = version.Nonce == Nonce; if(message.Node != null && connectedToSelf) { NodeServerTrace.ConnectionToSelfDetected(); message.Node.DisconnectAsync(); return; } if(message.Node == null) { var remoteEndpoint = version.AddressFrom; if(!remoteEndpoint.Address.IsRoutable(AllowLocalPeers)) { //Send his own endpoint remoteEndpoint = new IPEndPoint(((IPEndPoint)message.Socket.RemoteEndPoint).Address, Network.DefaultPort); } var peer = new NetworkAddress() { Endpoint = remoteEndpoint, Time = DateTimeOffset.UtcNow }; var node = new Node(peer, Network, CreateNodeConnectionParameters(), message.Socket, version); if(connectedToSelf) { node.SendMessage(CreateNodeConnectionParameters().CreateVersion(node.Peer.Endpoint, Network)); NodeServerTrace.ConnectionToSelfDetected(); node.Disconnect(); return; } CancellationTokenSource cancel = new CancellationTokenSource(); cancel.CancelAfter(TimeSpan.FromSeconds(10.0)); try { ConnectedNodes.Add(node); node.StateChanged += node_StateChanged; node.RespondToHandShake(cancel.Token); } catch(OperationCanceledException ex) { NodeServerTrace.Error("The remote node did not respond fast enough (10 seconds) to the handshake completion, dropping connection", ex); node.DisconnectAsync(); throw; } catch(Exception) { node.DisconnectAsync(); throw; } } } var messageReceived = MessageReceived; if(messageReceived != null) messageReceived(this, message); }
private AddressInfo Find(NetworkAddress addr, out int nId) { return Find(addr.Endpoint.Address, out nId); }
internal bool Match(NetworkAddress addr) { return Address.Endpoint.Address.Equals(addr.Endpoint.Address) && Address.Endpoint.Port == addr.Endpoint.Port; }
public void Good(NetworkAddress addr, DateTimeOffset nTime) { lock(cs) { Check(); Good_(addr, nTime); Check(); } }
public bool Add(NetworkAddress addr, IPAddress source, TimeSpan nTimePenalty) { bool fRet = false; lock(cs) { Check(); fRet |= Add_(addr, source, nTimePenalty); Check(); } return fRet; }
private bool Add_(NetworkAddress addr, object source, TimeSpan nTimePenalty) { return(true); }
private AddressInfo Create(NetworkAddress addr, IPAddress addrSource, out int pnId) { int nId = nIdCount++; mapInfo[nId] = new AddressInfo(addr, addrSource); mapAddr[addr.Endpoint.Address] = nId; mapInfo[nId].nRandomPos = vRandom.Count; vRandom.Add(nId); pnId = nId; return mapInfo[nId]; }
//! Mark an entry as connection attempted to. public void Attempt(NetworkAddress addr) { Attempt(addr, DateTimeOffset.UtcNow); }
public void Good(NetworkAddress addr) { Good(addr, DateTimeOffset.UtcNow); }
//! Mark an entry as currently-connected-to. public void Connected(NetworkAddress addr) { Connected(addr, DateTimeOffset.UtcNow); }
private void Good_(NetworkAddress addr, DateTimeOffset nTime) { int nId; AddressInfo pinfo = Find(addr, out nId); // if not found, bail out if(pinfo == null) return; AddressInfo info = pinfo; // check whether we are talking about the exact same CService (including same port) if(!info.Match(addr)) return; // update info info.LastSuccess = nTime; info.LastTry = nTime; info.nAttempts = 0; // nTime is not updated here, to avoid leaking information about // currently-connected peers. // if it is already in the tried set, don't do anything else if(info.fInTried) return; // find a bucket it is in now int nRnd = GetRandInt(ADDRMAN_NEW_BUCKET_COUNT); int nUBucket = -1; for(int n = 0 ; n < ADDRMAN_NEW_BUCKET_COUNT ; n++) { int nB = (n + nRnd) % ADDRMAN_NEW_BUCKET_COUNT; int nBpos = info.GetBucketPosition(nKey, true, nB); if(vvNew[nB, nBpos] == nId) { nUBucket = nB; break; } } // if no bucket is found, something bad happened; // TODO: maybe re-add the node, but for now, just bail out if(nUBucket == -1) return; // move nId to the tried tables MakeTried(info, nId); }
public AddressInfo(NetworkAddress addr, IPAddress addrSource) { Address = addr; Source = addrSource; }
//! Mark an entry as connection attempted to. public void Attempt(NetworkAddress addr, DateTimeOffset nTime) { lock(cs) { Check(); Attempt_(addr, nTime); Check(); } }
internal bool Match(NetworkAddress addr) { return (Address.Endpoint.Address.Equals(addr.Endpoint.Address) && Address.Endpoint.Port == addr.Endpoint.Port); }
//! Mark an entry as currently-connected-to. public void Connected(NetworkAddress addr) { Connected(addr, DateTimeOffset.UtcNow); }
//! Add a single address. public bool Add(NetworkAddress addr, IPAddress source) { return(Add(addr, source, TimeSpan.Zero)); }
//! Mark an entry as currently-connected-to. public void Connected(NetworkAddress addr, DateTimeOffset nTime) { lock(cs) { Check(); Connected_(addr, nTime); Check(); } }
public bool Add(NetworkAddress addr) { return(Add(addr, IPAddress.Loopback)); }
private void ProcessMessageCore(IncomingMessage message) { if (message.Message.Payload is VersionPayload) { var version = message.AssertPayload <VersionPayload>(); var connectedToSelf = version.Nonce == Nonce; if (message.Node != null && connectedToSelf) { NodeServerTrace.ConnectionToSelfDetected(); message.Node.DisconnectAsync(); return; } if (message.Node == null) { var remoteEndpoint = version.AddressFrom; if (!remoteEndpoint.Address.IsRoutable(AllowLocalPeers)) { //Send his own endpoint remoteEndpoint = new IPEndPoint(((IPEndPoint)message.Socket.RemoteEndPoint).Address, Network.DefaultPort); } var peer = new NetworkAddress() { Endpoint = remoteEndpoint, Time = DateTimeOffset.UtcNow }; var node = new Node(peer, Network, CreateNodeConnectionParameters(), message.Socket, version); if (connectedToSelf) { node.SendMessage(CreateNodeConnectionParameters().CreateVersion(node.Peer.Endpoint, Network)); NodeServerTrace.ConnectionToSelfDetected(); node.Disconnect(); return; } CancellationTokenSource cancel = new CancellationTokenSource(); cancel.CancelAfter(TimeSpan.FromSeconds(10.0)); try { ConnectedNodes.Add(node); node.StateChanged += node_StateChanged; node.RespondToHandShake(cancel.Token); } catch (OperationCanceledException ex) { NodeServerTrace.Error("The remote node did not respond fast enough (10 seconds) to the handshake completion, dropping connection", ex); node.DisconnectAsync(); throw; } catch (Exception) { node.DisconnectAsync(); throw; } } } var messageReceived = MessageReceived; if (messageReceived != null) { messageReceived(this, message); } }
public Peer(PeerOrigin origin, NetworkAddress address) { _Origin = origin; _NetworkAddress = address; }