Exemplo n.º 1
0
        private void AnnounceCallback(IAsyncResult ar)
        {
            ConnectAnnounceState announceState = (ConnectAnnounceState)ar;

            try
            {
                if (announceState.SavedException != null)
                {
                    FailureMessage = announceState.SavedException.Message;
                    DoAnnounceComplete(false, announceState.AsyncState, new List <Peer>());
                    return;
                }
                UdpTrackerMessage rsp = Receive(announceState, announceState.Data);
                if (!(rsp is AnnounceResponseMessage))
                {
                    DoAnnounceComplete(false, announceState.AsyncState, new List <Peer>());
                    return;
                }

                MinUpdateInterval = ((AnnounceResponseMessage)rsp).Interval;
                CompleteAnnounce(rsp, announceState.AsyncState);
            }
            catch
            {
                DoAnnounceComplete(false, announceState.AsyncState, null);
            }
        }
Exemplo n.º 2
0
        async Task <UdpTrackerMessage> ReceiveAsync(UdpClient client, int transactionId, CancellationToken token)
        {
            while (!token.IsCancellationRequested)
            {
                UdpReceiveResult received = await client.ReceiveAsync();

                var rsp = UdpTrackerMessage.DecodeMessage(received.Buffer, 0, received.Buffer.Length, MessageType.Response);

                if (transactionId == rsp.TransactionId)
                {
                    if (rsp is ErrorMessage error)
                    {
                        FailureMessage = error.Error;
                        throw new Exception("The tracker returned an error.");
                    }
                    else
                    {
                        return(rsp);
                    }
                }
            }
            // If we get here then the token will have been cancelled. We need the additional
            // 'throw' statement to keep the compiler happy.
            token.ThrowIfCancellationRequested();
            throw new OperationCanceledException("The tracker did not respond.");
        }
Exemplo n.º 3
0
        private bool ConnectCallback(IAsyncResult ar)
        {
            UdpTrackerAsyncState trackerState = (UdpTrackerAsyncState)ar;

            try
            {
                UdpTrackerMessage msg = Receive(trackerState, trackerState.Data);
                if (msg == null)
                {
                    return(false);//bad transaction id
                }
                ConnectResponseMessage rsp = msg as ConnectResponseMessage;
                if (rsp == null)
                {
                    //is there a possibility to have a message which is not error message or connect rsp but udp msg
                    FailureMessage = ((ErrorMessage)msg).Error;
                    return(false);//error message
                }
                connectionId = rsp.ConnectionId;
                hasConnected = true;
                amConnecting = false;
                return(true);
            }
            catch
            {
                return(false);
            }
        }
Exemplo n.º 4
0
        private static void Check(IMessage message, MessageType type)
        {
            var e = message.Encode();

            Assert.AreEqual(e.Length, message.ByteLength, "#1");
            Assert.IsTrue(Toolbox.ByteMatch(e, UdpTrackerMessage.DecodeMessage(e, 0, e.Length, type).Encode()), "#2");
        }
Exemplo n.º 5
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);
        }
Exemplo n.º 6
0
        private async Task SendRequestAsync(UdpTrackerMessage message)
        {
            var encodedMessage = message.Encode();
            var dataWriter1    = new DataWriter(_tracker.OutputStream);

            try
            {
                dataWriter1.WriteBytes(encodedMessage);
                await dataWriter1.StoreAsync();
            }
            finally
            {
                dataWriter1.DetachStream();
            }

            ClientEngine.MainLoop.QueueTimeout(RetryDelay, () =>
            {
                lock (_lock)
                {
                    if (_timeout == 0)
                    {
                        return(false);
                    }
                    if (_timeout <= 4)
                    {
                        _timeout++;
                        try
                        {
                            var dataWriter = new DataWriter(_tracker.OutputStream);
                            try
                            {
                                dataWriter.WriteBytes(encodedMessage);
                                dataWriter.StoreAsync().AsTask().Wait();
                            }
                            finally
                            {
                                dataWriter.DetachStream();
                            }
                        }
                        catch (Exception exception1)
                        {
                            var exception = exception1;
                            lock (_lock)
                            {
                                _timeout = 0;
                            }
                            _taskCompletionSource.TrySetException(exception);
                            return(false);
                        }
                        return(true);
                    }
                    _timeout = 0;
                    _taskCompletionSource.TrySetException(new Exception("Announce timeout."));
                }
                return(false);
            });
        }
