source: binary-improvements/MapRendering/Web/Web.cs @ 238

Last change on this file since 238 was 238, checked in by alloc, 5 years ago

Server fixes for A12

File size: 5.5 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 : IConsoleServer {
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                                handlers.Add (
58                                        "/itemicons/",
59                                        new ItemIconHandler (
60                                                "/itemicons/",
61                                                true)
62                                );
63
64                                handlers.Add (
65                                        "/map/",
66                                        new StaticHandler (
67                                                "/map/",
68                                                GameUtils.GetSaveGameDir () + "/map",
69                                                MapRendering.MapRendering.GetTileCache (),
70                                                false)
71                                );
72
73                                handlers.Add ("/api/", new ApiHandler ("/api/"));
74
75                                _listener.Prefixes.Add (String.Format ("http://*:{0}/", webPort + 2));
76                                authEnabled = File.Exists (dataFolder + "/protect");
77                                if (authEnabled) {
78                                        _listener.AuthenticationSchemes = AuthenticationSchemes.Basic;
79                                }
80                                _listener.Start ();
81                                _listener.Realm = realm;
82
83                                SdtdConsole.Instance.RegisterServer (this);
84
85                                _listener.BeginGetContext (new AsyncCallback (HandleRequest), _listener);
86
87                                Log.Out ("Started Webserver on " + (webPort + 2) + " (authentication " + (authEnabled ? "enabled" : "disabled") + ")");
88                        } catch (Exception e) {
89                                Log.Out ("Error in Web.ctor: " + e);
90                        }
91                }
92
93                private void HandleRequest (IAsyncResult result) {
94                        if (_listener.IsListening) {
95                                Interlocked.Increment (ref handlingCount);
96                                Interlocked.Increment (ref currentHandlers);
97                                HttpListenerContext ctx = _listener.EndGetContext (result);
98                                _listener.BeginGetContext (new AsyncCallback (HandleRequest), _listener);
99                                try {
100                                        ctx.Response.ProtocolVersion = new Version ("1.0");
101
102                                        HttpListenerBasicIdentity user = Authorize (ctx);
103
104                                        if (!authEnabled || (user.Name.ToLower ().Equals ("admin") && user.Password.Equals (GamePrefs.GetString (EnumGamePrefs.ControlPanelPassword)))) {
105                                                if (ctx.Request.Url.AbsolutePath.Length < 2) {
106                                                        handlers ["/index.htm"].HandleRequest (ctx.Request, ctx.Response, user);
107                                                        return;
108                                                } else {
109                                                        foreach (KeyValuePair<string, PathHandler> kvp in handlers) {
110                                                                if (ctx.Request.Url.AbsolutePath.StartsWith (kvp.Key)) {
111                                                                        kvp.Value.HandleRequest (ctx.Request, ctx.Response, user);
112                                                                        return;
113                                                                }
114                                                        }
115                                                }
116
117                                                Log.Out ("Error in Web.HandleRequest(): No handler found for path \"" + ctx.Request.Url.AbsolutePath + "\"");
118                                                ctx.Response.StatusCode = (int)HttpStatusCode.NotFound;
119                                        } else {
120                                                ctx.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
121                                                ctx.Response.Headers ["WWW-Authenticate"] = "Basic realm=\"" + realm + "\"";
122                                        }
123                                } catch (IOException e) {
124                                        if (e.InnerException is SocketException) {
125                                                Log.Out ("Error in Web.HandleRequest(): Remote host closed connection: " + e.InnerException.Message);
126                                        } else {
127                                                Log.Out ("Error (IO) in Web.HandleRequest(): " + e);
128                                        }
129                                } catch (Exception e) {
130                                        Log.Out ("Error in Web.HandleRequest(): " + e);
131                                } finally {
132                                        if (ctx != null) {
133                                                ctx.Response.OutputStream.Close ();
134                                        }
135                                        Interlocked.Decrement (ref currentHandlers);
136                                }
137                        }
138                }
139
140                private HttpListenerBasicIdentity Authorize (HttpListenerContext ctx) {
141                        try {
142                                return (HttpListenerBasicIdentity)ctx.User.Identity;
143                        } catch (NullReferenceException) {
144                                return null;
145                        }
146                }
147
148                public void Disconnect () {
149                        try {
150                                _listener.Stop ();
151                                _listener.Close ();
152                        } catch (Exception e) {
153                                Log.Out ("Error in Web.Disconnect: " + e);
154                        }
155                }
156
157                public void SendLine (string line) {
158                        try {
159                                //Log.Out ("NOT IMPLEMENTED: Web.WriteToClient");
160                        } catch (Exception e) {
161                                Log.Out ("Error in Web.WriteToClient: " + e);
162                        }
163                }
164
165                public void SendLog (string text, string trace, UnityEngine.LogType type) {
166                        //throw new System.NotImplementedException ();
167                }
168
169                public static void SetResponseTextContent (HttpListenerResponse resp, string text) {
170                        byte[] buf = Encoding.UTF8.GetBytes (text);
171                        resp.ContentLength64 = buf.Length;
172                        resp.ContentType = "text/html";
173                        resp.ContentEncoding = Encoding.UTF8;
174                        resp.OutputStream.Write (buf, 0, buf.Length);
175                }
176
177        }
178}
Note: See TracBrowser for help on using the repository browser.