Example #1
0
        public static TrackerBehavior Discover(Tracker tracker)
        {
            TrackerBehavior behavior = new TrackerBehavior(tracker);

            behavior.SupportsScrape = tracker.SupportsScrape;
            behavior.SupportsMultiScrape = false;
            behavior.MultiScrapeRange = 0;
            behavior.MultiScrapeThreshold = -1;
            behavior.SupportsFullScrape = false;
            behavior.IndicatesPasskey = false;
            behavior.IndicatesPrivacy = false;
            behavior.DefaultInterval = TrackerSettings.DefaultInterval;

            PeerId peerId1 = CreateDiscoveryPeerId();
            PeerId peerId2 = CreateDiscoveryPeerId();
            InfoHash infoHash1 = CreateDiscoveryInfoHash();
            InfoHash infoHash2 = CreateDiscoveryInfoHash();

            if (tracker.Protocol == TrackerProtocol.HTTP || tracker.Protocol == TrackerProtocol.HTTPS)
            {

                string[] announcePathFragments = tracker.AnnounceUrl.LocalPath.Split('/');
                string announceQueryLower = tracker.AnnounceUrl.Query.ToLower();

                if (announcePathFragments.Length > 2)
                {
                    if (Regex.IsMatch(announcePathFragments[announcePathFragments.Length - 2], @"\A[0-9a-fA-F]*\z"))
                    {
                        behavior.IndicatesPasskey = true;
                        behavior.IndicatesPrivacy = true;
                        goto EndExposureAssessment;
                    }
                }

                string passkey = HttpUtility.ParseQueryString(announceQueryLower)["passkey"];

                if (!String.IsNullOrEmpty(passkey))
                {
                    if (Regex.IsMatch(passkey, @"\A[0-9a-fA-F]*\z"))
                    {
                        behavior.IndicatesPasskey = true;
                        behavior.IndicatesPrivacy = true;
                    }
                }

            EndExposureAssessment: ;

            }

            if (behavior.SupportsScrape)
            {
                try
                {
                    behavior.DefaultInterval = tracker.CreateAnnounceRequest(infoHash1, peerId1, discoveryPort, 0, 0, 0).GetTransport().GetResponse().Interval;
                }
                catch (TrackerFailureException tfe)
                {
                    string messageLower = tfe.Message.ToLower();

                    if (messageLower.Contains("client") || messageLower.Contains("protocol"))
                        behavior.IndicatesClientRestriction = true;
                    else
                        behavior.IndicatesRegistration = true;
                }
                catch (Exception)
                {
                    throw;
                }

                if (tracker.Protocol == TrackerProtocol.HTTP || tracker.Protocol == TrackerProtocol.HTTPS)
                {
                    try
                    {
                        HttpScrapeTransport scrapeTestTransport = (HttpScrapeTransport)tracker.CreateScrapeRequest().GetTransport();
                        HttpWebResponse scrapeTestResponse = (HttpWebResponse)scrapeTestTransport.HttpRequest.GetResponse();

                        if (scrapeTestResponse.StatusCode == HttpStatusCode.OK)
                        {
                            char[] scrapeStartTestResponseBuffer = new char[httpMultiScrapeResponseStartFragment.Length];
                            char[] scrapeEndTestResponseBuffer = new char[httpMultiScrapeResponseEndFragment.Length];

                            using (StreamReader scrapeTestResponseReader = new StreamReader(scrapeTestResponse.GetResponseStream()))
                            {
                                if (
                                    scrapeTestResponseReader.Read(scrapeStartTestResponseBuffer, 0, scrapeStartTestResponseBuffer.Length) == scrapeStartTestResponseBuffer.Length &&
                                    scrapeTestResponseReader.Read(scrapeEndTestResponseBuffer, 0, scrapeEndTestResponseBuffer.Length) == scrapeEndTestResponseBuffer.Length
                                    )
                                {
                                    if (new string(scrapeStartTestResponseBuffer) == httpMultiScrapeResponseStartFragment)
                                    {
                                        if (scrapeTestResponse.ContentLength != -1 && new string(scrapeEndTestResponseBuffer) != httpMultiScrapeResponseEndFragment)
                                        {
                                            behavior.ScrapeThreshold = (int)Math.Ceiling((decimal)scrapeTestResponse.ContentLength / (decimal)(tracker.ScrapeUrl.ToString().Length + httpInfoHashQueryFieldSize));
                                            behavior.MultiScrapeThreshold = (int)Math.Ceiling((decimal)scrapeTestResponse.ContentLength / (decimal)httpInfoHashQueryFieldSize);
                                        }
                                        else
                                        {
                                            behavior.ScrapeThreshold = TrackerSettings.DefaultScrapeThreshold;
                                            behavior.MultiScrapeThreshold = TrackerSettings.DefaultMultiScrapeThreshold;
                                        }

                                        behavior.SupportsFullScrape = true;
                                    }
                                }
                            }
                        }
                    }
                    catch (TrackerFailureException tfe)
                    {
                        if (tfe.Message.ToLower().Contains("client"))
                            behavior.IndicatesClientRestriction = true;
                        else
                            behavior.IndicatesPrivacy = true;
                    }
                    catch (Exception)
                    {
                        throw;
                    }

                    if (!behavior.IndicatesRegistration && !behavior.IndicatesPrivacy)
                    {
                        try
                        {
                            tracker.CreateAnnounceRequest(infoHash2, peerId2, discoveryPort, 0, 0, 0).GetResponse();

                            IScrapeResponse scrapeResponse = tracker.CreateScrapeRequest(new InfoHash[2] { infoHash1, infoHash2 }).GetResponse();

                            if (scrapeResponse.Files.ContainsKey(infoHash1) && scrapeResponse.Files.ContainsKey(infoHash2))
                            {
                                behavior.SupportsMultiScrape = true;
                                behavior.MultiScrapeRange = HttpScrapeTransport.MultiScrapeRange;
                            }
                        }
                        catch (TrackerFailureException tfe)
                        {
                            string mutliScrapeError = tfe.Message.ToLower();

                            if (mutliScrapeError.Contains("register") && !mutliScrapeError.Contains("pass") && !mutliScrapeError.Contains("key"))
                                behavior.SupportsMultiScrape = true;
                        }
                    }
                    else
                    {
                        // Tracker is private, but multi-scrape is probably enabled
                        behavior.SupportsMultiScrape = true;
                    }
                }
                else if (tracker.Protocol == TrackerProtocol.UDP)
                {
                    behavior.SupportsMultiScrape = true;
                    behavior.MultiScrapeRange = UdpScrapeTransport.MultiScrapeRange;
                }
            }

            return behavior;
        }
Example #2
0
 private TrackerBehavior(Tracker tracker)
 {
     SupportsScrape = tracker.SupportsScrape;
     SupportsFullScrape = false;
     DefaultInterval = TrackerSettings.DefaultInterval;
 }
Example #3
0
            public TrackerBehavior this[Tracker tracker]
            {
                get
                {
                    lock (syncRoot)
                    {
                        if (tracker == null)
                            throw new ArgumentNullException("tracker");

                        if (cache.ContainsKey(tracker.AnnounceUrl))
                        {
                            BehaviorCacheItem item = cache[tracker.AnnounceUrl];

                            if (!item.Expired)
                                return item.Behavior;
                        }

                        return null;
                    }
                }
                set
                {
                    lock (syncRoot)
                    {
                        if (tracker == null)
                            throw new ArgumentNullException("tracker");

                        if (cache.ContainsKey(tracker.AnnounceUrl))
                            cache[tracker.AnnounceUrl] = new BehaviorCacheItem(value, cache[tracker.AnnounceUrl].LifeTime);
                        else
                            cache.Add(tracker.AnnounceUrl, new BehaviorCacheItem(value));
                    }
                }
            }