예제 #1
0
 public PeerStatistic(PeerAddress peerAddress)
 {
     if (peerAddress == null)
     {
         throw new ArgumentException("PeerAddress cannot be null.");
     }
     Created     = Convenient.CurrentTimeMillis();
     _peerId     = peerAddress.PeerId;
     PeerAddress = peerAddress;
 }
예제 #2
0
        /// <summary>
        /// Creates a peer address from a continuous byte array. This is useful if you don't know the size beforehand.
        /// The new offset can be accessed through the Offset property.
        /// </summary>
        /// <param name="me">The serialized array.</param>
        /// <param name="initialOffset">The offset where to start.</param>
        public PeerAddress(sbyte[] me, int initialOffset)
        {
            // get the peer ID, this is independent of the type
            long offset = initialOffset;

            // get the options
            int options = me[offset++] & Utils.Utils.MaskFf;

            IsIPv6          = (options & Net6) > 0; // TODO static methods could be used instead
            IsFirewalledUdp = (options & FirewallUdp) > 0;
            IsFirewalledTcp = (options & FirewallTcp) > 0;
            IsRelayed       = (options & Relayed) > 0;

            // get the relays
            int relays = me[offset++] & Utils.Utils.MaskFf;

            // first 3 bits are the size
            RelaySize = (relays >> TypeBitSize) & Mask07;

            // last 5 bits indicate if IPv6 or IPv4
            var b = (byte)(relays & Mask1F); // TODO check if works (2x)

            _relayType = new BitArray(b);

            // get the ID
            var tmp = new sbyte[Number160.ByteArraySize];

            Array.Copy(me, offset, tmp, 0, Number160.ByteArraySize);
            PeerId  = new Number160(tmp);
            offset += Number160.ByteArraySize;

            PeerSocketAddress = PeerSocketAddress.Create(me, IsIPv4, offset);
            offset            = PeerSocketAddress.Offset;
            if (RelaySize > 0)
            {
                PeerSocketAddresses = new List <PeerSocketAddress>(RelaySize);
                for (int i = 0; i < RelaySize; i++)
                {
                    var psa = PeerSocketAddress.Create(me, !_relayType.Get(i), offset);
                    PeerSocketAddresses.Add(psa);
                    offset = psa.Offset;
                }
            }
            else
            {
                PeerSocketAddresses = EmptyPeerSocketAddresses;
            }

            Size      = offset - initialOffset;
            Offset    = offset;
            _hashCode = PeerId.GetHashCode();
        }
예제 #3
0
 /// <summary>
 /// Creates a new Number320 key from given location and domain keys.
 /// </summary>
 /// <param name="locationKey">The location key.</param>
 /// <param name="domainKey">The domain key.</param>
 public Number320(Number160 locationKey, Number160 domainKey)
 {
     if (locationKey == null)
     {
         throw new SystemException("LocationKey cannot be null.");
     }
     LocationKey = locationKey;
     if (domainKey == null)
     {
         throw new SystemException("DomainKey cannot be null.");
     }
     DomainKey = domainKey;
 }
예제 #4
0
        /// <summary>
        /// Constructor with reasonable defaults.
        /// </summary>
        /// <param name="self">The peer ID of this peer.</param>
        public PeerMapConfiguration(Number160 self)
        {
            Self               = self;
            BagSizeVerified    = 10;
            BagSizeOverflow    = 10;
            OfflineTimeout     = 60;
            ShutdownTimeout    = 20;
            ExceptionTimeout   = 120;
            OfflineCount       = 3;
            Maintenance        = new DefaultMaintenance(4, new[] { 2, 4, 8, 16, 32, 64 });
            IsPeerVerification = true;

            PeerFilters = new List <IPeerFilter>(2);
        }
예제 #5
0
        public static SortedSet <PeerAddress> ClosePeers(Number160 self, Number160 other, int atLeast,
                                                         IList <IDictionary <Number160, PeerStatistic> > peerMap)
        {
            var set         = new SortedSet <PeerAddress>(CreateComparer(other));
            int classMember = ClassMember(self, other);

            // special treatment, as we can start iterating from 0
            if (classMember == -1)
            {
                for (int j = 0; j < Number160.Bits; j++)
                {
                    var tmp = peerMap[j];
                    if (FillSet(atLeast, set, tmp))
                    {
                        return(set);
                    }
                }
                return(set);
            }

            var tmp2 = peerMap[classMember];

            if (FillSet(atLeast, set, tmp2))
            {
                return(set);
            }

            // in this case we have to go over all the bags that are smaller
            bool last = false;

            for (int i = 0; i < classMember; i++)
            {
                tmp2 = peerMap[i];
                last = FillSet(atLeast, set, tmp2);
            }
            if (last)
            {
                return(set);
            }
            // in this case we have to go over all the bags that are larger
            for (int i = 0; i < Number160.Bits; i++)
            {
                tmp2 = peerMap[i];
                FillSet(atLeast, set, tmp2);
            }
            return(set);
        }
