예제 #1
0
        private CancelInvocationMessage BindCancelInvocationMessage(JObject json)
        {
            var invocationId = JsonUtils.GetRequiredProperty <string>(json, InvocationIdPropertyName, JTokenType.String);
            var metadata     = JsonUtils.GetOptionalMetadataDictionary(json, MetadataPropertyName);

            return(new CancelInvocationMessage(invocationId, metadata));
        }
예제 #2
0
        private InvocationMessage BindInvocationMessage(JObject json, IInvocationBinder binder)
        {
            var invocationId = JsonUtils.GetRequiredProperty <string>(json, InvocationIdPropertyName, JTokenType.String);
            var target       = JsonUtils.GetRequiredProperty <string>(json, TargetPropertyName, JTokenType.String);
            var nonBlocking  = JsonUtils.GetOptionalProperty <bool>(json, NonBlockingPropertyName, JTokenType.Boolean);

            var args = JsonUtils.GetRequiredProperty <JArray>(json, ArgumentsPropertyName, JTokenType.Array);

            var paramTypes = binder.GetParameterTypes(target);
            var arguments  = new object[args.Count];

            if (paramTypes.Length != arguments.Length)
            {
                throw new FormatException($"Invocation provides {arguments.Length} argument(s) but target expects {paramTypes.Length}.");
            }

            for (var i = 0; i < paramTypes.Length; i++)
            {
                var paramType = paramTypes[i];

                // TODO(anurse): We can add some DI magic here to allow users to provide their own serialization
                // Related Bug: https://github.com/aspnet/SignalR/issues/261
                arguments[i] = args[i].ToObject(paramType, _payloadSerializer);
            }

            return(new InvocationMessage(invocationId, nonBlocking, target, arguments));
        }
예제 #3
0
        private CancelInvocationMessage BindCancelInvocationMessage(JObject json)
        {
            var invocationId = JsonUtils.GetRequiredProperty <string>(json, InvocationIdPropertyName, JTokenType.String);
            var message      = new CancelInvocationMessage(invocationId);

            ReadHeaders(json, message.Headers);
            return(message);
        }
예제 #4
0
        private StreamItemMessage BindStreamItemMessage(JObject json, IInvocationBinder binder)
        {
            var invocationId = JsonUtils.GetRequiredProperty <string>(json, InvocationIdPropertyName, JTokenType.String);
            var result       = JsonUtils.GetRequiredProperty <JToken>(json, ItemPropertyName);

            var returnType = binder.GetReturnType(invocationId);

            return(new StreamItemMessage(invocationId, result?.ToObject(returnType, _payloadSerializer)));
        }
예제 #5
0
        private HubMessage ParseMessage(Stream input, IInvocationBinder binder)
        {
            using (var reader = new JsonTextReader(new StreamReader(input)))
            {
                try
                {
                    // PERF: Could probably use the JsonTextReader directly for better perf and fewer allocations
                    var token = JToken.ReadFrom(reader);

                    if (token == null || token.Type != JTokenType.Object)
                    {
                        throw new InvalidDataException($"Unexpected JSON Token Type '{token?.Type}'. Expected a JSON Object.");
                    }

                    var json = (JObject)token;

                    // Determine the type of the message
                    var type = JsonUtils.GetRequiredProperty <int>(json, TypePropertyName, JTokenType.Integer);

                    switch (type)
                    {
                    case HubProtocolConstants.InvocationMessageType:
                        return(BindInvocationMessage(json, binder));

                    case HubProtocolConstants.StreamInvocationMessageType:
                        return(BindStreamInvocationMessage(json, binder));

                    case HubProtocolConstants.StreamItemMessageType:
                        return(BindStreamItemMessage(json, binder));

                    case HubProtocolConstants.CompletionMessageType:
                        return(BindCompletionMessage(json, binder));

                    case HubProtocolConstants.CancelInvocationMessageType:
                        return(BindCancelInvocationMessage(json));

                    case HubProtocolConstants.PingMessageType:
                        return(PingMessage.Instance);

                    default:
                        throw new InvalidDataException($"Unknown message type: {type}");
                    }
                }
                catch (JsonReaderException jrex)
                {
                    throw new InvalidDataException("Error reading JSON.", jrex);
                }
            }
        }
