internal async void ReceiveMessagesAsync(IConnection2 connection, IEncryption decryptor, RateLimiterGroup downloadLimiter, ConnectionMonitor monitor, TorrentManager torrentManager, PeerId id)
        {
            try {
                while (true)
                {
                    Messages.PeerMessage message = await PeerIO.ReceiveMessageAsync(connection, decryptor, downloadLimiter, monitor, torrentManager.Monitor, torrentManager.Torrent);

                    if (id.Disposed)
                    {
                        if (message is PieceMessage msg)
                        {
                            msg.DataReleaser.Dispose();
                        }
                        break;
                    }
                    else
                    {
                        id.LastMessageReceived.Restart();
                        torrentManager.Mode.HandleMessage(id, message);
                    }
                }
            } catch {
                CleanupSocket(torrentManager, id);
            }
        }
Beispiel #2
0
        public static PeerMessage DecodeMessage(byte[] buffer, int offset, int count, ITorrentData manager)
        {
            if (count < 4)
            {
                throw new ArgumentException("A message must contain a 4 byte length prefix");
            }

            int messageLength = IPAddress.HostToNetworkOrder(BitConverter.ToInt32(buffer, offset));

            if (messageLength > (count - 4))
            {
                throw new ArgumentException("Incomplete message detected");
            }

            if (buffer[offset + 4] == ExtensionMessage.MessageId)
            {
                return(ExtensionMessage.DecodeExtensionMessage(buffer, offset + 4 + 1, count - 4 - 1, manager));
            }

            if (!messageDict.TryGetValue(buffer[offset + 4], out Func <ITorrentData, PeerMessage> creator))
            {
                throw new ProtocolException("Unknown message received");
            }

            // The message length is given in the second byte and the message body follows directly after that
            // We decode up to the number of bytes Received. If the message isn't complete, throw an exception
            PeerMessage message = creator(manager);

            message.Decode(buffer, offset + 4 + 1, count - 4 - 1);
            return(message);
        }
 /// <summary>
 ///     Creates a new PeerMessageEventArgs
 /// </summary>
 /// <param name="message">The peer message involved</param>
 /// <param name="direction">The direction of the message</param>
 internal PeerMessageEventArgs(TorrentManager manager, PeerMessage message, Direction direction, PeerId id)
     : base(manager)
 {
     this.direction = direction;
     this.id = id;
     this.message = message;
 }
 /// <summary>
 ///     Creates a new PeerMessageEventArgs
 /// </summary>
 /// <param name="message">The peer message involved</param>
 /// <param name="direction">The direction of the message</param>
 internal PeerMessageEventArgs(TorrentManager manager, PeerMessage message, Direction direction, PeerId id)
     : base(manager)
 {
     Direction = direction;
     ID = id;
     Message = message;
 }
        private void EncodeDecode(Message orig)
        {
            orig.Encode(buffer, offset);
            Message dec = PeerMessage.DecodeMessage(buffer, offset, orig.ByteLength, torrentData);

            Assert.IsTrue(orig.Equals(dec), $"orig: {orig}, new: {dec}");

            Assert.IsTrue(Toolbox.ByteMatch(orig.Encode(), PeerMessage.DecodeMessage(orig.Encode(), 0, orig.ByteLength, torrentData).Encode()));
        }
        public void BitfieldCorrupt()
        {
            Assert.Throws <MessageException> (() => {
                bool[] data    = { true, false, false, true, false, true, false, true, false, true, false, true, false, false, false, true };
                byte[] encoded = new BitfieldMessage(new BitField(data)).Encode();

                PeerMessage.DecodeMessage(encoded, 0, encoded.Length, null);
            });
        }
        public void LTChatDecodeTest()
        {
            LTChat m = new LTChat(LTChat.Support.MessageId, "This Is My Message");

            byte[] data    = m.Encode();
            LTChat decoded = (LTChat)PeerMessage.DecodeMessage(data, 0, data.Length, null);

            Assert.AreEqual(m.Message, decoded.Message, "#1");
        }
