예제 #1
0
 protected override void ReceiveAnnounce(AnnounceMessage announceMessage)
 {
     if (!IgnoreAnnounces)
     {
         base.ReceiveAnnounce(announceMessage);
     }
 }
예제 #2
0
 protected override async Task ReceiveAnnounce(UdpClient client, AnnounceMessage announceMessage, IPEndPoint remotePeer)
 {
     if (!IgnoreAnnounces)
     {
         await base.ReceiveAnnounce(client, announceMessage, remotePeer);
     }
 }
        public void AnnounceMessage_TryDecode()
        {
            AnnounceMessage message;

            byte[] data = "0000041727101980 00000001 00003300 6385736543351543134351535341535355433445 2D5443313031302D313131313131313131313131 0000000000000001 0000000000000002 0000000000000003 00000002 09080706 0000000A 0000000B 1354".Replace(" ", string.Empty).ToByteArray();

            if (AnnounceMessage.TryDecode(data, 0, out message))
            {
                Assert.AreEqual(98, message.Length);
                Assert.AreEqual(1, (int)message.Action);
                Assert.AreEqual(13056, message.TransactionId);
                Assert.AreEqual("6385736543351543134351535341535355433445", message.InfoHash);
                Assert.AreEqual("-TC1010-313131313131313131313131", message.PeerId);
                Assert.AreEqual(1, message.Downloaded);
                Assert.AreEqual(2, message.Left);
                Assert.AreEqual(3, message.Uploaded);
                Assert.AreEqual(2, (int)message.TrackingEvent);
                Assert.AreEqual(IPAddress.Parse("6.7.8.9"), message.Endpoint.Address);
                Assert.AreEqual((uint)0xA, message.Key);
                Assert.AreEqual((int)0xB, message.NumberWanted);
                Assert.AreEqual(0x1354, message.Endpoint.Port);
                CollectionAssert.AreEqual(data, message.Encode());
            }
            else
            {
                Assert.Fail();
            }
        }
예제 #4
0
        public async ReusableTask <AnnounceResponse> AnnounceAsync(AnnounceRequest parameters, CancellationToken token)
        {
            try {
                if (ConnectionIdTask == null || LastConnected.Elapsed > TimeSpan.FromMinutes(1))
                {
                    ConnectionIdTask = ConnectAsync();
                }
                long connectionId = await ConnectionIdTask;

                var message = new AnnounceMessage(DateTime.Now.GetHashCode(), connectionId, parameters);
                (var response, var errorString) = await SendAndReceiveAsync(message);

                // Did we receive an 'ErrorMessage' from the tracker? If so, propagate the failure
                if (errorString != null)
                {
                    ConnectionIdTask = null;
                    return(new AnnounceResponse(TrackerState.InvalidResponse, failureMessage: errorString));
                }

                var announce = (AnnounceResponseMessage)response;
                return(new AnnounceResponse(TrackerState.Ok, announce.Peers, minUpdateInterval: announce.Interval));
            } catch (OperationCanceledException) {
                ConnectionIdTask = null;
                return(new AnnounceResponse(TrackerState.Offline, failureMessage: "Announce could not be completed"));
            } catch {
                ConnectionIdTask = null;
                return(new AnnounceResponse(TrackerState.InvalidResponse, failureMessage: "Announce could not be completed"));
            }
        }
예제 #5
0
        protected override async Task <List <Peer> > DoAnnounceAsync(AnnounceParameters parameters)
        {
            try {
                if (ConnectionIdTask == null || LastConnected.Elapsed > TimeSpan.FromMinutes(1))
                {
                    ConnectionIdTask = ConnectAsync();
                }
                long connectionId = await ConnectionIdTask;

                var message  = new AnnounceMessage(DateTime.Now.GetHashCode(), connectionId, parameters);
                var announce = (AnnounceResponseMessage) await SendAndReceiveAsync(message);

                MinUpdateInterval = announce.Interval;

                Status = TrackerState.Ok;
                return(announce.Peers);
            } catch (OperationCanceledException e) {
                Status           = TrackerState.Offline;
                ConnectionIdTask = null;
                throw new TrackerException("Announce could not be completed", e);
            } catch (Exception e) {
                Status           = TrackerState.InvalidResponse;
                ConnectionIdTask = null;
                throw new TrackerException("Announce could not be completed", e);
            }
        }
