/// <inheritdoc /> public void WriteMessage(ServiceMessage message, IBufferWriter <byte> output) { var memoryBufferWriter = MemoryBufferWriter.Get(); try { var writer = new MessagePackWriter(memoryBufferWriter); // Write message to a buffer so we can get its length WriteMessageCore(ref writer, message); // Write length then message to output BinaryMessageFormatter.WriteLengthPrefix(memoryBufferWriter.Length, output); memoryBufferWriter.CopyTo(output); } finally { MemoryBufferWriter.Return(memoryBufferWriter); } }
public byte[] WriteAck(int messageId) { // Written as a MessagePack 'arr' containing at least these items: // * An 'int': The Id of the command being acknowledged. // Any additional items are discarded. var writer = MemoryBufferWriter.Get(); try { MessagePackBinary.WriteArrayHeader(writer, 1); MessagePackBinary.WriteInt32(writer, messageId); return(writer.ToArray()); } finally { MemoryBufferWriter.Return(writer); } }
public void WriteMessage(string protocolTestDataName) { var testData = ProtocolTestData[protocolTestDataName]; var expectedOutput = Frame(testData.Json); var writer = MemoryBufferWriter.Get(); try { JsonHubProtocol.WriteMessage(testData.Message, writer); var json = Encoding.UTF8.GetString(writer.ToArray()); Assert.Equal(expectedOutput, json); } finally { MemoryBufferWriter.Return(writer); } }
public void CustomWriteMessage(string protocolTestDataName) { var testData = CustomProtocolTestData[protocolTestDataName]; var expectedOutput = Frame(testData.Json); var writer = MemoryBufferWriter.Get(); try { var protocol = GetProtocolWithOptions(testData.UseCamelCase, testData.IgnoreNullValues); protocol.WriteMessage(testData.Message, writer); var json = Encoding.UTF8.GetString(writer.ToArray()); Assert.Equal(expectedOutput, json); } finally { MemoryBufferWriter.Return(writer); } }
public void WriteAndParseDateTimeOffset() { var dateTimeOffset = new DateTimeOffset(new DateTime(2018, 4, 9), TimeSpan.FromHours(10)); var writer = MemoryBufferWriter.Get(); try { HubProtocol.WriteMessage(CompletionMessage.WithResult("xyz", dateTimeOffset), writer); var bytes = new ReadOnlySequence <byte>(writer.ToArray()); HubProtocol.TryParseMessage(ref bytes, new TestBinder(typeof(DateTimeOffset)), out var hubMessage); var completionMessage = Assert.IsType <CompletionMessage>(hubMessage); var resultDateTimeOffset = (DateTimeOffset)completionMessage.Result; Assert.Equal(dateTimeOffset, resultDateTimeOffset); } finally { MemoryBufferWriter.Return(writer); } }
public static ReadOnlySpan <byte> GetSuccessfulHandshake(IHubProtocol protocol) { ReadOnlyMemory <byte> result; if (!_messageCache.TryGetValue(protocol, out result)) { var memoryBufferWriter = MemoryBufferWriter.Get(); try { WriteResponseMessage(HandshakeResponseMessage.Empty, memoryBufferWriter); result = memoryBufferWriter.ToArray(); _messageCache.TryAdd(protocol, result); } finally { MemoryBufferWriter.Return(memoryBufferWriter); } } return(result.Span); }
public async Task <string> ReadHandshakeAndSendResponseAsync() { var s = await ReadSentTextMessageAsync(); byte[] response; var output = MemoryBufferWriter.Get(); try { HandshakeProtocol.WriteResponseMessage(HandshakeResponseMessage.Empty, output); response = output.ToArray(); } finally { MemoryBufferWriter.Return(output); } await Application.Output.WriteAsync(response); return(s); }
private static byte[] GetMessage(string methodName, object[] args) { // 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); MessagePackBinary.WriteArrayHeader(writer, 0); WriteSerializedHubMessage(writer, new SerializedHubMessage(new InvocationMessage(methodName, args))); return(writer.ToArray()); } finally { MemoryBufferWriter.Return(writer); } }
public static byte[] WriteAck(int messageId) { // Written as a MessagePack 'arr' containing at least these items: // * An 'int': The Id of the command being acknowledged. // Any additional items are discarded. var memoryBufferWriter = MemoryBufferWriter.Get(); try { var writer = new MessagePackWriter(memoryBufferWriter); writer.WriteArrayHeader(1); writer.Write(messageId); writer.Flush(); return(memoryBufferWriter.ToArray()); } finally { MemoryBufferWriter.Return(memoryBufferWriter); } }
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 memoryBufferWriter = MemoryBufferWriter.Get(); try { var writer = new MessagePackWriter(memoryBufferWriter); 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(methodName, args)); writer.Flush(); return(memoryBufferWriter.ToArray()); } finally { MemoryBufferWriter.Return(memoryBufferWriter); } }
public void WriteAndParseDateTimeConvertsToUTC() { var dateTime = new DateTime(2018, 4, 9); var writer = MemoryBufferWriter.Get(); try { _hubProtocol.WriteMessage(CompletionMessage.WithResult("xyz", dateTime), 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 Assert.Equal(dateTime.ToUniversalTime(), resultDateTime); } 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(); 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(); }
public async Task ContinuesIfInvalidHandshakeResponse() { bool ExpectedErrors(WriteContext writeContext) { return(writeContext.LoggerName == typeof(HubConnection).FullName && (writeContext.EventId.Name == "ServerDisconnectedWithError" || writeContext.EventId.Name == "ReconnectingWithError" || writeContext.EventId.Name == "ErrorReceivingHandshakeResponse" || writeContext.EventId.Name == "HandshakeServerError" || writeContext.EventId.Name == "ErrorStartingConnection")); } using (StartVerifiableLog(ExpectedErrors)) { var builder = new HubConnectionBuilder().WithLoggerFactory(LoggerFactory).WithUrl("http://example.com"); var testConnectionFactory = new ReconnectingConnectionFactory(() => new TestConnection(autoHandshake: false)); builder.Services.AddSingleton <IConnectionFactory>(testConnectionFactory); var retryContexts = new List <RetryContext>(); var secondRetryDelayTcs = new TaskCompletionSource <object>(TaskCreationOptions.RunContinuationsAsynchronously); var mockReconnectPolicy = new Mock <IRetryPolicy>(); mockReconnectPolicy.Setup(p => p.NextRetryDelay(It.IsAny <RetryContext>())).Returns <RetryContext>(context => { retryContexts.Add(context); if (retryContexts.Count == 2) { secondRetryDelayTcs.SetResult(null); } return(TimeSpan.Zero); }); builder.WithAutomaticReconnect(mockReconnectPolicy.Object); await using var hubConnection = builder.Build(); var reconnectingCount = 0; var reconnectedCount = 0; var reconnectingErrorTcs = new TaskCompletionSource <Exception>(TaskCreationOptions.RunContinuationsAsynchronously); var reconnectedConnectionIdTcs = new TaskCompletionSource <string>(TaskCreationOptions.RunContinuationsAsynchronously); var closedErrorTcs = new TaskCompletionSource <Exception>(TaskCreationOptions.RunContinuationsAsynchronously); hubConnection.Reconnecting += error => { reconnectingCount++; reconnectingErrorTcs.SetResult(error); return(Task.CompletedTask); }; hubConnection.Reconnected += connectionId => { reconnectedCount++; reconnectedConnectionIdTcs.SetResult(connectionId); return(Task.CompletedTask); }; hubConnection.Closed += error => { closedErrorTcs.SetResult(error); return(Task.CompletedTask); }; var startTask = hubConnection.StartAsync(); // Complete handshake var currentTestConnection = await testConnectionFactory.GetNextOrCurrentTestConnection(); await currentTestConnection.ReadHandshakeAndSendResponseAsync().OrTimeout(); await startTask.OrTimeout(); var firstException = new Exception(); currentTestConnection.CompleteFromTransport(firstException); Assert.Same(firstException, await reconnectingErrorTcs.Task.OrTimeout()); Assert.Single(retryContexts); Assert.Same(firstException, retryContexts[0].RetryReason); Assert.Equal(0, retryContexts[0].PreviousRetryCount); Assert.Equal(TimeSpan.Zero, retryContexts[0].ElapsedTime); // Respond to handshake with error. currentTestConnection = await testConnectionFactory.GetNextOrCurrentTestConnection(); await currentTestConnection.ReadSentTextMessageAsync().OrTimeout(); var output = MemoryBufferWriter.Get(); try { HandshakeProtocol.WriteResponseMessage(new HandshakeResponseMessage("Error!"), output); await currentTestConnection.Application.Output.WriteAsync(output.ToArray()).OrTimeout(); } finally { MemoryBufferWriter.Return(output); } await secondRetryDelayTcs.Task.OrTimeout(); Assert.Equal(2, retryContexts.Count); Assert.IsType <HubException>(retryContexts[1].RetryReason); Assert.Equal(1, retryContexts[1].PreviousRetryCount); Assert.True(TimeSpan.Zero <= retryContexts[0].ElapsedTime); // Complete handshake currentTestConnection = await testConnectionFactory.GetNextOrCurrentTestConnection(); await currentTestConnection.ReadHandshakeAndSendResponseAsync().OrTimeout(); await reconnectedConnectionIdTcs.Task.OrTimeout(); Assert.Equal(1, reconnectingCount); Assert.Equal(1, reconnectedCount); Assert.Equal(TaskStatus.WaitingForActivation, closedErrorTcs.Task.Status); await hubConnection.StopAsync().OrTimeout(); var closeError = await closedErrorTcs.Task.OrTimeout(); Assert.Null(closeError); Assert.Equal(1, reconnectingCount); Assert.Equal(1, reconnectedCount); } }
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)); _invocationMessageBytes = hubProtocol.GetMessageBytes(new InvocationMessage(MethodName, arguments)); 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.On(MethodName, arguments.Select(v => v.GetType()).ToArray(), OnInvoke); _hubConnection.StartAsync().GetAwaiter().GetResult(); }