source: binary-improvements/WebInterface/Web/Web.cs@ 226

Last change on this file since 226 was 224, checked in by alloc, 10 years ago

A11 preps

File size: 5.8 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Net;
5using System.Net.Sockets;
6using System.Reflection;
7using System.Text;
8using System.Threading;
9using UnityEngine;
10
11namespace AllocsFixes.NetConnections.Servers.Web
12{
13 public class Web : IServer {
14 private readonly HttpListener _listener = new HttpListener ();
15 private Dictionary<string, PathHandler> handlers = new Dictionary<string, PathHandler> ();
16 private bool authEnabled = false;
17 private string realm = "7dtd Admin Panel";
18 public static int handlingCount = 0;
19 public static int currentHandlers = 0;
20 private string dataFolder;
21 private bool mapEnabled = false;
22
23 public Web () {
24 try {
25 int webPort = GamePrefs.GetInt (EnumGamePrefs.ControlPanelPort);
26 if (webPort < 1 || webPort > 65533) {
27 Log.Out ("Webserver not started (ControlPanelPort not within 1-65534)");
28 return;
29 }
30 if (!Directory.Exists (Path.GetDirectoryName (Assembly.GetExecutingAssembly ().Location) + "/webserver")) {
31 Log.Out ("Webserver not started (folder \"webserver\" not found in WebInterface mod folder)");
32 return;
33 }
34
35 dataFolder = Path.GetDirectoryName (Assembly.GetExecutingAssembly ().Location) + "/webserver";
36
37 if (!HttpListener.IsSupported) {
38 Log.Out ("Webserver not started (needs Windows XP SP2, Server 2003 or later or Mono)");
39 return;
40 }
41
42 handlers.Add (
43 "/index.htm",
44 new SimpleRedirectHandler ("/static/index.html"));
45 handlers.Add (
46 "/favicon.ico",
47 new SimpleRedirectHandler ("/static/favicon.ico"));
48 handlers.Add (
49 "/static/",
50 new StaticHandler (
51 "/static/",
52 dataFolder,
53 new AllocsFixes.FileCache.DirectAccess (),
54 true)
55 ); // TODO: Enable cache
56
57 {
58 if (AllocsFixes.Mods.ModLoaded ("AllocsMapRendering")) {
59 Assembly renderAssembly = AllocsFixes.Mods.GetModAssembly ("AllocsMapRendering");
60 foreach (Type t in renderAssembly.GetTypes ()) {
61 foreach (MethodInfo mi in t.GetMethods ()) {
62 if (mi.Name == "GetTileCache") {
63 handlers.Add (
64 "/map/",
65 new StaticHandler (
66 "/map/",
67 StaticDirectories.GetSaveGameDir () + "/map",
68 mi.Invoke (null, new object[0]) as AllocsFixes.FileCache.AbstractCache,
69 false)
70 );
71 mapEnabled = true;
72 }
73 }
74 }
75 }
76 }
77 handlers.Add ("/api/", new ApiHandler ("/api/"));
78
79 _listener.Prefixes.Add (String.Format ("http://*:{0}/", webPort + 2));
80 authEnabled = File.Exists (dataFolder + "/protect");
81 if (authEnabled) {
82 _listener.AuthenticationSchemes = AuthenticationSchemes.Basic;
83 }
84 _listener.Start ();
85 _listener.Realm = realm;
86
87 NetTelnetServer.RegisterServer (this);
88
89 _listener.BeginGetContext (new AsyncCallback (HandleRequest), _listener);
90
91 Log.Out ("Started Webserver on " + (webPort + 2) + " (authentication " + (authEnabled ? "enabled" : "disabled") + ")");
92 } catch (Exception e) {
93 Log.Out ("Error in Web.ctor: " + e);
94 }
95 }
96
97 private void HandleRequest (IAsyncResult result) {
98 if (_listener.IsListening) {
99 Interlocked.Increment (ref handlingCount);
100 Interlocked.Increment (ref currentHandlers);
101 HttpListenerContext ctx = _listener.EndGetContext (result);
102 _listener.BeginGetContext (new AsyncCallback (HandleRequest), _listener);
103 try {
104 ctx.Response.ProtocolVersion = new Version ("1.0");
105
106 HttpListenerBasicIdentity user = Authorize (ctx);
107
108 if (!authEnabled || (user.Name.ToLower ().Equals ("admin") && user.Password.Equals (GamePrefs.GetString (EnumGamePrefs.ControlPanelPassword)))) {
109 if (ctx.Request.Url.AbsolutePath.Length < 2) {
110 handlers ["/index.htm"].HandleRequest (ctx.Request, ctx.Response, user);
111 return;
112 } else {
113 foreach (KeyValuePair<string, PathHandler> kvp in handlers) {
114 if (ctx.Request.Url.AbsolutePath.StartsWith (kvp.Key)) {
115 kvp.Value.HandleRequest (ctx.Request, ctx.Response, user);
116 return;
117 }
118 }
119 }
120
121 Log.Out ("Error in Web.HandleRequest(): No handler found for path \"" + ctx.Request.Url.AbsolutePath + "\"");
122 ctx.Response.StatusCode = (int)HttpStatusCode.NotFound;
123 } else {
124 ctx.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
125 ctx.Response.Headers ["WWW-Authenticate"] = "Basic realm=\"" + realm + "\"";
126 }
127 } catch (IOException e) {
128 if (e.InnerException is SocketException) {
129 Log.Out ("Error in Web.HandleRequest(): Remote host closed connection: " + e.InnerException.Message);
130 } else {
131 Log.Out ("Error (IO) in Web.HandleRequest(): " + e);
132 }
133 } catch (Exception e) {
134 Log.Out ("Error in Web.HandleRequest(): " + e);
135 } finally {
136 if (ctx != null) {
137 ctx.Response.OutputStream.Close ();
138 }
139 Interlocked.Decrement (ref currentHandlers);
140 }
141 }
142 }
143
144 private HttpListenerBasicIdentity Authorize (HttpListenerContext ctx) {
145 try {
146 return (HttpListenerBasicIdentity)ctx.User.Identity;
147 } catch (NullReferenceException) {
148 return null;
149 }
150 }
151
152 public void Disconnect () {
153 try {
154 _listener.Stop ();
155 _listener.Close ();
156 } catch (Exception e) {
157 Log.Out ("Error in Web.Disconnect: " + e);
158 }
159 }
160
161 public void SendLine (string line) {
162 try {
163 //Log.Out ("NOT IMPLEMENTED: Web.WriteToClient");
164 } catch (Exception e) {
165 Log.Out ("Error in Web.WriteToClient: " + e);
166 }
167 }
168
169 public void SendLog (string text, string trace, UnityEngine.LogType type) {
170 throw new System.NotImplementedException ();
171 }
172
173 public static void SetResponseTextContent (HttpListenerResponse resp, string text) {
174 byte[] buf = Encoding.UTF8.GetBytes (text);
175 resp.ContentLength64 = buf.Length;
176 resp.ContentType = "text/html";
177 resp.ContentEncoding = Encoding.UTF8;
178 resp.OutputStream.Write (buf, 0, buf.Length);
179 }
180
181 }
182}
Note: See TracBrowser for help on using the repository browser.