Beispiel #8
0
        public static void EnqueueSendMessage (IConnection connection, IEncryption encryptor, PeerMessage message, IRateLimiter rateLimiter, ConnectionMonitor peerMonitor, ConnectionMonitor managerMonitor, AsyncIOCallback callback, object state)
        {
            int count = message.ByteLength;
            var buffer = ClientEngine.BufferManager.GetBuffer (count);
            message.Encode (buffer, 0);
            encryptor.Encrypt (buffer, 0, count);

            var data = sendCache.Dequeue ().Initialise (buffer, callback, state);
            NetworkIO.EnqueueSend (connection, buffer, 0, count, rateLimiter, peerMonitor, managerMonitor, EndSendCallback, data);
        }
Beispiel #9
0
        public void HandleMessage(PeerId id, PeerMessage message)
        {
            if (message is IFastPeerMessage && !id.SupportsFastPeer)
                throw new MessageException("Peer shouldn't support fast peer messages");

            if (message is ExtensionMessage && !id.SupportsLTMessages && !(message is ExtendedHandshakeMessage))
                throw new MessageException("Peer shouldn't support extension messages");

            if (message is HaveMessage)
                HandleHaveMessage(id, (HaveMessage)message);
            else if (message is RequestMessage)
                HandleRequestMessage(id, (RequestMessage)message);
            else if (message is PortMessage)
                HandlePortMessage(id, (PortMessage)message);
            else if (message is PieceMessage)
                HandlePieceMessage(id, (PieceMessage)message);
            else if (message is NotInterestedMessage)
                HandleNotInterested(id, (NotInterestedMessage)message);
            else if (message is KeepAliveMessage)
                HandleKeepAliveMessage(id, (KeepAliveMessage)message);
            else if (message is InterestedMessage)
                HandleInterestedMessage(id, (InterestedMessage)message);
            else if (message is ChokeMessage)
                HandleChokeMessage(id, (ChokeMessage)message);
            else if (message is CancelMessage)
                HandleCancelMessage(id, (CancelMessage)message);
            else if (message is BitfieldMessage)
                HandleBitfieldMessage(id, (BitfieldMessage)message);
            else if (message is UnchokeMessage)
                HandleUnchokeMessage(id, (UnchokeMessage)message);
            else if (message is HaveAllMessage)
                HandleHaveAllMessage(id, (HaveAllMessage)message);
            else if (message is HaveNoneMessage)
                HandleHaveNoneMessage(id, (HaveNoneMessage)message);
            else if (message is RejectRequestMessage)
                HandleRejectRequestMessage(id, (RejectRequestMessage)message);
            else if (message is SuggestPieceMessage)
                HandleSuggestedPieceMessage(id, (SuggestPieceMessage)message);
            else if (message is AllowedFastMessage)
                HandleAllowedFastMessage(id, (AllowedFastMessage)message);
            else if (message is ExtendedHandshakeMessage)
                HandleExtendedHandshakeMessage(id, (ExtendedHandshakeMessage)message);
            else if (message is LTMetadata)
                HandleLtMetadataMessage(id, (LTMetadata)message);
            else if (message is LTChat)
                HandleLtChat(id, (LTChat)message);
            else if (message is PeerExchangeMessage)
                HandlePeerExchangeMessage(id, (PeerExchangeMessage)message);
            else if (message is HandshakeMessage)
                HandleHandshakeMessage(id, (HandshakeMessage)message);
            else if (message is ExtensionMessage)
                HandleGenericExtensionMessage(id, (ExtensionMessage)message);
            else
                throw new MessageException(string.Format("Unsupported message found: {0}", message.GetType().Name));
        }
