Пример #1
0
        protected virtual void HandleHandshakeMessage(PeerId id, HandshakeMessage message)
        {
            if (!message.ProtocolString.Equals(Constants.ProtocolStringV100))
            {
                logger.InfoFormatted(id.Connection, "Invalid protocol in handshake: {0}", message.ProtocolString);
                throw new ProtocolException("Invalid protocol string");
            }

            // If we got the peer as a "compact" peer, then the peerid will be empty. In this case
            // we just copy the one that is in the handshake.
            if (BEncodedString.IsNullOrEmpty(id.Peer.PeerId))
            {
                id.Peer.PeerId = message.PeerId;
            }

            // If the infohash doesn't match, dump the connection
            if (message.InfoHash != Manager.InfoHash)
            {
                logger.Info(id.Connection, "HandShake.Handle - Invalid infohash");
                throw new TorrentException("Invalid infohash. Not tracking this torrent");
            }

            // If the peer id's don't match, dump the connection. This is due to peers faking usually
            if (!id.Peer.PeerId.Equals(message.PeerId))
            {
                if (Manager.HasMetadata && Manager.Torrent.IsPrivate)
                {
                    // If this is a private torrent we should be careful about peerids. If they don't
                    // match we should close the connection. I *think* uTorrent doesn't randomise peerids
                    // for private torrents. It's not documented very well. We may need to relax this check
                    // if other clients randomize for private torrents.
                    logger.Info(id.Connection, "HandShake.Handle - Invalid peerid");
                    throw new TorrentException("Supplied PeerID didn't match the one the tracker gave us");
                }
                else
                {
                    // We don't care about the mismatch for public torrents. uTorrent randomizes its PeerId, as do other clients.
                    id.Peer.PeerId = message.PeerId;
                }
            }

            // Attempt to parse the application that the peer is using
            id.ClientApp          = new Software(message.PeerId);
            id.SupportsFastPeer   = message.SupportsFastPeer;
            id.SupportsLTMessages = message.SupportsExtendedMessaging;

            // If they support fast peers, create their list of allowed pieces that they can request off me
            if (id.SupportsFastPeer && Manager != null && Manager.HasMetadata)
            {
                AllowedFastHasher ??= Manager.Engine.Factories.CreateSHA1();
                id.AmAllowedFastPieces = AllowedFastAlgorithm.Calculate(AllowedFastHasher, id.AddressBytes, Manager.InfoHash, (uint)Manager.Torrent.Pieces.Count);
            }
        }
Пример #2
0
        Uri CreateAnnounceString(AnnounceParameters parameters)
        {
            var b = new UriQueryBuilder(Uri);

            b.Add("info_hash", parameters.InfoHash.UrlEncode())
            .Add("peer_id", parameters.PeerId.UrlEncode())
            .Add("port", parameters.Port)
            .Add("uploaded", parameters.BytesUploaded)
            .Add("downloaded", parameters.BytesDownloaded)
            .Add("left", parameters.BytesLeft)
            .Add("compact", 1)
            .Add("numwant", 100);

            if (parameters.SupportsEncryption)
            {
                b.Add("supportcrypto", 1);
            }
            if (parameters.RequireEncryption)
            {
                b.Add("requirecrypto", 1);
            }
            if (!b.Contains("key") && Key != null)
            {
                b.Add("key", Key.UrlEncode());
            }
            if (!string.IsNullOrEmpty(parameters.IPAddress))
            {
                b.Add("ip", parameters.IPAddress);
            }

            // If we have not successfully sent the started event to this tier, override the passed in started event
            // Otherwise append the event if it is not "none"
            //if (!parameters.Id.Tracker.Tier.SentStartedEvent)
            //{
            //    sb.Append("&event=started");
            //    parameters.Id.Tracker.Tier.SendingStartedEvent = true;
            //}
            if (parameters.ClientEvent != TorrentEvent.None)
            {
                b.Add("event", parameters.ClientEvent.ToString().ToLower());
            }

            if (!BEncodedString.IsNullOrEmpty(TrackerId))
            {
                b.Add("trackerid", TrackerId.UrlEncode());
            }

            return(b.ToUri());
        }
Пример #3
0
        public bool Equals(Peer other)
        {
            if (other == null)
            {
                return(false);
            }

            // FIXME: Don't compare the port, just compare the IP
            if (BEncodedString.IsNullOrEmpty(PeerId) || BEncodedString.IsNullOrEmpty(other.PeerId))
            {
                return(ConnectionUri.Equals(other.ConnectionUri));
            }

            return(PeerId.Equals(other.PeerId));
        }
