コード例 #1
0
 public static void SendingMessage(ILogger logger, HubMessage message)
 {
     if (logger.IsEnabled(LogLevel.Debug))
     {
         if (message is HubInvocationMessage invocationMessage)
         {
             SendingMessage(logger, message.GetType().Name, invocationMessage.InvocationId);
         }
         else
         {
             SendingMessageGeneric(logger, message.GetType().Name);
         }
     }
 }
コード例 #2
0
ファイル: HubConnection.Log.cs プロジェクト: wserr/AspNetCore
 public static void MessageSent(ILogger logger, HubMessage message)
 {
     if (logger.IsEnabled(LogLevel.Debug))
     {
         if (message is HubInvocationMessage invocationMessage)
         {
             _messageSent(logger, message.GetType().Name, invocationMessage.InvocationId, null);
         }
         else
         {
             _messageSentGeneric(logger, message.GetType().Name, null);
         }
     }
 }
コード例 #3
0
        private void WriteMessageCore(HubMessage message, Stream stream)
        {
            using (var writer = new JsonTextWriter(new StreamWriter(stream)))
            {
                switch (message)
                {
                case InvocationMessage m:
                    WriteInvocationMessage(m, writer);
                    break;

                case StreamInvocationMessage m:
                    WriteStreamInvocationMessage(m, writer);
                    break;

                case StreamItemMessage m:
                    WriteStreamItemMessage(m, writer);
                    break;

                case CompletionMessage m:
                    WriteCompletionMessage(m, writer);
                    break;

                case CancelInvocationMessage m:
                    WriteCancelInvocationMessage(m, writer);
                    break;

                case PingMessage m:
                    WritePingMessage(m, writer);
                    break;

                default:
                    throw new InvalidOperationException($"Unsupported message type: {message.GetType().FullName}");
                }
            }
        }
コード例 #4
0
        public static void AssertHubMessage(HubMessage expected, HubMessage actual)
        {
            // We aren't testing InvocationIds here
            switch (expected)
            {
            case CompletionMessage expectedCompletion:
                var actualCompletion = Assert.IsType <CompletionMessage>(actual);
                Assert.Equal(expectedCompletion.Error, actualCompletion.Error);
                Assert.Equal(expectedCompletion.HasResult, actualCompletion.HasResult);
                Assert.Equal(expectedCompletion.Result, actualCompletion.Result);
                break;

            case StreamItemMessage expectedStreamItem:
                var actualStreamItem = Assert.IsType <StreamItemMessage>(actual);
                Assert.Equal(expectedStreamItem.Item, actualStreamItem.Item);
                break;

            case InvocationMessage expectedInvocation:
                var actualInvocation = Assert.IsType <InvocationMessage>(actual);

                // Either both must have non-null invocationIds or both must have null invocation IDs. Checking the exact value is NOT desired here though as it could be randomly generated
                Assert.True((expectedInvocation.InvocationId == null && actualInvocation.InvocationId == null) ||
                            (expectedInvocation.InvocationId != null && actualInvocation.InvocationId != null));
                Assert.Equal(expectedInvocation.Target, actualInvocation.Target);
                Assert.Equal(expectedInvocation.Arguments, actualInvocation.Arguments);
                break;

            default:
                throw new InvalidOperationException($"Unsupported Hub Message type {expected.GetType()}");
            }
        }
