diff --git a/S7.Net.UnitTest/ProtocolTests.cs b/S7.Net.UnitTest/ProtocolTests.cs index 2051edb..e63fac6 100644 --- a/S7.Net.UnitTest/ProtocolTests.cs +++ b/S7.Net.UnitTest/ProtocolTests.cs @@ -1,14 +1,10 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using S7.Net; - using System.IO; +using System.Linq; +using System.Threading; using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; using S7.Net.Protocol; -using System.Collections; namespace S7.Net.UnitTest { @@ -21,21 +17,17 @@ namespace S7.Net.UnitTest public async Task TPKT_Read() { var m = new MemoryStream(StringToByteArray("0300002902f0803203000000010002001400000401ff0400807710000100000103000000033f8ccccd")); - var t = TPKT.Read(m); - Assert.AreEqual(0x03, t.Version); - Assert.AreEqual(0x29, t.Length); - m.Position = 0; - t = await TPKT.ReadAsync(m, TestContext.CancellationTokenSource.Token); + var t = await TPKT.ReadAsync(m, TestContext.CancellationTokenSource.Token); Assert.AreEqual(0x03, t.Version); Assert.AreEqual(0x29, t.Length); } [TestMethod] [ExpectedException(typeof(TPKTInvalidException))] - public void TPKT_ReadShort() + public async Task TPKT_ReadShort() { var m = new MemoryStream(StringToByteArray("0300002902f0803203000000010002001400000401ff040080")); - var t = TPKT.Read(m); + var t = await TPKT.ReadAsync(m, CancellationToken.None); } @@ -48,14 +40,11 @@ namespace S7.Net.UnitTest } [TestMethod] - public void COTP_ReadTSDU() + public async Task COTP_ReadTSDU() { var expected = StringToByteArray("320700000400000800080001120411440100ff09000400000000"); var m = new MemoryStream(StringToByteArray("0300000702f0000300000702f0000300002102f080320700000400000800080001120411440100ff09000400000000")); - var t = COTP.TSDU.Read(m); - Assert.IsTrue(expected.SequenceEqual(t)); - m.Position = 0; - t = COTP.TSDU.ReadAsync(m, TestContext.CancellationTokenSource.Token).Result; + var t = await COTP.TSDU.ReadAsync(m, TestContext.CancellationTokenSource.Token); Assert.IsTrue(expected.SequenceEqual(t)); } @@ -69,14 +58,13 @@ namespace S7.Net.UnitTest [TestMethod] - public void TestResponseCode() + public async Task TestResponseCode() { var expected = StringToByteArray("320700000400000800080001120411440100ff09000400000000"); var m = new MemoryStream(StringToByteArray("0300000702f0000300000702f0000300002102f080320700000400000800080001120411440100ff09000400000000")); - var t = COTP.TSDU.Read(m); + var t = await COTP.TSDU.ReadAsync(m, CancellationToken.None); Assert.IsTrue(expected.SequenceEqual(t)); - // Test all possible byte values. Everything except 0xff should throw an exception. var testData = Enumerable.Range(0, 256).Select(i => new { StatusCode = (ReadWriteErrorCode)i, ThrowsException = i != (byte)ReadWriteErrorCode.Success }); diff --git a/S7.Net.UnitTest/StreamTests.cs b/S7.Net.UnitTest/StreamTests.cs index 9cb0969..d5fe2a1 100644 --- a/S7.Net.UnitTest/StreamTests.cs +++ b/S7.Net.UnitTest/StreamTests.cs @@ -2,6 +2,7 @@ using System; using System.IO; using System.Linq; +using System.Threading; using System.Threading.Tasks; namespace S7.Net.UnitTest @@ -15,6 +16,7 @@ namespace S7.Net.UnitTest { Data = data; } + public override bool CanRead => _position < Data.Length; public override bool CanSeek => throw new NotImplementedException(); @@ -26,21 +28,31 @@ namespace S7.Net.UnitTest public override long Position { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } public byte[] Data { get; } + int _position = 0; + public override void Flush() { throw new NotImplementedException(); } - int _position = 0; public override int Read(byte[] buffer, int offset, int count) { + throw new NotImplementedException(); + } + + public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + if (_position >= Data.Length) { - return 0; + return Task.FromResult(0); } + buffer[offset] = Data[_position]; ++_position; - return 1; + + return Task.FromResult(1); } public override long Seek(long offset, SeekOrigin origin) @@ -78,21 +90,21 @@ namespace S7.Net.UnitTest } [TestMethod] - public void TPKT_ReadRestrictedStream() + public async Task TPKT_ReadRestrictedStream() { var fullMessage = ProtocolUnitTest.StringToByteArray("0300002902f0803203000000010002001400000401ff0400807710000100000103000000033f8ccccd"); var m = new TestStream1BytePerRead(fullMessage); - var t = TPKT.Read(m); + var t = await TPKT.ReadAsync(m, CancellationToken.None); Assert.AreEqual(fullMessage.Length, t.Length); Assert.AreEqual(fullMessage.Last(), t.Data.Last()); } [TestMethod] - public void TPKT_ReadStreamTooShort() + public async Task TPKT_ReadStreamTooShort() { var fullMessage = ProtocolUnitTest.StringToByteArray("0300002902f0803203000000010002001400"); var m = new TestStream1BytePerRead(fullMessage); - Assert.ThrowsException(() => TPKT.Read(m)); + await Assert.ThrowsExceptionAsync(() => TPKT.ReadAsync(m, CancellationToken.None)); } } } diff --git a/S7.Net/COTP.cs b/S7.Net/COTP.cs index a7d9fd7..3e5abbb 100644 --- a/S7.Net/COTP.cs +++ b/S7.Net/COTP.cs @@ -50,22 +50,6 @@ namespace S7.Net Data = new byte[0]; } - /// - /// Reads COTP TPDU (Transport protocol data unit) from the network stream - /// See: https://tools.ietf.org/html/rfc905 - /// - /// The socket to read from - /// COTP DPDU instance - public static TPDU Read(Stream stream) - { - var tpkt = TPKT.Read(stream); - if (tpkt.Length == 0) - { - throw new TPDUInvalidException("No protocol data received"); - } - return new TPDU(tpkt); - } - /// /// Reads COTP TPDU (Transport protocol data unit) from the network stream /// See: https://tools.ietf.org/html/rfc905 @@ -100,36 +84,6 @@ namespace S7.Net /// public class TSDU { - /// - /// Reads the full COTP TSDU (Transport service data unit) - /// See: https://tools.ietf.org/html/rfc905 - /// - /// The stream to read from - /// Data in TSDU - public static byte[] Read(Stream stream) - { - var segment = TPDU.Read(stream); - - if (segment.LastDataUnit) - { - return segment.Data; - } - - // More segments are expected, prepare a buffer to store all data - var buffer = new byte[segment.Data.Length]; - Array.Copy(segment.Data, buffer, segment.Data.Length); - - while (!segment.LastDataUnit) - { - segment = TPDU.Read(stream); - var previousLength = buffer.Length; - Array.Resize(ref buffer, buffer.Length + segment.Data.Length); - Array.Copy(segment.Data, 0, buffer, previousLength, segment.Data.Length); - } - - return buffer; - } - /// /// Reads the full COTP TSDU (Transport service data unit) /// See: https://tools.ietf.org/html/rfc905 @@ -137,7 +91,7 @@ namespace S7.Net /// The stream to read from /// Data in TSDU public static async Task ReadAsync(Stream stream, CancellationToken cancellationToken) - { + { var segment = await TPDU.ReadAsync(stream, cancellationToken).ConfigureAwait(false); if (segment.LastDataUnit) diff --git a/S7.Net/TPKT.cs b/S7.Net/TPKT.cs index e3d26f7..a311dce 100644 --- a/S7.Net/TPKT.cs +++ b/S7.Net/TPKT.cs @@ -25,34 +25,6 @@ namespace S7.Net Data = data; } - /// - /// Reads a TPKT from the socket - /// - /// The stream to read from - /// TPKT Instance - public static TPKT Read(Stream stream) - { - var buf = new byte[4]; - int len = stream.ReadExact(buf, 0, 4); - if (len < 4) throw new TPKTInvalidException($"TPKT header is incomplete / invalid. Received Bytes: {len} expected: {buf.Length}"); - var version = buf[0]; - var reserved1 = buf[1]; - var length = buf[2] * 256 + buf[3]; //BigEndian - - var data = new byte[length - 4]; - len = stream.ReadExact(data, 0, data.Length); - if (len < data.Length) - throw new TPKTInvalidException($"TPKT payload is incomplete / invalid. Received Bytes: {len} expected: {data.Length}"); - - return new TPKT - ( - version: version, - reserved1: reserved1, - length: length, - data: data - ); - } - /// /// Reads a TPKT from the socket Async ///