// Constructors HttpWebResponse(Uri uri, string method, WebConnectionData data, CookieContainer container) { _uri = uri; _method = method; _webHeaders = data.Headers; _version = data.Version; _statusCode = (HttpStatusCode)data.StatusCode; _statusDescription = data.StatusDescription; _stream = data.Stream; _contentLength = -1; try { var cl = _webHeaders["Content-Length"]; if (String.IsNullOrEmpty(cl) || !Int64.TryParse(cl, out _contentLength)) _contentLength = -1; } catch (Exception) { _contentLength = -1; } if (container != null) { _cookieContainer = container; //FillCookiesAsync(); } #if false string content_encoding = webHeaders ["Content-Encoding"]; if (content_encoding == "gzip" && (data.request.AutomaticDecompression & DecompressionMethods.GZip) != 0) stream = new GZipStream (stream, CompressionMode.Decompress); else if (content_encoding == "deflate" && (data.request.AutomaticDecompression & DecompressionMethods.Deflate) != 0) stream = new DeflateStream (stream, CompressionMode.Decompress); #endif }
internal static async Task<HttpWebResponse> CreateAsync(Uri uri, string method, WebConnectionData data, CookieContainer container) { var response = new HttpWebResponse(uri, method, data, container); if (null != container) await response.FillCookiesAsync().ConfigureAwait(false); return response; }
async Task InitConnectionAsync(HttpWebRequest request) { request.WebConnection = this; if (request.ReuseConnection) request.StoredConnection = this; if (request.Aborted) return; _keepAlive = request.KeepAlive; Data = new WebConnectionData(request); retry: await ConnectAsync(request).ConfigureAwait(false); if (request.Aborted) return; if (_status != WebExceptionStatus.Success) { if (!request.Aborted) { request.SetWriteStreamError(_status, _connectException); Close(true); } return; } if (!await CreateStreamAsync(request).ConfigureAwait(false)) { if (request.Aborted) return; var st = _status; if (Data.Challenge != null) goto retry; var cncExc = _connectException; _connectException = null; request.SetWriteStreamError(st, cncExc); Close(true); return; } await request.SetWriteStreamAsync(new WebConnectionStream(this, request)).ConfigureAwait(false); }
static async Task<int> GetResponseAsync(StreamSocketStream nstream, WebConnectionData data, ServicePoint sPoint) { var isContinue = false; var emptyFirstLine = false; using (var lineReader = new HttpLineReader(nstream)) { do { if (data.ReadState == ReadState.Aborted) return -1; if (data.ReadState == ReadState.None) { var line = await lineReader.ReadLineAsync(CancellationToken.None).ConfigureAwait(false); if (null == line) { data.ReadState = ReadState.Aborted; return 0; } if (string.IsNullOrEmpty(line)) { emptyFirstLine = true; continue; } emptyFirstLine = false; data.ReadState = ReadState.Status; var parts = line.Split(' '); if (parts.Length < 2) return -1; if (string.Compare(parts[0], "HTTP/1.1", StringComparison.OrdinalIgnoreCase) == 0) { data.Version = HttpVersion.Version11; sPoint.SetVersion(HttpVersion.Version11); } else { data.Version = HttpVersion.Version10; sPoint.SetVersion(HttpVersion.Version10); } data.StatusCode = (int)UInt32.Parse(parts[1]); if (parts.Length >= 3) data.StatusDescription = string.Join(" ", parts, 2, parts.Length - 2); else data.StatusDescription = ""; } emptyFirstLine = false; if (data.ReadState == ReadState.Status) { data.ReadState = ReadState.Headers; data.Headers = new WebHeaderCollection(); var headers = new List<string>(); var finished = false; while (!finished) { var line = await lineReader.ReadLineAsync(CancellationToken.None).ConfigureAwait(false); if (null == line) break; if (string.IsNullOrEmpty(line)) { // Empty line: end of headers finished = true; continue; } if (line.Length > 0 && (line[0] == ' ' || line[0] == '\t')) { var count = headers.Count - 1; if (count < 0) break; var prev = headers[count] + line; headers[count] = prev; } else headers.Add(line); } if (!finished) return 0; lineReader.SyncStream(); foreach (var s in headers) data.Headers.SetInternal(s); if (data.StatusCode == (int)HttpStatusCode.Continue) { sPoint.SendContinue = true; if (data.Request.ExpectContinue) { data.Request.DoContinueDelegate(data.StatusCode, data.Headers); // Prevent double calls when getting the // headers in several packets. data.Request.ExpectContinue = false; } data.ReadState = ReadState.None; isContinue = true; } else { data.ReadState = ReadState.Content; return 1; } } } while (emptyFirstLine || isContinue); } return -1; }
void HandleError(WebExceptionStatus st, Exception e, string where) { _status = st; lock (this) { if (st == WebExceptionStatus.RequestCanceled) Data = new WebConnectionData(); } if (e == null) { // At least we now where it comes from try { #if TARGET_JVM throw new Exception (); #else throw new Exception(new StackTrace().ToString()); #endif } catch (Exception e2) { e = e2; } } HttpWebRequest req = null; if (Data != null && Data.Request != null) req = Data.Request; Close(true); if (req != null) { req.FinishedReading = true; req.SetResponseError(st, e, where); } }
//internal IAsyncResult BeginWrite(HttpWebRequest request, byte[] buffer, int offset, int size, AsyncCallback cb, object state) //{ // Stream s = null; // lock (this) // { // if (Data.Request != request) // throw new ObjectDisposedException(typeof (StreamSocketStream).FullName); // if (_nstream == null) // return null; // s = _nstream; // } // IAsyncResult result = null; // try // { // result = s.BeginWrite(buffer, offset, size, cb, state); // var x = s.WriteAsync(buffer, offset, size).ConfigureAwait(false) // } // catch (Exception) // { // _status = WebExceptionStatus.SendFailure; // throw; // } // return result; //} //internal bool EndWrite(HttpWebRequest request, bool throwOnError, IAsyncResult result) //{ // if (request.FinishedReading) // return true; // Stream s = null; // lock (this) // { // if (Data.Request != request) // throw new ObjectDisposedException(typeof(StreamSocketStream).FullName); // if (_nstream == null) // throw new ObjectDisposedException(typeof(StreamSocketStream).FullName); // s = _nstream; // } // try // { // s.EndWrite(result); // return true; // } // catch (Exception exc) // { // _status = WebExceptionStatus.SendFailure; // if (throwOnError && exc.InnerException != null) // throw exc.InnerException; // return false; // } //} //internal int Read(HttpWebRequest request, byte[] buffer, int offset, int size) //{ // Stream s = null; // lock (this) // { // if (Data.Request != request) // throw new ObjectDisposedException(typeof(StreamSocketStream).FullName); // if (_nstream == null) // return 0; // s = _nstream; // } // var result = 0; // try // { // var done = false; // if (!_chunkedRead) // { // result = s.Read(buffer, offset, size); // done = (result == 0); // } // if (_chunkedRead) // { // try // { // _chunkStream.WriteAndReadBack(buffer, offset, size, ref result); // if (!done && result == 0 && _chunkStream.WantMore) // result = EnsureReadAsync(buffer, offset, size); // } // catch (Exception e) // { // HandleError(WebExceptionStatus.ReceiveFailure, e, "chunked Read1"); // throw; // } // if ((done || result == 0) && _chunkStream.WantMore) // { // HandleError(WebExceptionStatus.ReceiveFailure, null, "chunked Read2"); // throw new WebException("Read error", null, WebExceptionStatus.ReceiveFailure, null); // } // } // } // catch (Exception e) // { // HandleError(WebExceptionStatus.ReceiveFailure, e, "Read"); // } // return result; //} internal bool Write(HttpWebRequest request, byte[] buffer, int offset, int size, ref string err_msg) { err_msg = null; Stream s = null; lock (this) { if (Data.Request != request) throw new ObjectDisposedException(typeof(StreamSocketStream).FullName); s = _nstream; if (s == null) return false; } try { s.Write(buffer, offset, size); // here SSL handshake should have been done if (_ssl && !_certsAvailable) GetCertificates(s); } catch (Exception e) { err_msg = e.Message; var wes = WebExceptionStatus.SendFailure; var msg = "Write: " + err_msg; if (e is WebException) { HandleError(wes, e, msg); return false; } // if SSL is in use then check for TrustFailure if (_ssl) { #if SECURITY_DEP && MONOTOUCH HttpsClientStream https = (s as HttpsClientStream); if (https.TrustFailure) { #else if ((bool)_piTrustFailure.GetValue(s, null)) { #endif wes = WebExceptionStatus.TrustFailure; msg = "Trust failure"; } } HandleError(wes, e, msg); return false; } return true; } internal void Close(bool sendNext) { lock (this) { if (Data != null && Data.Request != null && Data.Request.ReuseConnection) { Data.Request.ReuseConnection = false; return; } if (_nstream != null) { try { _nstream.Close(); } catch { } _nstream = null; } if (_socket != null) { try { _socket.Dispose(); } catch { } _socket = null; } if (_ntlmAuthenticated) ResetNtlm(); if (Data != null) { lock (Data) { Data.ReadState = ReadState.Aborted; } } _state.SetIdle(); Data = new WebConnectionData(); if (sendNext) SendNext(); _connectRequest = null; _connectNtlmAuthState = NtlmAuthState.None; } } void Abort(object sender, EventArgs args) { lock (this) { lock (_queue) { var req = (HttpWebRequest)sender; if (Data.Request == req || Data.Request == null) { if (!req.FinishedReading) { _status = WebExceptionStatus.RequestCanceled; Close(false); if (_queue.Count > 0) { Data.Request = _queue.Dequeue(); SendRequest(Data.Request); } } return; } req.FinishedReading = true; req.SetResponseError(WebExceptionStatus.RequestCanceled, null, "User aborted"); if (_queue.Count > 0 && _queue.Peek() == sender) _queue.Dequeue(); else if (_queue.Count > 0) { var old = _queue.ToArray(); _queue.Clear(); for (var i = old.Length - 1; i >= 0; i--) { if (old[i] != sender) _queue.Enqueue(old[i]); } } } } }
//internal ChunkStream ChunkStream //{ // get { return _chunkStream; } //} public WebConnection(IWebConnectionState wcs, ServicePoint sPoint) { _state = wcs; _sPoint = sPoint; _buffer = new byte[4096]; Data = new WebConnectionData(); _queue = wcs.Group.Queue; abortHelper = new AbortHelper { Connection = this }; _abortHandler = abortHelper.Abort; }