internal async Task InitReadAsync(CancellationToken cancellationToken) { WebConnection.Debug($"{ME} INIT READ ASYNC"); var buffer = new BufferOffsetSize(new byte[4096], false); var state = ReadState.None; int position = 0; while (true) { Operation.ThrowIfClosedOrDisposed(cancellationToken); WebConnection.Debug($"{ME} INIT READ ASYNC LOOP: {state} {position} - {buffer.Offset}/{buffer.Size}"); var nread = await RequestStream.InnerStream.ReadAsync( buffer.Buffer, buffer.Offset, buffer.Size, cancellationToken).ConfigureAwait(false); WebConnection.Debug($"{ME} INIT READ ASYNC LOOP #1: {state} {position} - {buffer.Offset}/{buffer.Size} - {nread}"); if (nread == 0) { throw GetReadException(WebExceptionStatus.ReceiveFailure, null, "ReadDoneAsync2"); } if (nread < 0) { throw GetReadException(WebExceptionStatus.ServerProtocolViolation, null, "ReadDoneAsync3"); } buffer.Offset += nread; buffer.Size -= nread; if (state == ReadState.None) { try { var oldPos = position; if (!GetResponse(buffer, ref position, ref state)) { position = oldPos; } } catch (Exception e) { WebConnection.Debug($"{ME} INIT READ ASYNC FAILED: {e.Message}\n{e}"); throw GetReadException(WebExceptionStatus.ServerProtocolViolation, e, "ReadDoneAsync4"); } } if (state == ReadState.Aborted) { throw GetReadException(WebExceptionStatus.RequestCanceled, null, "ReadDoneAsync5"); } if (state == ReadState.Content) { buffer.Size = buffer.Offset - position; buffer.Offset = position; break; } int est = nread * 2; if (est > buffer.Size) { var newBuffer = new byte [buffer.Buffer.Length + est]; Buffer.BlockCopy(buffer.Buffer, 0, newBuffer, 0, buffer.Offset); buffer = new BufferOffsetSize(newBuffer, buffer.Offset, newBuffer.Length - buffer.Offset, false); } state = ReadState.None; position = 0; } WebConnection.Debug($"{ME} INIT READ ASYNC LOOP DONE: {buffer.Offset} {buffer.Size}"); try { Initialize(buffer); } catch (Exception e) { throw GetReadException(WebExceptionStatus.ReceiveFailure, e, "ReadDoneAsync6"); } }
public override async Task <int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { WebConnection.Debug($"{ME} READ ASYNC"); cancellationToken.ThrowIfCancellationRequested(); if (buffer == null) { throw new ArgumentNullException(nameof(buffer)); } int length = buffer.Length; if (offset < 0 || length < offset) { throw new ArgumentOutOfRangeException(nameof(offset)); } if (count < 0 || (length - offset) < count) { throw new ArgumentOutOfRangeException(nameof(count)); } if (Interlocked.CompareExchange(ref nestedRead, 1, 0) != 0) { throw new InvalidOperationException("Invalid nested call."); } var completion = new WebCompletionSource(); while (!cancellationToken.IsCancellationRequested) { /* * 'currentRead' is set by ReadAllAsync(). */ var oldCompletion = Interlocked.CompareExchange(ref pendingRead, completion, null); WebConnection.Debug($"{ME} READ ASYNC #1: {oldCompletion != null}"); if (oldCompletion == null) { break; } await oldCompletion.WaitForCompletion().ConfigureAwait(false); } WebConnection.Debug($"{ME} READ ASYNC #2"); int nbytes = 0; Exception throwMe = null; try { nbytes = await ProcessRead(buffer, offset, count, cancellationToken).ConfigureAwait(false); } catch (Exception e) { throwMe = GetReadException(WebExceptionStatus.ReceiveFailure, e, "ReadAsync"); } WebConnection.Debug($"{ME} READ ASYNC #3: {nbytes} {throwMe?.Message}"); if (throwMe != null) { lock (locker) { completion.TrySetException(throwMe); pendingRead = null; nestedRead = 0; } closed = true; Operation.Finish(false, throwMe); throw throwMe; } lock (locker) { completion.TrySetCompleted(); pendingRead = null; nestedRead = 0; } if (nbytes <= 0 && !read_eof) { read_eof = true; if (!nextReadCalled) { WebConnection.Debug($"{ME} READ ASYNC - READ COMPLETE: {nbytes} - {nextReadCalled}"); if (!nextReadCalled) { nextReadCalled = true; Operation.Finish(true); } } } return(nbytes); }
void Initialize(BufferOffsetSize buffer) { WebConnection.Debug($"{ME} INIT: status={(int)StatusCode} bos={buffer.Offset}/{buffer.Size}"); long contentLength; string contentType = Headers["Transfer-Encoding"]; bool chunkedRead = (contentType != null && contentType.IndexOf("chunked", StringComparison.OrdinalIgnoreCase) != -1); string clength = Headers["Content-Length"]; if (!chunkedRead && !string.IsNullOrEmpty(clength)) { if (!long.TryParse(clength, out contentLength)) { contentLength = Int64.MaxValue; } } else { contentLength = Int64.MaxValue; } string tencoding = null; if (ExpectContent) { tencoding = Headers["Transfer-Encoding"]; } ChunkedRead = (tencoding != null && tencoding.IndexOf("chunked", StringComparison.OrdinalIgnoreCase) != -1); if (Version == HttpVersion.Version11 && RequestStream.KeepAlive) { KeepAlive = true; var cncHeader = Headers[ServicePoint.UsesProxy ? "Proxy-Connection" : "Connection"]; if (cncHeader != null) { cncHeader = cncHeader.ToLower(); KeepAlive = cncHeader.IndexOf("keep-alive", StringComparison.Ordinal) != -1; if (cncHeader.IndexOf("close", StringComparison.Ordinal) != -1) { KeepAlive = false; } } if (!ChunkedRead && contentLength == Int64.MaxValue) { /* * This is a violation of the HTTP Spec - the server neither send a * "Content-Length:" nor a "Transfer-Encoding: chunked" header. * The only way to recover from this is to keep reading until the * remote closes the connection, so we can't reuse it. */ KeepAlive = false; } } /* * Inner layer: * We may have read a few extra bytes while parsing the headers, these will be * passed to us in the @buffer parameter and we need to read these before * reading from the `InnerStream`. */ Stream networkStream; if (!ExpectContent || (!ChunkedRead && buffer.Size >= contentLength)) { bufferedEntireContent = true; innerStream = new BufferedReadStream(Operation, null, buffer); networkStream = innerStream; } else if (buffer.Size > 0) { networkStream = new BufferedReadStream(Operation, RequestStream.InnerStream, buffer); } else { networkStream = RequestStream.InnerStream; } /* * Intermediate layer: * - Wrap with MonoChunkStream when using chunked encoding. * - Otherwise, we should have a Content-Length, wrap with * FixedSizeReadStream to read exactly that many bytes. */ if (ChunkedRead) { innerStream = new MonoChunkStream(Operation, networkStream, Headers); } else if (bufferedEntireContent) { // 'innerStream' has already been set above. } else if (contentLength != Int64.MaxValue) { innerStream = new FixedSizeReadStream(Operation, networkStream, contentLength); } else { // Violation of the HTTP Spec - neither chunked nor length. innerStream = new BufferedReadStream(Operation, networkStream, null); } /* * Outer layer: * - Decode gzip/deflate if requested. */ string content_encoding = Headers["Content-Encoding"]; if (content_encoding == "gzip" && (Request.AutomaticDecompression & DecompressionMethods.GZip) != 0) { innerStream = ContentDecodeStream.Create(Operation, innerStream, ContentDecodeStream.Mode.GZip); Headers.Remove(HttpRequestHeader.ContentEncoding); } else if (content_encoding == "deflate" && (Request.AutomaticDecompression & DecompressionMethods.Deflate) != 0) { innerStream = ContentDecodeStream.Create(Operation, innerStream, ContentDecodeStream.Mode.Deflate); Headers.Remove(HttpRequestHeader.ContentEncoding); } WebConnection.Debug($"{ME} INIT #1: - {ExpectContent} {closed} {nextReadCalled}"); if (!ExpectContent) { nextReadCalled = true; Operation.Finish(true); } }
internal async Task ReadAllAsync(bool resending, CancellationToken cancellationToken) { WebConnection.Debug($"{ME} READ ALL ASYNC: resending={resending} eof={read_eof} " + "nextReadCalled={nextReadCalled}"); if (read_eof || bufferedEntireContent || nextReadCalled) { if (!nextReadCalled) { nextReadCalled = true; Operation.Finish(true); } return; } var completion = new WebCompletionSource(); var timeoutCts = new CancellationTokenSource(); try { var timeoutTask = Task.Delay(ReadTimeout, timeoutCts.Token); while (true) { /* * 'currentRead' is set by ReadAsync(). */ cancellationToken.ThrowIfCancellationRequested(); var oldCompletion = Interlocked.CompareExchange(ref pendingRead, completion, null); if (oldCompletion == null) { break; } // ReadAsync() is in progress. var oldReadTask = oldCompletion.WaitForCompletion(); var anyTask = await Task.WhenAny(oldReadTask, timeoutTask).ConfigureAwait(false); if (anyTask == timeoutTask) { throw new WebException("The operation has timed out.", WebExceptionStatus.Timeout); } } } finally { timeoutCts.Cancel(); timeoutCts.Dispose(); } WebConnection.Debug($"{ME} READ ALL ASYNC #1"); try { cancellationToken.ThrowIfCancellationRequested(); /* * We may have awaited on the 'readTcs', so check * for eof again as ReadAsync() may have set it. */ if (read_eof || bufferedEntireContent) { return; } /* * Simplify: if we're resending on a new connection, * then we can simply close the connection here. */ if (resending && !KeepAlive) { Close(); return; } var buffer = await ReadAllAsyncInner(cancellationToken).ConfigureAwait(false); var bos = new BufferOffsetSize(buffer, 0, buffer.Length, false); innerStream = new BufferedReadStream(Operation, null, bos); nextReadCalled = true; completion.TrySetCompleted(); } catch (Exception ex) { WebConnection.Debug($"{ME} READ ALL ASYNC EX: {ex.Message}"); completion.TrySetException(ex); throw; } finally { WebConnection.Debug($"{ME} READ ALL ASYNC #2"); pendingRead = null; } Operation.Finish(true); }
internal async Task ReadAllAsync(bool resending, CancellationToken cancellationToken) { WebConnection.Debug($"{ME} READ ALL ASYNC: resending={resending} eof={read_eof} total={totalRead} " + "length={contentLength} nextReadCalled={nextReadCalled}"); if (read_eof || totalRead >= contentLength || nextReadCalled) { if (!nextReadCalled) { nextReadCalled = true; Operation.Finish(true); } return; } var completion = new WebCompletionSource(); var timeoutCts = new CancellationTokenSource(); try { var timeoutTask = Task.Delay(ReadTimeout, timeoutCts.Token); while (true) { /* * 'currentRead' is set by ReadAsync(). */ cancellationToken.ThrowIfCancellationRequested(); var oldCompletion = Interlocked.CompareExchange(ref pendingRead, completion, null); if (oldCompletion == null) { break; } // ReadAsync() is in progress. var oldReadTask = oldCompletion.WaitForCompletion(); var anyTask = await Task.WhenAny(oldReadTask, timeoutTask).ConfigureAwait(false); if (anyTask == timeoutTask) { throw new WebException("The operation has timed out.", WebExceptionStatus.Timeout); } } } finally { timeoutCts.Cancel(); timeoutCts.Dispose(); } WebConnection.Debug($"{ME} READ ALL ASYNC #1"); cancellationToken.ThrowIfCancellationRequested(); try { if (totalRead >= contentLength) { return; } byte[] b = null; int new_size; if (contentLength == Int64.MaxValue && !ChunkedRead) { WebConnection.Debug($"{ME} READ ALL ASYNC - NEITHER LENGTH NOR CHUNKED"); /* * This is a violation of the HTTP Spec - the server neither send a * "Content-Length:" nor a "Transfer-Encoding: chunked" header. * * When we're redirecting or resending for NTLM, then we can simply close * the connection here. * * However, if it's the final reply, then we need to try our best to read it. */ if (resending) { Close(); return; } KeepAlive = false; } if (contentLength == Int64.MaxValue) { MemoryStream ms = new MemoryStream(); BufferOffsetSize buffer = null; if (readBuffer != null && readBuffer.Size > 0) { ms.Write(readBuffer.Buffer, readBuffer.Offset, readBuffer.Size); readBuffer.Offset = 0; readBuffer.Size = readBuffer.Buffer.Length; if (readBuffer.Buffer.Length >= 8192) { buffer = readBuffer; } } if (buffer == null) { buffer = new BufferOffsetSize(new byte[8192], false); } int read; while ((read = await InnerReadAsync(buffer.Buffer, buffer.Offset, buffer.Size, cancellationToken)) != 0) { ms.Write(buffer.Buffer, buffer.Offset, read); } new_size = (int)ms.Length; contentLength = new_size; readBuffer = new BufferOffsetSize(ms.GetBuffer(), 0, new_size, false); } else { new_size = (int)(contentLength - totalRead); b = new byte[new_size]; int readSize = 0; if (readBuffer != null && readBuffer.Size > 0) { readSize = readBuffer.Size; if (readSize > new_size) { readSize = new_size; } Buffer.BlockCopy(readBuffer.Buffer, readBuffer.Offset, b, 0, readSize); } int remaining = new_size - readSize; int r = -1; while (remaining > 0 && r != 0) { r = await InnerReadAsync(b, readSize, remaining, cancellationToken); remaining -= r; readSize += r; } } readBuffer = new BufferOffsetSize(b, 0, new_size, false); totalRead = 0; nextReadCalled = true; completion.TrySetCompleted(); } catch (Exception ex) { WebConnection.Debug($"{ME} READ ALL ASYNC EX: {ex.Message}"); completion.TrySetException(ex); throw; } finally { WebConnection.Debug($"{ME} READ ALL ASYNC #2"); pendingRead = null; } Operation.Finish(true); }
void Debug(string message) { WebConnection.Debug($"SPS({ID}): {message}"); }
async Task <(int, int)> ProcessRead(byte[] buffer, int offset, int size, CancellationToken cancellationToken) { WebConnection.Debug($"{ME} PROCESS READ: {totalRead} {contentLength}"); cancellationToken.ThrowIfCancellationRequested(); if (totalRead >= contentLength) { read_eof = true; contentLength = totalRead; return(0, 0); } int oldBytes = 0; int remaining = readBuffer?.Size ?? 0; if (remaining > 0) { int copy = (remaining > size) ? size : remaining; Buffer.BlockCopy(readBuffer.Buffer, readBuffer.Offset, buffer, offset, copy); readBuffer.Offset += copy; readBuffer.Size -= copy; offset += copy; size -= copy; totalRead += copy; if (totalRead >= contentLength) { contentLength = totalRead; read_eof = true; } if (size == 0 || totalRead >= contentLength) { return(0, copy); } oldBytes = copy; } if (contentLength != Int64.MaxValue && contentLength - totalRead < size) { size = (int)(contentLength - totalRead); } WebConnection.Debug($"{ME} PROCESS READ #1: {oldBytes} {size} {read_eof}"); if (read_eof) { contentLength = totalRead; return(oldBytes, 0); } var ret = await InnerReadAsync(buffer, offset, size, cancellationToken).ConfigureAwait(false); if (ret <= 0) { read_eof = true; contentLength = totalRead; return(oldBytes, 0); } totalRead += ret; return(oldBytes, ret); }
async Task Initialize(BufferOffsetSize buffer, CancellationToken cancellationToken) { WebConnection.Debug($"{ME} INIT: status={(int)StatusCode} bos={buffer.Offset}/{buffer.Size}"); string contentType = Headers["Transfer-Encoding"]; bool chunkedRead = (contentType != null && contentType.IndexOf("chunked", StringComparison.OrdinalIgnoreCase) != -1); string clength = Headers["Content-Length"]; if (!chunkedRead && !string.IsNullOrEmpty(clength)) { if (!long.TryParse(clength, out contentLength)) { contentLength = Int64.MaxValue; } } else { contentLength = Int64.MaxValue; } if (Version == HttpVersion.Version11 && RequestStream.KeepAlive) { KeepAlive = true; var cncHeader = Headers[ServicePoint.UsesProxy ? "Proxy-Connection" : "Connection"]; if (cncHeader != null) { cncHeader = cncHeader.ToLower(); KeepAlive = cncHeader.IndexOf("keep-alive", StringComparison.Ordinal) != -1; if (cncHeader.IndexOf("close", StringComparison.Ordinal) != -1) { KeepAlive = false; } } } // Negative numbers? if (!Int32.TryParse(clength, out stream_length)) { stream_length = -1; } string me = "WebResponseStream.Initialize()"; string tencoding = null; if (ExpectContent) { tencoding = Headers["Transfer-Encoding"]; } ChunkedRead = (tencoding != null && tencoding.IndexOf("chunked", StringComparison.OrdinalIgnoreCase) != -1); if (!ChunkedRead) { readBuffer = buffer; try { if (contentLength > 0 && readBuffer.Size >= contentLength) { if (!IsNtlmAuth()) { await ReadAllAsync(false, cancellationToken).ConfigureAwait(false); } } } catch (Exception e) { throw GetReadException(WebExceptionStatus.ReceiveFailure, e, me); } } else if (ChunkStream == null) { try { ChunkStream = new MonoChunkStream(buffer.Buffer, buffer.Offset, buffer.Offset + buffer.Size, Headers); } catch (Exception e) { throw GetReadException(WebExceptionStatus.ServerProtocolViolation, e, me); } } else { ChunkStream.ResetBuffer(); try { ChunkStream.Write(buffer.Buffer, buffer.Offset, buffer.Size); } catch (Exception e) { throw GetReadException(WebExceptionStatus.ServerProtocolViolation, e, me); } } WebConnection.Debug($"{ME} INIT #1: - {ExpectContent} {closed} {nextReadCalled}"); if (!ExpectContent) { if (!closed && !nextReadCalled) { if (contentLength == Int64.MaxValue) { contentLength = 0; } nextReadCalled = true; } Operation.Finish(true); } }
public override async Task <int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { WebConnection.Debug($"{ME} READ ASYNC"); cancellationToken.ThrowIfCancellationRequested(); if (buffer == null) { throw new ArgumentNullException(nameof(buffer)); } int length = buffer.Length; if (offset < 0 || length < offset) { throw new ArgumentOutOfRangeException(nameof(offset)); } if (count < 0 || (length - offset) < count) { throw new ArgumentOutOfRangeException(nameof(count)); } if (Interlocked.CompareExchange(ref nestedRead, 1, 0) != 0) { throw new InvalidOperationException("Invalid nested call."); } var completion = new WebCompletionSource(); while (!cancellationToken.IsCancellationRequested) { /* * 'currentRead' is set by ReadAllAsync(). */ var oldCompletion = Interlocked.CompareExchange(ref pendingRead, completion, null); WebConnection.Debug($"{ME} READ ASYNC #1: {oldCompletion != null}"); if (oldCompletion == null) { break; } await oldCompletion.WaitForCompletion().ConfigureAwait(false); } WebConnection.Debug($"{ME} READ ASYNC #2: {totalRead} {contentLength}"); int oldBytes = 0, nbytes = 0; Exception throwMe = null; try { // FIXME: NetworkStream.ReadAsync() does not support cancellation. (oldBytes, nbytes) = await HttpWebRequest.RunWithTimeout( ct => ProcessRead(buffer, offset, count, ct), ReadTimeout, () => { Operation.Abort(); InnerStream.Dispose(); }, () => Operation.Aborted, cancellationToken).ConfigureAwait(false); } catch (Exception e) { throwMe = GetReadException(WebExceptionStatus.ReceiveFailure, e, "ReadAsync"); } WebConnection.Debug($"{ME} READ ASYNC #3: {totalRead} {contentLength} - {oldBytes} {nbytes} {throwMe?.Message}"); if (throwMe != null) { lock (locker) { completion.TrySetException(throwMe); pendingRead = null; nestedRead = 0; } closed = true; Operation.Finish(false, throwMe); throw throwMe; } lock (locker) { pendingRead.TrySetCompleted(); pendingRead = null; nestedRead = 0; } if (totalRead >= contentLength && !nextReadCalled) { WebConnection.Debug($"{ME} READ ASYNC - READ COMPLETE: {oldBytes} {nbytes} - {totalRead} {contentLength} {nextReadCalled}"); if (!nextReadCalled) { nextReadCalled = true; Operation.Finish(true); } } return(oldBytes + nbytes); }
void Debug(string message, params object[] args) { WebConnection.Debug($"SPS({ID}): {string.Format (message, args)}"); }
void Initialize(BufferOffsetSize buffer) { WebConnection.Debug($"{ME} INIT: status={(int)StatusCode} bos={buffer.Offset}/{buffer.Size}"); string contentType = Headers["Transfer-Encoding"]; bool chunkedRead = (contentType != null && contentType.IndexOf("chunked", StringComparison.OrdinalIgnoreCase) != -1); string clength = Headers["Content-Length"]; if (!chunkedRead && !string.IsNullOrEmpty(clength)) { if (!long.TryParse(clength, out contentLength)) { contentLength = Int64.MaxValue; } } else { contentLength = Int64.MaxValue; } if (Version == HttpVersion.Version11 && RequestStream.KeepAlive) { KeepAlive = true; var cncHeader = Headers[ServicePoint.UsesProxy ? "Proxy-Connection" : "Connection"]; if (cncHeader != null) { cncHeader = cncHeader.ToLower(); KeepAlive = cncHeader.IndexOf("keep-alive", StringComparison.Ordinal) != -1; if (cncHeader.IndexOf("close", StringComparison.Ordinal) != -1) { KeepAlive = false; } } } // Negative numbers? if (!Int32.TryParse(clength, out stream_length)) { stream_length = -1; } string tencoding = null; if (ExpectContent) { tencoding = Headers["Transfer-Encoding"]; } ChunkedRead = (tencoding != null && tencoding.IndexOf("chunked", StringComparison.OrdinalIgnoreCase) != -1); if (ChunkedRead) { innerStreamWrapper = innerChunkStream = new MonoChunkStream( Operation, CreateStreamWrapper(buffer), Headers); } else if (!IsNtlmAuth() && contentLength > 0 && buffer.Size >= contentLength) { innerStreamWrapper = new BufferedReadStream(Operation, null, buffer); } else { innerStreamWrapper = CreateStreamWrapper(buffer); } string content_encoding = Headers["Content-Encoding"]; if (content_encoding == "gzip" && (Request.AutomaticDecompression & DecompressionMethods.GZip) != 0) { innerStreamWrapper = new GZipStream(innerStreamWrapper, CompressionMode.Decompress); Headers.Remove(HttpRequestHeader.ContentEncoding); } else if (content_encoding == "deflate" && (Request.AutomaticDecompression & DecompressionMethods.Deflate) != 0) { innerStreamWrapper = new DeflateStream(innerStreamWrapper, CompressionMode.Decompress); Headers.Remove(HttpRequestHeader.ContentEncoding); } WebConnection.Debug($"{ME} INIT #1: - {ExpectContent} {closed} {nextReadCalled}"); if (!ExpectContent) { if (!closed && !nextReadCalled) { if (contentLength == Int64.MaxValue) { contentLength = 0; } nextReadCalled = true; } Operation.CompleteResponseRead(true); } }
public override async Task <int> ReadAsync(byte[] buffer, int offset, int size, CancellationToken cancellationToken) { WebConnection.Debug($"{ME} READ ASYNC"); cancellationToken.ThrowIfCancellationRequested(); if (buffer == null) { throw new ArgumentNullException(nameof(buffer)); } int length = buffer.Length; if (offset < 0 || length < offset) { throw new ArgumentOutOfRangeException(nameof(offset)); } if (size < 0 || (length - offset) < size) { throw new ArgumentOutOfRangeException(nameof(size)); } if (Interlocked.CompareExchange(ref nestedRead, 1, 0) != 0) { throw new InvalidOperationException("Invalid nested call."); } var myReadTcs = new TaskCompletionSource <int> (); while (!cancellationToken.IsCancellationRequested) { /* * 'readTcs' is set by ReadAllAsync(). */ var oldReadTcs = Interlocked.CompareExchange(ref readTcs, myReadTcs, null); WebConnection.Debug($"{ME} READ ASYNC #1: {oldReadTcs != null}"); if (oldReadTcs == null) { break; } await oldReadTcs.Task.ConfigureAwait(false); } WebConnection.Debug($"{ME} READ ASYNC #2: {totalRead} {contentLength}"); int nbytes = 0; Exception throwMe = null; try { // FIXME: NetworkStream.ReadAsync() does not support cancellation. nbytes = await HttpWebRequest.RunWithTimeout( ct => ProcessRead(buffer, offset, size, ct), ReadTimeout, () => { Operation.Abort(); InnerStream.Dispose(); }).ConfigureAwait(false); } catch (Exception e) { throwMe = GetReadException(WebExceptionStatus.ReceiveFailure, e, "ReadAsync"); } WebConnection.Debug($"{ME} READ ASYNC #3: {totalRead} {contentLength} - {nbytes} {throwMe?.Message}"); if (throwMe != null) { lock (locker) { myReadTcs.TrySetException(throwMe); readTcs = null; nestedRead = 0; } closed = true; Operation.CompleteResponseRead(false, throwMe); throw throwMe; } lock (locker) { readTcs.TrySetResult(nbytes); readTcs = null; nestedRead = 0; } if (totalRead >= contentLength && !nextReadCalled) { WebConnection.Debug($"{ME} READ ASYNC - READ COMPLETE: {nbytes} - {totalRead} {contentLength} {nextReadCalled}"); if (!nextReadCalled) { nextReadCalled = true; Operation.CompleteResponseRead(true); } } return(nbytes); }
public override async Task WriteAsync(byte[] buffer, int offset, int size, CancellationToken cancellationToken) { WebConnection.Debug($"{ME} WRITE ASYNC: {buffer.Length}/{offset}/{size}"); Operation.ThrowIfClosedOrDisposed(cancellationToken); if (Operation.WriteBuffer != null) { throw new InvalidOperationException(); } if (buffer == null) { throw new ArgumentNullException(nameof(buffer)); } int length = buffer.Length; if (offset < 0 || length < offset) { throw new ArgumentOutOfRangeException(nameof(offset)); } if (size < 0 || (length - offset) < size) { throw new ArgumentOutOfRangeException(nameof(size)); } var myWriteTcs = new TaskCompletionSource <int> (); if (Interlocked.CompareExchange(ref pendingWrite, myWriteTcs, null) != null) { throw new InvalidOperationException(SR.GetString(SR.net_repcall)); } try { await ProcessWrite(buffer, offset, size, cancellationToken).ConfigureAwait(false); WebConnection.Debug($"{ME} WRITE ASYNC #1: {allowBuffering} {sendChunked} {Request.ContentLength} {totalWritten}"); if (Request.ContentLength > 0 && totalWritten == Request.ContentLength) { await FinishWriting(cancellationToken); } pendingWrite = null; myWriteTcs.TrySetResult(0); } catch (Exception ex) { KillBuffer(); closed = true; WebConnection.Debug($"{ME} WRITE ASYNC EX: {ex.Message}"); if (ex is SocketException) { ex = new IOException("Error writing request", ex); } Operation.CompleteRequestWritten(this, ex); pendingWrite = null; myWriteTcs.TrySetException(ex); throw; } }