/// <summary> /// Returns the number of bytes to read from the stream. /// </summary> /// <param name="state">Instance of <see cref="T:NavtelecomProtocol.SessionState" />.</param> /// <param name="reader"><see cref="T:SharpStructures.BinaryListReader" /> linked to a FLEX message body.</param> /// <param name="writer"><see cref="T:SharpStructures.MemoryBufferWriter" /> with data to be sent to the client.</param> /// <param name="token">The token to monitor for cancellation requests.</param> /// <returns>A task that represents the asynchronous operation. Contains the total number of bytes to read from the socket. Zero bytes to stop reading and send the response.</returns> public async Task <int> GetPendingBytesAsync(SessionState state, BinaryListReader reader, MemoryBufferWriter writer, CancellationToken token) { switch (reader.ByteList.Count) { case 2: return(13); case 15: reader.SetPosition(13); return(reader.ReadUInt16() + 1); default: if (reader.ByteList.Last() != BinaryUtilities.GetCrc8(reader.ByteList.Take(reader.ByteList.Count - 1))) { throw new ArgumentException("Invalid FLEX message CRC."); } reader.SetPosition(4); var result = reader.ReadByte(); var crashTime = reader.ReadUInt32(); var offset = reader.ReadUInt32(); var sizeRead = reader.ReadUInt16(); if (state.CrashInfo != null && result == 0x00 && state.CrashInfo.Timestamp == crashTime) { for (var i = 0; i < sizeRead; ++i) { state.CrashInfo.Data[offset + i] = reader.ByteList[15 + i]; } state.CrashInfo.Offset = offset + sizeRead; var bytesLeft = state.CrashInfo.Data.Length - state.CrashInfo.Offset; writer.Write(CrashInformation.CrashDataQuery); writer.Write(crashTime); writer.Write(state.CrashInfo.Offset); writer.Write(bytesLeft > ushort.MaxValue ? ushort.MaxValue : (ushort)bytesLeft); writer.Write(BinaryUtilities.GetCrc8(writer.Buffer)); if (bytesLeft == 0) { if (_onReadyCrash != null) { await _onReadyCrash(state, token).ConfigureAwait(false); } state.CrashInfo = null; } } return(0); } }
/// <summary> /// Returns the number of bytes to read from the stream. /// </summary> /// <param name="state">Instance of <see cref="T:NavtelecomProtocol.SessionState" />.</param> /// <param name="reader"><see cref="T:SharpStructures.BinaryListReader" /> linked to a FLEX message body.</param> /// <param name="writer"><see cref="T:SharpStructures.MemoryBufferWriter" /> with data to be sent to the client.</param> /// <param name="token">The token to monitor for cancellation requests.</param> /// <returns>A task that represents the asynchronous operation. Contains the total number of bytes to read from the socket. Zero bytes to stop reading and send the response.</returns> public Task <int> GetPendingBytesAsync(SessionState state, BinaryListReader reader, MemoryBufferWriter writer, CancellationToken token) { switch (reader.ByteList.Count) { case 2: return(Task.FromResult(12)); case 14: return(Task.FromResult(reader.ByteList[13] + 1)); default: if (reader.ByteList.Last() != BinaryUtilities.GetCrc8(reader.ByteList.Take(reader.ByteList.Count - 1))) { throw new ArgumentException("Invalid FLEX message CRC."); } reader.SetPosition(2); reader.ReadByte(); reader.ReadByte(); var crashTime = reader.ReadUInt32(); var crashLength = reader.ReadUInt32(); var flags = reader.ReadByte(); var nameLength = reader.ReadByte(); var crashName = new string(reader.ReadBytes(nameLength).Select(x => (char)x).ToArray()); if (crashTime > 0 && crashLength > 0 && flags == 0xFF) { state.CrashInfo = new CrashInformation { Data = new byte[crashLength], Name = crashName, Timestamp = crashTime }; writer.Write(CrashInformation.CrashDataQuery); writer.Write(crashTime); writer.Write(0U); writer.Write(crashLength > ushort.MaxValue ? ushort.MaxValue : (ushort)crashLength); writer.Write(BinaryUtilities.GetCrc8(writer.Buffer)); } return(Task.FromResult(0)); } }
public void CopyToWithSomeFullSegmentsWorks_CopyTo() { var inputSize = (MinimumSegmentSize * 2) + 1; var input = Enumerable.Range(0, inputSize).Select(i => (byte)i).ToArray(); using (var bufferWriter = new MemoryBufferWriter(MinimumSegmentSize)) { bufferWriter.Write(input, 0, input.Length); Assert.Equal(input.Length, bufferWriter.Length); using (var destination = new MemoryBufferWriter()) { bufferWriter.CopyTo(destination); var data = new byte[bufferWriter.Length]; bufferWriter.CopyTo(data); Assert.Equal(input, data); Array.Clear(data, 0, data.Length); destination.CopyTo(data); Assert.Equal(input, data); } } }
public void WriteMultipleMessages() { var expectedEncoding = new byte[] { /* length: */ 0x00, /* body: <empty> */ /* length: */ 0x0E, /* body: */ 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x2C, 0x0D, 0x0A, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21, }; var messages = new[] { new byte[0], Encoding.UTF8.GetBytes("Hello,\r\nWorld!") }; using (var writer = new MemoryBufferWriter()) // Use small chunks to test Advance/Enlarge and partial payload writing { foreach (var message in messages) { BinaryMessageFormatter.WriteLengthPrefix(message.Length, writer); writer.Write(message); } Assert.Equal(expectedEncoding, writer.ToArray()); } }
public void MemoryBufferWriter() { var array = new byte[WriteCount * WritePerSize]; var writer = new MemoryBufferWriter <byte>(array); for (var i = 0; i < WriteCount; i++) { writer.Write(this.filedValue); } }
public void WriteBinaryMessage(byte[] encoded, byte[] payload) { using (var writer = new MemoryBufferWriter()) { BinaryMessageFormatter.WriteLengthPrefix(payload.Length, writer); writer.Write(payload); Assert.Equal(encoded, writer.ToArray()); } }
/// <summary> /// Processes the body of the message. /// </summary> /// <param name="state">Instance of <see cref="T:NavtelecomProtocol.SessionState" />.</param> /// <param name="reader"><see cref="T:SharpStructures.BinaryListReader" /> linked to an NTCB message body.</param> /// <param name="writer"><see cref="T:SharpStructures.MemoryBufferWriter" /> with data to be sent to the client.</param> public void ProcessBody(SessionState state, BinaryListReader reader, MemoryBufferWriter writer) { if (!reader.ReadBytes(Prefix.Length).Select(x => (char)x).SequenceEqual(Prefix)) { throw new ArgumentException("NTCB identity message prefix does not match."); } state.DeviceIdentifier = new string(reader.ReadBytes(15).Select(x => (char)x).ToArray()); writer.Write(Response); }
public void RoundTrippingTest(byte[] payload) { using (var writer = new MemoryBufferWriter()) { BinaryMessageFormatter.WriteLengthPrefix(payload.Length, writer); writer.Write(payload); var buffer = new ReadOnlySequence <byte>(writer.ToArray()); Assert.True(BinaryMessageParser.TryParseMessage(ref buffer, out var roundtripped)); Assert.Equal(payload, roundtripped.ToArray()); } }
public void WriteTextMessage(byte[] encoded, string payload) { var message = Encoding.UTF8.GetBytes(payload); using (var writer = new MemoryBufferWriter()) { BinaryMessageFormatter.WriteLengthPrefix(message.Length, writer); writer.Write(message); Assert.Equal(encoded, writer.ToArray()); } }
public void ToArrayWithSomeFullSegmentsWorks() { var inputSize = (MinimumSegmentSize * 2) + 1; var input = Enumerable.Range(0, inputSize).Select(i => (byte)i).ToArray(); using (var bufferWriter = new MemoryBufferWriter(MinimumSegmentSize)) { bufferWriter.Write(input, 0, input.Length); Assert.Equal(input.Length, bufferWriter.Length); var data = bufferWriter.ToArray(); Assert.Equal(input, data); } }
public void ToArrayWithExactlyFullSegmentsWorks_CopyTo() { var inputSize = MinimumSegmentSize * 2; var input = Enumerable.Range(0, inputSize).Select(i => (byte)i).ToArray(); using (var bufferWriter = new MemoryBufferWriter(MinimumSegmentSize)) { bufferWriter.Write(input, 0, input.Length); Assert.Equal(input.Length, bufferWriter.Length); var data = new byte[bufferWriter.Length]; bufferWriter.CopyTo(data); Assert.Equal(input, data); } }
public void WriteByteWorksIfFirstByteInNewSegment() { var inputSize = MinimumSegmentSize; var input = Enumerable.Range(0, inputSize).Select(i => (byte)i).ToArray(); using (var bufferWriter = new MemoryBufferWriter(MinimumSegmentSize)) { bufferWriter.Write(input, 0, input.Length); Assert.Equal(16, bufferWriter.Length); bufferWriter.WriteByte(16); Assert.Equal(17, bufferWriter.Length); var data = bufferWriter.ToArray(); Assert.Equal(input, data.Take(16)); Assert.Equal(16, data[16]); } }
public void WriteSpanWorksAtNonZeroOffset_CopyTo() { using (var bufferWriter = new MemoryBufferWriter()) { bufferWriter.WriteByte(1); bufferWriter.Write(new byte[] { 2, 3, 4 }.AsSpan()); Assert.Equal(4, bufferWriter.Length); var data = new byte[bufferWriter.Length]; bufferWriter.CopyTo(data); Assert.Equal(1, data[0]); Assert.Equal(2, data[1]); Assert.Equal(3, data[2]); Assert.Equal(4, data[3]); } }
public async Task CopyToAsyncWithExactlyFullSegmentsWorks() { var inputSize = MinimumSegmentSize * 2; var input = Enumerable.Range(0, inputSize).Select(i => (byte)i).ToArray(); using (var bufferWriter = new MemoryBufferWriter(MinimumSegmentSize)) { bufferWriter.Write(input, 0, input.Length); Assert.Equal(input.Length, bufferWriter.Length); var ms = new MemoryStream(); await bufferWriter.CopyToAsync(ms); var data = ms.ToArray(); Assert.Equal(input, data); } }
public void WriteByteWorksIfSegmentHasSpace() { var input = new byte[] { 11, 12, 13 }; using (var bufferWriter = new MemoryBufferWriter()) { bufferWriter.Write(input, 0, input.Length); bufferWriter.WriteByte(14); Assert.Equal(4, bufferWriter.Length); var data = bufferWriter.ToArray(); Assert.Equal(4, data.Length); Assert.Equal(11, data[0]); Assert.Equal(12, data[1]); Assert.Equal(13, data[2]); Assert.Equal(14, data[3]); } }
public void Setup() { var buffer = new byte[MessageLength]; Random.NextBytes(buffer); using (var writer = new MemoryBufferWriter()) { BinaryMessageFormatter.WriteLengthPrefix(buffer.Length, writer); writer.Write(buffer); _binaryInput = writer.ToArray(); } buffer = new byte[MessageLength]; Random.NextBytes(buffer); using (var writer = new MemoryBufferWriter()) { writer.Write(buffer); TextMessageFormatter.WriteRecordSeparator(writer); _textInput = writer.ToArray(); } }
/// <summary> /// Returns the number of bytes to read from the stream. /// </summary> /// <param name="sessionState">Instance of <see cref="T:NavtelecomProtocol.SessionState" />.</param> /// <param name="receiveBuffer">A read-only collection of bytes received from a stream.</param> /// <param name="sendBuffer"><see cref="T:SharpStructures.MemoryBuffer" /> with data to be sent to the client.</param> /// <param name="token">The token to monitor for cancellation requests.</param> /// <returns>A task that represents the asynchronous operation. Contains the total number of bytes to read from the socket. Zero bytes to stop reading and send the response.</returns> public Task <int> GetPendingBytesAsync(SessionState sessionState, IReadOnlyList <byte> receiveBuffer, MemoryBuffer sendBuffer, CancellationToken token) { switch (receiveBuffer.Count) { case 1: return(Task.FromResult(HeaderLength - 1)); case HeaderLength: var reader = new BinaryListReader(receiveBuffer, true); if (!reader.ReadBytes(HeaderPreamble.Length).Select(x => (char)x).SequenceEqual(HeaderPreamble)) { throw new ArgumentException("NTCB header preamble does not match."); } sessionState.ReceiverId = reader.ReadUInt32(); sessionState.SenderId = reader.ReadUInt32(); var payloadLength = reader.ReadUInt16(); reader.ReadByte(); var headerChecksum = reader.ReadByte(); if (BinaryUtilities.GetXorSum(receiveBuffer.Take(HeaderLength - 1)) != headerChecksum) { throw new ArgumentException("NTCB header checksum does not match."); } return(Task.FromResult((int)payloadLength)); default: if (BinaryUtilities.GetXorSum(receiveBuffer.Skip(HeaderLength)) != receiveBuffer[14]) { throw new ArgumentException("NTCB body checksum does not match."); } var bodyProcessor = _bodyProcessors.GetValueOrDefault(receiveBuffer.Skip(HeaderLength).Select(x => (char)x)); if (bodyProcessor == null) { throw new ArgumentException("Unknown NTCB message type."); } var bodyReader = new BinaryListReader(receiveBuffer, true); bodyReader.SetPosition(HeaderLength); sendBuffer.AllocateSpace(HeaderLength); var writer = new MemoryBufferWriter(sendBuffer, true); bodyProcessor.ProcessBody(sessionState, bodyReader, writer); var responseLength = sendBuffer.Position - HeaderLength; sendBuffer.SetPosition(0); writer.Write(HeaderPreamble.Select(x => (byte)x).ToArray()); writer.Write(sessionState.SenderId); writer.Write(sessionState.ReceiverId); writer.Write((ushort)responseLength); writer.Write(BinaryUtilities.GetXorSum(sendBuffer.Array.Skip(HeaderLength).Take(responseLength))); writer.Write(BinaryUtilities.GetXorSum(sendBuffer.Array.Take(HeaderLength - 1))); sendBuffer.SetPosition(responseLength + HeaderLength); return(Task.FromResult(0)); } }