Example #1
0
        /// <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);
            }
        }
Example #2
0
        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);
            }
        }
Example #5
0
        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);
        }
Example #7
0
        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);
        }
Example #8
0
        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);
            }
        }
Example #9
0
    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);
        }
    }
Example #10
0
        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);
            }
        }
Example #11
0
        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();
        }
Example #13
0
            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);
                }
            }
Example #14
0
        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();
        }