166 lines
4.8 KiB
C#
166 lines
4.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using ln.http.resources.session;
|
|
using ln.logging;
|
|
using ln.types.threads;
|
|
using ln.types;
|
|
using ln.http.listener;
|
|
using ln.http.connections;
|
|
using ln.types.net;
|
|
using ln.http.cert;
|
|
using System.Globalization;
|
|
using System.Net.Sockets;
|
|
|
|
|
|
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; }
|
|
public SessionCache SessionCache { get; set; }
|
|
|
|
public bool IsRunning => !shutdown && (threadPool.CurrentPoolSize > 0);
|
|
public Func<HTTPServer,HTTPServerConnection> CreateServerConnection { get; set; }
|
|
|
|
public Logger Logger { get; set; }
|
|
bool shutdown = false;
|
|
|
|
List<Listener> listeners = new List<Listener>();
|
|
public Listener[] Listeners => listeners.ToArray();
|
|
|
|
Dictionary<URI, HttpApplication> applications = new Dictionary<URI, HttpApplication>();
|
|
|
|
DynamicPool threadPool;
|
|
public DynamicPool ThreadPool => threadPool;
|
|
|
|
public HTTPServer()
|
|
{
|
|
Logger = Logger.Default;
|
|
|
|
SessionCache = new SessionCache();
|
|
threadPool = new DynamicPool(1024);
|
|
}
|
|
|
|
public void AddListener(Listener listener)
|
|
{
|
|
listeners.Add(listener);
|
|
if (IsRunning)
|
|
StartListener(listener);
|
|
}
|
|
|
|
public void StartListener(Listener listener)
|
|
{
|
|
listener.Open();
|
|
|
|
threadPool.Enqueue(
|
|
() => listener.AcceptMany(
|
|
(connection) => threadPool.Enqueue(
|
|
() => this.HandleConnection(connection)
|
|
)
|
|
)
|
|
);
|
|
}
|
|
|
|
public void StopListener(Listener listener)
|
|
{
|
|
listener.Close();
|
|
}
|
|
|
|
|
|
public void AddEndpoint(Endpoint endpoint)
|
|
{
|
|
AddListener(new HttpListener(endpoint));
|
|
}
|
|
|
|
public void AddApplication(URI BaseURI, HttpApplication application)
|
|
{
|
|
applications[BaseURI] = application;
|
|
}
|
|
|
|
public HttpApplication GetHttpApplication(URI baseURI)
|
|
{
|
|
HttpApplication application = DefaultApplication;
|
|
|
|
if (applications.ContainsKey(baseURI))
|
|
application = applications[baseURI];
|
|
|
|
return application;
|
|
}
|
|
|
|
|
|
public void Start()
|
|
{
|
|
threadPool.Start();
|
|
|
|
foreach (Listener listener in listeners)
|
|
StartListener(listener);
|
|
}
|
|
|
|
public void Stop()
|
|
{
|
|
lock (this)
|
|
{
|
|
this.shutdown = true;
|
|
}
|
|
foreach (Listener listener in listeners)
|
|
StopListener(listener);
|
|
|
|
threadPool.Stop(true);
|
|
}
|
|
|
|
private void HandleConnection(Connection connection)
|
|
{
|
|
HttpRequest httpRequest = null;
|
|
bool keepAlive = true;
|
|
try
|
|
{
|
|
do
|
|
{
|
|
httpRequest = connection.ReadRequest(this);
|
|
if (httpRequest == null)
|
|
break;
|
|
|
|
httpRequest.ApplySession(SessionCache);
|
|
|
|
HttpApplication application = GetHttpApplication(new URI(httpRequest.BaseURI.ToString()));
|
|
|
|
application.Authenticate(httpRequest);
|
|
application.Authorize(httpRequest);
|
|
|
|
HttpResponse response = application.GetResponse(httpRequest);
|
|
|
|
keepAlive = httpRequest.GetRequestHeader("connection","keep-alive").Equals("keep-alive") && response.GetHeader("connection", "keep-alive").Equals("keep-alive");
|
|
response.SetHeader("connection", keepAlive ? "keep-alive" : "close");
|
|
|
|
connection.SendResponse(response);
|
|
|
|
} while (keepAlive);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Logging.Log(e);
|
|
if (httpRequest != null)
|
|
{
|
|
HttpResponse httpResponse = new HttpResponse(httpRequest);
|
|
httpResponse.StatusCode = 500;
|
|
httpResponse.ContentWriter.WriteLine("500 Internal Server Error");
|
|
|
|
connection.SendResponse(httpResponse);
|
|
}
|
|
}
|
|
|
|
connection.GetStream().Close();
|
|
}
|
|
|
|
public void Log(DateTime startTime,double duration,HttpRequest httpRequest,HttpResponse httpResponse)
|
|
{
|
|
Logger.Log(LogLevel.INFO, "{0} {1} {2} {3}",startTime.ToString("yyyyMMdd-HH:mm:ss"),duration.ToString(CultureInfo.InvariantCulture),httpRequest.Hostname,httpRequest.RequestURL);
|
|
}
|
|
|
|
}
|
|
}
|