コード例 #5
0
ファイル: HubConnection.cs プロジェクト: zjnny/SignalR
        private async Task <(bool close, Exception exception)> ProcessMessagesAsync(HubMessage message, ConnectionState connectionState)
        {
            InvocationRequest irq;

            switch (message)
            {
            case InvocationMessage invocation:
                Log.ReceivedInvocation(_logger, invocation.InvocationId, invocation.Target,
                                       invocation.ArgumentBindingException != null ? null : invocation.Arguments);
                await DispatchInvocationAsync(invocation);

                break;

            case CompletionMessage completion:
                if (!connectionState.TryRemoveInvocation(completion.InvocationId, out irq))
                {
                    Log.DroppedCompletionMessage(_logger, completion.InvocationId);
                }
                else
                {
                    DispatchInvocationCompletion(completion, irq);
                    irq.Dispose();
                }
                break;

            case StreamItemMessage streamItem:
                // Complete the invocation with an error, we don't support streaming (yet)
                if (!connectionState.TryGetInvocation(streamItem.InvocationId, out irq))
                {
                    Log.DroppedStreamMessage(_logger, streamItem.InvocationId);
                    return(close : false, exception : null);
                }
                await DispatchInvocationStreamItemAsync(streamItem, irq);

                break;

            case CloseMessage close:
                if (string.IsNullOrEmpty(close.Error))
                {
                    Log.ReceivedClose(_logger);
                    return(close : true, exception : null);
                }
                else
                {
                    Log.ReceivedCloseWithError(_logger, close.Error);
                    return(close : true, exception : new HubException($"The server closed the connection with the following error: {close.Error}"));
                }

            case PingMessage _:
                Log.ReceivedPing(_logger);
                // Nothing to do on receipt of a ping.
                break;

            default:
                throw new InvalidOperationException($"Unexpected message type: {message.GetType().FullName}");
            }

            return(close : false, exception : null);
        }
コード例 #6
0
ファイル: DefaultHubDispatcher.cs プロジェクト: sk1e/SignalR
        public override Task DispatchMessageAsync(HubConnectionContext connection, HubMessage hubMessage)
        {
            // Messages are dispatched sequentially and will stop other messages from being processed until they complete.
            // Streaming methods will run sequentially until they start streaming, then they will fire-and-forget allowing other messages to run.

            switch (hubMessage)
            {
            case InvocationBindingFailureMessage bindingFailureMessage:
                return(ProcessInvocationBindingFailure(connection, bindingFailureMessage));

            case StreamBindingFailureMessage bindingFailureMessage:
                return(ProcessStreamBindingFailure(connection, bindingFailureMessage));

            case InvocationMessage invocationMessage:
                Log.ReceivedHubInvocation(_logger, invocationMessage);
                return(ProcessInvocation(connection, invocationMessage, isStreamResponse: false));

            case StreamInvocationMessage streamInvocationMessage:
                Log.ReceivedStreamHubInvocation(_logger, streamInvocationMessage);
                return(ProcessInvocation(connection, streamInvocationMessage, isStreamResponse: true));

            case CancelInvocationMessage cancelInvocationMessage:
                // Check if there is an associated active stream and cancel it if it exists.
                // The cts will be removed when the streaming method completes executing
                if (connection.ActiveRequestCancellationSources.TryGetValue(cancelInvocationMessage.InvocationId, out var cts))
                {
                    Log.CancelStream(_logger, cancelInvocationMessage.InvocationId);
                    cts.Cancel();
                }
                else
                {
                    // Stream can be canceled on the server while client is canceling stream.
                    Log.UnexpectedCancel(_logger);
                }
                break;

            case PingMessage _:
                connection.StartClientTimeout();
                break;

            case StreamDataMessage streamItem:
                Log.ReceivedStreamItem(_logger, streamItem);
                return(ProcessStreamItem(connection, streamItem));

            case StreamCompleteMessage streamCompleteMessage:
                // closes channels, removes from Lookup dict
                // user's method can see the channel is complete and begin wrapping up
                Log.CompletingStream(_logger, streamCompleteMessage);
                connection.StreamTracker.Complete(streamCompleteMessage);
                break;

            // Other kind of message we weren't expecting
            default:
                Log.UnsupportedMessageReceived(_logger, hubMessage.GetType().FullName);
                throw new NotSupportedException($"Received unsupported message: {hubMessage}");
            }

            return(Task.CompletedTask);
        }