Exemplo n.º 7
0
        private async Task <byte[]> SendAndReceiveAsync(UdpTrackerMessage message)
        {
            lock (_lock)
                _timeout = 1;
            _taskCompletionSource = new TaskCompletionSource <byte[]>();
            await SendRequestAsync(message);

            return(await _taskCompletionSource.Task);
        }
Exemplo n.º 8
0
        async Task <UdpTrackerMessage> SendAndReceiveAsync(UdpTrackerMessage msg)
        {
            var cts = new CancellationTokenSource(TimeSpan.FromSeconds(RetryDelay.TotalSeconds * MaxRetries));

            using (var udpClient = new UdpClient(Uri.Host, Uri.Port))
                using (cts.Token.Register(() => udpClient.Dispose())) {
                    SendAsync(udpClient, msg, cts.Token);
                    return(await ReceiveAsync(udpClient, msg.TransactionId, cts.Token));
                }
        }
Exemplo n.º 9
0
        async void ReceiveAsync(UdpClient client, CancellationToken token)
        {
            Task sendTask = null;

            while (!token.IsCancellationRequested)
            {
                try
                {
                    var result = await client.ReceiveAsync();

                    byte[] data = result.Buffer;
                    if (data.Length < 16)
                    {
                        return;//bad request
                    }
                    UdpTrackerMessage request = UdpTrackerMessage.DecodeMessage(data, 0, data.Length, MessageType.Request);

                    if (sendTask != null)
                    {
                        try {
                            await sendTask;
                        } catch {
                        }
                    }


                    switch (request.Action)
                    {
                    case 0:
                        sendTask = ReceiveConnect(client, (ConnectMessage)request, result.RemoteEndPoint);
                        break;

                    case 1:
                        sendTask = ReceiveAnnounce(client, (AnnounceMessage)request, result.RemoteEndPoint);
                        break;

                    case 2:
                        sendTask = ReceiveScrape(client, (ScrapeMessage)request, result.RemoteEndPoint);
                        break;

                    case 3:
                        sendTask = ReceiveError(client, (ErrorMessage)request, result.RemoteEndPoint);
                        break;

                    default:
                        throw new ProtocolException(string.Format("Invalid udp message received: {0}", request.Action));
                    }
                }
                catch (Exception e)
                {
                    Logger.Log(null, e.ToString());
                }
            }
        }
Exemplo n.º 10
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);
        }
        private void ReceiveData(IAsyncResult ar)
        {
            try
            {
                System.Net.Sockets.UdpClient listener = (System.Net.Sockets.UdpClient)ar.AsyncState;
                byte[] data = listener.EndReceive(ar, ref endpoint);
#endif
                if (data.Length < 16)
                {
                    return;//bad request
                }
                UdpTrackerMessage request = UdpTrackerMessage.DecodeMessage(data, 0, data.Length, MessageType.Request);

                switch (request.Action)
                {
                case 0:
                    ReceiveConnect((ConnectMessage)request);
                    break;

                case 1:
                    ReceiveAnnounce((AnnounceMessage)request);
                    break;

                case 2:
                    ReceiveScrape((ScrapeMessage)request);
                    break;

                case 3:
                    ReceiveError((ErrorMessage)request);
                    break;

                default:
                    throw new ProtocolException(string.Format("Invalid udp message received: {0}", request.Action));
                }
            }
            catch (Exception e)
            {
                Logger.Log(null, e.ToString());
            }
            finally
            {
                if (Running)
                {
#if NETSTANDARD1_5
                    result = await listener.ReceiveAsync();

                    ReceiveData(result, client);
#else
                    listener.BeginReceive(new AsyncCallback(ReceiveData), listener);
#endif
                }
            }
        }
Exemplo n.º 12
0
 async void SendAsync(UdpClient client, UdpTrackerMessage msg, CancellationToken token)
 {
     byte[] buffer = msg.Encode();
     try {
         do
         {
             client.Send(buffer, buffer.Length);
             await Task.Delay(RetryDelay, token);
         }while (!token.IsCancellationRequested);
     } catch {
     }
 }
