Example #1
0
        /// <summary>
        /// Process a byte[] request which contains the json data.
        /// </summary>
        /// <param name="serviceName">The name of the service.</param>
        /// <param name="requestData">The request data</param>
        /// <param name="cancellationToken">The cancellation token which can cancel this method.</param>
        /// <returns>The response data.</returns>
        public async Task <byte[]> ProcessAsync(string serviceName, byte[] requestData, CancellationToken cancellationToken)
        {
            if (_router == null)
            {
                throw new NullReferenceException("The router is null");
            }
            if (Logger.DebugMode)
            {
                var requestString = Encoding.UTF8.GetString(requestData);
                Logger.WriteDebug($"Receive request data:{requestString}");
            }

            await using var requestStream = new MemoryStream(requestData);
            var requests = await JsonRpcCodec.DecodeRequestsAsync(requestStream, cancellationToken).ConfigureAwait(false);

            var responses = await _router.DispatchRequestsAsync(serviceName, requests, cancellationToken).ConfigureAwait(false);

            var responseData = await JsonRpcCodec.EncodeResponsesAsync(responses, cancellationToken).ConfigureAwait(false);

            if (Logger.DebugMode)
            {
                var responseString = Encoding.UTF8.GetString(responseData);
                Logger.WriteDebug($"Response data sent:{responseString}");
            }
            return(responseData);
        }
Example #2
0
        /// <summary>
        /// Dispatch request to specified service.
        /// </summary>
        /// <param name="context">The HttpListenerContext</param>
        /// <param name="router">The router to handle the rpc request</param>
        /// <param name="serviceName">The name of the service</param>
        /// <param name="cancellationToken">The cancellation token which can cancel this method</param>
        /// <returns>Void</returns>
        private async Task DispatchAsync(IJsonRpcHttpContext context, IJsonRpcRouter router, string serviceName, CancellationToken cancellationToken = default)
        {
            var dataLength  = (int)context.GetRequestContentLength();
            var requestData = ArrayPool <byte> .Shared.Rent(dataLength);

            JsonRpcRequest[] requests;
            try
            {
                var inputStream = context.GetInputStream();
                await ReadRequestDataAsync(inputStream, requestData, dataLength, cancellationToken).ConfigureAwait(false);

                if (Logger.DebugMode)
                {
                    var requestString = Encoding.UTF8.GetString(requestData);
                    Logger.WriteDebug($"Receive request data:{requestString}");
                }

                requests = await JsonRpcCodec.DecodeRequestsAsync(requestData, cancellationToken, dataLength).ConfigureAwait(false);
            }
            finally
            {
                ArrayPool <byte> .Shared.Return(requestData);
            }

            var responses = await router.DispatchRequestsAsync(serviceName, requests, cancellationToken).ConfigureAwait(false);

            await WriteRpcResponsesAsync(context, responses, cancellationToken).ConfigureAwait(false);
        }
        /// <summary>
        /// Dispatch request to different services.
        /// </summary>
        /// <param name="service">The service to handle the context</param>
        /// <param name="context">The http context</param>
        /// <returns>Void</returns>
        private async Task DispatchCall(JsonRpcService service, WebSocketContext context)
        {
            var webSocket = context.WebSocket;

            while (true)
            {
                if (webSocket.CloseStatus != null)
                {
                    throw new WebSocketException((int)webSocket.CloseStatus, webSocket.CloseStatusDescription);
                }

                JsonRpcRequest[] requests;
                await using (var requestStream = await GetRequestStreamAsync(webSocket).ConfigureAwait(false))
                {
                    var requestData = ArrayPool <byte> .Shared.Rent((int)requestStream.Length);

                    try
                    {
                        await ReadRequestDataAsync(requestStream, requestData).ConfigureAwait(false);

                        if (Logger.DebugMode)
                        {
                            var requestString = Encoding.UTF8.GetString(requestData);
                            Logger.WriteDebug($"Receive request data:{requestString}");
                        }
                        requests = await JsonRpcCodec.DecodeRequestsAsync(requestData).ConfigureAwait(false);
                    }
                    finally
                    {
                        ArrayPool <byte> .Shared.Return(requestData);
                    }
                }

                if (requests.Length == 1)
                {
                    var request  = requests[0];
                    var response = await GetResponseAsync(service, request).ConfigureAwait(false);
                    await WriteResponse(context, response).ConfigureAwait(false);
                }
                else
                {
                    //batch call.
                    var responseList = new List <JsonRpcResponse>();
                    foreach (var request in requests)
                    {
                        var response = await GetResponseAsync(service, request).ConfigureAwait(false);

                        if (response != null)
                        {
                            responseList.Add(response);
                        }
                    }

                    if (responseList.Count > 0)
                    {
                        await WriteResponses(context, responseList.ToArray()).ConfigureAwait(false);
                    }
                }
            }
        }
