示例#1
0
        public async Task <long> InvokeClientMethodAsync(string socketId, string methodName, object[] arguments)
        {
            object methodParams = null;

            if (arguments.Length == 1)
            {
                methodParams = arguments[0];
            }
            else
            {
                methodParams = arguments;
            }
            // create the method invocation descriptor.
            WebSocketConnection  socket = WebSocketConnectionManager.GetSocketById(socketId);
            InvocationDescriptor invocationDescriptor = new InvocationDescriptor {
                MethodName = methodName, Params = methodParams
            };

            if (socket == null)
            {
                return(-1);
            }

            invocationDescriptor.Id = socket.NextCmdId();
            var message = new Message()
            {
                MessageType = MessageType.MethodInvocation,
                Data        = JsonConvert.SerializeObject(invocationDescriptor)
            };

            await SendMessageAsync(socketId, message).ConfigureAwait(false);

            return(invocationDescriptor.Id);
        }
示例#2
0
 public bool Matches(InvocationDescriptor invocationDescriptor)
 {
     return(smartParameters.Count == invocationDescriptor.Arguments.Length &&
            smartParameters.Zip(invocationDescriptor.Arguments,
                                (smartParameter, argument) => smartParameter.Matches(argument))
            .All(x => x));
 }
示例#3
0
 public void ExpectUnverifiedInvocation(InvocationDescriptor invocationDescriptor)
 {
     expectedInvocationDescriptors.AddOrUpdate(
         invocationDescriptor,
         add => new AnyCounter(),
         (update, existing) => existing);
 }
示例#4
0
        public async Task SendAllNotifyAsync(string methodName, object result)
        {
            // create the method invocation descriptor.
            InvocationDescriptor invocationDescriptor = new InvocationDescriptor {
                Id = 0, MethodName = methodName, Params = result
            };

            var message = new Message()
            {
                MessageType = MessageType.MethodInvocation,
                Data        = JsonConvert.SerializeObject(invocationDescriptor)
            };

            foreach (var pair in WebSocketConnectionManager.GetAll())
            {
                try
                {
                    if (pair.Value.WebSocket.State == WebSocketState.Open)
                    {
                        await SendMessageAsync(pair.Value, message).ConfigureAwait(false);
                    }
                }
                catch (WebSocketException e)
                {
                    if (e.WebSocketErrorCode == WebSocketError.ConnectionClosedPrematurely)
                    {
                        await OnDisconnected(pair.Value);
                    }
                }
            }
        }
示例#5
0
 public void HandleUnverifiedInvocation(InvocationDescriptor invocationDescriptor)
 {
     unverifiedInvocationDescriptors.AddOrUpdate(
         invocationDescriptor,
         add => new TimesCounter(1),
         (update, existing) => new TimesCounter(existing.Remaining + 1));
 }
示例#6
0
 /// <summary>
 /// Send a method invoke request to the server.
 /// </summary>
 /// <param name="invocationDescriptor">Example usage: set the MethodName to SendMessage and set the arguments to the connectionID with a text message</param>
 /// <returns>An awaitable task.</returns>
 public async Task SendAsync(InvocationDescriptor invocationDescriptor)
 {
     // send the method invocation to the server.
     var bytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new Message {
         MessageType = MessageType.MethodInvocation, Data = JsonConvert.SerializeObject(invocationDescriptor)
     }));
     await _clientWebSocket.SendAsync(new ArraySegment <byte>(bytes), WebSocketMessageType.Text, true, CancellationToken.None);
 }