Exemplo n.º 13
0
        public void AnnounceResponseTest()
        {
            var peers = peerEndpoints.Select(t => new Peer("", new Uri($"ipv4://{t.Address}:{t.Port}"))).ToList();
            AnnounceResponseMessage m = new AnnounceResponseMessage(12345, TimeSpan.FromSeconds(10), 43, 65, peers);
            AnnounceResponseMessage d = (AnnounceResponseMessage)UdpTrackerMessage.DecodeMessage(m.Encode(), 0, m.ByteLength, MessageType.Response);

            Check(m, MessageType.Response);

            Assert.AreEqual(1, m.Action);
            Assert.AreEqual(m.Action, d.Action);
            Assert.IsTrue(Toolbox.ByteMatch(m.Encode(), d.Encode()));
            Assert.AreEqual(12345, d.TransactionId);
        }
Exemplo n.º 14
0
        private UdpTrackerMessage Receive(UdpTrackerAsyncState trackerState, byte[] receivedMessage)
        {
            timeout = 0;//we have receive so unactive the timeout
            byte[]            data = receivedMessage;
            UdpTrackerMessage rsp  = UdpTrackerMessage.DecodeMessage(data, 0, data.Length, MessageType.Response);

            if (trackerState.Message.TransactionId != rsp.TransactionId)
            {
                FailureMessage = "Invalid transaction Id in response from udp tracker!";
                return(null);//to raise event fail outside
            }
            return(rsp);
        }
Exemplo n.º 15
0
        public void ConnectMessageTest()
        {
            ConnectMessage m = new ConnectMessage();
            ConnectMessage d = (ConnectMessage)UdpTrackerMessage.DecodeMessage(m.Encode(), 0, m.ByteLength, MessageType.Request);

            Check(m, MessageType.Request);

            Assert.AreEqual(0, m.Action, "#0");
            Assert.AreEqual(m.Action, d.Action, "#1");
            Assert.AreEqual(m.ConnectionId, d.ConnectionId, "#2");
            Assert.AreEqual(m.TransactionId, d.TransactionId, "#3");
            Assert.IsTrue(Toolbox.ByteMatch(m.Encode(), d.Encode()), "#4");
        }
        public void ConnectResponseTest()
        {
            ConnectResponseMessage m = new ConnectResponseMessage(5371, 12345);
            ConnectResponseMessage d = (ConnectResponseMessage)UdpTrackerMessage.DecodeMessage(m.Encode(), MessageType.Response);

            Check(m, MessageType.Response);

            Assert.AreEqual(0, m.Action, "#0");
            Assert.AreEqual(m.Action, d.Action, "#1");
            Assert.AreEqual(m.ConnectionId, d.ConnectionId, "#2");
            Assert.AreEqual(m.TransactionId, d.TransactionId, "#3");
            Assert.IsTrue(Toolbox.ByteMatch(m.Encode(), d.Encode()), "#4");
            Assert.AreEqual(12345, d.ConnectionId);
            Assert.AreEqual(5371, d.TransactionId);
        }
Exemplo n.º 17
0
        private void CompleteScrape(UdpTrackerMessage message, object state)
        {
            ErrorMessage error = message as ErrorMessage;

            if (error != null)
            {
                FailureMessage = error.Error;
                DoScrapeComplete(false, state);
            }
            else
            {
                //response.Scrapes not used for moment
                //ScrapeResponseMessage response = (ScrapeResponseMessage)message;
                DoScrapeComplete(true, state);
            }
        }
Exemplo n.º 18
0
        void SendAsync(UdpClient client, UdpTrackerMessage msg, CancellationToken token)
        {
            byte[] buffer = msg.Encode();
            client.Send(buffer, buffer.Length);

            ClientEngine.MainLoop.QueueTimeout(RetryDelay, () => {
                try {
                    if (!token.IsCancellationRequested)
                    {
                        client.Send(buffer, buffer.Length);
                    }
                    return(!token.IsCancellationRequested);
                } catch {
                    return(false);
                }
            });
        }
Exemplo n.º 19
0
        public void ConnectResponseTest()
        {
            var expectedMessage = new ConnectResponseMessage(5371, 12345);
            var actualMessage   =
                (ConnectResponseMessage)
                UdpTrackerMessage.DecodeMessage(expectedMessage.Encode(), 0, expectedMessage.ByteLength, MessageType.Response);

            Check(expectedMessage, MessageType.Response);

            Assert.AreEqual(0, expectedMessage.Action, "#0");
            Assert.AreEqual(expectedMessage.Action, actualMessage.Action, "#1");
            Assert.AreEqual(expectedMessage.ConnectionId, actualMessage.ConnectionId, "#2");
            Assert.AreEqual(expectedMessage.TransactionId, actualMessage.TransactionId, "#3");
            Assert.IsTrue(Toolbox.ByteMatch(expectedMessage.Encode(), actualMessage.Encode()), "#4");
            Assert.AreEqual(12345, actualMessage.ConnectionId);
            Assert.AreEqual(5371, actualMessage.TransactionId);
        }