Beispiel #10
0
 internal void EnqueueAt(PeerMessage message, int index)
 {
     lock (SendQueue) {
         if (SendQueue.Count == 0 || index >= SendQueue.Count)
         {
             SendQueue.Add(message);
         }
         else
         {
             SendQueue.Insert(index, message);
         }
     }
 }
        public void PeerExchangeMessageDecode()
        {
            // Decodes as: 192.168.0.1:100
            byte[] peer     = { 192, 168, 0, 1, 100, 0 };
            byte[] supports = { 1 | 2 }; // 1 == encryption, 2 == seeder

            byte id = PeerExchangeMessage.Support.MessageId;
            PeerExchangeMessage message = new PeerExchangeMessage(id, peer, supports, null);

            byte[] buffer         = message.Encode();
            PeerExchangeMessage m = (PeerExchangeMessage)PeerMessage.DecodeMessage(buffer, 0, buffer.Length, null);

            Assert.IsTrue(Toolbox.ByteMatch(peer, m.Added), "#1");
            Assert.IsTrue(Toolbox.ByteMatch(supports, m.AddedDotF), "#1");
        }
        public void HandshakeDecodeTest()
        {
            ExtendedHandshakeMessage m = new ExtendedHandshakeMessage(false, 123, 5555);

            byte[] data = m.Encode();
            ExtendedHandshakeMessage decoded = (ExtendedHandshakeMessage)PeerMessage.DecodeMessage(data, 0, data.Length, null);

            Assert.AreEqual(m.ByteLength, data.Length);
            Assert.AreEqual(m.ByteLength, decoded.ByteLength, "#1");
            Assert.AreEqual(m.LocalPort, decoded.LocalPort, "#2");
            Assert.AreEqual(m.MaxRequests, decoded.MaxRequests, "#3");
            Assert.AreEqual(m.Version, decoded.Version, "#4");
            Assert.AreEqual(m.Supports.Count, decoded.Supports.Count, "#5");
            m.Supports.ForEach(delegate(ExtensionSupport s) { Assert.IsTrue(decoded.Supports.Contains(s), "#6:" + s); });
        }
        public void BitFieldEncoding()
        {
            bool[] data = { true,  false, false, true,  false, true,  false, true,  false, true,
                            false, true,  false, false, false, true,  true,  true,  false, false,
                            false, true,  false, true,  false, false, true,  false, true,  false,
                            true,  true,  false, false, true,  false, false, true,  true,  false };

            Assert.AreEqual(data.Length, (int)Math.Ceiling((double)torrentData.Size / torrentData.PieceLength), "#0");
            byte[] encoded = new BitfieldMessage(new BitField(data)).Encode();

            BitfieldMessage m = (BitfieldMessage)PeerMessage.DecodeMessage(encoded, 0, encoded.Length, torrentData);

            Assert.AreEqual(data.Length, m.BitField.Length, "#1");
            for (int i = 0; i < data.Length; i++)
            {
                Assert.AreEqual(data[i], m.BitField[i], "#2." + i);
            }
        }
Beispiel #14
0
        internal PeerMessage TryDequeue()
        {
            lock (SendQueue) {
                if (!Ready)
                {
                    throw new InvalidOperationException("Cannot dequeue messages before the queue has been marked 'ready'.");
                }

                if (SendQueue.Count == 0)
                {
                    ProcessingQueue = false;
                    return(null);
                }

                PeerMessage message = SendQueue[0];
                SendQueue.RemoveAt(0);
                return(message);
            }
        }