示例#7
0
        private void Invoke(InvocationDescriptor invocationDescriptor)
        {
            var invocationHandler = this._handlers[invocationDescriptor.MethodName];

            if (invocationHandler != null)
            {
                invocationHandler.Handler(invocationDescriptor.Arguments);
            }
        }
 public InvocationFinishedEventDescriptor(
     InvocationDescriptor methodCallDescriptor,
     InvocationResult result,
     long durationMs)
 {
     MethodCallDescriptor = methodCallDescriptor;
     Result     = result;
     DurationMs = durationMs;
 }
        public void IsApplicable_GivenParamslessMethod_ReturnsFalse()
        {
            var invocationDescriptor = new InvocationDescriptor {
                Arguments = new object[] { 2, new[] { "asdf" } },
                Method    = paramslessMethod
            };

            Assert.False(testObj.IsApplicable(invocationDescriptor));
        }
        public void IsApplicable_GivenParamsfulMethodWithNonNullParams_ReturnsTrue()
        {
            var invocationDescriptor = new InvocationDescriptor {
                Arguments = new object[] { 2, new[] { "asdf" } },
                Method    = paramsfulMethod
            };

            Assert.True(testObj.IsApplicable(invocationDescriptor));
        }
示例#11
0
        /// <summary>
        /// Called when an invoke method call has been received. The default implementation calls
        /// actions registered with the <see cref="On(string, Action{object[]})"/> method.
        /// </summary>
        /// <param name="invocationDescriptor">
        /// The invocation descriptor containing the method name and parameters.
        /// </param>
        protected virtual void Invoke(InvocationDescriptor invocationDescriptor)
        {
            var invocationHandler = _handlers[invocationDescriptor.MethodName];

            if (invocationHandler != null)
            {
                invocationHandler.Handler(invocationDescriptor.Arguments);
            }
        }
        public override Task InvokeUserAsync(string userId, string methodName, object[] args)
        {
            var message = new InvocationDescriptor
            {
                Method    = methodName,
                Arguments = args
            };

            return(PublishAsync(typeof(THub).FullName + "." + userId, message));
        }
        public void Forward_FlattensParamsArgument_HappyPathTest()
        {
            var invocationDescriptor = new InvocationDescriptor {
                Arguments = new object[] { 2, new[] { "asdf", "jkl" } },
                Method    = paramsfulMethod
            };

            testObj.Forward(invocationDescriptor);
            Assert.True(new object[] { 2, "asdf", "jkl" }.SequenceEqual(invocationDescriptor.Arguments));
        }
示例#14
0
        private Task HandleMissingReceivedInvocationDescriptor(InvocationDescriptor invocationDescriptor)
        {
            var methodName = invocationDescriptor.MethodName;

            methodName = string.IsNullOrWhiteSpace(methodName) ? "[Invalid Method Name]" : methodName;

            object[] argumentTokenList = invocationDescriptor.Arguments;
            var      argumentList      = argumentTokenList?.Length > 0 ? String.Join(", ", argumentTokenList) : "[No Parameters]";

            return(HandleMissingReceivedInvocationDescriptor(invocationDescriptor.Id, methodName, argumentList));
        }
示例#15
0
 public static Generated.InvocationDescriptor ToProto(this InvocationDescriptor info)
 {
     return(new Generated.InvocationDescriptor
     {
         Source = info.SourceConnection.ToProto(),
         Target = info.TargetConnection.ToProto(),
         MethodId = info.MethodId,
         ServiceId = info.ServiceId,
         ServiceAliasId = info.ServiceAlias ?? string.Empty
     });
 }
