void Init() { context_bound = false; i_stream = null; o_stream = null; prefix = null; chunked = false; ms = new MemoryStream(); position = 0; input_state = InputState.RequestLine; line_state = LineState.None; context = new HttpListenerContext(this); }
internal void FinishInitialization() { string host = UserHostName; if (version > HttpVersion.Version10 && (host == null || host.Length == 0)) { context.ErrorMessage = "Invalid host name"; return; } string path; Uri raw_uri = null; if (MaybeUri(raw_url) && Uri.TryCreate(raw_url, UriKind.Absolute, out raw_uri)) { path = raw_uri.PathAndQuery; } else { path = raw_url; } if ((host == null || host.Length == 0)) { host = UserHostAddress; } if (raw_uri != null) { host = raw_uri.Host; } int colon = host.IndexOf(':'); if (colon >= 0) { host = host.Substring(0, colon); } string base_uri = String.Format("{0}://{1}:{2}", (IsSecureConnection) ? "https" : "http", host, LocalEndPoint.Port); if (!Uri.TryCreate(base_uri + path, UriKind.Absolute, out url)) { context.ErrorMessage = "Invalid url: " + base_uri + path; return; } CreateQueryString(url.Query); if (version >= HttpVersion.Version11) { string t_encoding = Headers["Transfer-Encoding"]; is_chunked = (t_encoding != null && String.Compare(t_encoding, "chunked", StringComparison.OrdinalIgnoreCase) == 0); // 'identity' is not valid! if (t_encoding != null && !is_chunked) { context.Connection.SendError(null, 501); return; } } if (!is_chunked && !cl_set) { if (String.Compare(method, "POST", StringComparison.OrdinalIgnoreCase) == 0 || String.Compare(method, "PUT", StringComparison.OrdinalIgnoreCase) == 0) { context.Connection.SendError(null, 411); return; } } if (String.Compare(Headers["Expect"], "100-continue", StringComparison.OrdinalIgnoreCase) == 0) { ResponseStream output = context.Connection.GetResponseStream(); output.InternalWrite(_100continue, 0, _100continue.Length); } }
internal void Close(bool force_close) { if (sock != null) { Stream st = GetResponseStream(); if (st != null) { st.Close(); } o_stream = null; } if (sock != null) { force_close |= !context.Request.KeepAlive; if (!force_close) { force_close = (context.Response.Headers["connection"] == "close"); } /* * if (!force_close) { * // bool conn_close = (status_code == 400 || status_code == 408 || status_code == 411 || * // status_code == 413 || status_code == 414 || status_code == 500 || * // status_code == 503); * * force_close |= (context.Request.ProtocolVersion <= HttpVersion.Version10); * } */ if (!force_close && context.Request.FlushInput()) { if (chunked && context.Response.ForceCloseChunked == false) { // Don't close. Keep working. reuses++; Unbind(); Init(); BeginReadRequest(); return; } reuses++; Unbind(); Init(); BeginReadRequest(); return; } Socket s = sock; sock = null; try { if (s != null) { s.Shutdown(SocketShutdown.Both); } } catch { } finally { if (s != null) { s.Close(); } } Unbind(); RemoveConnection(); try { this.timer.Dispose(); } catch { } return; } }
internal void SendHeaders(bool closing, MemoryStream ms) { Encoding encoding = content_encoding; if (encoding == null) { encoding = Encoding.Default; } if (content_type != null) { if (content_encoding != null && content_type.IndexOf("charset=", StringComparison.Ordinal) == -1) { string enc_name = content_encoding.WebName; headers.SetInternal("Content-Type", content_type + "; charset=" + enc_name); } else { headers.SetInternal("Content-Type", content_type); } } if (headers["Server"] == null) { headers.SetInternal("Server", "Reactor-HTTPAPI/1.0"); } CultureInfo inv = CultureInfo.InvariantCulture; if (headers["Date"] == null) { headers.SetInternal("Date", DateTime.UtcNow.ToString("r", inv)); } if (!chunked) { if (!cl_set && closing) { cl_set = true; content_length = 0; } if (cl_set) { headers.SetInternal("Content-Length", content_length.ToString(inv)); } } Version v = context.Request.ProtocolVersion; if (!cl_set && !chunked && v >= HttpVersion.Version11) { chunked = true; } /* Apache forces closing the connection for these status codes: * HttpStatusCode.BadRequest 400 * HttpStatusCode.RequestTimeout 408 * HttpStatusCode.LengthRequired 411 * HttpStatusCode.RequestEntityTooLarge 413 * HttpStatusCode.RequestUriTooLong 414 * HttpStatusCode.InternalServerError 500 * HttpStatusCode.ServiceUnavailable 503 */ bool conn_close = (status_code == 400 || status_code == 408 || status_code == 411 || status_code == 413 || status_code == 414 || status_code == 500 || status_code == 503); if (conn_close == false) { conn_close = !context.Request.KeepAlive; } // They sent both KeepAlive: true and Connection: close!? if (!keep_alive || conn_close) { headers.SetInternal("Connection", "close"); conn_close = true; } if (chunked) { headers.SetInternal("Transfer-Encoding", "chunked"); } int reuses = context.Connection.Reuses; if (reuses >= 100) { force_close_chunked = true; if (!conn_close) { headers.SetInternal("Connection", "close"); conn_close = true; } } if (!conn_close) { headers.SetInternal("Keep-Alive", String.Format("timeout=15,max={0}", 100 - reuses)); if (context.Request.ProtocolVersion <= HttpVersion.Version10) { headers.SetInternal("Connection", "keep-alive"); } } if (location != null) { headers.SetInternal("Location", location); } if (cookies != null) { foreach (Cookie cookie in cookies) { headers.SetInternal("Set-Cookie", cookie.ToClientString()); } } StreamWriter writer = new StreamWriter(ms, encoding, 256); writer.Write("HTTP/{0} {1} {2}\r\n", version, status_code, status_description); string headers_str = headers.ToStringMultiValue(); writer.Write(headers_str); writer.Flush(); int preamble = (encoding.CodePage == 65001) ? 3 : encoding.GetPreamble().Length; if (output_stream == null) { output_stream = context.Connection.GetResponseStream(); } /* Assumes that the ms was at position 0 */ ms.Position = preamble; HeadersSent = true; }