Beispiel #15
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="manager">The torrent which the peer is associated with.</param>
        /// <param name="id">The peer whose message queue you want to start processing</param>
        internal async void ProcessQueue(TorrentManager manager, PeerId id)
        {
            while (id.QueueLength > 0)
            {
                Messages.PeerMessage msg = id.Dequeue();
                var pm = msg as PieceMessage;

                try {
                    if (pm != null)
                    {
                        pm.Data = ClientEngine.BufferPool.Rent(pm.ByteLength);
                        try {
                            await DiskManager.ReadAsync(manager.Torrent, pm.StartOffset + ((long)pm.PieceIndex * manager.Torrent.PieceLength), pm.Data, pm.RequestLength);
                        } catch (Exception ex) {
                            manager.TrySetError(Reason.ReadFailure, ex);
                            return;
                        }
                        id.PiecesSent++;
                    }

                    await PeerIO.SendMessageAsync(id.Connection, id.Encryptor, msg, manager.UploadLimiters, id.Monitor, manager.Monitor);

                    if (msg is PieceMessage)
                    {
                        id.IsRequestingPiecesCount--;
                    }

                    id.LastMessageSent.Restart();
                } catch {
                    CleanupSocket(manager, id);
                    break;
                } finally {
                    if (pm?.Data != null)
                    {
                        ClientEngine.BufferPool.Return(pm.Data);
                    }
                }
            }

            id.ProcessingQueue = false;
        }
        public void BitFieldDecoding()
        {
            byte[]          buf = { 0x00, 0x00, 0x00, 0x04, 0x05, 0xff, 0x08, 0xAA, 0xE3, 0x00 };
            BitfieldMessage msg = (BitfieldMessage)PeerMessage.DecodeMessage(buf, 0, 8, torrentData);

            for (int i = 0; i < 8; i++)
            {
                Assert.IsTrue(msg.BitField[i], i.ToString());
            }

            for (int i = 8; i < 12; i++)
            {
                Assert.IsFalse(msg.BitField[i], i.ToString());
            }

            Assert.IsTrue(msg.BitField[12], 12.ToString ());
            for (int i = 13; i < 15; i++)
            {
                Assert.IsFalse(msg.BitField[i], i.ToString());
            }
            EncodeDecode(msg);
        }
        internal async void ReceiveMessagesAsync(IConnection2 connection, IEncryption decryptor, RateLimiterGroup downloadLimiter, ConnectionMonitor monitor, TorrentManager torrentManager, PeerId id)
        {
            try {
                while (true)
                {
                    Messages.PeerMessage message = await PeerIO.ReceiveMessageAsync(connection, decryptor, downloadLimiter, monitor, torrentManager);

                    if (id.Disposed)
                    {
                        if (message is PieceMessage msg)
                        {
                            ClientEngine.BufferPool.Return(msg.Data);
                        }
                    }
                    else
                    {
                        id.LastMessageReceived.Restart();
                        message.Handle(torrentManager, id);
                    }
                }
            } catch {
                CleanupSocket(torrentManager, id);
            }
        }
Beispiel #18
0
 private void SendMessage(PeerMessage message, CustomConnection connection)
 {
     byte[] b = message.Encode();
     encryptor.Encrypt(b);
     IAsyncResult result = connection.BeginSend(b, 0, b.Length, null, null);
     if (!result.AsyncWaitHandle.WaitOne(5000, true))
         throw new Exception("Message didn't send correctly");
     connection.EndSend(result);
 }
        private void SendMessage(PeerId id, PeerMessage message, MessagingCallback callback)
        {
            try
            {
                id.MessageSentCallback = callback;
                id.CurrentlySendingMessage = message;

                RateLimiterGroup limiter = id.TorrentManager.UploadLimiter;

                if (message is PieceMessage)
                {
                    PeerIO.EnqueueSendMessage (id.Connection, id.Encryptor, message, limiter, id.Monitor, id.TorrentManager.Monitor, endSendMessageCallback, id);
                    ClientEngine.BufferManager.FreeBuffer(ref ((PieceMessage)message).Data);
                    id.IsRequestingPiecesCount--;
                }
                else
                    PeerIO.EnqueueSendMessage (id.Connection, id.Encryptor, message, null, id.Monitor, id.TorrentManager.Monitor, endSendMessageCallback, id);
            }
            catch (Exception ex)
            {
                CleanupSocket(id, ex.Message);
            }
        }
Beispiel #20
0
 internal void Enqueue(PeerMessage msg)
 {
     sendQueue.Add(msg);
     if (!processingQueue)
     {
         processingQueue = true;
         ConnectionManager.ProcessQueue(this);
     }
 }
Beispiel #21
0
        public void SendMessage(PeerMessage message)
        {
            if (message == null)
                throw new ArgumentNullException("message");

            ClientEngine.MainLoop.QueueWait((MainLoopTask)delegate {
                if (Connection == null)
                    return;

                Enqueue(message);
            });
        }
Beispiel #22
0
 public MessageBundle(PeerMessage message)
     : this()
 {
     messages.Add(message);
 }