示例#16
0
        public async Task <T> InvokeClientMethodAsync <T>(string socketId, string methodName, object[] arguments)
        {
            // create the method invocation descriptor.
            InvocationDescriptor invocationDescriptor = new InvocationDescriptor {
                MethodName = methodName, Arguments = arguments
            };

            // generate a unique identifier for this invocation.
            invocationDescriptor.Identifier = Guid.NewGuid();

            // add ourselves to the waiting list for return values.
            TaskCompletionSource <InvocationResult> task = new TaskCompletionSource <InvocationResult>();

            // after a timeout of 60 seconds we will cancel the task and remove it from the waiting list.
            new CancellationTokenSource(1000 * 60).Token.Register(() => { _waitingRemoteInvocations.Remove(invocationDescriptor.Identifier); task.TrySetCanceled(); });
            _waitingRemoteInvocations.Add(invocationDescriptor.Identifier, task);

            // send the method invocation to the client.
            var message = new Message()
            {
                MessageType = MessageType.MethodInvocation, Data = JsonConvert.SerializeObject(invocationDescriptor, _jsonSerializerSettings)
            };

            await SendMessageAsync(socketId, message).ConfigureAwait(false);

            // wait for the return value elsewhere in the program.
            InvocationResult result = await task.Task;

            // ... we just got an answer.

            // if we have completed successfully:
            if (task.Task.IsCompleted)
            {
                // there was a remote exception so we throw it here.
                if (result.Exception != null)
                {
                    throw new Exception(result.Exception.Message);
                }

                // return the value.

                // support null.
                if (result.Result == null)
                {
                    return(default(T));
                }
                // cast anything to T and hope it works.
                return((T)result.Result);
            }

            // if we reach here we got cancelled or alike so throw a timeout exception.
            throw new TimeoutException(); // todo: insert fancy message here.
        }
        public void Backward_UnflattensParamsArgument_HappyPathTest()
        {
            var invocationDescriptor = new InvocationDescriptor {
                Arguments = new object[] { 5, "asdf", "jkl" },
                Method    = paramsfulMethod
            };

            testObj.Backward(invocationDescriptor);
            Assert.Equal(2, invocationDescriptor.Arguments.Length);
            Assert.Equal(5, invocationDescriptor.Arguments[0]);
            Assert.True(new object[] { "asdf", "jkl" }.SequenceEqual((string[])invocationDescriptor.Arguments[1]));
        }
 private void OnActionFinished(InvocationDescriptor callDescriptor, InvocationResult callResult, long startMs)
 {
     if (callDescriptor == null)
     {
         return;
     }
     _appLifecycleManager.OnInvocationFinished(
         new InvocationFinishedEventDescriptor(
             callDescriptor,
             callResult,
             _stopwatch.ElapsedMilliseconds - startMs));
 }
        public void Forward(InvocationDescriptor invocationDescriptor)
        {
            var arguments       = invocationDescriptor.Arguments;
            var smartParameters = new SmartParameter[arguments.Length];

            for (var i = 0; i < arguments.Length; i++)
            {
                smartParameters[i] = new EqualitySmartParameter(arguments[i]);
            }

            invocationDescriptor.SmartParameters = new SmartParameterCollection(smartParameters);
        }
        public void Forward(InvocationDescriptor invocationDescriptor)
        {
            var arguments              = invocationDescriptor.Arguments;
            var argumentCount          = arguments.Length;
            var preParamsArgumentCount = argumentCount - 1;
            var paramsArray            = (Array)arguments.Last();

            var newArguments = new object[preParamsArgumentCount + paramsArray.Length];

            Array.Copy(arguments, 0, newArguments, 0, preParamsArgumentCount);
            Array.Copy(paramsArray, 0, newArguments, preParamsArgumentCount, paramsArray.Length);
            invocationDescriptor.Arguments = newArguments;
        }
示例#21
0
        public void Forward(InvocationDescriptor invocationDescriptor)
        {
            var parameters = invocationDescriptor.Method.GetParameters();

            for (var i = 0; i < parameters.Length; i++)
            {
                var parameter = parameters[i];
                if (parameter.IsOut)
                {
                    invocationDescriptor.Arguments[i] = parameter.ParameterType.GetDefaultValue();
                }
            }
        }
        private async Task PublishAsync(string channel, InvocationDescriptor message)
        {
            // TODO: What format??
            var invocationAdapter = _registry.GetInvocationAdapter("json");

            // BAD
            using (var ms = new MemoryStream())
            {
                await invocationAdapter.WriteInvocationDescriptorAsync(message, ms);

                await _bus.PublishAsync(channel, ms.ToArray());
            }
        }