コード例 #7
0
        private void ProcessHubMessage(HubConnectionContext connection, HubMessage hubMessage)
        {
            switch (hubMessage)
            {
            case InvocationMessage invocationMessage:
                _logger.ReceivedHubInvocation(invocationMessage);

                // Don't wait on the result of execution, continue processing other
                // incoming messages on this connection.
                _ = _hubInvoker.OnInvocationAsync(connection, invocationMessage, isStreamedInvocation: false);
                break;

            case StreamInvocationMessage streamInvocationMessage:
                _logger.ReceivedStreamHubInvocation(streamInvocationMessage);

                // Don't wait on the result of execution, continue processing other
                // incoming messages on this connection.
                _ = _hubInvoker.OnInvocationAsync(connection, streamInvocationMessage, isStreamedInvocation: true);
                break;

            case CancelInvocationMessage cancelInvocationMessage:
                // Check if there is an associated active stream and cancel it if it exists.
                // The cts will be removed when the streaming method completes executing
                if (connection.ActiveRequestCancellationSources.TryGetValue(cancelInvocationMessage.InvocationId, out var cts))
                {
                    _logger.CancelStream(cancelInvocationMessage.InvocationId);
                    cts.Cancel();
                }
                else
                {
                    // Stream can be canceled on the server while client is canceling stream.
                    _logger.UnexpectedCancel();
                }
                break;

            case CompletionMessage completionMessage:
                _logger.ReceivedCompletion(completionMessage);

                _ = _hubInvoker.OnCompletionAsync(connection, completionMessage);
                break;

            case PingMessage _:
                // We don't care about pings
                break;

            // Other kind of message we weren't expecting
            default:
                _logger.UnsupportedMessageReceived(hubMessage.GetType().FullName);
                throw new NotSupportedException($"Received unsupported message: {hubMessage}");
            }
        }
コード例 #8
0
        public override async Task DispatchMessageAsync(HubConnectionContext connection, HubMessage hubMessage)
        {
            if (!(connection is CloudHubConnectionContext cloudConnection))
            {
                _logger.LogError("Invalid type. CloudHubConnectionContext expected.");
                return;
            }

            switch (hubMessage)
            {
            case InvocationMessage invocationMessage:
                _logger.LogDebug($"Received invocation: {invocationMessage}");
                await ProcessInvocation(cloudConnection, invocationMessage, isStreamedInvocation : false);

                break;

            case StreamInvocationMessage streamInvocationMessage:
                _logger.LogDebug($"Received stream invocation: {streamInvocationMessage}");
                await ProcessInvocation(cloudConnection, streamInvocationMessage, isStreamedInvocation : true);

                break;

            case CompletionMessage completionMessage:
                break;

            case CancelInvocationMessage cancelInvocationMessage:
                // Check if there is an associated active stream and cancel it if it exists.
                // The cts will be removed when the streaming method completes executing
                if (cloudConnection.ActiveRequestCancellationSources.TryGetValue(cancelInvocationMessage.InvocationId, out var cts))
                {
                    _logger.LogDebug($"Cancel stream invocation: {cancelInvocationMessage.InvocationId}");
                    cts.Cancel();
                }
                else
                {
                    _logger.LogWarning("Unexpected stream invocation cancel.");
                }
                break;

            case PingMessage _:
                // We don't care about pings
                break;

            // Other kind of message we weren't expecting
            default:
                _logger.LogError($"Received unsupported message type: {hubMessage.GetType().FullName}");
                throw new NotSupportedException($"Received unsupported message: {hubMessage}");
            }
        }
コード例 #9
0
        public override async Task DispatchMessageAsync(HubConnectionContext connection, HubMessage hubMessage)
        {
            switch (hubMessage)
            {
            case InvocationBindingFailureMessage bindingFailureMessage:
                await ProcessBindingFailure(connection, bindingFailureMessage);

                break;

            case InvocationMessage invocationMessage:
                Log.ReceivedHubInvocation(_logger, invocationMessage);
                await ProcessInvocation(connection, invocationMessage, isStreamedInvocation : false);

                break;

            case StreamInvocationMessage streamInvocationMessage:
                Log.ReceivedStreamHubInvocation(_logger, streamInvocationMessage);
                await ProcessInvocation(connection, streamInvocationMessage, isStreamedInvocation : true);

                break;

            case CancelInvocationMessage cancelInvocationMessage:
                // Check if there is an associated active stream and cancel it if it exists.
                // The cts will be removed when the streaming method completes executing
                if (connection.ActiveRequestCancellationSources.TryGetValue(cancelInvocationMessage.InvocationId, out var cts))
                {
                    Log.CancelStream(_logger, cancelInvocationMessage.InvocationId);
                    cts.Cancel();
                }
                else
                {
                    // Stream can be canceled on the server while client is canceling stream.
                    Log.UnexpectedCancel(_logger);
                }
                break;

            case PingMessage _:
                // We don't care about pings
                break;

            // Other kind of message we weren't expecting
            default:
                Log.UnsupportedMessageReceived(_logger, hubMessage.GetType().FullName);
                throw new NotSupportedException($"Received unsupported message: {hubMessage}");
            }
        }