예제 #6
0
        /// <summary>
        /// Creates a peer address from a byte buffer.
        /// </summary>
        /// <param name="buffer">The channel buffer to read from.</param>
        public PeerAddress(AlternativeCompositeByteBuf buffer)
        {
            long readerIndex = buffer.ReaderIndex;

            // get the type
            int options = buffer.ReadByte();

            IsIPv6          = (options & Net6) > 0;
            IsFirewalledUdp = (options & FirewallUdp) > 0;
            IsFirewalledTcp = (options & FirewallTcp) > 0;
            IsRelayed       = (options & Relayed) > 0;

            // get the relays
            int relays = buffer.ReadByte();

            RelaySize = (relays >> TypeBitSize) & Mask07;
            var b = (byte)(relays & Mask1F);  // TODO check if works (2x)

            _relayType = new BitArray(b);

            // get the ID
            var me = new sbyte[Number160.ByteArraySize];

            buffer.ReadBytes(me);
            PeerId = new Number160(me);

            PeerSocketAddress = PeerSocketAddress.Create(buffer, IsIPv4);

            if (RelaySize > 0)
            {
                PeerSocketAddresses = new List <PeerSocketAddress>(RelaySize);
                for (int i = 0; i < RelaySize; i++)
                {
                    PeerSocketAddresses.Add(PeerSocketAddress.Create(buffer, !_relayType.Get(i)));
                }
            }
            else
            {
                PeerSocketAddresses = EmptyPeerSocketAddresses;
            }

            Size = buffer.ReaderIndex - readerIndex;

            Offset    = -1; // not used here
            _hashCode = PeerId.GetHashCode();
        }
예제 #7
0
        /// <summary>
        /// Creates a peer address if all the values are known.
        /// </summary>
        /// <param name="id">The ID of the peer.</param>
        /// <param name="peerSocketAddress">The peer socket address including both ports UDP and TCP.</param>
        /// <param name="isFirewalledTcp">Indicates if the peer is not reachable via UDP.</param>
        /// <param name="isFirewalledUdp">Indicates if the peer is not reachable via TCP.</param>
        /// <param name="isRelayed">Indicates if the peer is used as a relay.</param>
        /// <param name="peerSocketAddresses">The relay peers.</param>
        public PeerAddress(Number160 id, PeerSocketAddress peerSocketAddress, bool isFirewalledTcp, bool isFirewalledUdp,
                           bool isRelayed, ICollection <PeerSocketAddress> peerSocketAddresses)
        {
            PeerId = id;
            int size = Number160.ByteArraySize;

            PeerSocketAddress = peerSocketAddress;
            _hashCode         = id.GetHashCode();
            IsIPv6            = peerSocketAddress.InetAddress.IsIPv6();
            IsFirewalledUdp   = isFirewalledUdp;
            IsFirewalledTcp   = isFirewalledTcp;
            IsRelayed         = isRelayed;

            // header + TCP port + UDP port
            size += HeaderSize + PortsSize + (IsIPv6 ? Utils.Utils.IPv6Bytes : Utils.Utils.IPv4Bytes);

            if (PeerSocketAddresses == null)
            {
                PeerSocketAddresses = EmptyPeerSocketAddresses;
                _relayType          = EmptyRelayType;
                RelaySize           = 0;
            }
            else
            {
                RelaySize = PeerSocketAddresses.Count;
                if (RelaySize > TypeBitSize)
                {
                    throw new ArgumentException(String.Format("Can only store up to {0} relay peers. Tried to store {1} relay peers.", TypeBitSize, RelaySize));
                }
                PeerSocketAddresses = peerSocketAddresses;
                _relayType          = new BitArray(RelaySize);
            }
            int index = 0;

            foreach (var psa in peerSocketAddresses)
            {
                bool isIPv6 = psa.InetAddress.IsIPv6();
                _relayType.Set(index, isIPv6);
                size += psa.Size();
                index++;
            }
            Size   = size;
            Offset = -1; // not used here
        }
예제 #8
0
 /// <summary>
 /// Creates a new Number640 key from given location, domain, content and version keys.
 /// </summary>
 /// <param name="locationKey">The location key.</param>
 /// <param name="domainKey">The domain key.</param>
 /// <param name="contentKey">The content key.</param>
 /// <param name="versionKey">The version key.</param>
 public Number640(Number160 locationKey, Number160 domainKey, Number160 contentKey, Number160 versionKey)
 {
     if (locationKey == null)
     {
         throw new SystemException("LocationKey cannot be null.");
     }
     LocationKey = locationKey;
     if (domainKey == null)
     {
         throw new SystemException("DomainKey cannot be null.");
     }
     DomainKey = domainKey;
     if (contentKey == null)
     {
         throw new SystemException("ContentKey cannot be null.");
     }
     ContentKey = contentKey;
     if (versionKey == null) // TODO check if necessary
     {
         throw new SystemException("VersionKey cannot be null.");
     }
     VersionKey = versionKey;
 }
