public void TestTryDecodePieceMessge() { PieceMessage message; int offset = 0; byte[] data = "0000000B070000000500000006ABCD".ToByteArray(); bool isIncomplete; if (PieceMessage.TryDecode(data, ref offset, data.Length, out message, out isIncomplete)) { Assert.AreEqual(15, message.Length); Assert.AreEqual(5, message.PieceIndex); Assert.AreEqual(6, message.BlockOffset); Assert.AreEqual(171, message.Data[0]); Assert.AreEqual(205, message.Data[1]); Assert.AreEqual(false, isIncomplete); Assert.AreEqual(data.Length, offset); CollectionAssert.AreEqual(data, message.Encode()); } else { Assert.Fail(); } }
/// <summary> /// Asynchronous write callback. /// </summary> /// <param name="ar">The async result.</param> private void Receive(IAsyncResult ar) { AsyncReadData data = ar.AsyncState as AsyncReadData; int bytesRead = 0; int offset = data.OffsetStart; PeerMessage message; PieceMessage pieceMessage; bool isIncomplete; lock (this.locker) { if (!this.IsDisposed) { try { // read data bytesRead = this.stream.EndRead(ar); if (bytesRead > 0) { data.OffsetEnd += bytesRead; // walk through the array and try to decode messages while (offset <= data.OffsetEnd) { if (PieceMessage.TryDecode(data.Buffer, ref offset, data.OffsetEnd, out pieceMessage, out isIncomplete, this.PieceData)) { // successfully decoded message this.OnMessageReceived(this, new PeerMessgeReceivedEventArgs((PeerMessage)pieceMessage)); // remember where we left off data.OffsetStart = offset; } else if (PeerMessage.TryDecode(data.Buffer, ref offset, data.OffsetEnd, out message, out isIncomplete)) { // successfully decoded message this.OnMessageReceived(this, new PeerMessgeReceivedEventArgs(message)); // remember where we left off data.OffsetStart = offset; } else if (isIncomplete) { // message of variable length is present but incomplete -> stop advancing break; } else { // move to next byte offset++; } } if (data.OffsetStart == data.OffsetEnd) { // reset offset data.OffsetStart = 0; data.OffsetEnd = 0; } else if (data.OffsetStart > 0 && data.OffsetStart < data.OffsetEnd) { // move data to beginning of the buffere for (int i = data.OffsetStart; i < data.OffsetEnd; i++) { data.Buffer[i - data.OffsetStart] = data.Buffer[i]; } // reset offset data.OffsetEnd = data.OffsetEnd - data.OffsetStart; data.OffsetStart = 0; } else if (data.OffsetStart > data.OffsetEnd) { throw new PeerWireProtocolException("Invalid data."); } this.tm.Read(bytesRead); // resume reading if (!this.IsDisposed) { this.stream.BeginRead(data.Buffer, data.OffsetEnd, data.Buffer.Length - data.OffsetEnd, this.Receive, data); } } else { // we received no data Debug.WriteLine($"received no data from {this.Endpoint}"); } } catch (IOException ex) { Debug.WriteLine($"could not read data from {this.Endpoint}: {ex.Message}"); this.OnCommunicationError(this, new CommunicationErrorEventArgs(ex.Message)); } } } }