Example #1
0
        /// <summary>
        /// Indicates if a peer needs a maintenance check.
        /// </summary>
        /// <param name="peerStatistic">The peer with its statistics.</param>
        /// <param name="intervalSeconds"></param>
        /// <returns>True, if the peer needs a maintenance check.</returns>
        public static bool NeedMaintenance(PeerStatistic peerStatistic, int[] intervalSeconds)
        {
            int onlineSec = peerStatistic.OnlineTime / 1000;
            int index;

            if (onlineSec <= 0)
            {
                index = 0;
            }
            else
            {
                index = intervalSeconds.Length - 1;
                for (int i = 0; i < intervalSeconds.Length; i++)
                {
                    if (intervalSeconds[i] >= onlineSec)
                    {
                        index = i;
                        break;
                    }
                }
            }
            int  time = intervalSeconds[index];
            long lastTimeWhenChecked = Convenient.CurrentTimeMillis() - peerStatistic.LastSeenOnline;

            return(lastTimeWhenChecked > TimeSpan.FromSeconds(time).TotalSeconds);
        }
Example #2
0
 /// <summary>
 /// Notifies on update. This method is thread-safe.
 /// </summary>
 /// <param name="peerAddress">The address of the updated peer.</param>
 /// <param name="storedPeerAddress">Contains statistical information.</param>
 private void NotifyUpdate(PeerAddress peerAddress, PeerStatistic storedPeerAddress)
 {
     lock (_peerMapChangeListeners)
     {
         foreach (var listener in _peerMapChangeListeners)
         {
             listener.PeerUpdated(peerAddress, storedPeerAddress);
         }
     }
 }
Example #3
0
        /// <summary>
        /// Adds a neighbor to the neighbor list. If the bag is full, the ID zero or the same
        /// as our ID, the neighbor is not added. This method is thread-safe.
        /// </summary>
        /// <param name="remotePeer">The node to be added.</param>
        /// <param name="referrer">If we had direct contact and we know for sure that this node
        /// is online, we set first hand to true. Information from 3rd party peers are always
        /// second hand and treated as suc.</param>
        /// <param name="peerConnection"></param>
        /// <returns>True, if the neighbor could be added or updated. False, otherwise.</returns>
        public bool PeerFound(PeerAddress remotePeer, PeerAddress referrer, PeerConnection peerConnection)
        {
            Logger.Debug("Peer {0} is online. Reporter was {1}.", remotePeer, referrer);
            bool firstHand = referrer == null;
            // if we got contacted by this peer, but we did not initiate the connection
            bool secondHand = remotePeer.Equals(referrer);
            // if a peer reported about other peers
            bool thirdHand = !firstHand && !secondHand;

            // always trust first hand information
            if (firstHand)
            {
                _offlineMap.Remove(remotePeer.PeerId);
                _shutdownMap.Remove(remotePeer.PeerId);
            }
            if (secondHand && !_peerVerification)
            {
                _offlineMap.Remove(remotePeer.PeerId);
                _shutdownMap.Remove(remotePeer.PeerId);
            }

            // don't add nodes with zero node ID, don't add myself and don't add nodes marked as bad
            if (remotePeer.PeerId.IsZero || Self.Equals(remotePeer.PeerId) || Reject(remotePeer))
            {
                return(false);
            }

            if (remotePeer.IsFirewalledTcp || remotePeer.IsFirewalledUdp)
            {
                return(false);
            }

            // if a peer is relayed but cannot provide any relays, it is useless
            if (remotePeer.IsRelayed && remotePeer.PeerSocketAddresses.Count == 0)
            {
                return(false);
            }

            bool probablyDead = _offlineMap.ContainsKey(remotePeer.PeerId) ||
                                _shutdownMap.ContainsKey(remotePeer.PeerId) ||
                                _exceptionMap.ContainsKey(remotePeer.PeerId);

            if (thirdHand && probablyDead)
            {
                Logger.Debug("Don't add {0}.", remotePeer.PeerId);
                return(false);
            }

            int classMember = ClassMember(remotePeer.PeerId);

            // the peer might have a new port
            var oldPeerStatistic = UpdateExistingVerifiedPeerAddress(PeerMapVerified[classMember], remotePeer,
                                                                     firstHand);

            if (oldPeerStatistic != null)
            {
                // we update the peer, so we can exit here and report that we have updated it
                NotifyUpdate(remotePeer, oldPeerStatistic);
                return(true);
            }
            else
            {
                if (firstHand || (secondHand && !_peerVerification))
                {
                    var  map      = PeerMapVerified[classMember];
                    bool inserted = false;
                    lock (map)
                    {
                        // check again, now we are synchronized
                        if (map.ContainsKey(remotePeer.PeerId))
                        {
                            return(PeerFound(remotePeer, referrer, peerConnection));
                        }
                        if (map.Count < BagSizeVerified)
                        {
                            var peerStatistic = new PeerStatistic(remotePeer);
                            peerStatistic.SuccessfullyChecked();
                            map.Add(remotePeer.PeerId, peerStatistic);
                            inserted = true;
                        }
                    }

                    if (inserted)
                    {
                        // if we inserted into the verified map, remove it from the non-verified map
                        var mapOverflow = PeerMapOverflow[classMember];
                        lock (mapOverflow)
                        {
                            mapOverflow.Remove(remotePeer.PeerId);
                        }
                        NotifyInsert(remotePeer, true);
                        return(true);
                    }
                }
            }

            // if we are here, we did not have this peer, but our verified map was full
            // check if we have it stored in the non-verified map
            var mapOverflow2 = PeerMapOverflow[classMember];

            lock (mapOverflow2)
            {
                PeerStatistic peerStatistic;
                if (!mapOverflow2.TryGetValue(remotePeer.PeerId, out peerStatistic))
                {
                    peerStatistic = new PeerStatistic(remotePeer);
                }
                if (firstHand)
                {
                    peerStatistic.SuccessfullyChecked();
                }
                mapOverflow2.Add(remotePeer.PeerId, peerStatistic);
            }
            NotifyInsert(remotePeer, false);
            return(true);
        }