wasSharpNET – Rev 10
?pathlinks?
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3 //
// Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
// rights of fair usage, the disclaimer and warranty conditions. //
///////////////////////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.Net;
using System.Threading;
namespace wasSharpNET.Network.HTTP
{
public abstract class HTTPServer
{
private int activeRequests;
private readonly HttpListener HTTPListener = new HttpListener()
{
AuthenticationSchemes = AuthenticationSchemes.None
};
private int processedRequests;
private readonly AutoResetEvent StopServerEvent = new AutoResetEvent(false);
private readonly AutoResetEvent ServerStoppedEvent = new AutoResetEvent(false);
public AuthenticationSchemes AuthenticationSchemes
{
get
{
return HTTPListener.AuthenticationSchemes;
}
set
{
HTTPListener.AuthenticationSchemes = value;
}
}
public bool IsRunning => HTTPListener.IsListening;
public bool Start(IEnumerable<string> prefixes)
{
// Do not start the HTTP server if it is already running.
if (HTTPListener.IsListening)
return false;
// Add all prefixes.
foreach (var prefix in prefixes)
{
HTTPListener.Prefixes.Add(prefix);
}
// Do not bomb if the client disconnects.
HTTPListener.IgnoreWriteExceptions = true;
HTTPListener.Start();
ThreadPool.QueueUserWorkItem(Listen, new HTTPServerCallbackState(HTTPListener));
return true;
}
public bool Stop()
{
StopServerEvent.Set();
ServerStoppedEvent.WaitOne();
HTTPListener.Prefixes.Clear();
return true;
}
private void Listen(object state)
{
var callbackState = (HTTPServerCallbackState) state;
while (callbackState.Listener.IsListening)
{
callbackState.Listener.BeginGetContext(ContextCallback, callbackState);
var n = WaitHandle.WaitAny(new WaitHandle[] {callbackState.ContextRetrieved, StopServerEvent});
if (n.Equals(1))
{
callbackState.Listener.Stop();
break;
}
}
ServerStoppedEvent.Set();
}
public abstract void ProcessHTTPContext(HttpListenerContext context);
private void ContextCallback(IAsyncResult ar)
{
var callbackState = (HTTPServerCallbackState) ar.AsyncState;
HttpListenerContext httpContext = null;
Interlocked.Increment(ref processedRequests);
Interlocked.Increment(ref activeRequests);
try
{
httpContext = callbackState.Listener.EndGetContext(ar);
}
catch (Exception)
{
Interlocked.Decrement(ref activeRequests);
return;
}
finally
{
callbackState.ContextRetrieved.Set();
}
if (httpContext == null)
return;
try
{
ProcessHTTPContext(httpContext);
}
finally
{
Interlocked.Decrement(ref activeRequests);
}
}
private class HTTPServerCallbackState
{
public HTTPServerCallbackState(HttpListener listener)
{
if (listener == null)
throw new ArgumentNullException("listener");
Listener = listener;
ContextRetrieved = new AutoResetEvent(false);
}
public HttpListener Listener { get; }
public AutoResetEvent ContextRetrieved { get; }
}
}
}
Generated by GNU Enscript 1.6.5.90.