Exemplo n.º 1
0
 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();
 }
Exemplo n.º 2
0
		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));
		}
Exemplo n.º 3
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++;
        }
Exemplo n.º 4
0
		//! Mark an entry as connection attempted to.
		public void Attempt(NetworkAddress addr)
		{
			Attempt(addr, DateTimeOffset.UtcNow);
		}
Exemplo n.º 5
0
		//! Add a single address.
		public bool Add(NetworkAddress addr, IPAddress source)
		{
			return Add(addr, source, TimeSpan.Zero);
		}
Exemplo n.º 6
0
 private AddressInfo Create(NetworkAddress addr, object addrSource, out int pnId)
 {
     pnId = 0;
     return(null);
 }
Exemplo n.º 7
0
 public void Good(NetworkAddress addr)
 {
     Good(addr, DateTimeOffset.UtcNow);
 }
Exemplo n.º 8
0
 public Peer(PeerOrigin origin, NetworkAddress address)
 {
     _Origin         = origin;
     _NetworkAddress = address;
 }
Exemplo n.º 9
0
		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;
		}
Exemplo n.º 10
0
        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);
        }
Exemplo n.º 11
0
 public AddrPayload(NetworkAddress[] addresses)
 {
     addr_list = addresses.ToArray();
 }
Exemplo n.º 12
0
 public static Node Connect(NetworkInfo network,
                            NetworkAddress endpoint,
                            NodeConnectionParameters parameters)
 {
     return(new Node(endpoint, network, parameters));
 }
Exemplo n.º 13
0
 public AddrV2Payload(NetworkAddress address)
     : base(address)
 {
 }
Exemplo n.º 14
0
 public AddrPayload(NetworkAddress address)
 {
     addr_list = new NetworkAddress[] { address };
 }
Exemplo n.º 15
0
        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);
        }
Exemplo n.º 16
0
 private void Attempt_(NetworkAddress addr, DateTimeOffset nTime)
 {
 }
Exemplo n.º 17
0
 private AddressInfo Find(NetworkAddress addr, out int nId)
 {
     nId = 0;
     return(null);
 }
Exemplo n.º 18
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++;
		}
Exemplo n.º 19
0
        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();
            }
        }
Exemplo n.º 20
0
			public AddressInfo(NetworkAddress addr, IPAddress addrSource)
			{
				Address = addr;
				Source = addrSource;
			}
Exemplo n.º 21
0
 public bool Add(NetworkAddress addr)
 {
     return(false);
 }
Exemplo n.º 22
0
 internal bool Match(NetworkAddress addr)
 {
     return(false);
 }
Exemplo n.º 23
0
 public AddrPayload(NetworkAddress address)
 {
     addr_list = new NetworkAddress[] { address };
 }
Exemplo n.º 24
0
 private AddressInfo Find(NetworkAddress addr, out int nId)
 {
     return(Find(addr.Endpoint.Address, out nId));
 }
Exemplo n.º 25
0
		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;
		}
Exemplo n.º 26
0
		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);
		}
Exemplo n.º 27
0
		private AddressInfo Find(NetworkAddress addr, out int nId)
		{
			return Find(addr.Endpoint.Address, out nId);
		}
Exemplo n.º 28
0
			internal bool Match(NetworkAddress addr)
			{
				return
					Address.Endpoint.Address.Equals(addr.Endpoint.Address) &&
					Address.Endpoint.Port == addr.Endpoint.Port;
			}
Exemplo n.º 29
0
		public void Good(NetworkAddress addr, DateTimeOffset nTime)
		{
			lock(cs)
			{
				Check();
				Good_(addr, nTime);
				Check();
			}
		}
Exemplo n.º 30
0
		public bool Add(NetworkAddress addr, IPAddress source, TimeSpan nTimePenalty)
		{
			bool fRet = false;
			lock(cs)
			{
				Check();
				fRet |= Add_(addr, source, nTimePenalty);
				Check();
			}
			return fRet;
		}
Exemplo n.º 31
0
 private bool Add_(NetworkAddress addr, object source, TimeSpan nTimePenalty)
 {
     return(true);
 }
Exemplo n.º 32
0
		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];
		}
Exemplo n.º 33
0
 //! Mark an entry as connection attempted to.
 public void Attempt(NetworkAddress addr)
 {
     Attempt(addr, DateTimeOffset.UtcNow);
 }
Exemplo n.º 34
0
		public void Good(NetworkAddress addr)
		{
			Good(addr, DateTimeOffset.UtcNow);
		}
Exemplo n.º 35
0
 //! Mark an entry as currently-connected-to.
 public void Connected(NetworkAddress addr)
 {
     Connected(addr, DateTimeOffset.UtcNow);
 }
Exemplo n.º 36
0
		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);
		}
Exemplo n.º 37
0
 public AddressInfo(NetworkAddress addr, IPAddress addrSource)
 {
     Address = addr;
     Source  = addrSource;
 }
Exemplo n.º 38
0
		//! Mark an entry as connection attempted to.
		public void Attempt(NetworkAddress addr, DateTimeOffset nTime)
		{
			lock(cs)
			{
				Check();
				Attempt_(addr, nTime);
				Check();
			}
		}
Exemplo n.º 39
0
 internal bool Match(NetworkAddress addr)
 {
     return
         (Address.Endpoint.Address.Equals(addr.Endpoint.Address) &&
          Address.Endpoint.Port == addr.Endpoint.Port);
 }
Exemplo n.º 40
0
		//! Mark an entry as currently-connected-to.
		public void Connected(NetworkAddress addr)
		{
			Connected(addr, DateTimeOffset.UtcNow);
		}
Exemplo n.º 41
0
 //! Add a single address.
 public bool Add(NetworkAddress addr, IPAddress source)
 {
     return(Add(addr, source, TimeSpan.Zero));
 }
Exemplo n.º 42
0
		//! Mark an entry as currently-connected-to.
		public void Connected(NetworkAddress addr, DateTimeOffset nTime)
		{
			lock(cs)
			{
				Check();
				Connected_(addr, nTime);
				Check();
			}
		}
Exemplo n.º 43
0
 public bool Add(NetworkAddress addr)
 {
     return(Add(addr, IPAddress.Loopback));
 }
Exemplo n.º 44
0
        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);
            }
        }
Exemplo n.º 45
0
 public Peer(PeerOrigin origin, NetworkAddress address)
 {
     _Origin = origin;
     _NetworkAddress = address;
 }