public ChunkedInputStream(HttpListenerContext context, Stream stream, byte [] buffer, int offset, int length) : base(stream, buffer, offset, length) { this.context = context; WebHeaderCollection coll = (WebHeaderCollection)context.Request.Headers; decoder = new MonoChunkStream(coll); }
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); } }
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); } }
void ReadDone(IAsyncResult result) { WebConnectionData data = Data; Stream ns = nstream; if (ns == null) { Close(true); return; } int nread = -1; try { nread = ns.EndRead(result); } catch (ObjectDisposedException) { return; } catch (Exception e) { if (e.InnerException is ObjectDisposedException) { return; } HandleError(WebExceptionStatus.ReceiveFailure, e, "ReadDone1"); return; } if (nread == 0) { HandleError(WebExceptionStatus.ReceiveFailure, null, "ReadDone2"); return; } if (nread < 0) { HandleError(WebExceptionStatus.ServerProtocolViolation, null, "ReadDone3"); return; } int pos = -1; nread += position; if (data.ReadState == ReadState.None) { Exception exc = null; try { pos = GetResponse(data, sPoint, buffer, nread); } catch (Exception e) { exc = e; } if (exc != null || pos == -1) { HandleError(WebExceptionStatus.ServerProtocolViolation, exc, "ReadDone4"); return; } } if (data.ReadState == ReadState.Aborted) { HandleError(WebExceptionStatus.RequestCanceled, null, "ReadDone"); return; } if (data.ReadState != ReadState.Content) { int est = nread * 2; int max = (est < buffer.Length) ? buffer.Length : est; byte [] newBuffer = new byte [max]; Buffer.BlockCopy(buffer, 0, newBuffer, 0, nread); buffer = newBuffer; position = nread; data.ReadState = ReadState.None; InitRead(); return; } position = 0; WebConnectionStream stream = new WebConnectionStream(this, data); bool expect_content = ExpectContent(data.StatusCode, data.request.Method); string tencoding = null; if (expect_content) { tencoding = data.Headers ["Transfer-Encoding"]; } chunkedRead = (tencoding != null && tencoding.IndexOf("chunked", StringComparison.OrdinalIgnoreCase) != -1); if (!chunkedRead) { stream.ReadBuffer = buffer; stream.ReadBufferOffset = pos; stream.ReadBufferSize = nread; try { stream.CheckResponseInBuffer(); } catch (Exception e) { HandleError(WebExceptionStatus.ReceiveFailure, e, "ReadDone7"); } } else if (chunkStream == null) { try { chunkStream = new MonoChunkStream(buffer, pos, nread, data.Headers); } catch (Exception e) { HandleError(WebExceptionStatus.ServerProtocolViolation, e, "ReadDone5"); return; } } else { chunkStream.ResetBuffer(); try { chunkStream.Write(buffer, pos, nread); } catch (Exception e) { HandleError(WebExceptionStatus.ServerProtocolViolation, e, "ReadDone6"); return; } } data.stream = stream; if (!expect_content) { stream.ForceCompletion(); } data.request.SetResponseData(data); }
void Connect(HttpWebRequest request) { lock (socketLock) { if (socket != null && socket.Connected && status == WebExceptionStatus.Success) { // Take the chunked stream to the expected state (State.None) if (CanReuse() && CompleteChunkedRead()) { reused = true; return; } } reused = false; if (socket != null) { socket.Close(); socket = null; } chunkStream = null; IPHostEntry hostEntry = sPoint.HostEntry; if (hostEntry == null) { #if MONOTOUCH && !MONOTOUCH_TV && !MONOTOUCH_WATCH xamarin_start_wwan(sPoint.Address.ToString()); hostEntry = sPoint.HostEntry; if (hostEntry == null) { #endif status = sPoint.UsesProxy ? WebExceptionStatus.ProxyNameResolutionFailure : WebExceptionStatus.NameResolutionFailure; return; #if MONOTOUCH && !MONOTOUCH_TV && !MONOTOUCH_WATCH } #endif } //WebConnectionData data = Data; foreach (IPAddress address in hostEntry.AddressList) { try { socket = new Socket(address.AddressFamily, SocketType.Stream, ProtocolType.Tcp); } catch (Exception se) { // The Socket ctor can throw if we run out of FD's if (!request.Aborted) { status = WebExceptionStatus.ConnectFailure; } connect_exception = se; return; } IPEndPoint remote = new IPEndPoint(address, sPoint.Address.Port); socket.NoDelay = !sPoint.UseNagleAlgorithm; try { sPoint.KeepAliveSetup(socket); } catch { // Ignore. Not supported in all platforms. } if (!sPoint.CallEndPointDelegate(socket, remote)) { socket.Close(); socket = null; status = WebExceptionStatus.ConnectFailure; } else { try { if (request.Aborted) { return; } socket.Connect(remote); status = WebExceptionStatus.Success; break; } catch (ThreadAbortException) { // program exiting... Socket s = socket; socket = null; if (s != null) { s.Close(); } return; } catch (ObjectDisposedException) { // socket closed from another thread return; } catch (Exception exc) { Socket s = socket; socket = null; if (s != null) { s.Close(); } if (!request.Aborted) { status = WebExceptionStatus.ConnectFailure; } connect_exception = exc; } } } } }