public async Task 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. InvocationDescriptor invocationDescriptor = new InvocationDescriptor { MethodName = methodName, Params = methodParams }; WebSocketConnection socket = WebSocketConnectionManager.GetSocketById(socketId); if (socket == null) { return; } invocationDescriptor.Id = socket.NextCmdId(); var message = new Message() { MessageType = MessageType.MethodInvocation, Data = JsonConvert.SerializeObject(invocationDescriptor) }; await SendMessageAsync(socketId, message).ConfigureAwait(false); }
public async Task SendAllNotifyAsync(string methodName, object result) { // create the method invocation descriptor. InvocationDescriptor invocationDescriptor = new InvocationDescriptor { 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); } } } }
private void Invoke(InvocationDescriptor invocationDescriptor) { var invocationHandler = _handlers[invocationDescriptor.MethodName]; if (invocationHandler != null) { invocationHandler.Handler(invocationDescriptor.Arguments); } }
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 async Task ReceiveAsync(WebSocket socket, WebSocketReceiveResult result, string serializedInvocationDescriptor) { InvocationDescriptor invocationDescriptor = null; try { invocationDescriptor = JsonConvert.DeserializeObject <InvocationDescriptor>(serializedInvocationDescriptor); if (invocationDescriptor == null) { return; } } catch { } // ignore invalid data sent to the server. await OnInvokeMethodReceived(socket, invocationDescriptor); }
public async Task SendClientNotifyAsync(string socketId, string methodName, object result) { // create the method invocation descriptor. InvocationDescriptor invocationDescriptor = new InvocationDescriptor { MethodName = methodName, Params = result }; WebSocketConnection socket = WebSocketConnectionManager.GetSocketById(socketId); if (socket == null) { return; } var message = new Message() { MessageType = MessageType.MethodInvocation, Data = JsonConvert.SerializeObject(invocationDescriptor) }; await SendMessageAsync(socketId, message).ConfigureAwait(false); }
public async Task SendGroupNotifyAsync(string groupID, string methodName, object result) { // create the method invocation descriptor. InvocationDescriptor invocationDescriptor = new InvocationDescriptor { MethodName = methodName, Params = result }; var message = new Message() { MessageType = MessageType.MethodInvocation, Data = JsonConvert.SerializeObject(invocationDescriptor) }; var sockets = WebSocketConnectionManager.GetAllFromGroup(groupID); if (sockets != null) { foreach (var id in sockets) { await SendMessageAsync(id, message); } } }
/// <summary> /// Called when an invoke method call has been received. The default implementation uses /// reflection to find the method in this <see cref="WebSocketHandler"/>. /// </summary> /// <param name="socket">The web-socket of the client that wants to invoke a method.</param> /// <param name="invocationDescriptor">The invocation descriptor containing the method name and parameters.</param> /// <returns>Awaitable Task.</returns> public virtual async Task OnInvokeMethodReceived(WebSocket socket, InvocationDescriptor invocationDescriptor) { var method = this.GetType().GetMethod(invocationDescriptor.MethodName); if (method == null) { await SendMessageAsync(socket, new Message() { MessageType = MessageType.Text, Data = $"Cannot find method {invocationDescriptor.MethodName}" }).ConfigureAwait(false); return; } try { method.Invoke(this, invocationDescriptor.Arguments); } catch (TargetParameterCountException) { await SendMessageAsync(socket, new Message() { MessageType = MessageType.Text, Data = $"The {invocationDescriptor.MethodName} method does not take {invocationDescriptor.Arguments.Length} parameters!" }).ConfigureAwait(false); } catch (ArgumentException) { await SendMessageAsync(socket, new Message() { MessageType = MessageType.Text, Data = $"The {invocationDescriptor.MethodName} method takes different arguments!" }).ConfigureAwait(false); } }
/// <summary> /// Called when an invoke method call has been received. /// </summary> /// <param name="socket">The web-socket of the client that wants to invoke a method.</param> /// <param name="invocationDescriptor"> /// The invocation descriptor containing the method name and parameters. /// </param> /// <returns>Awaitable Task.</returns> public virtual Task <object> OnInvokeMethodReceivedAsync(WebSocket socket, InvocationDescriptor invocationDescriptor) { throw new NotImplementedException(); }
/// <summary> /// Called when an invoke method call has been received. /// </summary> /// <param name="socket">The web-socket of the client that wants to invoke a method.</param> /// <param name="invocationDescriptor"> /// The invocation descriptor containing the method name and parameters. /// </param> /// <returns>Awaitable Task.</returns> public override async Task <object> OnInvokeMethodReceivedAsync(WebSocket socket, InvocationDescriptor invocationDescriptor) { // there must be a separator in the method name. if (!invocationDescriptor.MethodName.Contains(Separator)) { throw new Exception($"Invalid controller or method name '{invocationDescriptor.MethodName}'."); } // find the controller and the method name. string[] names = invocationDescriptor.MethodName.Split(Separator); string controller = names[0].ToLower(); string command = Prefix + names[1]; // find the desired controller. if (Controllers.TryGetValue(controller, out object self)) { // use reflection to find the method in the desired controller. MethodInfo method = self.GetType().GetMethod(command); // if the method could not be found: if (method == null) { throw new Exception($"Received unknown command '{command}' for controller '{controller}'."); } // optionally insert client as parameter. List <object> args = invocationDescriptor.Arguments.ToList(); if (!NoWebsocketArgument) { args.Insert(0, socket); } // call the method asynchronously. try { return(await Task.Run(() => method.Invoke(self, args.ToArray()))); } catch (TargetInvocationException ex) { throw ex.InnerException; } } else { throw new Exception($"Received command '{command}' for unknown controller '{controller}'."); } }
public async Task ReceiveAsync(WebSocket socket, WebSocketReceiveResult result, Message receivedMessage) { // method invocation request. if (receivedMessage.MessageType == MessageType.MethodInvocation) { // retrieve the method invocation request. InvocationDescriptor invocationDescriptor = null; try { invocationDescriptor = JsonConvert.DeserializeObject <InvocationDescriptor>(receivedMessage.Data, _jsonSerializerSettings); if (invocationDescriptor == null) { return; } } catch { return; } // ignore invalid data sent to the server. // if the unique identifier hasn't been set then the client doesn't want a return value. if (invocationDescriptor.Identifier == Guid.Empty) { // invoke the method only. try { await MethodInvocationStrategy.OnInvokeMethodReceivedAsync(socket, invocationDescriptor); } catch (Exception) { // we consume all exceptions. } } else { // invoke the method and get the result. InvocationResult invokeResult; try { // create an invocation result with the results. invokeResult = new InvocationResult() { Identifier = invocationDescriptor.Identifier, Result = await MethodInvocationStrategy.OnInvokeMethodReceivedAsync(socket, invocationDescriptor), Exception = null }; } // send the exception as the invocation result if there was one. catch (Exception ex) { invokeResult = new InvocationResult() { Identifier = invocationDescriptor.Identifier, Result = null, Exception = new RemoteException(ex) }; } // send a message to the client containing the result. var message = new Message() { MessageType = MessageType.MethodReturnValue, Data = JsonConvert.SerializeObject(invokeResult, _jsonSerializerSettings) }; await SendMessageAsync(socket, message).ConfigureAwait(false); } } // method return value. else if (receivedMessage.MessageType == MessageType.MethodReturnValue) { var invocationResult = JsonConvert.DeserializeObject <InvocationResult>(receivedMessage.Data, _jsonSerializerSettings); // find the completion source in the waiting list. if (_waitingRemoteInvocations.ContainsKey(invocationResult.Identifier)) { // set the result of the completion source so the invoke method continues executing. _waitingRemoteInvocations[invocationResult.Identifier].SetResult(invocationResult); // remove the completion source from the waiting list. _waitingRemoteInvocations.Remove(invocationResult.Identifier); } } }
/// <summary> /// Called when an invoke method call has been received. /// </summary> /// <param name="socket">The web-socket of the client that wants to invoke a method.</param> /// <param name="invocationDescriptor"> /// The invocation descriptor containing the method name and parameters. /// </param> /// <returns>Awaitable Task.</returns> public override async Task <object> OnInvokeMethodReceivedAsync(WebSocket socket, InvocationDescriptor invocationDescriptor) { // create the method name that has to be found. string command = Prefix + invocationDescriptor.MethodName; // use reflection to find the method in the desired controller. MethodInfo method = Controller.GetType().GetMethod(command); // if the method could not be found: if (method == null) { throw new Exception($"Received unknown command '{command}' for controller '{Controller.GetType().Name}'."); } // optionally insert client as parameter. List <object> args = invocationDescriptor.Arguments.ToList(); if (!NoWebsocketArgument) { args.Insert(0, socket); } // call the method asynchronously. try { return(await Task.Run(() => method.Invoke(Controller, args.ToArray()))); } catch (TargetInvocationException ex) { throw ex.InnerException; } }
public async Task OnReceivedTextAsync(WebSocketConnection socket, string serializedMessage) { InvocationDescriptor invocationDescriptor = null; try { invocationDescriptor = JsonConvert.DeserializeObject <InvocationDescriptor>(serializedMessage); //invocationDescriptor = JsonConvert.DeserializeObject<InvocationDescriptor>(serializedMessage, _jsonSerializerSettings); //invocationDescriptor = JsonConvert.DeserializeObject<InvocationDescriptor>(receivedMessage.Data, _jsonSerializerSettings); if (invocationDescriptor == null) { return; } } catch (Exception ex) { return; } // ignore invalid data sent to the server. // method invocation request. if (invocationDescriptor.Params != null) { // retrieve the method invocation request. // if the unique identifier hasn't been set then the client doesn't want a return value. if (invocationDescriptor.Id == 0) { // invoke the method only. try { await MethodInvocationStrategy.OnInvokeMethodReceivedAsync(socket.Id, invocationDescriptor); } catch (Exception) { // we consume all exceptions. } } else { // invoke the method and get the result. InvocationResult invokeResult; try { // create an invocation result with the results. invokeResult = new InvocationResult() { MethodName = invocationDescriptor.MethodName, Id = invocationDescriptor.Id, Result = await MethodInvocationStrategy.OnInvokeMethodReceivedAsync(socket.Id, invocationDescriptor), Exception = null }; } // send the exception as the invocation result if there was one. catch (Exception ex) { invokeResult = new InvocationResult() { MethodName = invocationDescriptor.MethodName, Id = invocationDescriptor.Id, Result = null, Exception = new RemoteException(ex) }; } string json = JsonConvert.SerializeObject(invokeResult); // send a message to the client containing the result. var message = new Message() { MessageType = MessageType.MethodReturnValue, Data = json //Data = JsonConvert.SerializeObject(invokeResult, _jsonSerializerSettings) }; await SendMessageAsync(socket, message).ConfigureAwait(false); } } else { await OnResponseAsync(socket, serializedMessage); } }
/// <summary> /// Called when an invoke method call has been received. /// </summary> /// <param name="socket">The web-socket of the client that wants to invoke a method.</param> /// <param name="invocationDescriptor"> /// The invocation descriptor containing the method name and parameters. /// </param> /// <returns>Awaitable Task.</returns> public override async Task <object> OnInvokeMethodReceivedAsync(WebSocket socket, InvocationDescriptor invocationDescriptor) { if (!_handlers.ContainsKey(invocationDescriptor.MethodName)) { throw new Exception($"Received unknown command '{invocationDescriptor.MethodName}'."); } var invocationHandler = _handlers[invocationDescriptor.MethodName]; if (invocationHandler != null) { return(await Task.Run(() => invocationHandler.Handler(invocationDescriptor.Arguments))); } return(await Task.FromResult <object>(null)); }