예제 #6
0
            static void ValidateAnnounceMessage(object possibleMessage, DistributedHost host)
            {
                AnnounceMessage announceMessage = possibleMessage as AnnounceMessage;

                Assert.IsNotNull(announceMessage);
                Assert.AreEqual(host.SocketAddress, announceMessage.AnnouncerSocketAddress);
                Assert.AreEqual(0, announceMessage.KnownPeers.Length);
            }
예제 #7
0
        public static UdpTrackerMessage DecodeMessage(byte[] buffer, int offset, int count, MessageType type)
        {
            UdpTrackerMessage m = null;
            int action          = type == MessageType.Request ? ReadInt(buffer, offset + 8) : ReadInt(buffer, offset);

            switch (action)
            {
            case 0:
                if (type == MessageType.Request)
                {
                    m = new ConnectMessage();
                }
                else
                {
                    m = new ConnectResponseMessage();
                }
                break;

            case 1:
                if (type == MessageType.Request)
                {
                    m = new AnnounceMessage();
                }
                else
                {
                    m = new AnnounceResponseMessage();
                }
                break;

            case 2:
                if (type == MessageType.Request)
                {
                    m = new ScrapeMessage();
                }
                else
                {
                    m = new ScrapeResponseMessage();
                }
                break;

            case 3:
                m = new ErrorMessage();
                break;

            default:
                throw new ProtocolException(string.Format("Invalid udp message received: {0}", buffer[offset]));
            }

            try
            {
                m.Decode(buffer, offset, count);
            }
            catch
            {
                m = new ErrorMessage(0, "Couldn't decode the tracker response");
            }
            return(m);
        }
예제 #8
0
        /// <summary>
        /// Gets the tracker URI.
        /// </summary>
        /// <returns>The tracker URI.</returns>
        private Uri GetUri()
        {
            string uri;

            uri  = this.TrackerUri.ToString();
            uri += "?";
            uri += new AnnounceMessage(this.TorrentInfoHash, this.PeerId, this.ListeningPort, this.BytesUploaded, this.BytesDownloaded, this.BytesLeftToDownload, this.WantedPeerCount, this.TrackingEvent).Encode();

            return(new Uri(uri));
        }
        //QUICKHACK: format bencoded val and get it back wereas must refactor tracker system to have more generic object...
        protected virtual void ReceiveAnnounce(AnnounceMessage announceMessage)
        {
            UdpTrackerMessage  m;
            BEncodedDictionary dict = Handle(getCollection(announceMessage), endpoint.Address, false);

            if (dict.ContainsKey(RequestParameters.FailureKey))
            {
                m = new ErrorMessage(announceMessage.TransactionId, dict[RequestParameters.FailureKey].ToString());
            }
            else
            {
                TimeSpan interval = TimeSpan.Zero;
                int      leechers = 0;
                int      seeders  = 0;
                List <System.Net.BitTorrent.Client.Peer> peers = new List <System.Net.BitTorrent.Client.Peer>();
                foreach (KeyValuePair <BEncodedString, BEncodedValue> keypair in dict)
                {
                    switch (keypair.Key.Text)
                    {
                    case ("complete"):
                        seeders = Convert.ToInt32(keypair.Value.ToString());    //same as seeder?
                        break;

                    case ("incomplete"):
                        leechers = Convert.ToInt32(keypair.Value.ToString());    //same as leecher?
                        break;

                    case ("interval"):
                        interval = TimeSpan.FromSeconds(int.Parse(keypair.Value.ToString()));
                        break;

                    case ("peers"):
                        if (keypair.Value is BEncodedList)              // Non-compact response
                        {
                            peers.AddRange(System.Net.BitTorrent.Client.Peer.Decode((BEncodedList)keypair.Value));
                        }
                        else if (keypair.Value is BEncodedString)       // Compact response
                        {
                            peers.AddRange(System.Net.BitTorrent.Client.Peer.Decode((BEncodedString)keypair.Value));
                        }
                        break;

                    default:
                        break;
                    }
                }
                m = new AnnounceResponseMessage(announceMessage.TransactionId, interval, leechers, seeders, peers);
            }
            byte[] data = m.Encode();
#if NETSTANDARD1_5
            listener.SendAsync(data, data.Length, endpoint);
#else
            listener.Send(data, data.Length, endpoint);
#endif
        }
        public PlaytestService(DataService data, GoogleCalendar calendar, LogHandler log, Random random)
        {
            _data     = data;
            _log      = log;
            _calendar = calendar;

            PlaytestAnnouncementMessage = null;
            _oldMessage = null;

            _announcementMessage = new AnnouncementMessage(_calendar, _data, random, _log);
        }