コード例 #10
0
        private void WriteMessageCore(HubMessage message, IBufferWriter <byte> bufferWriter)
        {
            var writer = new MessagePackWriter(bufferWriter);

            switch (message)
            {
            case InvocationMessage invocationMessage:
                WriteInvocationMessage(invocationMessage, ref writer);
                break;

            case StreamInvocationMessage streamInvocationMessage:
                WriteStreamInvocationMessage(streamInvocationMessage, ref writer);
                break;

            case StreamItemMessage streamItemMessage:
                WriteStreamingItemMessage(streamItemMessage, ref writer);
                break;

            case CompletionMessage completionMessage:
                WriteCompletionMessage(completionMessage, ref writer);
                break;

            case CancelInvocationMessage cancelInvocationMessage:
                WriteCancelInvocationMessage(cancelInvocationMessage, ref writer);
                break;

            case PingMessage pingMessage:
                WritePingMessage(pingMessage, ref writer);
                break;

            case CloseMessage closeMessage:
                WriteCloseMessage(closeMessage, ref writer);
                break;

            default:
                throw new InvalidDataException($"Unexpected message type: {message.GetType().Name}");
            }

            writer.Flush();
        }
        private void WriteMessageCore(HubMessage message, IBufferWriter <byte> output)
        {
            switch (message)
            {
            case InvocationMessage invocationMessage:
                WriteInvocationMessage(invocationMessage, output);
                break;

            case StreamInvocationMessage streamInvocationMessage:
                WriteStreamInvocationMessage(streamInvocationMessage, output);
                break;

            case StreamItemMessage streamItemMessage:
                WriteItemMessage(streamItemMessage, output);
                break;

            case CompletionMessage completionMessage:
                WriteCompletionMessage(completionMessage, output);
                break;

            case CancelInvocationMessage cancelInvocationMessage:
                WriteCancelInvocationMessage(cancelInvocationMessage, output);
                break;

            case PingMessage pingMessage:
                WritePingMessage(pingMessage, output);
                break;

            case CloseMessage closeMessage:
                WriteCloseMessage(closeMessage, output);
                break;

            default:
                _logger.LogCritical($"Unexpected message type: {message.GetType().Name}");
                break;
            }
        }
コード例 #12
0
        private void WriteMessageCore(HubMessage message, Stream output)
        {
            // PackerCompatibilityOptions.None prevents from serializing byte[] as strings
            // and allows extended objects
            var packer = Packer.Create(output, PackerCompatibilityOptions.None);

            switch (message)
            {
            case InvocationMessage invocationMessage:
                WriteInvocationMessage(invocationMessage, packer);
                break;

            case StreamInvocationMessage streamInvocationMessage:
                WriteStreamInvocationMessage(streamInvocationMessage, packer);
                break;

            case StreamItemMessage streamItemMessage:
                WriteStreamingItemMessage(streamItemMessage, packer);
                break;

            case CompletionMessage completionMessage:
                WriteCompletionMessage(completionMessage, packer);
                break;

            case CancelInvocationMessage cancelInvocationMessage:
                WriteCancelInvocationMessage(cancelInvocationMessage, packer);
                break;

            case PingMessage pingMessage:
                WritePingMessage(pingMessage, packer);
                break;

            default:
                throw new FormatException($"Unexpected message type: {message.GetType().Name}");
            }
        }
