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); } }
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"); }
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); }
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)); }
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); } }
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); } }
/// <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); } }
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); } }
internal void Enqueue(PeerMessage msg) { sendQueue.Add(msg); if (!processingQueue) { processingQueue = true; ConnectionManager.ProcessQueue(this); } }
public void SendMessage(PeerMessage message) { if (message == null) throw new ArgumentNullException("message"); ClientEngine.MainLoop.QueueWait((MainLoopTask)delegate { if (Connection == null) return; Enqueue(message); }); }
public MessageBundle(PeerMessage message) : this() { messages.Add(message); }
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"); } }
internal void Enqueue(PeerMessage message) { lock (SendQueue) EnqueueAt(message, SendQueue.Count); }
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); } }
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(); } }
public MessageBundle(PeerMessage message) : this() { Messages.Add(message); }