예제 #9
0
 public bool Reject(PeerAddress peerAddress, ICollection <PeerAddress> all, Number160 target)
 {
     if (peerAddress.InetAddress.IsIPv4())
     {
         var ipv4 = IPv4.FromInetAddress(peerAddress.InetAddress);
         // ReSharper disable once LoopCanBeConvertedToQuery
         foreach (var paddr in all)
         {
             if (paddr.InetAddress.IsIPv4())
             {
                 var ipv4Test = IPv4.FromInetAddress(paddr.InetAddress);
                 if (ipv4.MaskWithNetworkMask(_mask4).Equals(ipv4Test.MaskWithNetworkMask(_mask4)))
                 {
                     return(true);
                 }
             }
         }
     }
     else
     {
         var ipv6 = IPv6.FromInetAddress(peerAddress.InetAddress);
         // ReSharper disable once LoopCanBeConvertedToQuery
         foreach (var paddr in all)
         {
             if (paddr.InetAddress.IsIPv6())
             {
                 var ipv6Test = IPv6.FromInetAddress(paddr.InetAddress);
                 if (ipv6.MaskWithNetworkMask(_mask6).Equals(ipv6Test.MaskWithNetworkMask(_mask6)))
                 {
                     return(true);
                 }
             }
         }
     }
     return(false);
 }
예제 #10
0
 /// <summary>
 /// If you only need to know the ID.
 /// </summary>
 /// <param name="id">The ID of the peer.</param>
 public PeerAddress(Number160 id)
     : this(id, (IPAddress)null, -1, -1)
 {
 }
예제 #11
0
 public bool Reject(PeerAddress peerAddress, ICollection <PeerAddress> all, Number160 target)
 {
     // TODO in Java: to be implemented
     return(false);
 }
예제 #12
0
 /// <summary>
 /// Returns -1 if the first remote node is closer to the key.
 /// If the second node is closer, then 1 is returned.
 /// If both are equal, 0 is returned.
 /// </summary>
 /// <param name="id">The ID as a distance reference.</param>
 /// <param name="rn">The peer to test if closer to the ID.</param>
 /// <param name="rn2">The other peer to test if closer to the ID.</param>
 /// <returns>-1 if the first peer is closer, 1 otherwise. 0 if both are equal.</returns>
 public static int IsKadCloser(Number160 id, PeerAddress rn, PeerAddress rn2)
 {
     return(Distance(id, rn.PeerId).CompareTo(Distance(id, rn2.PeerId)));
 }
예제 #13
0
 /// <summary>
 /// Creates a Kademlia distance comparer.
 /// </summary>
 /// <param name="id">The ID of this peer.</param>
 public KademliaComparer(Number160 id)
 {
     _id = id;
 }
예제 #14
0
 /// <summary>
 /// Returns the difference in terms of bit counts of two IDs, minus 1.
 /// So two IDs with one bit difference are in the class 0.
 /// </summary>
 /// <param name="id1">The first ID.</param>
 /// <param name="id2">The second ID.</param>
 /// <returns>The bit difference and -1 if they are equal.</returns>
 internal static int ClassMember(Number160 id1, Number160 id2)
 {
     return(Distance(id1, id2).BitLength - 1);
 }
예제 #15
0
 /// <summary>
 /// The distance metric is the XOR metric.
 /// </summary>
 /// <param name="id1">The first ID.</param>
 /// <param name="id2">The second ID.</param>
 /// <returns>The XOR distance.</returns>
 internal static Number160 Distance(Number160 id1, Number160 id2)
 {
     return(id1.Xor(id2));
 }
예제 #16
0
 /// <summary>
 /// Creates the Kademlia distance comparer.
 /// </summary>
 /// <param name="id">The ID of this peer.</param>
 /// <returns>The XOR comparer.</returns>
 public static IComparer <PeerAddress> CreateComparer(Number160 id)
 {
     return(new KademliaComparer(id));
 }
예제 #17
0
 /// <summary>
 /// Returns the number of the class that this ID belongs to.
 /// </summary>
 /// <param name="remoteId">The ID to test.</param>
 /// <returns>The number of bits used in the difference.</returns>
 private int ClassMember(Number160 remoteId)
 {
     return(ClassMember(Self, remoteId));
 }
