private async Task <System.Text.Json.JsonElement> ReceiveAsync(HttpResponseMessage response) { var body = await response.Content.ReadAsStringAsync(); if (response.StatusCode == System.Net.HttpStatusCode.OK) { var json = System.Text.Json.JsonDocument.Parse(body); var result = json.RootElement.GetProperty("result"); var status = result.GetProperty("status").GetString(); if (status == "success") { return(result); } else if (status == "error") { var error = result.GetProperty("error").GetString(); var request = result.GetProperty("request"); RippleException exception; if (result.TryGetProperty("error_exception", out var element)) { exception = new RippleSubmitRequestException(error, element.GetString(), request); } else { exception = new RippleRequestException(error, request); } throw exception; } else { throw new NotSupportedException(string.Format("{0} not a supported status", status)); } } else { throw new RippleException(body); } }
private async Task ReceiveLoop() { var response = new System.Buffers.ArrayBufferWriter <byte>(); while (!cancellationTokenSource.IsCancellationRequested) { var buffer = response.GetMemory(); try { var result = await socket.ReceiveAsync(buffer, cancellationTokenSource.Token); response.Advance(result.Count); if (result.EndOfMessage) { var json = System.Text.Json.JsonDocument.Parse(response.WrittenMemory); var type = json.RootElement.GetProperty("type").GetString(); if (type == "response") { var id = json.RootElement.GetProperty("id").GetUInt32(); var status = json.RootElement.GetProperty("status").GetString(); if (status == "success") { lock (responses) { if (responses.TryGetValue(id, out var task)) { responses.Remove(id); task.SetResult(json.RootElement.GetProperty("result").Clone()); } } } else if (status == "error") { var error = json.RootElement.GetProperty("error").GetString(); var request = json.RootElement.GetProperty("request").Clone(); RippleException exception; if (json.RootElement.TryGetProperty("error_exception", out var element)) { exception = new RippleSubmitRequestException(error, element.GetString(), request); } else { exception = new RippleRequestException(error, request); } lock (responses) { if (responses.TryGetValue(id, out var task)) { responses.Remove(id); task.SetException(exception); } } } else { lock (responses) { if (responses.TryGetValue(id, out var task)) { responses.Remove(id); task.SetException(new NotSupportedException(string.Format("{0} not a supported status", status))); } } } } else if (type == "path_find") { var id = json.RootElement.GetProperty("id").GetUInt32(); var pathFindResponse = new PathFindResponse(json.RootElement); try { OnPathFind?.Invoke(this, id, pathFindResponse); } catch (Exception exc) { // TODO: We don't want user exceptions from the OnPathFind event to tear down this thread but we should bubble them up somehow. } } response.Clear(); } } catch (TaskCanceledException taskCanceledException) { if (taskCanceledException.CancellationToken == cancellationTokenSource.Token) { // We canceled the receive, while loop will now terminate and task completes successfully } else { // Something else unexpected was cancelled, rethrow throw; } } } socket.Dispose(); }