예제 #11
0
        public void AnnounceMessageTest()
        {
            var m = new AnnounceMessage(0, 12345, _announceParams);
            var d = (AnnounceMessage) UdpTrackerMessage.DecodeMessage(m.Encode(), 0, m.ByteLength, MessageType.Request);
            Check(m, MessageType.Request);

            Assert.AreEqual(1, m.Action);
            Assert.AreEqual(m.Action, d.Action);
            Assert.IsTrue(Toolbox.ByteMatch(m.Encode(), d.Encode()));
            Assert.AreEqual(12345, d.ConnectionId);
        }
예제 #12
0
        public void AnnounceMessageTest()
        {
            AnnounceMessage m = new AnnounceMessage(0, 12345, announceparams);
            AnnounceMessage d = (AnnounceMessage)UdpTrackerMessage.DecodeMessage(m.Encode(), 0, m.ByteLength, MessageType.Request);

            Check(m, MessageType.Request);

            Assert.AreEqual(1, m.Action);
            Assert.AreEqual(m.Action, d.Action);
            Assert.IsTrue(Toolbox.ByteMatch(m.Encode(), d.Encode()));
            Assert.AreEqual(12345, d.ConnectionId);
        }
        public void RoundTripWithRequiredData()
        {
            AnnounceMessage announceMessage = new AnnounceMessage();

            announceMessage.HeadHash        = Keccak.Compute("1");
            announceMessage.HeadBlockNo     = 4;
            announceMessage.TotalDifficulty = 131200;
            announceMessage.ReorgDepth      = 0;

            AnnounceMessageSerializer serializer = new AnnounceMessageSerializer();

            SerializerTester.TestZero(serializer, announceMessage, "e8a0c89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6048302008080c0");
        }
        //QUICKHACK: format bencoded val and get it back wereas must refactor tracker system to have more generic object...
        protected virtual async Task ReceiveAnnounce(UdpClient client, AnnounceMessage announceMessage, IPEndPoint remotePeer)
        {
            UdpTrackerMessage  m;
            BEncodedDictionary dict = Handle(getCollection(announceMessage), remotePeer.Address, false);

            if (dict.ContainsKey(TrackerRequest.FailureKey))
            {
                m = new ErrorMessage(announceMessage.TransactionId, dict[TrackerRequest.FailureKey].ToString());
            }
            else
            {
                TimeSpan interval = TimeSpan.Zero;
                int      leechers = 0;
                int      seeders  = 0;
                var      peers    = new List <MonoTorrent.Client.Peer> ();
                foreach (KeyValuePair <BEncodedString, BEncodedValue> keypair in dict)
                {
                    switch (keypair.Key.Text)
                    {
                    case ("complete"):
                        seeders = Convert.ToInt32(keypair.Value.ToString());      //same as seeder?
                        break;

                    case ("incomplete"):
                        leechers = Convert.ToInt32(keypair.Value.ToString());      //same as leecher?
                        break;

                    case ("interval"):
                        interval = TimeSpan.FromSeconds(int.Parse(keypair.Value.ToString()));
                        break;

                    case ("peers"):
                        if (keypair.Value is BEncodedList)              // Non-compact response
                        {
                            peers.AddRange(MonoTorrent.Client.Peer.Decode((BEncodedList)keypair.Value));
                        }
                        else if (keypair.Value is BEncodedString)       // Compact response
                        {
                            peers.AddRange(MonoTorrent.Client.Peer.Decode((BEncodedString)keypair.Value));
                        }
                        break;

                    default:
                        break;
                    }
                }
                m = new AnnounceResponseMessage(announceMessage.TransactionId, interval, leechers, seeders, peers);
            }
            byte[] data = m.Encode();
            await client.SendAsync(data, data.Length, remotePeer);
        }
        protected override async Task ReceiveAnnounce(UdpClient client, AnnounceMessage announceMessage, IPEndPoint remotePeer)
        {
            if (IncompleteAnnounce)
            {
                await client.SendAsync(Enumerable.Repeat ((byte)200, 50).ToArray(), 50, remotePeer);

                return;
            }

            if (!IgnoreAnnounces)
            {
                await base.ReceiveAnnounce(client, announceMessage, remotePeer);
            }
        }
예제 #16
0
        private async Task DoAnnounceAsync(AnnounceParameters parameter, object state)
        {
            var announceMessage = new AnnounceMessage(DateTime.Now.GetHashCode(), _connectionId, parameter);
            var responseBytes   = await SendAndReceiveAsync(announceMessage);

            var msg = Receive(announceMessage, responseBytes);

            if (!(msg is AnnounceResponseMessage))
            {
                throw new Exception(FailureMessage);
            }

            MinUpdateInterval = ((AnnounceResponseMessage)msg).Interval;
            CompleteAnnounce(msg, state);
        }