コード例 #13
0
    private void WriteMessageCore(HubMessage message, IBufferWriter <byte> stream)
    {
        var textWriter = Utf8BufferTextWriter.Get(stream);

        try
        {
            using (var writer = JsonUtils.CreateJsonTextWriter(textWriter))
            {
                writer.WriteStartObject();
                switch (message)
                {
                case InvocationMessage m:
                    WriteMessageType(writer, HubProtocolConstants.InvocationMessageType);
                    WriteHeaders(writer, m);
                    WriteInvocationMessage(m, writer);
                    break;

                case StreamInvocationMessage m:
                    WriteMessageType(writer, HubProtocolConstants.StreamInvocationMessageType);
                    WriteHeaders(writer, m);
                    WriteStreamInvocationMessage(m, writer);
                    break;

                case StreamItemMessage m:
                    WriteMessageType(writer, HubProtocolConstants.StreamItemMessageType);
                    WriteHeaders(writer, m);
                    WriteStreamItemMessage(m, writer);
                    break;

                case CompletionMessage m:
                    WriteMessageType(writer, HubProtocolConstants.CompletionMessageType);
                    WriteHeaders(writer, m);
                    WriteCompletionMessage(m, writer);
                    break;

                case CancelInvocationMessage m:
                    WriteMessageType(writer, HubProtocolConstants.CancelInvocationMessageType);
                    WriteHeaders(writer, m);
                    WriteCancelInvocationMessage(m, writer);
                    break;

                case PingMessage _:
                    WriteMessageType(writer, HubProtocolConstants.PingMessageType);
                    break;

                case CloseMessage m:
                    WriteMessageType(writer, HubProtocolConstants.CloseMessageType);
                    WriteCloseMessage(m, writer);
                    break;

                default:
                    throw new InvalidOperationException($"Unsupported message type: {message.GetType().FullName}");
                }
                writer.WriteEndObject();
                writer.Flush();
            }
        }
        finally
        {
            Utf8BufferTextWriter.Return(textWriter);
        }
    }
コード例 #14
0
ファイル: InvocationRequest.cs プロジェクト: masums/SignalR
            public override void Complete(HubMessage message)
            {
                Debug.Assert(message != null, "message is null");

                if (!(message is StreamCompletionMessage streamCompletionMessage))
                {
                    Logger.ReceivedUnexpectedMessageTypeForStreamCompletion(InvocationId, message.GetType().Name);
                    // This is not 100% accurate but it is the only case that can be encountered today when running end-to-end
                    // and this is the most useful message to show to the user.
                    Fail(new InvalidOperationException($"Streaming hub methods must be invoked with the '{nameof(HubConnection)}.{nameof(HubConnection.StreamAsync)}' method."));
                    return;
                }

                if (!string.IsNullOrEmpty(streamCompletionMessage.Error))
                {
                    Fail(new HubException(streamCompletionMessage.Error));
                    return;
                }

                Logger.InvocationCompleted(InvocationId);
                _channel.Out.TryComplete();
            }