예제 #18
0
 /// <summary>
 /// Creates a new Number640 key from given location, domain, content and version keys.
 /// </summary>
 /// <param name="key"></param>
 /// <param name="contentKey"></param>
 /// <param name="versionKey"></param>
 public Number640(Number320 key, Number160 contentKey, Number160 versionKey)
     : this(key.LocationKey, key.DomainKey, contentKey, versionKey)
 {
 }
예제 #19
0
 /// <summary>
 /// If you only need to know the ID and the internet address.
 /// </summary>
 /// <param name="id">The ID of the peer.</param>
 /// <param name="inetAddress">The internet address of the peer.</param>
 public PeerAddress(Number160 id, IPAddress inetAddress)
     : this(id, inetAddress, -1, -1)
 {
 }
예제 #20
0
 /// <summary>
 /// Create a new peer address and change the peer ID.
 /// </summary>
 /// <param name="peerId">The new peer ID.</param>
 /// <returns>The newly created peer address.</returns>
 public PeerAddress ChangePeerId(Number160 peerId)
 {
     return(new PeerAddress(peerId, PeerSocketAddress, IsFirewalledTcp, IsFirewalledUdp, IsRelayed, PeerSocketAddresses));
 }
예제 #21
0
 /// <summary>
 /// Facade for PeerAddress(Number160, IPAddress, int, int).
 /// </summary>
 /// <param name="peerId">The ID of the peer.</param>
 /// <param name="inetSocketAddress">The socket address of the peer. Both TCP and UDP will be set to the same port.</param>
 public PeerAddress(Number160 peerId, IPEndPoint inetSocketAddress)
     : this(peerId, inetSocketAddress.Address, inetSocketAddress.Port, inetSocketAddress.Port)
 {
 }
예제 #22
0
 /// <summary>
 /// Facade for PeerAddress(Number160, IPAddress, int, int).
 /// </summary>
 /// <param name="peerId">The ID of the peer.</param>
 /// <param name="inetAddress">The internet address of the peer.</param>
 /// <param name="tcpPort">The TCP port of the peer.</param>
 /// <param name="udpPort">The UDP port of the peer.</param>
 public PeerAddress(Number160 peerId, string inetAddress, int tcpPort, int udpPort)
     : this(peerId, IPAddress.Parse(inetAddress), tcpPort, udpPort)
 {
 }
예제 #23
0
 /// <summary>
 /// Facade for PeerAddress(Number160, PeerSocketAddress, bool, bool, bool, Collection-PeerSocketAddress>.
 /// </summary>
 /// <param name="peerId">The ID of the peer.</param>
 /// <param name="inetAddress">The internet address of the peer.</param>
 /// <param name="tcpPort">The TCP port of the peer.</param>
 /// <param name="udpPort">The UDP port of the peer.</param>
 /// <param name="options">The options for the created <see cref="PeerAddress"/>.</param>
 public PeerAddress(Number160 peerId, IPAddress inetAddress, int tcpPort, int udpPort, int options)
     : this(peerId, new PeerSocketAddress(inetAddress, tcpPort, udpPort), ReadIsFirewalledTcp(options), ReadIsFirewalledUdp(options), ReadIsRelay(options), EmptyPeerSocketAddresses)
 {
 }
예제 #24
0
        // Facade Constructors:

        /// <summary>
        /// Facade for PeerAddress(Number160, PeerSocketAddress, bool, bool, bool, Collection-PeerSocketAddress>)}.
        /// </summary>
        /// <param name="peerId">The ID of the peer.</param>
        /// <param name="inetAddress">The internet address of the peer.</param>
        /// <param name="tcpPort">The TCP port of the peer.</param>
        /// <param name="udpPort">The UDP port of the peer.</param>
        public PeerAddress(Number160 peerId, IPAddress inetAddress, int tcpPort, int udpPort) // TODO both IPv4 and IPv6 can be passed here -> fix flags
            : this(peerId, new PeerSocketAddress(inetAddress, tcpPort, udpPort), false, false, false, EmptyPeerSocketAddresses)
        {
        }
예제 #25
0
 /// <summary>
 /// Returns close peers from the set to a given key. This method is thread-safe.
 /// You can use the returned set as it is a copy of the actual peer map and changes
 /// in the return set do not affect the peer map.
 /// </summary>
 /// <param name="id">The key that should be close to the keys in the map.</param>
 /// <param name="atLeast">The number we want to find at least.</param>
 /// <returns>A sorted set with close peers first in this set.</returns>
 public SortedSet <PeerAddress> ClosePeers(Number160 id, int atLeast)
 {
     return(ClosePeers(Self, id, atLeast, PeerMapVerified));
 }
예제 #26
0
 public bool Reject(PeerAddress peerAddress, ICollection <PeerAddress> all, Number160 target)
 {
     // by default, don't reject anything
     return(false);
 }