private async Task <NonSeekableStream> WriteMessageCoreAsync( S101Message message, CancellationToken cancellationToken) { this.AssertNotDisposed(); if (message == null) { throw new ArgumentNullException(nameof(message)); } if ((this.stream != null) && this.stream.CanWrite) { throw new InvalidOperationException( "DisposeAsync() has not been called on the payload stream of the previous message."); } this.stream = await MessageEncodingStream.CreateAsync(this.writeBuffer, message, cancellationToken); if (!message.CanHavePayload) { await this.stream.DisposeAsync(cancellationToken); this.stream = null; } return(this.stream); }
private void ValidateMessage(S101Message newMessage) { if (newMessage == null) { throw new S101Exception("Unexpected end of stream."); } if (this.message.Slot != newMessage.Slot) { throw new S101Exception("Inconsistent Slot in multi-packet message."); } if (!this.message.Command.Equals(newMessage.Command)) { throw new S101Exception("Inconsistent Command in multi-packet message."); } if ((newMessage.PacketFlags & PacketFlags.FirstPacket) > 0) { throw new S101Exception(string.Format( CultureInfo.InvariantCulture, "{0} flag in subsequent packet.", PacketFlags.FirstPacket)); } this.message = newMessage; }
private MessageEncodingStream(S101Message message, WriteBuffer rawBuffer, FramingStream framingStream) { this.unframedBuffer = new WriteBuffer(this.WriteUnframedAsync, Constants.MessageHeaderMaxLength); this.message = message; this.rawBuffer = rawBuffer; this.framingStream = framingStream; }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// internal EventInfo LogMessage(DateTime timeUtc, string direction, S101Message message, byte[] payload) { if (message == null) { throw new ArgumentNullException(nameof(message)); } if (direction == null) { throw new ArgumentNullException(nameof(direction)); } this.WriteStartEvent(LogNames.Message, timeUtc); int number; this.messageCounts.TryGetValue(direction, out number); this.messageCounts[direction] = ++number; this.xmlLogWriter.WriteAttributeString(LogNames.Direction, direction); this.xmlLogWriter.WriteAttributeString(LogNames.Number, number.ToString(CultureInfo.InvariantCulture)); this.xmlLogWriter.WriteElementString( LogNames.Slot, message.Slot.ToString("X2", CultureInfo.InvariantCulture)); this.xmlLogWriter.WriteElementString(LogNames.Command, message.Command.ToString()); this.xmlLogWriter.WriteStartElement(LogNames.Payload); if (payload != null) { this.converter.ToXml(payload, this.xmlLogWriter); } this.xmlLogWriter.WriteEndElement(); this.WriteEndEvent(); return(new EventInfo(timeUtc, number)); }
private void Clear() { this.eventType = null; this.timeUtc = DateTime.Today; this.direction = null; this.number = 0; this.message = null; this.payload = null; }
public void PayloadTest() { AsyncPump.Run( async() => { #pragma warning disable SA1123 // Do not place regions within elements. Necessary so that tested code snippets can be included in the documentation. #region Payload Test var writtenMessage = new S101Message(0x00, new EmberData(0x01, 0x0A, 0x02)); var writtenPayload = new byte[8192]; this.Random.NextBytes(writtenPayload); using (var encodedStream = new MemoryStream()) { // First we create a writer, which can be used to write multiple messages. // We specify which methods are used to write encoded output and flush it plus the size the internal // buffer should have. var writer = new S101Writer(encodedStream.WriteAsync); // Next we write the message. In return we get a Stream object for the payload. using (var payloadStream = await writer.WriteMessageAsync(writtenMessage, CancellationToken.None)) { // Now we write the payload. await payloadStream.WriteAsync(writtenPayload, 0, writtenPayload.Length); await payloadStream.DisposeAsync(CancellationToken.None); } await writer.DisposeAsync(CancellationToken.None); // Reset the encoded stream to the beginning, so that we can read from it. encodedStream.Position = 0; // First we create a reader, which can be used to read multiple messages. // We specify which methods are used to read encoded input. var reader = new S101Reader(encodedStream.ReadAsync); Assert.IsTrue(await reader.ReadAsync(CancellationToken.None)); // Read the first message var readMessage = reader.Message; // Assert the written and read messages are equal Assert.AreEqual(writtenMessage.Slot, readMessage.Slot); Assert.AreEqual(writtenMessage.Command, readMessage.Command); using (var readPayload = new MemoryStream()) { await reader.Payload.CopyToAsync(readPayload); // Copy the payload. // Assert that there is only one message Assert.IsFalse(await reader.ReadAsync(CancellationToken.None)); CollectionAssert.AreEqual(writtenPayload, readPayload.ToArray()); } await reader.DisposeAsync(CancellationToken.None); } #endregion #pragma warning restore SA1123 // Do not place regions within elements }); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// internal static async Task<MessageEncodingStream> CreateAsync( WriteBuffer rawBuffer, S101Message message, CancellationToken cancellationToken) { message.PacketFlags = PacketFlags.FirstPacket | (message.CanHaveMultiplePackets ? PacketFlags.None : PacketFlags.LastPacket); var framingStream = await FramingStream.CreateAsync(rawBuffer, cancellationToken); var result = new MessageEncodingStream(message, rawBuffer, framingStream); await message.WriteToAsync(result.unframedBuffer, cancellationToken); return result; }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// internal static async Task <MessageEncodingStream> CreateAsync( WriteBuffer rawBuffer, S101Message message, CancellationToken cancellationToken) { message.PacketFlags = PacketFlags.FirstPacket | (message.CanHaveMultiplePackets ? PacketFlags.None : PacketFlags.LastPacket); var framingStream = await FramingStream.CreateAsync(rawBuffer, cancellationToken); var result = new MessageEncodingStream(message, rawBuffer, framingStream); await message.WriteToAsync(result.unframedBuffer, cancellationToken); return(result); }
private bool ReadCore() { while (this.logReader.IsStartElement(LogNames.Event)) { switch (this.eventType = this.logReader.GetAttribute(LogNames.Type)) { case LogNames.Message: this.timeUtc = this.ReadTime(); this.direction = this.logReader.GetAttribute(LogNames.Direction); this.number = int.Parse( this.logReader.GetAttribute(LogNames.Number), NumberStyles.None, CultureInfo.InvariantCulture); this.logReader.ReadStartElement(LogNames.Event); this.logReader.ReadStartElement(LogNames.Slot); var slot = ParseHex(this.logReader.ReadContentAsString()); this.logReader.ReadEndElement(); this.logReader.ReadStartElement(LogNames.Command); var command = S101Command.Parse(this.logReader.ReadContentAsString()); this.logReader.ReadEndElement(); this.message = new S101Message(slot, command); if (!this.logReader.IsStartElement(LogNames.Payload)) { throw new XmlException("The Payload element is missing."); } this.payload = this.GetLogPayload(); return(true); case LogNames.OutOfFrameByte: this.timeUtc = this.ReadTime(); this.direction = this.logReader.GetAttribute(LogNames.Direction); this.number = 0; this.message = null; this.logReader.ReadStartElement(LogNames.Event); this.payload = new[] { ParseHex(this.logReader.ReadContentAsString()) }; this.logReader.ReadEndElement(); return(true); default: this.logReader.Skip(); break; } } this.logReader.ReadEndElement(); this.Clear(); return(false); }
private async Task <int> ReadFromCurrentPacketAsync( byte[] buffer, int offset, int count, CancellationToken cancellationToken) { int read; while (((read = await this.deframedBuffer.ReadAsync(buffer, offset, count, cancellationToken)) == 0) && (count > 0) && (this.message != null) && this.message.CanHavePayload && this.message.CanHaveMultiplePackets && ((this.message.PacketFlags & PacketFlags.LastPacket) == 0)) { this.deframingStream.Dispose(); this.deframingStream = new DeframingStream(this.rawBuffer, this.outOfFrameByteReceived); this.ValidateMessage(await S101Message.ReadFromAsync(this.deframedBuffer, cancellationToken)); } return(read); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// internal static async Task <MessageDecodingStream> CreateAsync( ReadBuffer rawBuffer, byte[] discardBuffer, Action <byte> outOfFrameByteReceived, CancellationToken cancellationToken) { var result = new MessageDecodingStream(rawBuffer, discardBuffer, outOfFrameByteReceived); var newMessage = await S101Message.ReadFromAsync(result.deframedBuffer, cancellationToken); if ((newMessage != null) && newMessage.CanHaveMultiplePackets && ((newMessage.PacketFlags & PacketFlags.FirstPacket) == 0)) { throw new S101Exception(string.Format( CultureInfo.InvariantCulture, "Missing {0} flag in first packet.", PacketFlags.FirstPacket)); } result.message = newMessage; return(result); }
private static async Task <byte[]> Encode(S101Message message, byte[] payload = null) { using (var asyncStream = new MemoryStream()) { var writer = new S101Writer( async(b, o, c, t) => { // This makes the read operation truly asynchronous, which helps to improve code coverage. await Task.Delay(1); await asyncStream.WriteAsync(b, o, c, t); }, 1); using (var encodingStream = await writer.WriteMessageAsync(message, CancellationToken.None)) { Assert.AreEqual(encodingStream == null, payload == null); if (encodingStream != null) { Assert.IsFalse(encodingStream.CanRead); Assert.IsTrue(encodingStream.CanWrite); await encodingStream.WriteAsync(payload, 0, payload.Length, CancellationToken.None); await encodingStream.FlushAsync(CancellationToken.None); await encodingStream.DisposeAsync(CancellationToken.None); Assert.IsFalse(encodingStream.CanWrite); await AssertThrowAsync <ObjectDisposedException>( () => encodingStream.WriteAsync(new byte[] { 0 }, 0, 1, CancellationToken.None)); await AssertThrowAsync <ObjectDisposedException>( () => encodingStream.FlushAsync(CancellationToken.None)); } } await writer.DisposeAsync(CancellationToken.None); return(asyncStream.ToArray()); } }
private async Task SendMessageCoreAsync(S101Message message, byte[] payload) { await this.EnqueueLogOperation(() => this.logger.LogMessage(LogNames.Send, message, payload)); await this.sendQueue.Enqueue( async() => { var payloadStream = await this.writer.WriteMessageAsync(message, this.source.Token); if ((payload == null) != (payloadStream == null)) { throw new ArgumentException( "The payload requirements of the command of the passed message do not match the passed payload.", nameof(payload)); } if (payload != null) { await payloadStream.WriteAsync(payload, 0, payload.Length, this.source.Token); await payloadStream.DisposeAsync(this.source.Token); } }); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// internal MessageReceivedEventArgs(S101Message message, byte[] payload, bool isAnotherMessageAvailable) { this.message = message; this.payload = payload; this.isAnotherMessageAvailable = isAnotherMessageAvailable; }
private MessageEncodingStream(S101Message message, WriteBuffer rawBuffer, FramingStream framingStream) { this.unframedBuffer = new WriteBuffer(this.WriteUnframedAsync, Constants.MessageHeaderMaxLength); this.message = message; this.rawBuffer = rawBuffer; this.framingStream = framingStream; }
public Task<NonSeekableStream> WriteMessageAsync(S101Message message, CancellationToken cancellationToken) { return this.taskSingleton.Execute(() => this.WriteMessageCoreAsync(message, cancellationToken)); }
private async Task<NonSeekableStream> WriteMessageCoreAsync( S101Message message, CancellationToken cancellationToken) { this.AssertNotDisposed(); if (message == null) { throw new ArgumentNullException(nameof(message)); } if ((this.stream != null) && this.stream.CanWrite) { throw new InvalidOperationException( "DisposeAsync() has not been called on the payload stream of the previous message."); } this.stream = await MessageEncodingStream.CreateAsync(this.writeBuffer, message, cancellationToken); if (!message.CanHavePayload) { await this.stream.DisposeAsync(cancellationToken); this.stream = null; } return this.stream; }
public Task <NonSeekableStream> WriteMessageAsync(S101Message message, CancellationToken cancellationToken) { return(this.taskSingleton.Execute(() => this.WriteMessageCoreAsync(message, cancellationToken))); }
public void PayloadTest() { AsyncPump.Run( async () => { #pragma warning disable SA1123 // Do not place regions within elements. Necessary so that tested code snippets can be included in the documentation. #region Payload Test var writtenMessage = new S101Message(0x00, new EmberData(0x01, 0x0A, 0x02)); var writtenPayload = new byte[8192]; this.Random.NextBytes(writtenPayload); using (var encodedStream = new MemoryStream()) { // First we create a writer, which can be used to write multiple messages. // We specify which methods are used to write encoded output and flush it plus the size the internal // buffer should have. var writer = new S101Writer(encodedStream.WriteAsync); // Next we write the message. In return we get a Stream object for the payload. using (var payloadStream = await writer.WriteMessageAsync(writtenMessage, CancellationToken.None)) { // Now we write the payload. await payloadStream.WriteAsync(writtenPayload, 0, writtenPayload.Length); await payloadStream.DisposeAsync(CancellationToken.None); } await writer.DisposeAsync(CancellationToken.None); // Reset the encoded stream to the beginning, so that we can read from it. encodedStream.Position = 0; // First we create a reader, which can be used to read multiple messages. // We specify which methods are used to read encoded input. var reader = new S101Reader(encodedStream.ReadAsync); Assert.IsTrue(await reader.ReadAsync(CancellationToken.None)); // Read the first message var readMessage = reader.Message; // Assert the written and read messages are equal Assert.AreEqual(writtenMessage.Slot, readMessage.Slot); Assert.AreEqual(writtenMessage.Command, readMessage.Command); using (var readPayload = new MemoryStream()) { await reader.Payload.CopyToAsync(readPayload); // Copy the payload. // Assert that there is only one message Assert.IsFalse(await reader.ReadAsync(CancellationToken.None)); CollectionAssert.AreEqual(writtenPayload, readPayload.ToArray()); } await reader.DisposeAsync(CancellationToken.None); } #endregion #pragma warning restore SA1123 // Do not place regions within elements }); }
private void Clear() { this.eventType = null; this.timeUtc = DateTime.Today; this.direction = null; this.number = 0; this.message = null; this.payload = null; }
private bool ReadCore() { while (this.logReader.IsStartElement(LogNames.Event)) { switch (this.eventType = this.logReader.GetAttribute(LogNames.Type)) { case LogNames.Message: this.timeUtc = this.ReadTime(); this.direction = this.logReader.GetAttribute(LogNames.Direction); this.number = int.Parse( this.logReader.GetAttribute(LogNames.Number), NumberStyles.None, CultureInfo.InvariantCulture); this.logReader.ReadStartElement(LogNames.Event); this.logReader.ReadStartElement(LogNames.Slot); var slot = ParseHex(this.logReader.ReadContentAsString()); this.logReader.ReadEndElement(); this.logReader.ReadStartElement(LogNames.Command); var command = S101Command.Parse(this.logReader.ReadContentAsString()); this.logReader.ReadEndElement(); this.message = new S101Message(slot, command); if (!this.logReader.IsStartElement(LogNames.Payload)) { throw new XmlException("The Payload element is missing."); } this.payload = this.GetLogPayload(); return true; case LogNames.OutOfFrameByte: this.timeUtc = this.ReadTime(); this.direction = this.logReader.GetAttribute(LogNames.Direction); this.number = 0; this.message = null; this.logReader.ReadStartElement(LogNames.Event); this.payload = new[] { ParseHex(this.logReader.ReadContentAsString()) }; this.logReader.ReadEndElement(); return true; default: this.logReader.Skip(); break; } } this.logReader.ReadEndElement(); this.Clear(); return false; }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// internal EventInfo LogMessage(DateTime timeUtc, string direction, S101Message message, byte[] payload) { if (message == null) { throw new ArgumentNullException(nameof(message)); } if (direction == null) { throw new ArgumentNullException(nameof(direction)); } this.WriteStartEvent(LogNames.Message, timeUtc); int number; this.messageCounts.TryGetValue(direction, out number); this.messageCounts[direction] = ++number; this.xmlLogWriter.WriteAttributeString(LogNames.Direction, direction); this.xmlLogWriter.WriteAttributeString(LogNames.Number, number.ToString(CultureInfo.InvariantCulture)); this.xmlLogWriter.WriteElementString( LogNames.Slot, message.Slot.ToString("X2", CultureInfo.InvariantCulture)); this.xmlLogWriter.WriteElementString(LogNames.Command, message.Command.ToString()); this.xmlLogWriter.WriteStartElement(LogNames.Payload); if (payload != null) { this.converter.ToXml(payload, this.xmlLogWriter); } this.xmlLogWriter.WriteEndElement(); this.WriteEndEvent(); return new EventInfo(timeUtc, number); }
/// <inheritdoc/> public EventInfo LogMessage(string direction, S101Message message, byte[] payload) => this.LogMessage(DateTime.UtcNow, direction, message, payload);
public Task SendMessageAsync(S101Message message, byte[] payload) { this.AssertPreconditions(); return(this.SendMessageCoreAsync(message, payload)); }
private void ValidateMessage(S101Message newMessage) { if (newMessage == null) { throw new S101Exception("Unexpected end of stream."); } if (this.message.Slot != newMessage.Slot) { throw new S101Exception("Inconsistent Slot in multi-packet message."); } if (!this.message.Command.Equals(newMessage.Command)) { throw new S101Exception("Inconsistent Command in multi-packet message."); } if ((newMessage.PacketFlags & PacketFlags.FirstPacket) > 0) { throw new S101Exception(string.Format( CultureInfo.InvariantCulture, "{0} flag in subsequent packet.", PacketFlags.FirstPacket)); } this.message = newMessage; }
private static async Task<byte[]> Encode(S101Message message, byte[] payload = null) { using (var asyncStream = new MemoryStream()) { var writer = new S101Writer( async (b, o, c, t) => { // This makes the read operation truly asynchronous, which helps to improve code coverage. await Task.Delay(1); await asyncStream.WriteAsync(b, o, c, t); }, 1); using (var encodingStream = await writer.WriteMessageAsync(message, CancellationToken.None)) { Assert.AreEqual(encodingStream == null, payload == null); if (encodingStream != null) { Assert.IsFalse(encodingStream.CanRead); Assert.IsTrue(encodingStream.CanWrite); await encodingStream.WriteAsync(payload, 0, payload.Length, CancellationToken.None); await encodingStream.FlushAsync(CancellationToken.None); await encodingStream.DisposeAsync(CancellationToken.None); Assert.IsFalse(encodingStream.CanWrite); await AssertThrowAsync<ObjectDisposedException>( () => encodingStream.WriteAsync(new byte[] { 0 }, 0, 1, CancellationToken.None)); await AssertThrowAsync<ObjectDisposedException>( () => encodingStream.FlushAsync(CancellationToken.None)); } } await writer.DisposeAsync(CancellationToken.None); return asyncStream.ToArray(); } }
/// <inheritdoc/> public EventInfo LogMessage(string direction, S101Message message, byte[] payload) => this.LogMessage(DateTime.UtcNow, direction, message, payload);
/// <summary>Calls /// <see cref="SendMessageAsync(S101Message, byte[])">SendMessageAsync(<paramref name="message"/>, null)</see>. /// </summary> public Task SendMessageAsync(S101Message message) => this.SendMessageAsync(message, null);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// internal MessageReceivedEventArgs(S101Message message, byte[] payload, bool isAnotherMessageAvailable) { this.message = message; this.payload = payload; this.isAnotherMessageAvailable = isAnotherMessageAvailable; }