using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Text; using System.Threading; using UnityEngine; namespace AllocsFixes.NetConnections.Servers.Web { public class Web : IServer { private readonly HttpListener _listener = new HttpListener (); private Dictionary handlers = new Dictionary (); public Web (int port) { try { if (!HttpListener.IsSupported) throw new NotSupportedException ("Needs Windows XP SP2, Server 2003 or later."); handlers.Add ("/index.htm", new SimpleRedirectHandler ("/static/index.html")); handlers.Add ("/static/", new StaticHandler ("/static/", Application.dataPath + "/../webserver", false/*true*/, true)); // TODO: Enable cache handlers.Add ("/map/", new StaticHandler ("/map/", StaticDirectories.GetSaveGameDir () + "/map", false, false)); handlers.Add ("/api/", new ApiHandler ("/api/")); _listener.Prefixes.Add (String.Format ("http://*:{0}/", port)); if (File.Exists (Application.dataPath + "/../webserver/protect")) _listener.AuthenticationSchemes = AuthenticationSchemes.Basic; _listener.Start (); ThreadPool.QueueUserWorkItem ((o) => { try { while (_listener.IsListening) { ThreadPool.QueueUserWorkItem ((c) => { HttpListenerContext ctx = c as HttpListenerContext; HandleRequest (ctx); }, _listener.GetContext ()); } } catch { } } ); Log.Out ("Started Webserver on " + port + " (authentication " + (_listener.AuthenticationSchemes == AuthenticationSchemes.Basic ? "enabled" : "disabled") + ")"); } catch (Exception e) { Log.Out ("Error in Web.ctor: " + e); } } private void HandleRequest (HttpListenerContext ctx) { try { ctx.Response.ProtocolVersion = new Version ("1.1"); HttpListenerBasicIdentity user = Authorize (ctx); if (ctx.Request.Url.AbsolutePath.Length < 2) { handlers ["/index.htm"].HandleRequest (ctx.Request, ctx.Response, user); return; } else { foreach (KeyValuePair kvp in handlers) { if (ctx.Request.Url.AbsolutePath.StartsWith (kvp.Key)) { kvp.Value.HandleRequest (ctx.Request, ctx.Response, user); return; } } } Log.Out ("Error in Web.HandleRequest(): No handler found for path \"" + ctx.Request.Url.AbsolutePath + "\""); ctx.Response.StatusCode = (int)HttpStatusCode.NotFound; // byte[] buf = Encoding.UTF8.GetBytes ("Hello World"); // resp.ContentLength64 = buf.Length; // resp.ContentType = "text/html"; // resp.ContentEncoding = Encoding.UTF8; // resp.OutputStream.Write (buf, 0, buf.Length); } catch (Exception e) { Log.Out ("Error in Web.HandleRequest(): " + e); } finally { ctx.Response.Close (); } } private HttpListenerBasicIdentity Authorize (HttpListenerContext ctx) { try { return (HttpListenerBasicIdentity)ctx.User.Identity; } catch (NullReferenceException) { return null; } } public void Disconnect () { try { _listener.Stop (); _listener.Close (); } catch (Exception e) { Log.Out ("Error in Web.Disconnect: " + e); } } public void WriteToClient (string line) { try { //Log.Out ("NOT IMPLEMENTED: Web.WriteToClient"); } catch (Exception e) { Log.Out ("Error in Web.WriteToClient: " + e); } } public void WriteToClient_Single (string line, IConnection client) { try { //Log.Out ("NOT IMPLEMENTED: Web.WriteToClient_Single"); } catch (Exception e) { Log.Out ("Error in Web.WriteToClient_Single: " + e); } } public static void SetResponseTextContent (HttpListenerResponse resp, string text) { byte[] buf = Encoding.UTF8.GetBytes (text); resp.ContentLength64 = buf.Length; resp.ContentType = "text/html"; resp.ContentEncoding = Encoding.UTF8; resp.OutputStream.Write (buf, 0, buf.Length); } } }