コード例 #1
0
ファイル: MessageLoop.cs プロジェクト: gweffect/monotorrent
        async void MessageReceived(byte[] buffer, IPEndPoint endpoint)
        {
            await DhtEngine.MainLoop;

            // Don't handle new messages if we have already stopped the dht engine.
            if (Listener.Status == ListenerStatus.NotListening)
            {
                return;
            }

            // I should check the IP address matches as well as the transaction id
            // FIXME: This should throw an exception if the message doesn't exist, we need to handle this
            // and return an error message (if that's what the spec allows)
            try {
                if (DhtMessageFactory.TryDecodeMessage((BEncodedDictionary)BEncodedValue.Decode(buffer, false), out DhtMessage message))
                {
                    Monitor.ReceiveMonitor.AddDelta(buffer.Length);
                    ReceiveQueue.Enqueue(new KeyValuePair <IPEndPoint, DhtMessage> (endpoint, message));
                }
            } catch (MessageException) {
                // Caused by bad transaction id usually - ignore
            } catch (Exception) {
                //throw new Exception("IP:" + endpoint.Address.ToString() + "bad transaction:" + e.Message);
            }
        }
コード例 #2
0
 internal void Start()
 {
     DhtMessageFactory = new DhtMessageFactory();
     if (Listener.Status != ListenerStatus.Listening)
     {
         Listener.Start();
     }
 }
コード例 #3
0
ファイル: MessageLoop.cs プロジェクト: gweffect/monotorrent
        void TimeoutMessage(SendDetails v)
        {
            DhtMessageFactory.UnregisterSend((QueryMessage)v.Message);
            WaitingResponse.Remove(v.Message.TransactionId);

            v.CompletionSource?.TrySetResult(new SendQueryEventArgs(v.Node, v.Destination, (QueryMessage)v.Message));
            RaiseMessageSent(v.Node, v.Destination, (QueryMessage)v.Message);
        }
コード例 #4
0
        public void PingResponseDecode()
        {
            PingEncode();
            DhtMessageFactory.RegisterSend(message);

            string       text = "d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re";
            PingResponse m    = (PingResponse)Decode(text);

            Assert.AreEqual(infohash, m.Id);

            Compare(m, "d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re");
        }
コード例 #5
0
        public void FindNodeResponseDecode()
        {
            FindNodeEncode();
            DhtMessageFactory.RegisterSend(message);
            string           text = "d1:rd2:id20:abcdefghij01234567895:nodes9:def456...e1:t2:aa1:y1:re";
            FindNodeResponse m    = (FindNodeResponse)Decode(text);

            Assert.AreEqual(id, m.Id, "#1");
            Assert.AreEqual((BEncodedString)"def456...", m.Nodes, "#2");
            Assert.AreEqual(transactionId, m.TransactionId, "#3");

            Compare(m, text);
        }
コード例 #6
0
        public void AnnouncePeerResponseDecode()
        {
            // Register the query as being sent so we can decode the response
            AnnouncePeerDecode();
            DhtMessageFactory.RegisterSend(message);
            string text = "d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re";

            AnnouncePeerResponse m = (AnnouncePeerResponse)Decode(text);

            Assert.AreEqual(infohash, m.Id, "#1");

            Compare(m, text);
        }
コード例 #7
0
        internal void Stop()
        {
            DhtMessageFactory = new DhtMessageFactory();
            SendQueue.Clear();
            ReceiveQueue.Clear();
            WaitingResponse.Clear();
            WaitingResponseTimedOut.Clear();

            if (Listener.Status != ListenerStatus.NotListening)
            {
                Listener.Stop();
            }
        }
コード例 #8
0
ファイル: TestListener.cs プロジェクト: zjklee/monotorrent
        public async Task SendAsync(byte[] buffer, IPEndPoint endpoint)
        {
            if (SendAsynchronously)
            {
                await Task.Yield();
            }

            if (DhtMessageFactory.TryDecodeMessage(BEncodedValue.Decode <BEncodedDictionary> (buffer), out DhtMessage message))
            {
                MessageSent?.Invoke(message, endpoint);
            }
            else
            {
                throw new Exception("Could not decode the message");
            }
        }