Exemplo n.º 20
0
        private void CompleteAnnounce(UdpTrackerMessage message, object state)
        {
            ErrorMessage error = message as ErrorMessage;

            if (error != null)
            {
                FailureMessage = error.Error;
                DoAnnounceComplete(false, state, new List <Peer>());
            }
            else
            {
                AnnounceResponseMessage response = (AnnounceResponseMessage)message;
                DoAnnounceComplete(true, state, response.Peers);

                //TODO seeders and leechers is not used in event.
            }
        }
Exemplo n.º 21
0
        public void ScrapeResponseTest()
        {
            List <ScrapeDetails> details = new List <ScrapeDetails>();

            details.Add(new ScrapeDetails(1, 2, 3));
            details.Add(new ScrapeDetails(4, 5, 6));
            details.Add(new ScrapeDetails(7, 8, 9));

            ScrapeResponseMessage m = new ScrapeResponseMessage(12345, details);
            ScrapeResponseMessage d = (ScrapeResponseMessage)UdpTrackerMessage.DecodeMessage(m.Encode(), 0, m.ByteLength, MessageType.Response);

            Check(m, MessageType.Response);

            Assert.AreEqual(2, m.Action);
            Assert.AreEqual(m.Action, d.Action);
            Assert.IsTrue(Toolbox.ByteMatch(m.Encode(), d.Encode()));
            Assert.AreEqual(12345, d.TransactionId);
        }
Exemplo n.º 22
0
        public void AnnounceResponseTest()
        {
            List <Peer> peers = new List <Peer>();

            peers.Add(new Peer(new string('1', 20), new Uri("tcp://127.0.0.1:1")));
            peers.Add(new Peer(new string('2', 20), new Uri("tcp://127.0.0.1:2")));
            peers.Add(new Peer(new string('3', 20), new Uri("tcp://127.0.0.1:3")));

            AnnounceResponseMessage m = new AnnounceResponseMessage(12345, TimeSpan.FromSeconds(10), 43, 65, peers);
            AnnounceResponseMessage d = (AnnounceResponseMessage)UdpTrackerMessage.DecodeMessage(m.Encode(), 0, m.ByteLength, MessageType.Response);

            Check(m, MessageType.Response);

            Assert.AreEqual(1, m.Action);
            Assert.AreEqual(m.Action, d.Action);
            Assert.IsTrue(Toolbox.ByteMatch(m.Encode(), d.Encode()));
            Assert.AreEqual(12345, d.TransactionId);
        }
Exemplo n.º 23
0
        async Task <(UdpTrackerMessage, string)> SendAndReceiveAsync(UdpTrackerMessage msg)
        {
            var cts = new CancellationTokenSource(TimeSpan.FromSeconds(RetryDelay.TotalSeconds * MaxRetries));

            try {
                // Calling the UdpClient ctor which takes a hostname, or calling the Connect method,
                // results in a synchronous DNS resolve. Ensure we're on a threadpool thread to avoid
                // blocking.
                await new ThreadSwitcher();
                using var udpClient = new UdpClient(Uri.Host, Uri.Port);
                using (cts.Token.Register(() => udpClient.Dispose())) {
                    SendAsync(udpClient, msg, cts.Token);
                    return(await ReceiveAsync(udpClient, msg.TransactionId, cts.Token).ConfigureAwait(false));
                }
            } catch {
                cts.Token.ThrowIfCancellationRequested();
                throw;
            }
        }
Exemplo n.º 24
0
        public void ScrapeResponseTest()
        {
            var details = new List <ScrapeDetails>
            {
                new ScrapeDetails(1, 2, 3),
                new ScrapeDetails(4, 5, 6),
                new ScrapeDetails(7, 8, 9)
            };

            var expectedMessage = new ScrapeResponseMessage(12345, details);
            var actualMessage   =
                (ScrapeResponseMessage)
                UdpTrackerMessage.DecodeMessage(expectedMessage.Encode(), 0, expectedMessage.ByteLength, MessageType.Response);

            Check(expectedMessage, MessageType.Response);

            Assert.AreEqual(2, expectedMessage.Action);
            Assert.AreEqual(expectedMessage.Action, actualMessage.Action);
            Assert.IsTrue(Toolbox.ByteMatch(expectedMessage.Encode(), actualMessage.Encode()));
            Assert.AreEqual(12345, actualMessage.TransactionId);
        }