예제 #6
0
        private StreamInvocationMessage BindStreamInvocationMessage(JObject json, IInvocationBinder binder)
        {
            var invocationId = JsonUtils.GetRequiredProperty <string>(json, InvocationIdPropertyName, JTokenType.String);
            var target       = JsonUtils.GetRequiredProperty <string>(json, TargetPropertyName, JTokenType.String);

            var args = JsonUtils.GetRequiredProperty <JArray>(json, ArgumentsPropertyName, JTokenType.Array);

            var paramTypes = binder.GetParameterTypes(target);

            try
            {
                var arguments = BindArguments(args, paramTypes);
                return(new StreamInvocationMessage(invocationId, target, argumentBindingException: null, arguments: arguments));
            }
            catch (Exception ex)
            {
                return(new StreamInvocationMessage(invocationId, target, ExceptionDispatchInfo.Capture(ex)));
            }
        }
예제 #7
0
        private InvocationMessage BindInvocationMessage(JObject json, IInvocationBinder binder)
        {
            var invocationId = JsonUtils.GetOptionalProperty <string>(json, InvocationIdPropertyName, JTokenType.String);
            var metadata     = JsonUtils.GetOptionalMetadataDictionary(json, MetadataPropertyName);

            var target = JsonUtils.GetRequiredProperty <string>(json, TargetPropertyName, JTokenType.String);
            var args   = JsonUtils.GetRequiredProperty <JArray>(json, ArgumentsPropertyName, JTokenType.Array);

            var paramTypes = binder.GetParameterTypes(target);

            try
            {
                var arguments = BindArguments(args, paramTypes);
                return(new InvocationMessage(invocationId, metadata, target, arguments: arguments));
            }
            catch (Exception ex)
            {
                return(new InvocationMessage(invocationId, metadata, target, ExceptionDispatchInfo.Capture(ex)));
            }
        }
예제 #8
0
        private CompletionMessage BindCompletionMessage(JObject json, IInvocationBinder binder)
        {
            var invocationId = JsonUtils.GetRequiredProperty <string>(json, InvocationIdPropertyName, JTokenType.String);
            var error        = JsonUtils.GetOptionalProperty <string>(json, ErrorPropertyName, JTokenType.String);
            var resultProp   = json.Property(ResultPropertyName);

            if (error != null && resultProp != null)
            {
                throw new FormatException("The 'error' and 'result' properties are mutually exclusive.");
            }

            if (resultProp == null)
            {
                return(new CompletionMessage(invocationId, error, result: null, hasResult: false));
            }

            var returnType = binder.GetReturnType(invocationId);
            var payload    = resultProp.Value?.ToObject(returnType, _payloadSerializer);

            return(new CompletionMessage(invocationId, error, result: payload, hasResult: true));
        }
예제 #9
0
        public static bool TryParseRequestMessage(ReadOnlySequence <byte> buffer, out HandshakeRequestMessage requestMessage, out SequencePosition consumed, out SequencePosition examined)
        {
            if (!TryReadMessageIntoSingleMemory(buffer, out consumed, out examined, out var memory))
            {
                requestMessage = null;
                return(false);
            }

            if (!TextMessageParser.TryParseMessage(ref memory, out var payload))
            {
                throw new InvalidDataException("Unable to parse payload as a handshake request message.");
            }

            using (var reader = CreateJsonTextReader(payload))
            {
                var token            = JToken.ReadFrom(reader);
                var handshakeJObject = JsonUtils.GetObject(token);
                var protocol         = JsonUtils.GetRequiredProperty <string>(handshakeJObject, ProtocolPropertyName);
                requestMessage = new HandshakeRequestMessage(protocol);
            }

            return(true);
        }
예제 #10
0
        public static bool TryParseMessage(ReadOnlySpan <byte> input, out NegotiationMessage negotiationMessage)
        {
            if (!TextMessageParser.TryParseMessage(ref input, out var payload))
            {
                throw new InvalidDataException("Unable to parse payload as a negotiation message.");
            }

            using (var memoryStream = new MemoryStream(payload.ToArray()))
            {
                using (var reader = new JsonTextReader(new StreamReader(memoryStream)))
                {
                    var token = JToken.ReadFrom(reader);
                    if (token == null || token.Type != JTokenType.Object)
                    {
                        throw new InvalidDataException($"Unexpected JSON Token Type '{token?.Type}'. Expected a JSON Object.");
                    }

                    var negotiationJObject = (JObject)token;
                    var protocol           = JsonUtils.GetRequiredProperty <string>(negotiationJObject, ProtocolPropertyName);
                    negotiationMessage = new NegotiationMessage(protocol);
                }
            }
            return(true);
        }
예제 #11
0
        private CancelInvocationMessage BindCancelInvocationMessage(JObject json)
        {
            var invocationId = JsonUtils.GetRequiredProperty <string>(json, InvocationIdPropertyName, JTokenType.String);

            return(new CancelInvocationMessage(invocationId));
        }