Example #4
0
        /// <summary>
        /// Dispatch request to different services.
        /// </summary>
        /// <param name="service">The service to handle the context</param>
        /// <param name="context">The http context</param>
        /// <returns>Void</returns>
        private async Task DispatchCall(JsonRpcService service, HttpListenerContext context)
        {
            var httpMethod = context.Request.HttpMethod.ToLower();

            if (httpMethod != "post")
            {
                throw new ServerErrorException("Invalid http-method.", $"Invalid http-method:{httpMethod}");
            }

            Logger.WriteVerbose($"Handle request [{httpMethod}]: {context.Request.Url}");


            var requestData = ArrayPool <byte> .Shared.Rent((int)context.Request.ContentLength64);

            JsonRpcRequest[] requests;
            try
            {
                await ReadRequestDataAsync(context.Request.InputStream, requestData).ConfigureAwait(false);

                context.Request.InputStream.Close();
                if (Logger.DebugMode)
                {
                    var requestString = Encoding.UTF8.GetString(requestData);
                    Logger.WriteDebug($"Receive request data:{requestString}");
                }
                requests = await JsonRpcCodec.DecodeRequestsAsync(requestData).ConfigureAwait(false);
            }
            finally
            {
                ArrayPool <byte> .Shared.Return(requestData);
            }

            if (requests.Length == 1)
            {
                var request  = requests[0];
                var response = await GetResponseAsync(service, request).ConfigureAwait(false);
                await WriteResponse(context, response).ConfigureAwait(false);
            }
            else
            {
                //batch call.
                var responseList = new List <JsonRpcResponse>();
                foreach (var request in requests)
                {
                    var response = await GetResponseAsync(service, request).ConfigureAwait(false);

                    if (response != null)
                    {
                        responseList.Add(response);
                    }
                }

                if (responseList.Count > 0)
                {
                    await WriteResponses(context, responseList.ToArray()).ConfigureAwait(false);
                }
                else
                {
                    await WriteResultAsync(context).ConfigureAwait(false);
                }
            }
        }
Example #5
0
        /// <summary>
        /// Handle data from websocket and return result data to remote client.
        /// </summary>
        /// <param name="requestPath">The request path from the http request.</param>
        /// <param name="router">The router to handle the request data.</param>
        /// <param name="socket">The connected websocket.</param>
        /// <param name="cancellationToken">The cancellation token which can cancel this method</param>
        protected async Task HandleWebSocketAsync(string requestPath, IJsonRpcRouter router, WebSocket socket, CancellationToken cancellationToken = default)
        {
            try
            {
                var serviceName = GetRpcServiceName(requestPath);
                if (string.IsNullOrEmpty(serviceName) || !router.ServiceExists(serviceName))
                {
                    Logger.WriteWarning($"Service {serviceName} does not exist.");
                    throw new InvalidOperationException($"Service [{serviceName}] does not exist.");
                }

                byte[]       receiveBuffer = null;
                MemoryStream inputStream   = null;
                // While the WebSocket connection remains open run a simple loop that receives data and sends it back.
                while (socket.State == WebSocketState.Open)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    receiveBuffer ??= ArrayPool <byte> .Shared.Rent(1024);

                    inputStream ??= new MemoryStream();
                    var receiveResult = await socket.ReceiveAsync(receiveBuffer, cancellationToken).ConfigureAwait(false);

                    if (receiveResult.MessageType == WebSocketMessageType.Close)
                    {
                        await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "", cancellationToken).ConfigureAwait(false);
                    }
                    else if (receiveResult.MessageType == WebSocketMessageType.Text)
                    {
                        await socket.CloseAsync(WebSocketCloseStatus.InvalidMessageType, "Cannot accept text frame", cancellationToken).ConfigureAwait(false);
                    }
                    else
                    {
                        await inputStream.WriteAsync(receiveBuffer, 0, receiveResult.Count, cancellationToken).ConfigureAwait(false);

                        //handle stream
                        if (receiveResult.EndOfMessage)
                        {
                            //Release resources.
                            var requestData = inputStream.ToArray();
                            await inputStream.DisposeAsync().ConfigureAwait(false);

                            inputStream = null;
                            ArrayPool <byte> .Shared.Return(receiveBuffer);

                            receiveBuffer = null;

                            if (Logger.DebugMode)
                            {
                                var requestString = Encoding.UTF8.GetString(requestData);
                                Logger.WriteDebug($"Receive request data: {requestString}");
                            }

                            var requests = await JsonRpcCodec.DecodeRequestsAsync(requestData, cancellationToken).ConfigureAwait(false);

                            var responses = await router.DispatchRequestsAsync(serviceName, requests, cancellationToken).ConfigureAwait(false);

                            var responseData = await JsonRpcCodec.EncodeResponsesAsync(responses, cancellationToken).ConfigureAwait(false);

                            await socket.SendAsync(responseData, WebSocketMessageType.Binary, true, cancellationToken).ConfigureAwait(false);

                            if (Logger.DebugMode)
                            {
                                var resultString = Encoding.UTF8.GetString(responseData);
                                Logger.WriteDebug($"Response data sent:{resultString}");
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.WriteError($"Handle request {requestPath} error: {ex.Message}");
            }
            finally
            {
                socket.Dispose();
                Logger.WriteVerbose("Remote websocket closed.");
            }
        }