예제 #17
0
        private NameValueCollection getCollection(AnnounceMessage announceMessage)
        {
            NameValueCollection res = new NameValueCollection();

            res.Add("info_hash", announceMessage.Infohash.UrlEncode());
            res.Add("peer_id", announceMessage.PeerId);
            res.Add("port", announceMessage.Port.ToString());
            res.Add("uploaded", announceMessage.Uploaded.ToString());
            res.Add("downloaded", announceMessage.Downloaded.ToString());
            res.Add("left", announceMessage.Left.ToString());
            res.Add("compact", "1");//hardcode
            res.Add("numwant", announceMessage.NumWanted.ToString());
            res.Add("ip", announceMessage.Ip.ToString());
            res.Add("key", announceMessage.Key.ToString());
            res.Add("event", announceMessage.TorrentEvent.ToString().ToLower());
            return(res);
        }
        NameValueCollection getCollection(AnnounceMessage announceMessage)
        {
            var res = new NameValueCollection {
                { "info_hash", announceMessage.InfoHash.UrlEncode() },
                { "peer_id", announceMessage.PeerId.UrlEncode() },
                { "port", announceMessage.Port.ToString() },
                { "uploaded", announceMessage.Uploaded.ToString() },
                { "downloaded", announceMessage.Downloaded.ToString() },
                { "left", announceMessage.Left.ToString() },
                { "compact", "1" },//hardcode
                { "numwant", announceMessage.NumWanted.ToString() },
                { "ip", announceMessage.IP.ToString() },
                { "key", announceMessage.Key.ToString() },
                { "event", announceMessage.TorrentEvent.ToString().ToLower() }
            };

            return(res);
        }
예제 #19
0
        /// <summary>
        /// Called when announce is requested.
        /// </summary>
        protected override void OnAnnounce()
        {
            TrackerMessage message;

            this.OnAnnouncing(this, EventArgs.Empty);

            message = new AnnounceMessage(this.connectionId, this.transactionId, this.TorrentInfoHash, this.PeerId, this.BytesDownloaded, this.BytesLeftToDownload, this.BytesUploaded, this.TrackingEvent, 0, this.WantedPeerCount, new IPEndPoint(IPAddress.Loopback, this.ListeningPort));

            Debug.WriteLine($"{this.TrackerUri} -> {message}");

            message = this.ExecuteUdpRequest(this.TrackerUri, message);

            if (message is AnnounceResponseMessage)
            {
                Debug.WriteLine($"{this.TrackerUri} <- {message}");

                this.OnAnnounced(this, new AnnouncedEventArgs(message.As <AnnounceResponseMessage>().Interval, message.As <AnnounceResponseMessage>().LeecherCount, message.As <AnnounceResponseMessage>().SeederCount, message.As <AnnounceResponseMessage>().Peers));
            }
        }
예제 #20
0
        public override async Task AnnounceAsync(AnnounceParameters parameters, TrackerConnectionID state)
        {
            try {
                if (ConnectionIdTask == null || LastConnected.Elapsed > TimeSpan.FromMinutes(1))
                {
                    ConnectionIdTask = ConnectAsync();
                }
                await ConnectionIdTask;

                var message  = new AnnounceMessage(DateTime.Now.GetHashCode(), ConnectionIdTask.Result, parameters);
                var announce = (AnnounceResponseMessage) await SendAndReceiveAsync(message);

                MinUpdateInterval = announce.Interval;
                RaiseAnnounceComplete(new AnnounceResponseEventArgs(this, state, true, announce.Peers));
            } catch (Exception e) {
                ConnectionIdTask = null;
                RaiseAnnounceComplete(new AnnounceResponseEventArgs(this, state, false));
                throw new Exception("Announce could not be completed", e);
            }
        }
        public static UdpTrackerMessage DecodeMessage(byte[] buffer, int offset, int count, MessageType type)
        {
            UdpTrackerMessage m = null;
            var action = type == MessageType.Request ? ReadInt(buffer, offset + 8) : ReadInt(buffer, offset);
            switch (action)
            {
                case 0:
                    if (type == MessageType.Request)
                        m = new ConnectMessage();
                    else
                        m = new ConnectResponseMessage();
                    break;
                case 1:
                    if (type == MessageType.Request)
                        m = new AnnounceMessage();
                    else
                        m = new AnnounceResponseMessage();
                    break;
                case 2:
                    if (type == MessageType.Request)
                        m = new ScrapeMessage();
                    else
                        m = new ScrapeResponseMessage();
                    break;
                case 3:
                    m = new ErrorMessage();
                    break;
                default:
                    throw new ProtocolException(string.Format("Invalid udp message received: {0}", buffer[offset]));
            }

            try
            {
                m.Decode(buffer, offset, count);
            }
            catch
            {
                m = new ErrorMessage(0, "Couldn't decode the tracker response");
            }
            return m;
        }
        /// <summary>
        ///     Gets the stored announcement message from the DB.
        /// </summary>
        /// <returns>Found announcement message or null</returns>
        public static AnnounceMessage GetAnnouncementMessage()
        {
            AnnounceMessage foundMessage = null;

            try
            {
                using (var db = new LiteDatabase(DBPATH))
                {
                    //Grab our collection
                    var announcement = db.GetCollection <AnnounceMessage>(COLLECTION_ANNOUNCEMENT);

                    foundMessage = announcement.FindOne(Query.EQ("_id", 1));
                }
            }
            catch (Exception e)
            {
                //TODO: Don't actually know what exceptions can happen here, catch all for now.
                _ = _log.LogMessage("Something happened getting announcement message\n" +
                                    $"{e}", false, color: ConsoleColor.Red);
                return(foundMessage);
            }

            return(foundMessage);
        }