コード例 #15
0
        /// <summary>
        /// 处理消息
        /// </summary>
        /// <param name="hubMessage">转换后的消息对象</param>
        private void ProcessMessages(HubMessage hubMessage)
        {
            if (hubMessage == null)
            {
                Log.Debug("为获取到可处理的消息");
                throw new ArgumentNullException($"为获取到可处理的消息.{nameof(hubMessage)}");
            }
            switch (hubMessage)
            {
            case InvocationMessage invocation:
            {
                var handler = new InvocationMessageHandler(_handlers, (r) =>
                    {
                        if (!string.IsNullOrEmpty(invocation.InvocationId))
                        {
                            var completionMessage = new CompletionMessage(invocation.InvocationId, null, r, r != null);
                            SendHubMessage(completionMessage);
                        }
                    });
                try
                {
                    handler.Handler(invocation);
                }
                catch (Exception e)
                {
                    Log.Error(null, e);
                    if (invocation != null && !string.IsNullOrEmpty(invocation.InvocationId))
                    {
                        SendHubMessage(new CompletionMessage(invocation.InvocationId, e.Message, null, false));
                    }
                }
            }
            break;

            case StreamItemMessage streamItem:
            {
                Log.Info($"客户端暂不支持 {nameof(StreamItemMessage)}");
                if (streamItem != null && !string.IsNullOrEmpty(streamItem.InvocationId))
                {
                    SendHubMessage(new CompletionMessage(streamItem.InvocationId, $"客户端暂不支持 {nameof(StreamItemMessage)}", null, false));
                }
            }
            break;

            case StreamInvocationMessage streamInvocation:
            {
                Log.Info($"客户端暂不支持 {nameof(StreamInvocationMessage)}");
                if (streamInvocation != null && !string.IsNullOrEmpty(streamInvocation.InvocationId))
                {
                    SendHubMessage(new CompletionMessage(streamInvocation.InvocationId, $"客户端暂不支持 {nameof(StreamInvocationMessage)}", null, false));
                }
            }
            break;

            case CancelInvocationMessage cancelInvocation:
            {
                Log.Info($"客户端暂不支持 {nameof(CancelInvocationMessage)}");
            }
            break;

            case CompletionMessage completion:
            {
                var handler = new CompletionMessageHandler(_sendedMessageCallBacks);
                handler.Handler(completion);
                // 清除当前 InvocationId 对应的回调
                if (_sendedMessageCallBacks.ContainsKey(completion.InvocationId))
                {
                    lock (_sendedMessageCallBacks)
                    {
                        _sendedMessageCallBacks.Remove(completion.InvocationId);
                    }
                }
            }
            break;

            case CloseMessage close:
            {
                if (string.IsNullOrEmpty(close.Error))
                {
                    Log.Debug("服务器将关闭连接,客户端主动断开连接");
                }
                else
                {
                    Log.Error("服务器将关闭连接,客户端主动断开连接", new Exception(close.Error));
                }
                StopAsync();
            }
            break;

            case PingMessage _:
                Log.Debug("接收到服务器端 Ping");
                break;

            default:
                throw new InvalidOperationException($"未知的消息类型: {hubMessage.GetType().FullName}");
            }
        }
コード例 #16
0
ファイル: JsonHubProtocol.cs プロジェクト: pa-at/aspnetcore
    private void WriteMessageCore(HubMessage message, IBufferWriter <byte> stream)
    {
        var reusableWriter = ReusableUtf8JsonWriter.Get(stream);

        try
        {
            var writer = reusableWriter.GetJsonWriter();
            writer.WriteStartObject();
            switch (message)
            {
            case InvocationMessage m:
                WriteMessageType(writer, HubProtocolConstants.InvocationMessageType);
                WriteHeaders(writer, m);
                WriteInvocationMessage(m, writer);
                break;

            case StreamInvocationMessage m:
                WriteMessageType(writer, HubProtocolConstants.StreamInvocationMessageType);
                WriteHeaders(writer, m);
                WriteStreamInvocationMessage(m, writer);
                break;

            case StreamItemMessage m:
                WriteMessageType(writer, HubProtocolConstants.StreamItemMessageType);
                WriteHeaders(writer, m);
                WriteStreamItemMessage(m, writer);
                break;

            case CompletionMessage m:
                WriteMessageType(writer, HubProtocolConstants.CompletionMessageType);
                WriteHeaders(writer, m);
                WriteCompletionMessage(m, writer);
                break;

            case CancelInvocationMessage m:
                WriteMessageType(writer, HubProtocolConstants.CancelInvocationMessageType);
                WriteHeaders(writer, m);
                WriteCancelInvocationMessage(m, writer);
                break;

            case PingMessage _:
                WriteMessageType(writer, HubProtocolConstants.PingMessageType);
                break;

            case CloseMessage m:
                WriteMessageType(writer, HubProtocolConstants.CloseMessageType);
                WriteCloseMessage(m, writer);
                break;

            default:
                throw new InvalidOperationException($"Unsupported message type: {message.GetType().FullName}");
            }
            writer.WriteEndObject();
            writer.Flush();
            Debug.Assert(writer.CurrentDepth == 0);
        }
        finally
        {
            ReusableUtf8JsonWriter.Return(reusableWriter);
        }
    }
コード例 #17
0
 public void EnqueueMessage(HubMessage m) =>
 _hubMessagesFromSDK.GetOrAdd(m.GetType(), _ => CreateChannel <HubMessage>()).Writer.TryWrite(m);