/// <summary> /// Clean up can be called by: /// 1. The user. AsyncUnaryCall.Dispose et al will call this on Dispose /// 2. <see cref="ValidateHeaders"/> will call dispose if errors fail validation /// 3. <see cref="FinishResponseAndCleanUp"/> will call dispose /// </summary> private void Cleanup(Status status) { if (!ResponseFinished) { // If the response is not finished then cancel any pending actions: // 1. Call HttpClient.SendAsync // 2. Response Stream.ReadAsync // 3. Client stream // - Getting the Stream from the Request.HttpContent // - Holding the Request.HttpContent.SerializeToStream open // - Writing to the client stream CancelCall(status); } else { _callTcs.TrySetResult(status); ClientStreamWriter?.WriteStreamTcs.TrySetCanceled(); ClientStreamWriter?.CompleteTcs.TrySetCanceled(); ClientStreamReader?.HttpResponseTcs.TrySetCanceled(); } _ctsRegistration?.Dispose(); _deadlineTimer?.Dispose(); HttpResponse?.Dispose(); ClientStreamReader?.Dispose(); ClientStreamWriter?.Dispose(); // To avoid racing with Dispose, skip disposing the call CTS. // This avoid Dispose potentially calling cancel on a disposed CTS. // The call CTS is not exposed externally and all dependent registrations // are cleaned up. }
/// <summary> /// Dispose can be called by: /// 1. The user. AsyncUnaryCall.Dispose et al will call this Dispose /// 2. <see cref="ValidateHeaders"/> will call dispose if errors fail validation /// 3. <see cref="FinishResponse"/> will call dispose /// </summary> public void Dispose() { if (!Disposed) { Disposed = true; if (!ResponseFinished) { // If the response is not finished then cancel any pending actions: // 1. Call HttpClient.SendAsync // 2. Response Stream.ReadAsync // 3. Client stream // - Getting the Stream from the Request.HttpContent // - Holding the Request.HttpContent.SerializeToStream open // - Writing to the client stream _callCts.Cancel(); } _ctsRegistration?.Dispose(); _writerCtsRegistration?.Dispose(); _deadlineTimer?.Dispose(); HttpResponse?.Dispose(); ClientStreamReader?.Dispose(); ClientStreamWriter?.Dispose(); // To avoid racing with Dispose, skip disposing the call CTS // This avoid Dispose potentially calling cancel on a disposed CTS // The call CTS is not exposed externally and all dependent registrations // are cleaned up } }
private void DisposeCore() { if (!Disposed) { // Locking on the call because: // 1. Its not exposed publically // 2. Nothing else locks on call // 3. We want to avoid allocating a private lock object lock (this) { if (!Disposed) { Disposed = true; if (!ResponseFinished) { // If the response is not finished then cancel any pending actions: // 1. Call HttpClient.SendAsync // 2. Response Stream.ReadAsync // 3. Client stream // - Getting the Stream from the Request.HttpContent // - Holding the Request.HttpContent.SerializeToStream open // - Writing to the client stream CancelCall(); } else { _writeStreamTcs?.TrySetCanceled(); _writeCompleteTcs?.TrySetCanceled(); } // If response has successfully finished then the status will come from the trailers // If it didn't finish then complete with a Cancelled status _callTcs.TrySetResult(StatusCode.Cancelled); _ctsRegistration?.Dispose(); _deadlineTimer?.Dispose(); HttpResponse?.Dispose(); ClientStreamReader?.Dispose(); ClientStreamWriter?.Dispose(); // To avoid racing with Dispose, skip disposing the call CTS // This avoid Dispose potentially calling cancel on a disposed CTS // The call CTS is not exposed externally and all dependent registrations // are cleaned up } } } }
public string Decode() { int bytesRead; int totalBytesRead = 0; MemoryStream mw = new MemoryStream(); var buffer = ClientStreamReader.ReadBytes(RequestLength); while (totalBytesRead < RequestLength && (bytesRead = buffer.Length) > 0) { totalBytesRead += bytesRead; mw.Write(buffer, 0, bytesRead); } mw.Close(); return(Encoding.Default.GetString(mw.ToArray())); }
/// <summary> /// Clean up can be called by: /// 1. The user. AsyncUnaryCall.Dispose et al will call this on Dispose /// 2. <see cref="GrpcCall.ValidateHeaders"/> will call dispose if errors fail validation /// 3. <see cref="FinishResponseAndCleanUp"/> will call dispose /// </summary> private void Cleanup(Status status) { if (!ResponseFinished) { // If the response is not finished then cancel any pending actions: // 1. Call HttpClient.SendAsync // 2. Response Stream.ReadAsync // 3. Client stream // - Getting the Stream from the Request.HttpContent // - Holding the Request.HttpContent.SerializeToStream open // - Writing to the client stream CancelCall(status); } else { _callTcs.TrySetResult(status); ClientStreamWriter?.WriteStreamTcs.TrySetCanceled(); ClientStreamWriter?.CompleteTcs.TrySetCanceled(); ClientStreamReader?.HttpResponseTcs.TrySetCanceled(); } Channel.FinishActiveCall(this); _ctsRegistration?.Dispose(); if (_deadlineTimer != null) { lock (this) { // Timer callback can call Timer.Change so dispose deadline timer in a lock // and set to null to indicate to the callback that it has been disposed. _deadlineTimer?.Dispose(); _deadlineTimer = null; } } HttpResponse?.Dispose(); ClientStreamReader?.Dispose(); ClientStreamWriter?.Dispose(); // To avoid racing with Dispose, skip disposing the call CTS. // This avoid Dispose potentially calling cancel on a disposed CTS. // The call CTS is not exposed externally and all dependent registrations // are cleaned up. }
public string GetRequestHtmlBody() { if (RequestHtmlBody == null) { int bytesRead; int totalBytesRead = 0; MemoryStream mw = new MemoryStream(); var buffer = ClientStreamReader.ReadBytes(RequestLength); while (totalBytesRead < RequestLength && (bytesRead = buffer.Length) > 0) { totalBytesRead += bytesRead; mw.Write(buffer, 0, bytesRead); } mw.Close(); RequestHtmlBody = Encoding.Default.GetString(mw.ToArray()); } RequestWasModified = true; return(RequestHtmlBody); }
private void ReadRequestBody() { if ((ProxyRequest.Method.ToUpper() != "POST" && ProxyRequest.Method.ToUpper() != "PUT")) { throw new BodyNotFoundException("Request don't have a body." + "Please verify that this request is a Http POST/PUT and request content length is greater than zero before accessing the body."); } if (RequestBody == null) { var isChunked = false; string requestContentEncoding = null; if (RequestHeaders.Any(x => x.Name.ToLower() == "content-encoding")) { requestContentEncoding = RequestHeaders.First(x => x.Name.ToLower() == "content-encoding").Value; } if (RequestHeaders.Any(x => x.Name.ToLower() == "transfer-encoding")) { var transferEncoding = RequestHeaders.First(x => x.Name.ToLower() == "transfer-encoding").Value.ToLower(); if (transferEncoding.Contains("chunked")) { isChunked = true; } } if (requestContentEncoding == null && !isChunked) { RequestBody = ClientStreamReader.ReadBytes(RequestContentLength); } else { using (var requestBodyStream = new MemoryStream()) { if (isChunked) { while (true) { var chuchkHead = ClientStreamReader.ReadLine(); var chunkSize = int.Parse(chuchkHead, NumberStyles.HexNumber); if (chunkSize != 0) { var buffer = ClientStreamReader.ReadBytes(chunkSize); requestBodyStream.Write(buffer, 0, buffer.Length); //chunk trail ClientStreamReader.ReadLine(); } else { ClientStreamReader.ReadLine(); break; } } } try { switch (requestContentEncoding) { case "gzip": RequestBody = CompressionHelper.DecompressGzip(requestBodyStream); break; case "deflate": RequestBody = CompressionHelper.DecompressDeflate(requestBodyStream); break; case "zlib": RequestBody = CompressionHelper.DecompressGzip(requestBodyStream); break; default: RequestBody = requestBodyStream.ToArray(); break; } } catch { RequestBody = requestBodyStream.ToArray(); } } } } RequestBodyRead = true; }
internal ConnectionWaitState(ClientStreamReader <T1> parent, EventHandler onConnected) { _parent = parent; _onConnected += onConnected; }