using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Text; namespace ln.http { public abstract class HttpConnection { public Listener Listener { get; } public IPEndPoint LocalEndpoint => Listener.LocalEndpoint; public IPEndPoint RemoteEndpoint { get; } public Stream ConnectionStream { get; } public string Method { get; } //public Uri RequestUri { get; } public HttpVersion HttpVersion { get; } public string RequestUriLine { get; set; } public HttpConnection(Listener listener, IPEndPoint remoteEndpoint, Stream connectionStream, string method, String requestUriLine, HttpVersion httpVersion) { Listener = listener; RemoteEndpoint = remoteEndpoint; ConnectionStream = connectionStream; Method = method; RequestUriLine = requestUriLine; HttpVersion = httpVersion; } public abstract void Run(); public static string ReadLine(Stream stream) => ReadLine(stream, Encoding.ASCII); public static string ReadLine(Stream stream, Encoding encoding) { if (!stream.CanRead) return null; byte[] line = new byte[1024]; int n = 0; int ch; while ((ch = stream.ReadByte()) != -1) { switch (ch) { case '\r': break; case '\n': return encoding.GetString(line, 0, n); default: line[n++] = (byte)ch; break; } } if (n > 0) return encoding.GetString(line, 0, n); return null; } public static bool ReadRequestLine(Stream stream, out string method, out string requestUri, out HttpVersion httpVersion) { string requestLine = ReadLine(stream); if (requestLine is null) { method = null; requestUri = null; httpVersion = HttpVersion.None; return false; } int idxSpace1 = requestLine.IndexOf(' '); int idxSpace2 = requestLine.IndexOf(' ', idxSpace1 + 1); if ((idxSpace1 > 0) && (idxSpace2 > 0)) { method = requestLine.Substring(0, idxSpace1); requestUri = requestLine.Substring(idxSpace1 + 1, (idxSpace2 - idxSpace1 - 1)); string protocol = requestLine.Substring(idxSpace2 + 1); httpVersion = HttpVersion.None; if ("PRI".Equals(method) && Http2PrefaceUri.Equals(requestUri) && "HTTP/2.0".Equals(protocol)) httpVersion = HttpVersion.HTTP2; else if ("HTTP/1.0".Equals(protocol)) httpVersion = HttpVersion.HTTP10; else if ("HTTP/1.1".Equals(protocol)) httpVersion = HttpVersion.HTTP11; return true; } method = null; requestUri = null; httpVersion = HttpVersion.None; return false; } public abstract void SendResponse(HttpRequestContext requestContext); private static string Http2PrefaceUri = "*"; } }