示例#23
0
        private void IsolatedAction <T1, T2>(Action <T1, T2> callback, T1 value1, T2 value2)
        {
            var item = new InvocationDescriptor()
            {
                Delegate            = callback,
                Arguments           = new object[] { value1, value2 },
                ReturnValue         = null,
                InvocationCompleted = false
            };

            s_Queue.Enqueue(item);

            SpinWait.SpinUntil(() => item.InvocationCompleted);
        }
        public bool IsApplicable(InvocationDescriptor invocationDescriptor)
        {
            Type paramsType;

            if (!invocationDescriptor.Method.TryGetParamsType(out paramsType))
            {
                return(false);
            }
            if (invocationDescriptor.Arguments.Last() == null)
            {
                return(false);
            }
            return(true);
        }
示例#25
0
        private TResult IsolatedFunc <TResult, T1, T2>(Func <T1, T2, TResult> callback, T1 value1, T2 value2)
        {
            var item = new InvocationDescriptor()
            {
                Delegate            = callback,
                Arguments           = new object[] { value1, value2 },
                ReturnValue         = null,
                InvocationCompleted = false
            };

            s_Queue.Enqueue(item);

            SpinWait.SpinUntil(() => item.InvocationCompleted);
            return((TResult)item.ReturnValue);
        }
示例#26
0
        /// <summary>
        /// Send a method invoke request to the server and waits for a reply.
        /// </summary>
        /// <param name="invocationDescriptor">Example usage: set the MethodName to SendMessage and set the arguments to the connectionID with a text message</param>
        /// <returns>An awaitable task with the return value on success.</returns>
        public async Task <T> SendAsync <T>(InvocationDescriptor invocationDescriptor)
        {
            // generate a unique identifier for this invocation.
            invocationDescriptor.Identifier = Guid.NewGuid();

            // add ourselves to the waiting list for return values.
            TaskCompletionSource <InvocationResult> task = new TaskCompletionSource <InvocationResult>();

            // after a timeout of 60 seconds we will cancel the task and remove it from the waiting list.
            new CancellationTokenSource(1000 * 60).Token.Register(() => { _waitingRemoteInvocations.Remove(invocationDescriptor.Identifier); task.TrySetCanceled(); });
            _waitingRemoteInvocations.Add(invocationDescriptor.Identifier, task);

            // send the method invocation to the server.
            var bytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new Message {
                MessageType = MessageType.MethodInvocation, Data = JsonConvert.SerializeObject(invocationDescriptor, _jsonSerializerSettings)
            }, _jsonSerializerSettings));
            await _clientWebSocket.SendAsync(new ArraySegment <byte>(bytes), WebSocketMessageType.Text, true, CancellationToken.None);

            // wait for the return value elsewhere in the program.
            InvocationResult result = await task.Task;

            // ... we just got an answer.

            // if we have completed successfully:
            if (task.Task.IsCompleted)
            {
                // there was a remote exception so we throw it here.
                if (result.Exception != null)
                {
                    throw new Exception(result.Exception.Message);
                }

                // return the value.

                // support null.
                if (result.Result == null)
                {
                    return(default(T));
                }
                // cast anything to T and hope it works.
                return((T)result.Result);
            }

            // if we reach here we got cancelled or alike so throw a timeout exception.
            throw new TimeoutException(); // todo: insert fancy message here.
        }
        public void Backward(InvocationDescriptor invocationDescriptor)
        {
            var parameterCount          = invocationDescriptor.Method.GetParameters().Length;
            var preParamsArgumentsCount = parameterCount - 1;
            var arguments = invocationDescriptor.Arguments;

            Type paramsType = invocationDescriptor.Method.GetParamsType();
            var  newParams  = Array.CreateInstance(paramsType.GetElementType(), arguments.Length - parameterCount + 1);

            Array.Copy(arguments, preParamsArgumentsCount, newParams, 0, newParams.Length);

            var newArguments = new object[parameterCount];

            Array.Copy(arguments, 0, newArguments, 0, preParamsArgumentsCount);
            newArguments[parameterCount - 1] = newParams;

            invocationDescriptor.Arguments = newArguments;
        }