Exemplo n.º 25
0
        async Task <UdpTrackerMessage> ReceiveAsync(UdpClient client, int transactionId, CancellationToken token)
        {
            while (!token.IsCancellationRequested)
            {
                var received = await client.ReceiveAsync();

                UdpTrackerMessage rsp = UdpTrackerMessage.DecodeMessage(received.Buffer, 0, received.Buffer.Length, MessageType.Response);

                if (transactionId == rsp.TransactionId)
                {
                    if (rsp is ErrorMessage error)
                    {
                        FailureMessage = error.Error;
                        throw new Exception("The tracker returned an error.");
                    }
                    else
                    {
                        return(rsp);
                    }
                }
            }
            throw new Exception("The tracker did not respond.");
        }
Exemplo n.º 26
0
        public void ScrapeMessageTest()
        {
            List <byte[]> hashes = new List <byte[]>();
            Random        r      = new Random();

            byte[] hash1 = new byte[20];
            byte[] hash2 = new byte[20];
            byte[] hash3 = new byte[20];
            r.NextBytes(hash1);
            r.NextBytes(hash2);
            r.NextBytes(hash3);
            hashes.Add(hash1);
            hashes.Add(hash2);
            hashes.Add(hash3);

            ScrapeMessage m = new ScrapeMessage(12345, 123, hashes);
            ScrapeMessage d = (ScrapeMessage)UdpTrackerMessage.DecodeMessage(m.Encode(), 0, m.ByteLength, MessageType.Request);

            Check(m, MessageType.Request);

            Assert.AreEqual(2, m.Action);
            Assert.AreEqual(m.Action, d.Action);
            Assert.IsTrue(Toolbox.ByteMatch(m.Encode(), d.Encode()));
        }
Exemplo n.º 27
0
 private void ScrapeCallback(IAsyncResult ar)
 {
     try
     {
         ConnectScrapeState scrapeState = (ConnectScrapeState)ar;
         if (scrapeState.SavedException != null)
         {
             FailureMessage = scrapeState.SavedException.Message;
             DoScrapeComplete(false, scrapeState.AsyncState);
             return;
         }
         UdpTrackerMessage rsp = Receive(scrapeState, scrapeState.Data);
         if (!(rsp is ScrapeResponseMessage))
         {
             DoScrapeComplete(false, scrapeState.AsyncState);
             return;
         }
         CompleteScrape(rsp, scrapeState.AsyncState);
     }
     catch
     {
         // Nothing to do i think
     }
 }
Exemplo n.º 28
0
        async void ReceiveAsync(UdpClient client, CancellationToken token)
        {
            Task sendTask = null;

            while (!token.IsCancellationRequested)
            {
                try {
                    UdpReceiveResult result = await client.ReceiveAsync();

                    byte[] data = result.Buffer;
                    if (data.Length < 16)
                    {
                        return; //bad request
                    }
                    var request = UdpTrackerMessage.DecodeMessage(data.AsSpan(0, data.Length), MessageType.Request);

                    if (sendTask != null)
                    {
                        try {
                            await sendTask;
                        } catch {
                        }
                    }

                    sendTask = request.Action switch {
                        0 => ReceiveConnect(client, (ConnectMessage)request, result.RemoteEndPoint),
                        1 => ReceiveAnnounce(client, (AnnounceMessage)request, result.RemoteEndPoint),
                        2 => ReceiveScrape(client, (ScrapeMessage)request, result.RemoteEndPoint),
                        3 => ReceiveError(client, (ErrorMessage)request, result.RemoteEndPoint),
                        _ => throw new InvalidOperationException($"Invalid udp message received: {request.Action}")
                    };
                } catch (Exception e) {
                    logger.Exception(e, "Exception while receiving a message");
                }
            }
        }
 void Check(UdpTrackerMessage message, MessageType type)
 {
     byte[] e = message.Encode();
     Assert.AreEqual(e.Length, message.ByteLength, "#1");
     Assert.IsTrue(Toolbox.ByteMatch(e, UdpTrackerMessage.DecodeMessage(e, type).Encode()), "#2");
 }