WIP
parent
3cc4f92e40
commit
c4f456f8c5
|
@ -3,10 +3,11 @@ 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;
|
||||
using ln.logging;
|
||||
using ln.types.threads;
|
||||
|
||||
|
||||
namespace ln.http
|
||||
|
@ -19,17 +20,21 @@ namespace ln.http
|
|||
|
||||
public HttpApplication DefaultApplication { get; set; }
|
||||
|
||||
public SessionCache SessionCache { get; set; }
|
||||
|
||||
public bool IsRunning => (currentListenerThreads.Count > 0) || (threadPool.NumThreads > 0);
|
||||
|
||||
|
||||
|
||||
bool shutdown = false;
|
||||
|
||||
Dictionary<IPEndPoint, TcpListener> tcpListeners = new Dictionary<IPEndPoint, TcpListener>();
|
||||
Dictionary<Uri, HttpApplication> applications = new Dictionary<Uri, HttpApplication>();
|
||||
|
||||
Dictionary<TcpListener, Thread> currentListenerThreads = new Dictionary<TcpListener, Thread>();
|
||||
|
||||
Pool threadPool = new Pool();
|
||||
|
||||
public SessionCache SessionCache { get; set; }
|
||||
|
||||
|
||||
|
||||
public HTTPServer()
|
||||
{
|
||||
SessionCache = new SessionCache();
|
||||
|
@ -64,7 +69,9 @@ namespace ln.http
|
|||
foreach (TcpListener tcpListener in this.tcpListeners.Values)
|
||||
{
|
||||
tcpListener.Start(backlog);
|
||||
this.threadPool.Enqueue(() => AcceptConnections(tcpListener));
|
||||
|
||||
Thread listenerThread = new Thread(() => AcceptConnections(tcpListener));
|
||||
listenerThread.Start();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -74,20 +81,49 @@ namespace ln.http
|
|||
lock (this)
|
||||
{
|
||||
this.shutdown = true;
|
||||
|
||||
foreach (TcpListener tcpListener in tcpListeners.Values)
|
||||
{
|
||||
tcpListener.Stop();
|
||||
}
|
||||
|
||||
threadPool.NumThreads = 0;
|
||||
|
||||
while (IsRunning)
|
||||
{
|
||||
Thread.Sleep(50);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AcceptConnections(TcpListener tcpListener)
|
||||
{
|
||||
while (true)
|
||||
lock (this)
|
||||
{
|
||||
lock(this)
|
||||
if (currentListenerThreads.ContainsKey(tcpListener))
|
||||
{
|
||||
if (this.shutdown) {
|
||||
return;
|
||||
}
|
||||
throw new Exception("HTTP listener thread already running");
|
||||
}
|
||||
AcceptConnection(tcpListener);
|
||||
currentListenerThreads.Add(tcpListener, Thread.CurrentThread);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
while (!this.shutdown)
|
||||
{
|
||||
AcceptConnection(tcpListener);
|
||||
}
|
||||
|
||||
} catch (Exception e)
|
||||
{
|
||||
Logging.Log(LogLevel.ERROR, "HTTPServer: Listener thread caught exception {0}",e);
|
||||
Logging.Log(e);
|
||||
}
|
||||
|
||||
lock (this)
|
||||
{
|
||||
currentListenerThreads.Remove(tcpListener);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
<Compile Include="exceptions\HttpException.cs" />
|
||||
<Compile Include="exceptions\IllegalRequestException.cs" />
|
||||
<Compile Include="exceptions\ResourceNotFoundException.cs" />
|
||||
<Compile Include="threads\Pool.cs" />
|
||||
<Compile Include="HTTPServer.cs" />
|
||||
<Compile Include="HttpReader.cs" />
|
||||
<Compile Include="HttpRequest.cs" />
|
||||
|
@ -50,8 +49,17 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="exceptions\" />
|
||||
<Folder Include="threads\" />
|
||||
<Folder Include="session\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ln.logging\ln.logging.csproj">
|
||||
<Project>{D471A566-9FB6-41B2-A777-3C32874ECD0E}</Project>
|
||||
<Name>ln.logging</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\ln.types\ln.types.csproj">
|
||||
<Project>{8D9AB9A5-E513-4BA7-A450-534F6456BF28}</Project>
|
||||
<Name>ln.types</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
|
@ -1,82 +0,0 @@
|
|||
using System;
|
||||
using System.Threading;
|
||||
using System.Collections.Generic;
|
||||
namespace ln.http.threads
|
||||
{
|
||||
public delegate void JobDelegate();
|
||||
|
||||
public class Pool
|
||||
{
|
||||
public int Timeout { get; set; } = 15000;
|
||||
|
||||
ISet<Thread> threads = new HashSet<Thread>();
|
||||
Queue<JobDelegate> queuedJobs = new Queue<JobDelegate>();
|
||||
HashSet<Thread> idleThreads = new HashSet<Thread>();
|
||||
|
||||
public Pool()
|
||||
{
|
||||
}
|
||||
|
||||
private void AllocateThread()
|
||||
{
|
||||
Thread thread = new Thread(pool_thread);
|
||||
thread.Start();
|
||||
}
|
||||
|
||||
public void Enqueue(JobDelegate job)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
queuedJobs.Enqueue(job);
|
||||
|
||||
if (idleThreads.Count == 0)
|
||||
{
|
||||
AllocateThread();
|
||||
}
|
||||
else
|
||||
{
|
||||
Monitor.Pulse(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void pool_thread()
|
||||
{
|
||||
Thread me = Thread.CurrentThread;
|
||||
|
||||
try
|
||||
{
|
||||
JobDelegate job = null;
|
||||
do
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (queuedJobs.Count == 0)
|
||||
{
|
||||
idleThreads.Add(me);
|
||||
bool s = Monitor.Wait(this, Timeout);
|
||||
idleThreads.Remove(me);
|
||||
if (!s)
|
||||
break;
|
||||
}
|
||||
job = queuedJobs.Dequeue();
|
||||
}
|
||||
|
||||
job();
|
||||
|
||||
} while (true);
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Exception in worker thread: {0}", e);
|
||||
}
|
||||
|
||||
lock (this)
|
||||
{
|
||||
threads.Remove(me);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue