From 603b24560ab460736ea1e9215b4fea3dc37a560c Mon Sep 17 00:00:00 2001 From: DJGosnell Date: Sat, 23 Sep 2017 22:03:55 -0400 Subject: [PATCH] Added documentation to the MessageHandler class. When any MessageHandler throws on a call, the session is now terminated since it was unhanded due to invalid data sent. Added Guid to MqFrame as a type to read and write. Added Guid to MqMessageReader and MqMessageWriter. Added tests for new Guid methods. --- .../Mq/MqFrameTests.cs | 54 +++++++++++++++++++ .../Mq/MqMessageWriterReaderTests.cs | 19 +++++++ src/DtronixMessageQueue/MqFrame.cs | 29 +++++++++- src/DtronixMessageQueue/MqMessageReader.cs | 14 +++++ src/DtronixMessageQueue/MqMessageWriter.cs | 52 +++++++++++------- src/DtronixMessageQueue/Rpc/MessageHandler.cs | 35 +++++++++++- 6 files changed, 182 insertions(+), 21 deletions(-) diff --git a/src/DtronixMessageQueue.Tests/Mq/MqFrameTests.cs b/src/DtronixMessageQueue.Tests/Mq/MqFrameTests.cs index 8256f9e..2229410 100644 --- a/src/DtronixMessageQueue.Tests/Mq/MqFrameTests.cs +++ b/src/DtronixMessageQueue.Tests/Mq/MqFrameTests.cs @@ -847,5 +847,59 @@ public void Frame_throws_on_ascii_text_write_when_larger_than_frame() Assert.Throws(() => _actualFrame.WriteAscii(0, value, false)); } + + [Fact] + public void Frame_writes_guid() + { + var value = Guid.NewGuid(); + + _expectedBytes = new byte[] { 3, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + Buffer.BlockCopy(value.ToByteArray(), 0, _expectedBytes, 3, 16); + + _actualFrame = new MqFrame(new byte[17], MqFrameType.Last, _config); + _actualFrame.Write(0, value); + + _actualBytes = _actualFrame.RawFrame(); + + Assert.Equal(_expectedBytes, _actualBytes); + } + + [Fact] + public void Frame_writes_guid_position() + { + var value = Guid.NewGuid(); + + _expectedBytes = new byte[] {3, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + Buffer.BlockCopy(value.ToByteArray(), 0, _expectedBytes, 4, 16); + + _actualFrame = new MqFrame(new byte[18], MqFrameType.Last, _config); + _actualFrame.Write(1, value); + + _actualBytes = _actualFrame.RawFrame(); + + Assert.Equal(_expectedBytes, _actualBytes); + } + + [Fact] + public void Frame_reads_guid() + { + var value = Guid.NewGuid(); + _actualFrame = new MqFrame(new byte[16], MqFrameType.Last, _config); + _actualFrame.Write(0, value); + + Assert.Equal(value, _actualFrame.ReadGuid(0)); + } + + [Fact] + public void Frame_reads_guid_position() + { + var value = Guid.NewGuid(); + _actualFrame = new MqFrame(new byte[17], MqFrameType.Last, _config); + _actualFrame.Write(1, value); + + Assert.Equal(value, _actualFrame.ReadGuid(1)); + } } } \ No newline at end of file diff --git a/src/DtronixMessageQueue.Tests/Mq/MqMessageWriterReaderTests.cs b/src/DtronixMessageQueue.Tests/Mq/MqMessageWriterReaderTests.cs index fdc3f59..131f487 100644 --- a/src/DtronixMessageQueue.Tests/Mq/MqMessageWriterReaderTests.cs +++ b/src/DtronixMessageQueue.Tests/Mq/MqMessageWriterReaderTests.cs @@ -356,6 +356,7 @@ public void MessageReader_reads_multi_frame_string() [Fact] public void MessageWriter_multiple_reads_writes() { + _messageBuilder.Write(true); _messageBuilder.Write(false); @@ -387,6 +388,9 @@ public void MessageWriter_multiple_reads_writes() _messageBuilder.Write(FillerText); + var expectedGuid = Guid.NewGuid(); + _messageBuilder.Write((Guid)expectedGuid); + var message = _messageBuilder.ToMessage(); _messageReader.Message = message; @@ -423,6 +427,9 @@ public void MessageWriter_multiple_reads_writes() Assert.Equal(expectedByteArray, readByteArray); Assert.Equal(FillerText, _messageReader.ReadString()); + + Assert.Equal(expectedGuid, _messageReader.ReadGuid()); + Assert.True(_messageReader.IsAtEnd); } @@ -664,5 +671,17 @@ public void MessageReader_sets_position_and_updates_isatend() _messageReader.Position = 8; Assert.False(_messageReader.IsAtEnd); } + + [Fact] + public void MessageReader_writes_guid() + { + var expectedValue = (Guid)Guid.NewGuid(); + _messageBuilder.Write(expectedValue); + var message = _messageBuilder.ToMessage(); + _messageReader.Message = message; + + Assert.Equal(expectedValue, _messageReader.ReadGuid()); + Assert.True(_messageReader.IsAtEnd); + } } } \ No newline at end of file diff --git a/src/DtronixMessageQueue/MqFrame.cs b/src/DtronixMessageQueue/MqFrame.cs index 1d2c438..cece5b3 100644 --- a/src/DtronixMessageQueue/MqFrame.cs +++ b/src/DtronixMessageQueue/MqFrame.cs @@ -551,6 +551,7 @@ public string ReadAscii(int index, int stringLength = -1) return Encoding.ASCII.GetString(strBuffer); } + /// /// Writes a ASCII encoded string. /// (uint16?)(string) @@ -565,7 +566,7 @@ public void WriteAscii(int index, string value, bool prependSize = true) if (prependSize) { - Write(index, (ushort) stringBytes.Length); + Write(index, (ushort)stringBytes.Length); } if (index + stringBytes.Length + (prependSize ? 2 : 0) > _config.FrameBufferSize) @@ -576,6 +577,32 @@ public void WriteAscii(int index, string value, bool prependSize = true) Write(index + (prependSize ? 2 : 0), stringBytes, 0, stringBytes.Length); } + /// + /// Writes a Guid byte array value. + /// 16 Bytes. + /// + /// The zero-based index to write the value to. + /// Value to write to the specified index. + public void Write(int index, Guid value) + { + var guidBytes = value.ToByteArray(); + + Write(index, guidBytes, 0, guidBytes.Length); + } + + /// + /// Reads a Guid value at the specified index. + /// 16 Bytes. + /// + /// The zero-based index to read the value from. + public Guid ReadGuid(int index) + { + var guidBuffer = new byte[16]; + Read(index, guidBuffer, 0, 16); + return new Guid(guidBuffer); + } + + /// /// Reads the bytes from this frame. /// diff --git a/src/DtronixMessageQueue/MqMessageReader.cs b/src/DtronixMessageQueue/MqMessageReader.cs index de6312d..60126ac 100644 --- a/src/DtronixMessageQueue/MqMessageReader.cs +++ b/src/DtronixMessageQueue/MqMessageReader.cs @@ -498,6 +498,20 @@ public override string ReadString() return _encoding.GetString(strBuffer); } + /// + /// Reads a Guid. + /// 16 Bytes. + /// + public Guid ReadGuid() + { + EnsureBuffer(16); + var value = _currentFrame.ReadGuid(_framePosition); + _framePosition += 16; + _absolutePosition += 16; + + return value; + } + /// /// Reads the rest of the message bytes from the current position to the end. /// >1 Byte. diff --git a/src/DtronixMessageQueue/MqMessageWriter.cs b/src/DtronixMessageQueue/MqMessageWriter.cs index d75a711..ea240a5 100644 --- a/src/DtronixMessageQueue/MqMessageWriter.cs +++ b/src/DtronixMessageQueue/MqMessageWriter.cs @@ -296,6 +296,39 @@ public override void Write(decimal value) _position += 16; } + + /// + /// Writes a string. + /// >4 Bytes. + /// 1 or more frames. + /// + /// Value to write to the message. + public override void Write(string value) + { + var stringBytes = Encoding.UTF8.GetBytes(value); + + // Write the length prefix + EnsureSpace(4); + _builderFrame.Write(_position, stringBytes.Length); + _position += 4; + + // Write the buffer to the message. + Write(stringBytes, 0, stringBytes.Length); + } + + + /// + /// Writes a Guid. + /// 16 Bytes. + /// + /// Value to write to the message. + public void Write(Guid value) + { + EnsureSpace(16); + _builderFrame.Write(_position, value); + _position += 16; + } + /// /// Appends an existing message to this message. /// @@ -325,25 +358,6 @@ public void Write() _frames.Add(new MqFrame(null, MqFrameType.Empty, _config)); } - /// - /// Writes a string. - /// >4 Bytes. - /// 1 or more frames. - /// - /// Value to write to the message. - public override void Write(string value) - { - var stringBytes = Encoding.UTF8.GetBytes(value); - - // Write the length prefix - EnsureSpace(4); - _builderFrame.Write(_position, stringBytes.Length); - _position += 4; - - // Write the buffer to the message. - Write(stringBytes, 0, stringBytes.Length); - } - /// /// Writes a byte array to this one or more frames. /// >1 Byte. diff --git a/src/DtronixMessageQueue/Rpc/MessageHandler.cs b/src/DtronixMessageQueue/Rpc/MessageHandler.cs index daa198d..8a6b064 100644 --- a/src/DtronixMessageQueue/Rpc/MessageHandler.cs +++ b/src/DtronixMessageQueue/Rpc/MessageHandler.cs @@ -3,19 +3,35 @@ namespace DtronixMessageQueue.Rpc { + /// + /// Base class to be used for all Rpc message handlers. + /// + /// Session type for this connection. + /// Configuration for this connection. public abstract class MessageHandler where TSession : RpcSession, new() where TConfig : RpcConfig { - public delegate void ActionHandler(byte actionHandler, MqMessage message); + /// + /// Delegate used to be called on each successfully parsed action call in this MessageHandler. + /// + /// Value of the enum for the action called. + /// Full message excluding the action id. + public delegate void ActionHandler(byte actionId, MqMessage message); /// /// Id byte which precedes all messages all messages of this type. /// public abstract byte Id { get; } + /// + /// Session of the connection. + /// public TSession Session; + /// + /// All registered handlers for the MessageHandler. + /// protected Dictionary Handlers = new Dictionary(); protected MessageHandler(TSession session) @@ -23,6 +39,12 @@ protected MessageHandler(TSession session) Session = session; } + /// + /// Parses and passes the message to the correct action in the handler. + /// Automatically removes the first frame of the message used to determine which action id to call. + /// + /// Message to parse + /// True on successful parsing. public bool HandleMessage(MqMessage message) { if (message[0][0] != Id) @@ -45,15 +67,26 @@ public bool HandleMessage(MqMessage message) return false; } + /// + /// Send a null message to the + /// + /// public void SendHandlerMessage(byte actionId) { SendHandlerMessage(actionId, null); } + /// + /// Sends the passed message to the specified action handler. + /// + /// Action enum value to pass the message to. + /// Message to send to the connection. public void SendHandlerMessage(byte actionId, MqMessage message) { var headerFrame = Session.CreateFrame(new byte[2], MqFrameType.More); + // Id of the message handler. headerFrame.Write(0, Id); + // Id of the action to call. headerFrame.Write(1, actionId); var sendMessage = new MqMessage