Пример #4
0
        /// <summary>
        /// Creates a new tracker
        /// </summary>
        /// <param name="trackerId">The unique identifier to use as the <see cref="TrackerId"/></param>
        public TrackerServer(BEncodedString trackerId)
        {
            Requests = new RequestMonitor();
            Torrents = new Dictionary <InfoHash, SimpleTorrentManager> ();

            // Generate an ID which shows that this is monotorrent, and the version, and then a unique(ish) integer.
            if (BEncodedString.IsNullOrEmpty(trackerId))
            {
                lock (Random)
                    trackerId = $"{GitInfoHelper.ClientVersion}-{Random.Next (1, int.MaxValue)}";
            }
            TrackerId = trackerId;

            Listeners = new List <ITrackerListener> ();
            Client.ClientEngine.MainLoop.QueueTimeout(TimeSpan.FromSeconds(1), delegate {
                Requests.Tick();
                return(!Disposed);
            });
        }
Пример #5
0
        protected virtual void HandleHandshakeMessage(PeerId id, HandshakeMessage message)
        {
            if (!message.ProtocolString.Equals(VersionInfo.ProtocolStringV100))
            {
                Logger.Log(id.Connection, "HandShake.Handle - Invalid protocol in handshake: {0}", message.ProtocolString);
                throw new ProtocolException("Invalid protocol string");
            }

            // If we got the peer as a "compact" peer, then the peerid will be empty. In this case
            // we just copy the one that is in the handshake.
            if (BEncodedString.IsNullOrEmpty(id.Peer.PeerId))
            {
                id.Peer.PeerId = message.PeerId;
            }

            // If the infohash doesn't match, dump the connection
            if (message.InfoHash != id.TorrentManager.InfoHash)
            {
                Logger.Log(id.Connection, "HandShake.Handle - Invalid infohash");
                throw new TorrentException("Invalid infohash. Not tracking this torrent");
            }

            // If the peer id's don't match, dump the connection. This is due to peers faking usually
            if (!id.Peer.PeerId.Equals(message.PeerId))
            {
                Logger.Log(id.Connection, "HandShake.Handle - Invalid peerid");
                throw new TorrentException("Supplied PeerID didn't match the one the tracker gave us");
            }

            // Attempt to parse the application that the peer is using
            id.ClientApp          = new Software(message.PeerId);
            id.SupportsFastPeer   = message.SupportsFastPeer;
            id.SupportsLTMessages = message.SupportsExtendedMessaging;

            // If they support fast peers, create their list of allowed pieces that they can request off me
            if (id.SupportsFastPeer && id.TorrentManager != null && id.TorrentManager.HasMetadata)
            {
                id.AmAllowedFastPieces = AllowedFastAlgorithm.Calculate(id.AddressBytes, id.TorrentManager.InfoHash, (uint)id.TorrentManager.Torrent.Pieces.Count);
            }
        }
Пример #6
0
        protected virtual void HandleHandshakeMessage(PeerId id, HandshakeMessage message)
        {
            if (!message.ProtocolString.Equals(Constants.ProtocolStringV100))
            {
                logger.InfoFormatted(id.Connection, "Invalid protocol in handshake: {0}", message.ProtocolString);
                throw new ProtocolException("Invalid protocol string");
            }

            // If we got the peer as a "compact" peer, then the peerid will be empty. In this case
            // we just copy the one that is in the handshake.
            if (BEncodedString.IsNullOrEmpty(id.Peer.PeerId))
            {
                id.Peer.PeerId = message.PeerId;
            }

            // If the infohash doesn't match, dump the connection
            if (!Manager.InfoHashes.Contains(message.InfoHash))
            {
                logger.Info(id.Connection, "HandShake.Handle - Invalid infohash");
                throw new TorrentException("Invalid infohash. Not tracking this torrent");
            }

            // If the peer id's don't match, dump the connection. This is due to peers faking usually
            if (!id.Peer.PeerId.Equals(message.PeerId))
            {
                if (Manager.HasMetadata && Manager.Torrent !.IsPrivate)
                {
                    // If this is a private torrent we should be careful about peerids. If they don't
                    // match we should close the connection. I *think* uTorrent doesn't randomise peerids
                    // for private torrents. It's not documented very well. We may need to relax this check
                    // if other clients randomize for private torrents.
                    logger.Info(id.Connection, "HandShake.Handle - Invalid peerid");
                    throw new TorrentException("Supplied PeerID didn't match the one the tracker gave us");
                }
                else
                {
                    // We don't care about the mismatch for public torrents. uTorrent randomizes its PeerId, as do other clients.
                    id.Peer.PeerId = message.PeerId;
                }
            }