Ignore:
Timestamp:
Aug 11, 2021, 6:22:03 PM (3 years ago)
Author:
alloc
Message:

Web:

  • Added SSE (ServerSentEvents) subsystem
  • Added log endpoint to SSE. Less heavy weight and more responsive way of watching the server log
  • Bunch of refactoring
File:
1 edited

Legend:

Unmodified
Added
Removed
  • binary-improvements/MapRendering/Web/Web.cs

    r360 r367  
    99using AllocsFixes.FileCache;
    1010using AllocsFixes.NetConnections.Servers.Web.Handlers;
     11using AllocsFixes.NetConnections.Servers.Web.SSE;
    1112using UnityEngine;
    12 using UnityEngine.Profiling;
    1313
    1414namespace AllocsFixes.NetConnections.Servers.Web {
     
    1818                public static int currentHandlers;
    1919                public static long totalHandlingTime = 0;
    20                 private readonly HttpListener _listener = new HttpListener ();
    21                 private readonly string dataFolder;
     20                private readonly HttpListener listener = new HttpListener ();
    2221                private readonly Dictionary<string, PathHandler> handlers = new CaseInsensitiveStringDictionary<PathHandler> ();
    23                 private readonly bool useStaticCache;
    24 
    25                 public ConnectionHandler connectionHandler;
     22
     23                public readonly ConnectionHandler connectionHandler;
    2624
    2725                public Web () {
     
    4038
    4139                                // TODO: Read from config
    42                                 useStaticCache = false;
    43 
    44                                 dataFolder = Path.GetDirectoryName (Assembly.GetExecutingAssembly ().Location) + "/webserver";
     40                                bool useStaticCache = false;
     41
     42                                string dataFolder = Path.GetDirectoryName (Assembly.GetExecutingAssembly ().Location) + "/webserver";
    4543
    4644                                if (!HttpListener.IsSupported) {
     
    4947                                }
    5048
    51                                 handlers.Add (
    52                                         "/index.htm",
    53                                         new SimpleRedirectHandler ("/static/index.html"));
    54                                 handlers.Add (
    55                                         "/favicon.ico",
    56                                         new SimpleRedirectHandler ("/static/favicon.ico"));
    57                                 handlers.Add (
    58                                         "/session/",
    59                                         new SessionHandler (
    60                                                 "/session/",
     49                               
     50                                RegisterPathHandler ("/index.htm", new SimpleRedirectHandler ("/static/index.html"));
     51                                RegisterPathHandler ("/favicon.ico", new SimpleRedirectHandler ("/static/favicon.ico"));
     52                                RegisterPathHandler ("/session/", new SessionHandler (dataFolder));
     53                                RegisterPathHandler ("/userstatus", new UserStatusHandler ());
     54                                RegisterPathHandler ("/static/", new StaticHandler (
    6155                                                dataFolder,
    62                                                 this)
     56                                                useStaticCache ? (AbstractCache) new SimpleCache () : new DirectAccess (),
     57                                                false)
    6358                                );
    64                                 handlers.Add (
    65                                         "/userstatus",
    66                                         new UserStatusHandler ()
    67                                 );
    68                                 if (useStaticCache) {
    69                                         handlers.Add (
    70                                                 "/static/",
    71                                                 new StaticHandler (
    72                                                         "/static/",
    73                                                         dataFolder,
    74                                                         new SimpleCache (),
    75                                                         false)
    76                                         );
    77                                 } else {
    78                                         handlers.Add (
    79                                                 "/static/",
    80                                                 new StaticHandler (
    81                                                         "/static/",
    82                                                         dataFolder,
    83                                                         new DirectAccess (),
    84                                                         false)
    85                                         );
    86                                 }
    87 
    88                                 handlers.Add (
    89                                         "/itemicons/",
    90                                         new ItemIconHandler (
    91                                                 "/itemicons/",
    92                                                 true)
    93                                 );
    94 
    95                                 handlers.Add (
    96                                         "/map/",
    97                                         new StaticHandler (
    98                                                 "/map/",
     59                                RegisterPathHandler ("/itemicons/", new ItemIconHandler (true));
     60                                RegisterPathHandler ("/map/", new StaticHandler (
    9961                                                GameUtils.GetSaveGameDir () + "/map",
    10062                                                MapRendering.MapRendering.GetTileCache (),
     
    10264                                                "web.map")
    10365                                );
    104 
    105                                 handlers.Add (
    106                                         "/api/",
    107                                         new ApiHandler ("/api/")
    108                                 );
     66                                RegisterPathHandler ("/api/", new ApiHandler ());
     67                                RegisterPathHandler ("/sse/", new SseHandler ());
    10968
    11069                                connectionHandler = new ConnectionHandler ();
    11170
    112                                 _listener.Prefixes.Add (string.Format ("http://*:{0}/", webPort + 2));
    113                                 _listener.Start ();
     71                                listener.Prefixes.Add ($"http://*:{webPort + 2}/");
     72                                listener.Start ();
    11473
    11574                                SdtdConsole.Instance.RegisterServer (this);
    11675
    117                                 _listener.BeginGetContext (HandleRequest, _listener);
     76                                listener.BeginGetContext (HandleRequest, listener);
    11877
    11978                                Log.Out ("Started Webserver on " + (webPort + 2));
     
    12382                }
    12483
     84                public void RegisterPathHandler (string _urlBasePath, PathHandler _handler) {
     85                        if (handlers.ContainsKey (_urlBasePath)) {
     86                                Log.Error ($"Web: Handler for relative path {_urlBasePath} already registerd.");
     87                                return;
     88                        }
     89                       
     90                        handlers.Add (_urlBasePath, _handler);
     91                        _handler.SetBasePathAndParent (this, _urlBasePath);
     92                }
     93
    12594                public void Disconnect () {
    12695                        try {
    127                                 _listener.Stop ();
    128                                 _listener.Close ();
     96                                listener.Stop ();
     97                                listener.Close ();
    12998                        } catch (Exception e) {
    13099                                Log.Out ("Error in Web.Disconnect: " + e);
     
    132101                }
    133102
     103                public void Shutdown () {
     104                        foreach (KeyValuePair<string, PathHandler> kvp in handlers) {
     105                                kvp.Value.Shutdown ();
     106                        }
     107                }
     108
    134109                public void SendLine (string _line) {
    135110                        connectionHandler.SendLine (_line);
     
    140115                }
    141116
    142                 public static bool isSslRedirected (HttpListenerRequest _req) {
     117                public static bool IsSslRedirected (HttpListenerRequest _req) {
    143118                        string proto = _req.Headers ["X-Forwarded-Proto"];
    144                         if (!string.IsNullOrEmpty (proto)) {
    145                                 return proto.Equals ("https", StringComparison.OrdinalIgnoreCase);
    146                         }
    147 
    148                         return false;
     119                        return !string.IsNullOrEmpty (proto) && proto.Equals ("https", StringComparison.OrdinalIgnoreCase);
    149120                }
    150121               
     
    152123               
    153124#if ENABLE_PROFILER
    154                 private readonly CustomSampler authSampler = CustomSampler.Create ("Auth");
    155                 private readonly CustomSampler handlerSampler = CustomSampler.Create ("Handler");
     125                private readonly UnityEngine.Profiling.CustomSampler authSampler = UnityEngine.Profiling.CustomSampler.Create ("Auth");
     126                private readonly UnityEngine.Profiling.CustomSampler handlerSampler = UnityEngine.Profiling.CustomSampler.Create ("Handler");
    156127#endif
    157128
    158129                private void HandleRequest (IAsyncResult _result) {
    159                         if (!_listener.IsListening) {
     130                        if (!listener.IsListening) {
    160131                                return;
    161132                        }
     
    166137//                              MicroStopwatch msw = new MicroStopwatch ();
    167138#if ENABLE_PROFILER
    168                         Profiler.BeginThreadProfiling ("AllocsMods", "WebRequest");
     139                        UnityEngine.Profiling.Profiler.BeginThreadProfiling ("AllocsMods", "WebRequest");
    169140                        HttpListenerContext ctx = _listener.EndGetContext (_result);
    170141                        try {
    171142#else
    172                         HttpListenerContext ctx = _listener.EndGetContext (_result);
    173                         _listener.BeginGetContext (HandleRequest, _listener);
     143                        HttpListenerContext ctx = listener.EndGetContext (_result);
     144                        listener.BeginGetContext (HandleRequest, listener);
    174145#endif
    175146                        try {
     
    180151                                response.ProtocolVersion = HttpProtocolVersion;
    181152
    182                                 WebConnection conn;
    183153#if ENABLE_PROFILER
    184154                                authSampler.Begin ();
    185155#endif
    186                                 int permissionLevel = DoAuthentication (request, out conn);
     156                                int permissionLevel = DoAuthentication (request, out WebConnection conn);
    187157#if ENABLE_PROFILER
    188158                                authSampler.End ();
     
    194164
    195165                                if (conn != null) {
    196                                         Cookie cookie = new Cookie ("sid", conn.SessionID, "/");
    197                                         cookie.Expired = false;
    198                                         cookie.Expires = new DateTime (2020, 1, 1);
    199                                         cookie.HttpOnly = true;
    200                                         cookie.Secure = false;
     166                                        Cookie cookie = new Cookie ("sid", conn.SessionID, "/") {
     167                                                Expired = false,
     168                                                Expires = DateTime.MinValue,
     169                                                HttpOnly = true,
     170                                                Secure = false
     171                                        };
    201172                                        response.AppendCookie (cookie);
    202173                                }
     
    260231                        } finally {
    261232                                _listener.BeginGetContext (HandleRequest, _listener);
    262                                 Profiler.EndThreadProfiling ();
     233                                UnityEngine.Profiling.Profiler.EndThreadProfiling ();
    263234                        }
    264235#endif
     
    281252                        }
    282253
     254                        string remoteEndpointString = _req.RemoteEndPoint.ToString ();
     255
    283256                        if (_req.QueryString ["adminuser"] != null && _req.QueryString ["admintoken"] != null) {
    284257                                WebPermissions.AdminToken admin = WebPermissions.Instance.GetWebAdmin (_req.QueryString ["adminuser"],
     
    288261                                }
    289262
    290                                 Log.Warning ("Invalid Admintoken used from " + _req.RemoteEndPoint);
     263                                Log.Warning ("Invalid Admintoken used from " + remoteEndpointString);
    291264                        }
    292265
     
    299272                                                int level = GameManager.Instance.adminTools.GetUserPermissionLevel (id.ToString ());
    300273                                                Log.Out ("Steam OpenID login from {0} with ID {1}, permission level {2}",
    301                                                         _req.RemoteEndPoint.ToString (), con.SteamID, level);
     274                                                        remoteEndpointString, con.SteamID, level);
    302275                                                return level;
    303276                                        }
    304277
    305                                         Log.Out ("Steam OpenID login failed from {0}", _req.RemoteEndPoint.ToString ());
     278                                        Log.Out ("Steam OpenID login failed from {0}", remoteEndpointString);
    306279                                } catch (Exception e) {
    307280                                        Log.Error ("Error validating login:");
Note: See TracChangeset for help on using the changeset viewer.