public void WriteMessage(object message, IBufferWriter <byte> output) { if (_messageResolver.TryGetMessageId(message.GetType(), out var id)) { var options = new JsonWriterOptions(); var memory = MemoryBufferWriter.Get(); using var writer = new Utf8JsonWriter((IBufferWriter <byte>)memory, options); writer.WriteStartObject(); writer.WritePropertyName("$type"); writer.WriteStringValue(id); var str = JsonSerializer.Serialize(message); using var doc = JsonDocument.Parse(str); foreach (var property in doc.RootElement.EnumerateObject()) { property.WriteTo(writer); } writer.WriteEndObject(); writer.Flush(); memory.CopyTo(output); } }
public void GlobalSetup() { var memoryBufferWriter = MemoryBufferWriter.Get(); try { HandshakeProtocol.WriteRequestMessage(new HandshakeRequestMessage("json", 1), memoryBufferWriter); _handshakeRequestResult = new ReadResult(new ReadOnlySequence <byte>(memoryBufferWriter.ToArray()), false, false); } finally { MemoryBufferWriter.Return(memoryBufferWriter); } _pipe = new TestDuplexPipe(); var connection = new DefaultConnectionContext(Guid.NewGuid().ToString(), _pipe, _pipe); _hubConnectionContext = new HubConnectionContext(connection, Timeout.InfiniteTimeSpan, NullLoggerFactory.Instance); _successHubProtocolResolver = new TestHubProtocolResolver(new JsonHubProtocol()); _failureHubProtocolResolver = new TestHubProtocolResolver(null); _userIdProvider = new TestUserIdProvider(); _supportedProtocols = new List <string> { "json" }; }
public byte[] WriteGroupCommand(RedisGroupCommand command) { // Written as a MessagePack 'arr' containing at least these items: // * An 'int': the Id of the command // * A 'str': The server name // * An 'int': The action (likely less than 0x7F and thus a single-byte fixnum) // * A 'str': The group name // * A 'str': The connection Id // Any additional items are discarded. var writer = MemoryBufferWriter.Get(); try { MessagePackBinary.WriteArrayHeader(writer, 5); MessagePackBinary.WriteInt32(writer, command.Id); MessagePackBinary.WriteString(writer, command.ServerName); MessagePackBinary.WriteByte(writer, (byte)command.Action); MessagePackBinary.WriteString(writer, command.GroupName); MessagePackBinary.WriteString(writer, command.ConnectionId); return(writer.ToArray()); } finally { MemoryBufferWriter.Return(writer); } }
public void GlobalSetup() { var arguments = new object[ArgumentCount]; for (var i = 0; i < arguments.Length; i++) { arguments[i] = "Hello world!"; } var writer = MemoryBufferWriter.Get(); try { HandshakeProtocol.WriteResponseMessage(HandshakeResponseMessage.Empty, writer); var handshakeResponseResult = new ReadResult(new ReadOnlySequence <byte>(writer.ToArray()), false, false); _pipe = new TestDuplexPipe(); _pipe.AddReadResult(new ValueTask <ReadResult>(handshakeResponseResult)); } finally { MemoryBufferWriter.Return(writer); } _nextReadTcs = new TaskCompletionSource <ReadResult>(); _pipe.AddReadResult(new ValueTask <ReadResult>(_nextReadTcs.Task)); IHubProtocol hubProtocol; var hubConnectionBuilder = new HubConnectionBuilder(); if (Protocol == "json") { hubProtocol = new NewtonsoftJsonHubProtocol(); } else { hubProtocol = new MessagePackHubProtocol(); } hubConnectionBuilder.Services.TryAddEnumerable(ServiceDescriptor.Singleton(typeof(IHubProtocol), hubProtocol)); hubConnectionBuilder.WithUrl("http://doesntmatter"); _invocationMessageBytes = hubProtocol.GetMessageBytes(new InvocationMessage(MethodName, arguments)); var delegateConnectionFactory = new DelegateConnectionFactory(endPoint => { var connection = new DefaultConnectionContext(); // prevents keep alive time being activated connection.Features.Set <IConnectionInherentKeepAliveFeature>(new TestConnectionInherentKeepAliveFeature()); connection.Transport = _pipe; return(new ValueTask <ConnectionContext>(connection)); }); hubConnectionBuilder.Services.AddSingleton <IConnectionFactory>(delegateConnectionFactory); _hubConnection = hubConnectionBuilder.Build(); _hubConnection.On(MethodName, arguments.Select(v => v.GetType()).ToArray(), OnInvoke); _hubConnection.StartAsync().GetAwaiter().GetResult(); }
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!") }; var writer = MemoryBufferWriter.Get(); // Use small chunks to test Advance/Enlarge and partial payload writing try { foreach (var message in messages) { BinaryMessageFormatter.WriteLengthPrefix(message.Length, writer); writer.Write(message); } Assert.Equal(expectedEncoding, writer.ToArray()); } finally { MemoryBufferWriter.Return(writer); } }
public void GlobalSetup() { var writer = MemoryBufferWriter.Get(); try { HandshakeProtocol.WriteResponseMessage(HandshakeResponseMessage.Empty, writer); _handshakeResponseResult = new ReadResult(new ReadOnlySequence <byte>(writer.ToArray()), false, false); } finally { MemoryBufferWriter.Return(writer); } _pipe = new TestDuplexPipe(); var hubConnectionBuilder = new HubConnectionBuilder(); hubConnectionBuilder.WithHubProtocol(new JsonHubProtocol()); hubConnectionBuilder.WithConnectionFactory(format => { var connection = new DefaultConnectionContext(); // prevents keep alive time being activated connection.Features.Set <IConnectionInherentKeepAliveFeature>(new TestConnectionInherentKeepAliveFeature()); connection.Transport = _pipe; return(Task.FromResult <ConnectionContext>(connection)); }); _hubConnection = hubConnectionBuilder.Build(); }
/// <inheritdoc /> public ReadOnlyMemory <byte> GetMessageBytes(HubMessage message) { var memoryBufferWriter = MemoryBufferWriter.Get(); try { var writer = new MessagePackWriter(memoryBufferWriter); // Write message to a buffer so we can get its length WriteMessageCore(message, ref writer); var dataLength = memoryBufferWriter.Length; var prefixLength = BinaryMessageFormatter.LengthPrefixLength(memoryBufferWriter.Length); var array = new byte[dataLength + prefixLength]; var span = array.AsSpan(); // Write length then message to output var written = BinaryMessageFormatter.WriteLengthPrefix(memoryBufferWriter.Length, span); Debug.Assert(written == prefixLength); memoryBufferWriter.CopyTo(span.Slice(prefixLength)); return(array); } finally { MemoryBufferWriter.Return(memoryBufferWriter); } }
public void Setup() { var buffer = new byte[MessageLength]; Random.Shared.NextBytes(buffer); var writer = MemoryBufferWriter.Get(); try { BinaryMessageFormatter.WriteLengthPrefix(buffer.Length, writer); writer.Write(buffer); _binaryInput = writer.ToArray(); } finally { MemoryBufferWriter.Return(writer); } buffer = new byte[MessageLength]; Random.Shared.NextBytes(buffer); writer = MemoryBufferWriter.Get(); try { writer.Write(buffer); TextMessageFormatter.WriteRecordSeparator(writer); _textInput = writer.ToArray(); } finally { MemoryBufferWriter.Return(writer); } }
public void WriteAndParseDateTimeConvertsToUTC(DateTimeKind dateTimeKind) { // The messagepack Timestamp format always converts input DateTime to Utc if they are passed as "DateTimeKind.Local" : // https://github.com/neuecc/MessagePack-CSharp/pull/520/files#diff-ed970b3daebc708ce49f55d418075979 var originalDateTime = new DateTime(2018, 4, 9, 0, 0, 0, dateTimeKind); var writer = MemoryBufferWriter.Get(); try { HubProtocol.WriteMessage(CompletionMessage.WithResult("xyz", originalDateTime), writer); var bytes = new ReadOnlySequence <byte>(writer.ToArray()); HubProtocol.TryParseMessage(ref bytes, new TestBinder(typeof(DateTime)), out var hubMessage); var completionMessage = Assert.IsType <CompletionMessage>(hubMessage); var resultDateTime = (DateTime)completionMessage.Result; // The messagepack Timestamp format specifies that time is stored as seconds since 1970-01-01 UTC // so the library has no choice but to store the time as UTC // https://github.com/msgpack/msgpack/blob/master/spec.md#timestamp-extension-type // So If the original DateTiem was a "Local" one, we create a new DateTime equivalent to the original one but converted to Utc var expectedUtcDateTime = (originalDateTime.Kind == DateTimeKind.Local) ? originalDateTime.ToUniversalTime() : originalDateTime; Assert.Equal(expectedUtcDateTime, resultDateTime); } finally { MemoryBufferWriter.Return(writer); } }
private IMemoryOwner <byte> BuildCloseConnectionPayload(string error) { var writer = MemoryBufferWriter.Get(); try { using (var sw = new StreamWriter(writer)) using (var jw = new JsonTextWriter(sw)) { jw.WriteStartObject(); jw.WritePropertyName(nameof(ServerlessProtocol.CloseConnectionMessage.Type)); jw.WriteValue(ServerlessProtocol.Constants.CloseConnectionMessageType); if (error != null) { jw.WritePropertyName(nameof(ServerlessProtocol.CloseConnectionMessage.Error)); jw.WriteValue(error); } jw.WriteEndObject(); jw.Flush(); var result = ExactSizeMemoryPool.Shared.Rent((int)writer.Length); writer.CopyTo(result.Memory.Span); return(result); } } finally { MemoryBufferWriter.Return(writer); } }
public void WriteMessage(string protocolTestDataName) { var testData = ProtocolTestData[protocolTestDataName]; var expectedOutput = Frame(testData.Json); var protocolOptions = new JsonHubProtocolOptions { PayloadSerializerSettings = new JsonSerializerSettings() { NullValueHandling = testData.NullValueHandling, ContractResolver = testData.CamelCase ? new CamelCasePropertyNamesContractResolver() : new DefaultContractResolver() } }; var protocol = new JsonHubProtocol(Options.Create(protocolOptions)); var writer = MemoryBufferWriter.Get(); try { protocol.WriteMessage(testData.Message, writer); var json = Encoding.UTF8.GetString(writer.ToArray()); Assert.Equal(expectedOutput, json); } finally { MemoryBufferWriter.Return(writer); } }
public byte[] WriteInvocation( string methodName, object[] args, IReadOnlyList <string> connections, IReadOnlyList <string> groups, IReadOnlyList <string> users, IReadOnlyList <string> excludedConnectionIds) { // Written as a MessagePack 'arr' containing at least these items: // * A MessagePack 'arr' of 'str's representing the excluded ids // * [The output of WriteSerializedHubMessage, which is an 'arr'] // Any additional items are discarded. var writer = MemoryBufferWriter.Get(); try { MessagePackBinary.WriteArrayHeader(writer, 5); WriteList(excludedConnectionIds, writer); WriteList(connections, writer); WriteList(groups, writer); WriteList(users, writer); this.WriteSerializedHubMessage(writer, new SerializedHubMessage(new InvocationMessage(methodName, args))); return(writer.ToArray()); } finally { MemoryBufferWriter.Return(writer); } }
public void GlobalSetup() { var writer = MemoryBufferWriter.Get(); try { HandshakeProtocol.WriteResponseMessage(HandshakeResponseMessage.Empty, writer); _handshakeResponseResult = new ReadResult(new ReadOnlySequence <byte>(writer.ToArray()), false, false); } finally { MemoryBufferWriter.Return(writer); } _pipe = new TestDuplexPipe(); var hubConnectionBuilder = new HubConnectionBuilder(); hubConnectionBuilder.WithUrl("http://doesntmatter"); var delegateConnectionFactory = new DelegateConnectionFactory(endPoint => { var connection = new DefaultConnectionContext(); // prevents keep alive time being activated connection.Features.Set <IConnectionInherentKeepAliveFeature>(new TestConnectionInherentKeepAliveFeature()); connection.Transport = _pipe; return(new ValueTask <ConnectionContext>(connection)); }); hubConnectionBuilder.Services.AddSingleton <IConnectionFactory>(delegateConnectionFactory); _hubConnection = hubConnectionBuilder.Build(); }
public byte[] WriteInvocation(string methodName, object[] args, IReadOnlyList <string> excludedConnectionIds) { // Written as a MessagePack 'arr' containing at least these items: // * A MessagePack 'arr' of 'str's representing the excluded ids // * [The output of WriteSerializedHubMessage, which is an 'arr'] // Any additional items are discarded. var writer = MemoryBufferWriter.Get(); try { MessagePackBinary.WriteArrayHeader(writer, 2); if (excludedConnectionIds != null && excludedConnectionIds.Count > 0) { MessagePackBinary.WriteArrayHeader(writer, excludedConnectionIds.Count); foreach (var id in excludedConnectionIds) { MessagePackBinary.WriteString(writer, id); } } else { MessagePackBinary.WriteArrayHeader(writer, 0); } WriteSerializedHubMessage(writer, new SerializedHubMessage(new InvocationMessage(methodName, args))); return(writer.ToArray()); } finally { MemoryBufferWriter.Return(writer); } }
// The Redis Protocol: // * The message type is known in advance because messages are sent to different channels based on type // * Invocations are sent to the All, Group, Connection and User channels // * Group Commands are sent to the GroupManagement channel // * Acks are sent to the Acknowledgement channel. // * Completion messages (client results) are sent to the server specific Result channel // * See the Write[type] methods for a description of the protocol for each in-depth. // * The "Variable length integer" is the length-prefixing format used by BinaryReader/BinaryWriter: // * https://docs.microsoft.com/dotnet/api/system.io.binarywriter.write?view=netcore-2.2 // * The "Length prefixed string" is the string format used by BinaryReader/BinaryWriter: // * A 7-bit variable length integer encodes the length in bytes, followed by the encoded string in UTF-8. public byte[] WriteInvocation(string methodName, object?[] args, string?invocationId = null, IReadOnlyList <string>?excludedConnectionIds = null, string?returnChannel = null) { // Written as a MessagePack 'arr' containing at least these items: // * A MessagePack 'arr' of 'str's representing the excluded ids // * [The output of WriteSerializedHubMessage, which is an 'arr'] // For invocations expecting a result // * InvocationID // * Redis return channel // Any additional items are discarded. var memoryBufferWriter = MemoryBufferWriter.Get(); try { var writer = new MessagePackWriter(memoryBufferWriter); if (!string.IsNullOrEmpty(returnChannel)) { writer.WriteArrayHeader(4); } else { writer.WriteArrayHeader(2); } if (excludedConnectionIds != null && excludedConnectionIds.Count > 0) { writer.WriteArrayHeader(excludedConnectionIds.Count); foreach (var id in excludedConnectionIds) { writer.Write(id); } } else { writer.WriteArrayHeader(0); } WriteHubMessage(ref writer, new InvocationMessage(invocationId, methodName, args)); // Write last in order to preserve original order for cases where one server is updated and the other isn't. // Not really a supported scenario, but why not be nice if (!string.IsNullOrEmpty(returnChannel)) { writer.Write(invocationId); writer.Write(returnChannel); } writer.Flush(); return(memoryBufferWriter.ToArray()); } finally { MemoryBufferWriter.Return(memoryBufferWriter); } }
public void GlobalSetup() { var writer = MemoryBufferWriter.Get(); try { HandshakeProtocol.WriteResponseMessage(HandshakeResponseMessage.Empty, writer); var handshakeResponseResult = new ReadResult(new ReadOnlySequence <byte>(writer.ToArray()), false, false); _pipe = new TestDuplexPipe(); _pipe.AddReadResult(new ValueTask <ReadResult>(handshakeResponseResult)); } finally { MemoryBufferWriter.Return(writer); } _tcs = new TaskCompletionSource <ReadResult>(); _pipe.AddReadResult(new ValueTask <ReadResult>(_tcs.Task)); var hubConnectionBuilder = new HubConnectionBuilder(); if (Protocol == "json") { // JSON protocol added by default } else { hubConnectionBuilder.AddMessagePackProtocol(); } var delegateConnectionFactory = new DelegateConnectionFactory(format => { var connection = new DefaultConnectionContext(); // prevents keep alive time being activated connection.Features.Set <IConnectionInherentKeepAliveFeature>(new TestConnectionInherentKeepAliveFeature()); connection.Transport = _pipe; return(Task.FromResult <ConnectionContext>(connection)); }, connection => { connection.Transport.Output.Complete(); connection.Transport.Input.Complete(); return(Task.CompletedTask); }); hubConnectionBuilder.Services.AddSingleton <IConnectionFactory>(delegateConnectionFactory); _hubConnection = hubConnectionBuilder.Build(); _hubConnection.StartAsync().GetAwaiter().GetResult(); _arguments = new object[ArgumentCount]; for (var i = 0; i < _arguments.Length; i++) { _arguments[i] = "Hello world!"; } }
public void HandShakeWriteRequest_MemoryBufferWriter() { var memoryBufferWriter = MemoryBufferWriter.Get(); try { HandshakeProtocol.WriteRequestMessage(new HandshakeRequestMessage("json", 1), memoryBufferWriter); } finally { MemoryBufferWriter.Return(memoryBufferWriter); } }
public void HandShakeWriteResponseEmpty_MemoryBufferWriter() { var writer = MemoryBufferWriter.Get(); try { HandshakeProtocol.WriteResponseMessage(HandshakeResponseMessage.Empty, writer); } finally { MemoryBufferWriter.Return(writer); } }
static HubConnectionContext() { var memoryBufferWriter = MemoryBufferWriter.Get(); try { HandshakeProtocol.WriteResponseMessage(HandshakeResponseMessage.Empty, memoryBufferWriter); _successHandshakeResponseData = memoryBufferWriter.ToArray(); } finally { MemoryBufferWriter.Return(memoryBufferWriter); } }
private static ReadOnlyMemory <byte> GetSuccessHandshakeData() { var memoryBufferWriter = MemoryBufferWriter.Get(); try { WriteResponseMessage(HandshakeResponseMessage.Empty, memoryBufferWriter); return(memoryBufferWriter.ToArray()); } finally { MemoryBufferWriter.Return(memoryBufferWriter); } }
static HandshakeProtocol() { var memoryBufferWriter = MemoryBufferWriter.Get(); try { WriteResponseMessage(HandshakeResponseMessage.Empty, memoryBufferWriter); SuccessHandshakeData = memoryBufferWriter.ToArray(); } finally { MemoryBufferWriter.Return(memoryBufferWriter); } }
/// <summary> /// Converts the specified <see cref="HubMessage"/> to its serialized representation. /// </summary> /// <param name="hubProtocol">The hub protocol.</param> /// <param name="message">The message to convert to bytes.</param> /// <returns>The serialized representation of the specified message.</returns> public static byte[] GetMessageBytes(this IHubProtocol hubProtocol, HubMessage message) { var writer = MemoryBufferWriter.Get(); try { hubProtocol.WriteMessage(message, writer); return(writer.ToArray()); } finally { MemoryBufferWriter.Return(writer); } }
public static ReadOnlyMemory <byte> GetMessageBytes(Microsoft.AspNetCore.SignalR.Protocol.HandshakeRequestMessage message) { var writer = MemoryBufferWriter.Get(); try { Microsoft.AspNetCore.SignalR.Protocol.HandshakeProtocol.WriteRequestMessage(message, writer); return(writer.ToArray()); } finally { MemoryBufferWriter.Return(writer); } }
private static byte[] Write(HubMessage message) { var writer = MemoryBufferWriter.Get(); try { _hubProtocol.WriteMessage(message, writer); return(writer.ToArray()); } finally { MemoryBufferWriter.Return(writer); } }
private static byte[] Frame(byte[] input) { var stream = MemoryBufferWriter.Get(); try { BinaryMessageFormatter.WriteLengthPrefix(input.Length, stream); stream.Write(input); return stream.ToArray(); } finally { MemoryBufferWriter.Return(stream); } }
public void HandShakeWriteResponse_MemoryBufferWriter() { ReadOnlyMemory <byte> result; var memoryBufferWriter = MemoryBufferWriter.Get(); try { HandshakeProtocol.WriteResponseMessage(HandshakeResponseMessage.Empty, memoryBufferWriter); result = memoryBufferWriter.ToArray(); } finally { MemoryBufferWriter.Return(memoryBufferWriter); } }
public void VerifyMessageSize(string testDataName) { var testData = MessageSizeData[testDataName]; var writer = MemoryBufferWriter.Get(); try { JsonHubProtocol.WriteMessage(testData.Message, writer); Assert.Equal(testData.Size, writer.Length); } finally { MemoryBufferWriter.Return(writer); } }
public void WriteBinaryMessage(byte[] encoded, byte[] payload) { var writer = MemoryBufferWriter.Get(); try { BinaryMessageFormatter.WriteLengthPrefix(payload.Length, writer); writer.Write(payload); Assert.Equal(encoded, writer.ToArray()); } finally { MemoryBufferWriter.Return(writer); } }
public void WriteTextMessage(byte[] encoded, string payload) { var message = Encoding.UTF8.GetBytes(payload); var writer = MemoryBufferWriter.Get(); try { BinaryMessageFormatter.WriteLengthPrefix(message.Length, writer); writer.Write(message); Assert.Equal(encoded, writer.ToArray()); } finally { MemoryBufferWriter.Return(writer); } }
public void RoundTrippingTest(byte[] payload) { var writer = MemoryBufferWriter.Get(); try { 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()); } finally { MemoryBufferWriter.Return(writer); } }