The read method on a networkstream blocks only until the first byte is available.
It is not guaranteed to read the desired count into the buffer.
This solution tries to read the remaining bytes in a loop and aborts once the
full count is read or the Stream.Read method returns with 0 or less bytes read.
The synchronous read can block indefinitly if the lenght field is larger than the send package.
These unittests fail intentionally as the issue discussion has not reached
a consesual solution. Any solution should pass the unittests added in this commit.
I don't know what the correct expected connection response size is, so I just added checks for the minimal index access by the current code.
This change will just change NullReferenceExceptions into WrongNumberOfBytesException when the PLC response with not enough data for a connection attempt.
This removes the binary reader, and fixes too things:
1. Properly set the data length (previous implementation requested too much, but that did not matter with BinaryReader)
2. Start reading Data after HeaderLength+1 offset, not always at 3.
The previous problem of not being able to use a larger chunk size than 200 was that the complete header building code for the async implementation was incorrect. Specifically, it wrote the package size only as a byte instead of a int16, thus restricting the package size to something < 256.
With the sharing of the Header building code in the previous commits, this problem was resolved by accident, and thus the chunk size can be increased to the maximum value allowed by the PDUSize.
For me the tests work fine even when adjust the "chunk size" in WriteBytesAsync. So Snap7 seems to be fine, at least the current version.
This should probably be tested with some live PLC's as well.
Both Synchronous and Asynchronous need to build the same binary data package to write a bytes array. Move that package building out into a common function.
Also use IEnumerable to pass in data instead of converting it to array and back multiple times. Not that happy with the whole ByteArray class, we could probably just use a MemoryStream instead.
This requires reference types that can be null to be annotated by a ? operator, similar to value types.
This gives the advantage that the compiler can warn against any null dereference exceptions, of which this commits elimits a few.
To make the underlying protocol implementation not any more complicated and to eliminate existing problems, and not that precise error reporting, I replaced some return null statements with explicit Exceptions. This lead to the assumption that those core protocoll functions always return non-null objects if they do not throw, making the PLC code simpler.
Adjust some NotConnected tests to look for explicit PlcException instead of NullReferenceException.
Add new class Types.Dtl by taking the DateTime type and adjusting things.
Also add unit test with binary data calculated by hand. (Need to verify with actual S7 data)