wasSharpNET

Subversion Repositories:
Compare Path: Rev
With Path: Rev
?path1? @ 8  →  ?path2? @ 9
/Network/HTTP/HTTPServer.cs
@@ -0,0 +1,125 @@
///////////////////////////////////////////////////////////////////////////
// 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();
private int processedRequests;
 
private readonly ManualResetEvent stopEvent = new ManualResetEvent(false);
 
public HashSet<string> Prefixes { get; set; } = new HashSet<string>();
 
public AuthenticationSchemes AuthenticationSchemes { get; set; } = AuthenticationSchemes.None;
 
public bool IsRunning => HTTPListener.IsListening;
 
public bool Start()
{
foreach (var prefix in Prefixes)
{
if (!HTTPListener.Prefixes.Contains(prefix))
HTTPListener.Prefixes.Add(prefix);
}
 
// Set up HTTP listener.
HTTPListener.AuthenticationSchemes = AuthenticationSchemes;
 
// Do not start the HTTP server if it is already running.
if (HTTPListener.IsListening)
return false;
 
// Do not bomb if the client disconnects.
HTTPListener.IgnoreWriteExceptions = true;
HTTPListener.Start();
var state = new HTTPServerCallbackState(HTTPListener);
ThreadPool.QueueUserWorkItem(Listen, state);
return true;
}
 
public bool Stop()
{
return stopEvent.Set();
}
 
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, stopEvent});
 
if (n.Equals(1))
{
callbackState.Listener.Stop();
break;
}
}
}
 
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; }
}
}
}
/Network/TCP/Utilities.cs
@@ -0,0 +1,40 @@
///////////////////////////////////////////////////////////////////////////
// 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.Net;
using System.Net.Sockets;
 
namespace wasSharpNET.Network.TCP
{
public static class Utilities
{
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
/// <summary>
/// Try to find an unused port.
/// </summary>
/// <param name="address">the address associated with the port</param>
/// <param name="port">an integer to hold the port if found</param>
/// <returns>true if an unused port could be found</returns>
public static bool TryGetUnusedPort(IPAddress address, out int port)
{
try
{
var l = new TcpListener(address, 0);
l.Start();
port = ((IPEndPoint) l.LocalEndpoint).Port;
l.Stop();
return true;
}
catch
{
port = default(int);
return false;
}
}
}
}