ln.http/HTTPServer.cs

171 lines
4.9 KiB
C#

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<IPEndPoint, TcpListener> tcpListeners = new Dictionary<IPEndPoint, TcpListener>();
Dictionary<Uri, HttpApplication> applications = new Dictionary<Uri, HttpApplication>();
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();
}
}
}