コード例 #9
0
        public void ErrorReceived()
        {
            int failedCount    = 0;
            var pingSuccessful = new TaskCompletionSource <bool> ();

            var ping = new Ping(node.Id)
            {
                TransactionId = transactionId
            };

            engine.MessageLoop.QuerySent += (o, e) => {
                // This ping should not time out.
                if (e.Query.TransactionId.Equals(ping.TransactionId))
                {
                    pingSuccessful.TrySetResult(!e.TimedOut && e.Response == null && e.Error != null);
                }
            };

            listener.MessageSent += (message, endpoint) => {
                // This TransactionId should be registered and it should be pending a response.
                if (!DhtMessageFactory.IsRegistered(ping.TransactionId) || engine.MessageLoop.PendingQueries != 1)
                {
                    pingSuccessful.TrySetResult(false);
                }

                if (message.TransactionId.Equals(ping.TransactionId))
                {
                    listener.RaiseMessageReceived(new ErrorMessage(ping.TransactionId, ErrorCode.ServerError, "Ooops"), node.EndPoint);
                    failedCount++;
                }
            };

            // Send the ping
            var task = engine.SendQueryAsync(ping, node);

            // The query should complete, and the message should not have timed out.
            Assert.IsTrue(task.Wait(100000), "#1");
            Assert.IsTrue(pingSuccessful.Task.Wait(1000), "#2");
            Assert.IsTrue(pingSuccessful.Task.Result, "#3");
            Assert.IsFalse(DhtMessageFactory.IsRegistered(ping.TransactionId), "#4");
            Assert.AreEqual(0, engine.MessageLoop.PendingQueries, "#5");
            Assert.AreEqual(1, failedCount, "#6");
        }
コード例 #10
0
        public void GetPeersResponseDecode()
        {
            GetPeersEncode();
            DhtMessageFactory.RegisterSend(message);

            string           text = "d1:rd2:id20:abcdefghij01234567895:token8:aoeusnth6:valuesl6:axje.u6:idhtnmee1:t2:aa1:y1:re";
            GetPeersResponse m    = (GetPeersResponse)Decode(text);

            Assert.AreEqual(token, m.Token, "#1");
            Assert.AreEqual(id, m.Id, "#2");

            BEncodedList l = new BEncodedList();

            l.Add((BEncodedString)"axje.u");
            l.Add((BEncodedString)"idhtnm");
            Assert.AreEqual(l, m.Values, "#3");

            Compare(m, text);
        }
コード例 #11
0
ファイル: MessageLoop.cs プロジェクト: gweffect/monotorrent
        public MessageLoop(DhtEngine engine, TransferMonitor monitor)
        {
            Engine                  = engine ?? throw new ArgumentNullException(nameof(engine));
            Monitor                 = monitor;
            DhtMessageFactory       = new DhtMessageFactory();
            Listener                = new NullDhtListener();
            ReceiveQueue            = new Queue <KeyValuePair <IPEndPoint, DhtMessage> > ();
            SendQueue               = new Queue <SendDetails> ();
            Timeout                 = TimeSpan.FromSeconds(15);
            WaitingResponse         = new Dictionary <BEncodedValue, SendDetails> ();
            WaitingResponseTimedOut = new List <SendDetails> ();

            Task sendTask = null;

            DhtEngine.MainLoop.QueueTimeout(TimeSpan.FromMilliseconds(5), () => {
                monitor.ReceiveMonitor.Tick();
                monitor.SendMonitor.Tick();

                if (engine.Disposed)
                {
                    return(false);
                }
                try {
                    if (sendTask == null || sendTask.IsCompleted)
                    {
                        sendTask = SendMessages();
                    }

                    while (ReceiveQueue.Count > 0)
                    {
                        ReceiveMessage();
                    }

                    TimeoutMessages();
                } catch (Exception ex) {
                    Debug.WriteLine("Error in DHT main loop:");
                    Debug.WriteLine(ex);
                }

                return(!engine.Disposed);
            });
        }
