using System; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Threading; using ln.http.threads; using System.IO; using System.Text; using ln.http.resources.session; namespace ln.http { public class HTTPServer { public static int backlog = 5; public static int defaultPort = 8080; public static bool exclusivePortListener = false; public HttpApplication DefaultApplication { get; set; } bool shutdown = false; Dictionary tcpListeners = new Dictionary(); Dictionary applications = new Dictionary(); Pool threadPool = new Pool(); public SessionCache SessionCache { get; set; } public HTTPServer() { SessionCache = new SessionCache(); } public void AddEndpoint(IPEndPoint endpoint) { if (this.tcpListeners.ContainsKey(endpoint)) { throw new ArgumentOutOfRangeException(nameof(endpoint), "EndPoint already added"); } this.tcpListeners.Add(endpoint, new TcpListener(endpoint)); } public void RemoveEndpoint(IPEndPoint endpoint) { if (this.tcpListeners.ContainsKey(endpoint)) { this.tcpListeners[endpoint].Stop(); this.tcpListeners.Remove(endpoint); } } public void AddApplication(Uri BaseURI,HttpApplication application) { applications[BaseURI] = application; } public void Start() { foreach (TcpListener tcpListener in this.tcpListeners.Values) { tcpListener.Start(backlog); this.threadPool.Enqueue(() => AcceptConnections(tcpListener)); } } public void Stop() { lock (this) { this.shutdown = true; } } private void AcceptConnections(TcpListener tcpListener) { while (true) { lock(this) { if (this.shutdown) { return; } } AcceptConnection(tcpListener); } } private void AcceptConnection(TcpListener tcpListener) { TcpClient tcpClient = tcpListener.AcceptTcpClient(); this.threadPool.Enqueue(() => HandleConnection(tcpClient)); } private void HandleConnection(TcpClient tcpClient) { HttpReader httpReader = new HttpReader(tcpClient.GetStream()); httpReader.Read(); HttpRequest httpRequest = new HttpRequest(httpReader, (IPEndPoint)tcpClient.Client.LocalEndPoint); HttpResponse response = null; httpRequest.ApplySession(SessionCache); try { HttpApplication application = DefaultApplication; if (applications.ContainsKey(httpRequest.BaseURI)) application = applications[httpRequest.BaseURI]; application.Authenticate(httpRequest); application.Authorize(httpRequest); response = application.GetResponse( httpRequest ); } catch (Exception e) { response = new HttpResponse(httpRequest,"text/plain"); response.StatusCode = 500; response.ContentWriter.WriteLine("Exception caught: {0}",e); } if (!response.HasCustomContentStream) { response.ContentWriter.Flush(); MemoryStream cstream = (MemoryStream)response.ContentStream; cstream.Position = 0; response.SetHeader("content-length", cstream.Length.ToString()); } if (SessionCache != null) { SessionCache.ApplySessionID(response,httpRequest.Session); } response.AddCookie("LN_SEEN", DateTime.Now.ToString()); StreamWriter streamWriter = new StreamWriter(tcpClient.GetStream()); streamWriter.WriteLine("{0} {1} {2}", httpRequest.Protocol,response.StatusCode, response.StatusMessage); foreach (String headerName in response.GetHeaderNames()) { streamWriter.WriteLine("{0}: {1}", headerName, response.GetHeader(headerName)); } foreach (HttpCookie httpCookie in response.Cookies) { streamWriter.WriteLine("Set-Cookie: {0}",httpCookie.ToString()); } streamWriter.WriteLine(); streamWriter.Flush(); response.ContentStream.CopyTo(tcpClient.GetStream()); response.ContentStream.Close(); response.ContentStream.Dispose(); tcpClient.Close(); } } }