/// <summary> /// Process a string request which contains the json data. /// </summary> /// <param name="serviceName">The name of the service.</param> /// <param name="requestString">The request string</param> /// <param name="cancellationToken">The cancellation token which can cancel this method.</param> /// <returns>The response string.</returns> public async Task <string> ProcessAsync(string serviceName, string requestString, CancellationToken cancellationToken) { if (_router == null) { throw new NullReferenceException("The router is null"); } if (Logger.DebugMode) { Logger.WriteDebug($"Receive request data:{requestString}"); } using var utf8StringData = Utf8StringData.Get(requestString); var requestStream = utf8StringData.Stream; 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); var responseString = Encoding.UTF8.GetString(responseData); if (Logger.DebugMode) { Logger.WriteDebug($"Response data sent:{responseString}"); } return(responseString); }
/// <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> /// 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."); } }