コード例 #12
0
        void TimeoutMessage()
        {
            foreach (KeyValuePair <BEncodedValue, SendDetails> v in WaitingResponse)
            {
                if (Timeout == TimeSpan.Zero || v.Value.SentAt.Elapsed > Timeout)
                {
                    WaitingResponseTimedOut.Add(v.Value);
                }
            }

            foreach (SendDetails v in WaitingResponseTimedOut)
            {
                DhtMessageFactory.UnregisterSend((QueryMessage)v.Message);
                WaitingResponse.Remove(v.Message.TransactionId);

                v.CompletionSource?.TrySetResult(new SendQueryEventArgs(v.Node, v.Destination, (QueryMessage)v.Message));
                RaiseMessageSent(v.Node, v.Destination, (QueryMessage)v.Message);
            }

            WaitingResponseTimedOut.Clear();
        }
コード例 #13
0
        internal void EnqueueSend(DhtMessage message, Node node, IPEndPoint endpoint, TaskCompletionSource <SendQueryEventArgs> tcs = null)
        {
            if (message.TransactionId == null)
            {
                if (message is ResponseMessage)
                {
                    throw new ArgumentException("Message must have a transaction id");
                }
                do
                {
                    message.TransactionId = TransactionId.NextId();
                } while (DhtMessageFactory.IsRegistered(message.TransactionId));
            }

            // We need to be able to cancel a query message if we time out waiting for a response
            if (message is QueryMessage)
            {
                DhtMessageFactory.RegisterSend((QueryMessage)message);
            }

            SendQueue.Enqueue(new SendDetails(node, endpoint, message, tcs));
        }
コード例 #14
0
        async void MessageReceived(byte[] buffer, IPEndPoint endpoint)
        {
            await DhtEngine.MainLoop;

            // I should check the IP address matches as well as the transaction id
            // FIXME: This should throw an exception if the message doesn't exist, we need to handle this
            // and return an error message (if that's what the spec allows)
            try
            {
                DhtMessage message;
                if (DhtMessageFactory.TryDecodeMessage((BEncodedDictionary)BEncodedValue.Decode(buffer, 0, buffer.Length, false), out message))
                {
                    ReceiveQueue.Enqueue(new KeyValuePair <IPEndPoint, DhtMessage>(endpoint, message));
                }
            }
            catch (MessageException)
            {
                // Caused by bad transaction id usually - ignore
            }
            catch (Exception)
            {
                //throw new Exception("IP:" + endpoint.Address.ToString() + "bad transaction:" + e.Message);
            }
        }
コード例 #15
0
        private void TimeoutMessage()
        {
            foreach (var v in WaitingResponse)
            {
                if (Timeout == TimeSpan.Zero || v.Value.SentAt.Elapsed > Timeout)
                {
                    WaitingResponseTimedOut.Add(v.Value);
                }
            }

            foreach (var v in WaitingResponseTimedOut)
            {
                DhtMessageFactory.UnregisterSend((QueryMessage)v.Message);
                WaitingResponse.Remove(v.Message.TransactionId);

                if (v.CompletionSource != null)
                {
                    v.CompletionSource.TrySetResult(new SendQueryEventArgs(v.Node, v.Destination, (QueryMessage)v.Message));
                }
                RaiseMessageSent(v.Node, v.Destination, (QueryMessage)v.Message);
            }

            WaitingResponseTimedOut.Clear();
        }
コード例 #16
0
ファイル: MessageTests.cs プロジェクト: gweffect/monotorrent
 public void Setup()
 {
     DhtMessage.UseVersionKey = false;
     DhtMessageFactory        = new DhtMessageFactory();
 }
コード例 #17
0
 private DhtMessage Decode(string p)
 {
     byte[] buffer = Encoding.UTF8.GetBytes(p);
     return(DhtMessageFactory.DecodeMessage(BEncodedValue.Decode <BEncodedDictionary>(buffer)));
 }