예제 #1
0
        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);
        }
예제 #2
0
        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);
                    }
                }
            }
        }
예제 #3
0
        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);
        }
예제 #6
0
        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);
        }
예제 #7
0
        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();
 }
예제 #10
0
        /// <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);
                }
            }
        }
예제 #12
0
        /// <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;
            }
        }
예제 #13
0
        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);
            }
        }
예제 #14
0
        /// <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));
        }