Beispiel #23
0
        private void SendMessage(PeerId id, PeerMessage message, MessagingCallback callback)
        {
            bool cleanup = false;

            try
            {
                if (id.Connection == null)
                    return;
                ClientEngine.BufferManager.FreeBuffer(ref id.sendBuffer);
                ClientEngine.BufferManager.GetBuffer(ref id.sendBuffer, message.ByteLength);
                id.MessageSentCallback = callback;
                id.CurrentlySendingMessage = message;
                if (message is PieceMessage)
                    id.IsRequestingPiecesCount--;

                id.BytesSent = 0;
                id.BytesToSend = message.Encode(id.sendBuffer, 0);
                id.Encryptor.Encrypt(id.sendBuffer.Array, id.sendBuffer.Offset, id.BytesToSend);

                RateLimiter limiter = engine.Settings.GlobalMaxUploadSpeed > 0 ? engine.uploadLimiter : null;
                limiter = limiter ?? (id.TorrentManager.Settings.MaxUploadSpeed > 0 ? id.TorrentManager.uploadLimiter : null);
                NetworkIO.EnqueueSend(id.Connection, id.sendBuffer, id.BytesSent, id.BytesToSend, endSendMessageCallback, id, limiter, id.TorrentManager.Monitor, id.Monitor);
            }
            catch (Exception)
            {
                Logger.Log(id.Connection, "ConnectionManager - Socket error sending message");
                cleanup = true;
            }
            finally
            {
                if (cleanup)
                    CleanupSocket(id, "Couldn't SendMessage");
            }
        }
Beispiel #24
0
 internal void Enqueue(PeerMessage message)
 {
     lock (SendQueue)
         EnqueueAt(message, SendQueue.Count);
 }
Beispiel #25
0
 void SendMessage(PeerMessage message, CustomConnection connection)
 {
     byte[] b = message.Encode();
     encryptor.Encrypt(b);
     Send (connection, b, 0, b.Length);
 }
        private void MessageReceived(bool successful, PeerMessage message, object state)
        {
            PeerId id = (PeerId) state;
            if (!successful)
            {
                id.ConnectionManager.CleanupSocket (id, "Could not receive a message");
                return;
            }

            try
            {
                PeerMessageEventArgs e = new PeerMessageEventArgs(id.TorrentManager, (PeerMessage)message, Direction.Incoming, id);
                id.ConnectionManager.RaisePeerMessageTransferred(e);

                message.Handle(id);

                id.LastMessageReceived = DateTime.Now;
                PeerIO.EnqueueReceiveMessage (id.Connection, id.Decryptor, id.TorrentManager.DownloadLimiter, id.Monitor, id.TorrentManager, messageReceivedCallback, id);
            }
            catch (TorrentException ex)
            {
                id.ConnectionManager.CleanupSocket (id, ex.Message);
            }
        }
        private void PeerHandshakeReceived(bool succeeded, PeerMessage message, object state)
        {
            PeerId id = (PeerId)state;
            if (!succeeded)
            {
                CleanupSocket(id, "Handshaking failed");
                return;
            }

            try
            {
                message.Handle(id);

                // If there are any pending messages, send them otherwise set the queue
                // processing as finished.
                if (id.QueueLength > 0)
                    id.ConnectionManager.ProcessQueue(id);
                else
                    id.ProcessingQueue = false;

                PeerIO.EnqueueReceiveMessage (id.Connection, id.Decryptor, id.TorrentManager.DownloadLimiter, id.Monitor, id.TorrentManager, messageReceivedCallback, id);
                // Alert the engine that there is a new usable connection
                id.TorrentManager.HandlePeerConnected(id, Direction.Outgoing);
            }
            catch (TorrentException ex)
            {
                CleanupSocket(id, ex.Message);
            }
        }
Beispiel #28
0
 internal void EnqueueAt(PeerMessage message, int index)
 {
     if (sendQueue.Count == 0 || index >= sendQueue.Count)
         Enqueue(message);
     else
         sendQueue.Insert(index, message);
 }
        /// <summary>
        /// </summary>
        /// <param name="result"></param>
        private void onPeerHandshakeReceived(bool succeeded, PeerMessage message, object state)
        {
            var id = (PeerId) state;

            try
            {
                if (succeeded)
                    handleHandshake(id, (HandshakeMessage) message);
                else
                    id.Connection.Dispose();
            }
            catch (Exception)
            {
                Logger.Log(id.Connection, "ListenManager - Socket exception receiving handshake");
                id.Connection.Dispose();
            }
        }
Beispiel #30
0
 public MessageBundle(PeerMessage message)
     : this()
 {
     Messages.Add(message);
 }