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); }
public bool Matches(InvocationDescriptor invocationDescriptor) { return(smartParameters.Count == invocationDescriptor.Arguments.Length && smartParameters.Zip(invocationDescriptor.Arguments, (smartParameter, argument) => smartParameter.Matches(argument)) .All(x => x)); }
public void ExpectUnverifiedInvocation(InvocationDescriptor invocationDescriptor) { expectedInvocationDescriptors.AddOrUpdate( invocationDescriptor, add => new AnyCounter(), (update, existing) => existing); }
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); } } } }
public void HandleUnverifiedInvocation(InvocationDescriptor invocationDescriptor) { unverifiedInvocationDescriptors.AddOrUpdate( invocationDescriptor, add => new TimesCounter(1), (update, existing) => new TimesCounter(existing.Remaining + 1)); }
/// <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); }
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)); }
/// <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)); }
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)); }
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 }); }
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; }
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()); } }
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); }
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); }
/// <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; }
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; } } }
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(); }