private Task <Response> Create(Request request) { bool added = _queues.TryAdd(request.Path, new AsyncQueue <JObject>()); return(added ? Task.FromResult(ResponseFactory.SuccessResponse()) : Task.FromResult(ResponseFactory.InvalidRequestResponse("The given path already exists."))); }
public static async Task HandleResponse(TcpClient client, int clientId) { using (client) { var stream = client.GetStream(); using (stream) { while (true) { Response response; bool status = false; try { //serialize received request var request = await ReadRequest(stream) .WithWaitCancellation(CancellationTokenSource.Token); //log the received request to the console PrintRequest(request, clientId); //send the serialized request to the server response = await _server.ResolveRequest(request); status = response.Status != 200; } catch (OperationCanceledException) { response = status ? ResponseFactory.SuccessResponse("Server shutdown successful.") : ResponseFactory.ServiceUnavailableResponse(); } catch (Exception e) { //if an error occurred in the read process, get an error response to give to the client response = ResponseFactory.ServerErrorResponse(e.Message); } //deserialize and send the response to the client await WriteResponse(stream, response); //if the server is in shutdown terminate this client if (!CancellationTokenSource.IsCancellationRequested) { continue; } stream.Close(); return; } } } }
public async Task <Response> Shutdown(Request request) { if (_serverState == ServerState.Online) { lock (_shutdownMonitor) { if (_serverState == ServerState.Online) { _serverState = ServerState.Offline; } } } int timeout; try { bool timeoutIsNumber = int.TryParse(request.Headers["timeout"], out timeout); if (!timeoutIsNumber) { return(ResponseFactory.InvalidRequestResponse("Invalid timeout format.")); } if (timeout <= 0) { return(ResponseFactory.TimeoutResponse()); } } catch (Exception) { return(ResponseFactory.InvalidRequestResponse("Invalid timeout format.")); } _cancellationTokenSource.Cancel(); Response response; try { await Task.Delay(timeout, _shutdownCompletionSource.Token); response = ResponseFactory.TimeoutResponse("The server is shutting down, waiting time expired."); } catch (OperationCanceledException) { response = ResponseFactory.SuccessResponse("Server shutdown successful."); } return(response); }
private Task <Response> Send(Request request) { bool pathExists = _queues.TryGetValue(request.Path, out var queue); Response response; if (!pathExists) { response = ResponseFactory.QueueDoesNotExistResponse(); } else { queue.Enqueue(request.Payload); response = ResponseFactory.SuccessResponse("Message sent with success."); } return(Task.FromResult(response)); }
private async Task <Response> Receive(Request request) { bool pathExists = _queues.TryGetValue(request.Path, out var queue); if (!pathExists) { return(ResponseFactory.InvalidRequestResponse("The given path does not exist.")); } int timeout; try { bool timeoutIsNumber = int.TryParse(request.Headers["timeout"], out timeout); if (!timeoutIsNumber) { return(ResponseFactory.InvalidRequestResponse("Invalid timeout format.")); } if (timeout <= 0) { return(ResponseFactory.TimeoutResponse()); } } catch (Exception) { return(ResponseFactory.InvalidRequestResponse("Invalid timeout format.")); } JObject payload; try { payload = await queue.Dequeue(TimeSpan.FromMilliseconds(timeout), _cancellationTokenSource); } catch (TimeoutException) { return(ResponseFactory.TimeoutResponse()); } return(ResponseFactory.SuccessResponse(payload)); }
private static async Task Main() { _server = new Server(CancellationTokenSource); var listener = new TcpListener(IPAddress.Loopback, Port); listener.Start(); Console.WriteLine($"Server started on port: {Port}."); var requestTasks = new HashSet <Task>(); while (!CancellationTokenSource.IsCancellationRequested) { try { //With wait cancellation allows to cancel the acceptTcpClientAsync, if the server is currently //waiting for more connections and someone already shut it down var client = await listener .AcceptTcpClientAsync() .WithWaitCancellation(CancellationTokenSource.Token); //used to let the client know that he is now connected //server "handshake" await WriteResponse(client.GetStream(), ResponseFactory.SuccessResponse("Connection established with success.")); Console.WriteLine($"connection accepted with id: {_connectionIdCounter++}.\n"); //add the client to a task container "requestTasks" that will be awaited on server shutdown requestTasks.Add(HandleResponse(client, _connectionIdCounter)); //if the server limit was reached stop receiving more requests until one of the current ones finishes if (requestTasks.Count == MaximumConcurrentClients) { requestTasks.Remove(await Task.WhenAny(requestTasks)); } } catch (OperationCanceledException) { //on cancellation a shutdown is occurring, no need to handle the exception } catch (Exception e) { Console.WriteLine($"Unknown error: {e.Message}"); } } //wait for all tasks to be completed except the one that initiated the shutdown while (requestTasks.Count > 1) { requestTasks.Remove(await Task.WhenAny(requestTasks)); } //terminates the timeout on server shutdown _server.NotifyServerShutdownIsComplete(); //Wait for the last task to complete await Task.WhenAny(requestTasks); listener.Stop(); Console.Write("Server shutdown successful.\n"); }