예제 #23
0
 protected override void ReceiveAnnounce(AnnounceMessage announceMessage)
 {
     if (!IgnoreAnnounces)
         base.ReceiveAnnounce(announceMessage);
 }
        /// <summary>
        ///     Attempts to get a previously created announcement message based on values that were stored in the DB.
        ///     If the located message does not match the current event it will be deleted.
        ///     If nothing can be located, it does nothing.
        /// </summary>
        /// <returns></returns>
        public async Task TryAttachPreviousAnnounceMessage()
        {
            var testEvent = _calendar.GetTestEvent();

            //Get the last known message
            _oldMessage = DatabaseHandler.GetAnnouncementMessage();

            //No message found in the DB, do nothing. Likely to happen when DB is new.
            if (_oldMessage == null)
            {
                if (_data.RSettings.ProgramSettings.Debug)
                {
                    _ = _log.LogMessage("No message found in DB to reattach to", false, color: LOG_COLOR);
                }

                return;
            }

            //Make sure a test is valid
            if (!testEvent.IsValid)
            {
                if (_data.RSettings.ProgramSettings.Debug)
                {
                    _ = _log.LogMessage("No valid test found to post", false, color: LOG_COLOR);
                }

                return;
            }

            _ = _log.LogMessage("Attempting to get old announcement message\n" +
                                $"{_oldMessage.AnnouncementId} that was created at {_oldMessage.AnnouncementDateTime}",
                                false, color: LOG_COLOR);


            var eventEditTime = _calendar.GetTestEventNoUpdate().EventEditTime;

            if (eventEditTime != null && eventEditTime.Value.Equals(_oldMessage.AnnouncementDateTime))
            {
                try
                {
                    PlaytestAnnouncementMessage =
                        await _data.AnnouncementChannel.GetMessageAsync(_oldMessage.AnnouncementId) as IUserMessage;

                    if (PlaytestAnnouncementMessage != null)
                    {
                        _ = _log.LogMessage($"Retrieved old announcement! ID: {PlaytestAnnouncementMessage.Id}", false,
                                            color: LOG_COLOR);
                    }

                    var lastEditTime = _calendar.GetTestEventNoUpdate().LastEditTime;
                    if (lastEditTime != null)
                    {
                        _lastSeenEditTime = lastEditTime.Value;
                    }
                }
                catch
                {
                    _ = _log.LogMessage("Unable to retrieve old announcement message!", false, color: LOG_COLOR);
                }
            }
            else
            {
                _ = _log.LogMessage("Messages do not match, deleting old message", false, color: LOG_COLOR);
                try
                {
                    await _data.AnnouncementChannel.DeleteMessageAsync(_oldMessage.AnnouncementId);

                    PlaytestAnnouncementMessage = null;
                }
                catch
                {
                    _ = _log.LogMessage("Could not delete old message - it was likely deleted manually",
                                        false, color: LOG_COLOR);
                }
            }
        }
예제 #25
0
 NameValueCollection getCollection(AnnounceMessage announceMessage)
 {
     var res = new NameValueCollection {
         { "info_hash", announceMessage.InfoHash !.UrlEncode() },