示例#28
0
        public void Backward(InvocationDescriptor invocationDescriptor)
        {
            var parameters = invocationDescriptor.Method.GetParameters();

            for (var i = 0; i < parameters.Length; i++)
            {
                var parameter = parameters[i];
                if (parameter.IsOut)
                {
                    var outValue = invocationDescriptor.Arguments[i];
                    var realType = parameter.ParameterType.GetElementType();
                    if (outValue == null && realType.IsValueType)
                    {
                        outValue = realType.GetDefaultValue();
                    }
                    invocationDescriptor.Invocation.Arguments[i] = outValue;
                }
            }
        }
示例#29
0
        private Task InvokeOn(InvocationDescriptor descriptor)
        {
            if (!_handlers.ContainsKey(descriptor.MethodName))
            {
                return(HandleMissingReceivedInvocationDescriptor(descriptor));
            }

            var invocationHandler = _handlers[descriptor.MethodName];

            // This task is unawaited to allow in-bound packet payloads to be
            // handled in parallel. Should these tasks be waited each payload
            // is handled synchronously. This has the added disadvantage of
            // deadlocking a caller who does:
            // 1. Invoke(...) -> Pending Response (Blocks caller context)
            // 2.   <- On(...) callback fired (Blocks receive context)
            //      {
            // 3.     -> Invoke(...) -> Pending Response (Blocks receive context)
            // 4. Deadlock
            // In this scenario, the first Invoke(...) awaits on a
            // TaskCompletionSource who's SetResult is called when an
            // InvocationResultDescriptor comes in through the socket recieve
            // loop. When a message for an On callback, not the result descriptor,
            // comes in, the callback is fired allowing a caller to issue another
            // Invoke(...) call which again blocks on another
            // TaskCompletionSource, disallowing the On callback from concluding
            // which prevents the socket receive loop from moving to the
            // next message.

            /*! Unawaited Task !*/
            Task.Run(() => {
                try
                {
                    invocationHandler.Handler(descriptor.Arguments);
                }
                catch (Exception e)
                {
                    _logger?.LogError(new EventId(), e, $"Exception thrown during registered callback for {descriptor.MethodName}");
                    Error?.Invoke(new Exception($"Exception thrown during registered callback for {descriptor.MethodName}", e));
                }
            }).ConfigureAwait(false);

            return(Task.CompletedTask);
        }
        public async Task WriteInvocationDescriptorAsync(InvocationDescriptor invocationDescriptor, Stream stream)
        {
            var outputStream = new CodedOutputStream(stream, leaveOpen: true);

            outputStream.WriteMessage(new RpcMessageKind()
            {
                MessageKind = RpcMessageKind.Types.Kind.Invocation
            });

            var invocationHeader = new RpcInvocationHeader()
            {
                Id      = 0,
                Name    = invocationDescriptor.Method,
                NumArgs = invocationDescriptor.Arguments.Length
            };

            outputStream.WriteMessage(invocationHeader);

            foreach (var arg in invocationDescriptor.Arguments)
            {
                if (arg.GetType() == typeof(int))
                {
                    outputStream.WriteMessage(new PrimitiveValue {
                        Int32Value = (int)arg
                    });
                }
                else if (arg.GetType() == typeof(string))
                {
                    outputStream.WriteMessage(new PrimitiveValue {
                        StringValue = (string)arg
                    });
                }
                else
                {
                    var serializer = _serviceProvider.GetRequiredService <ProtobufSerializer>();
                    var message    = serializer.GetMessage(arg);
                    outputStream.WriteMessage(message);
                }
            }

            outputStream.Flush();
            await stream.FlushAsync();
        }