Exemple #1
0
        public void TestFlushableMemoryPool()
        {
            Assert.AreEqual(0, FlushableMemoryPool.AllocatedSize);

            List <IntPtr> pointers = new List <IntPtr>();

            int size = 0;

            for (int i = 1; i < 1025; i++)
            {
                size += i * sizeof(int);

                pointers.Add(FlushableMemoryPool.Allocate <int>(i));
            }

            Assert.AreEqual(size, FlushableMemoryPool.AllocatedSize);

            FlushableMemoryPool.AquireOrFlush();
            pointers.Clear();

            for (int i = 1; i < 1025; i++)
            {
                pointers.Add(FlushableMemoryPool.Allocate <int>(i));

                unsafe
                {
                    *(int *)(pointers.Last()) = i;
                }
            }

            Assert.AreEqual(size, FlushableMemoryPool.AllocatedSize);

            for (int i = 0; i < 1024; i++)
            {
                if (i > 0)
                {
                    Assert.IsTrue((pointers[i - 1] + i * sizeof(int)) == (pointers[i]));
                }

                unsafe
                {
                    *(int *)(pointers[i]) = i + 1;
                }
            }

            FlushableMemoryPool.Destroy();
        }
        /// <inheritdoc />
        protected override void HandleClient(TcpClient client, NetworkStream networkStream)
        {
            FlushableMemoryPool.AquireOrFlush();
            Stream   stream  = networkStream;
            Encoding enc     = Encoding.UTF8;
            string   lastmsg = null;

            CurrentClientRemoteEndpoint = client.Client.RemoteEndPoint.ToString();

            if (Certificate != null)
            {
                try
                {
                    System.Net.Security.SslStream sslStream = new System.Net.Security.SslStream(networkStream, false);
                    sslStream.AuthenticateAsServer(Certificate, false, EnabledSslProtocols, true);
                    stream = sslStream;
                    CurrentThreadStream = stream;
                }
                catch (ThreadAbortException)
                {
                    try
                    {
                        stream.Close();
                    }
                    catch { }

                    return;
                }
                catch (Exception e)
                {
                    Logger.LogError($"Failed to authenticate. ({e.Message} / Inner Exception: {e.InnerException?.Message})");

                    // With misconfigured Certificates every request might fail here.

                    if (BlockInsecureConnections)
                    {
                        try
                        {
                            stream.Close();
                        }
                        catch { }

                        return;
                    }

                    try
                    {
                        byte[] response = new HttpResponse(null, Master.GetErrorMsg(
                                                               "Error 500: Internal Server Error",
                                                               "<p>An Exception occured while trying to authenticate the connection.</p><br><br><div style='font-family:\"Consolas\",monospace;font-size: 13;color:#4C4C4C;'>"
                                                               + GetErrorMsg(e, null, null).Replace("\r\n", "<br>").Replace(" ", "&nbsp;") + "</div><br>"
                                                               + "</div></p>"))
                        {
                            Status = "500 Internal Server Error"
                        }.GetPackage();

                        networkStream.Write(response, 0, response.Length);

                        Logger.LogInformation($"Replied authentication error to client.");
                    }
                    catch (Exception ex)
                    {
                        Logger.LogInformation($"Failed to reply securely to unauthenticated ssl Connection. ({ex.Message})");
                    }

                    try
                    {
                        stream.Close();
                    }
                    catch { }

                    return;
                }
            }
            else if (BlockInsecureConnections)
            {
                Logger.LogCrashAndBurn($"Failed to authenticate. (No Certificate given.) This will fail every single time. Crashing...");

                try
                {
                    stream.Close();
                }
                catch { }

                return;
            }

            byte[] msg;
            int    bytes = 0;

            Stopwatch stopwatch = new Stopwatch();

            while (Running)
            {
                msg = new byte[RequestMaxPacketSize];

                try
                {
                    if (stopwatch.IsRunning)
                    {
                        stopwatch.Reset();
                    }

                    bytes = stream.Read(msg, 0, RequestMaxPacketSize);
                    stopwatch.Start();
                }
                catch (ThreadAbortException)
                {
                    break;
                }
                catch (Exception e)
                {
                    if (Running)
                    {
                        if (e.InnerException != null && e.InnerException is SocketException)
                        {
                            if (((SocketException)e.InnerException).SocketErrorCode == SocketError.TimedOut)
                            {
                                try
                                {
                                    string remoteEndPoint = client.Client.RemoteEndPoint.ToString();

                                    client.Client.Shutdown(SocketShutdown.Both);
                                    client.Close();

                                    Logger.LogTrace($"The connection to {remoteEndPoint} has been closed ordinarily after the timeout has been reached.", stopwatch);
                                }
                                catch { };

                                break;
                            }
                            else
                            {
                                string remoteEndPoint = "<unknown remote endpoint>";

                                try
                                {
                                    remoteEndPoint = client.Client.RemoteEndPoint.ToString();

                                    client.Client.Shutdown(SocketShutdown.Both);
                                    client.Close();

                                    Logger.LogTrace($"The connection to {remoteEndPoint} has been closed ordinarily after a SocketException occured. ({((SocketException)e.InnerException).SocketErrorCode})", stopwatch);

                                    break;
                                }
                                catch { };

                                Logger.LogTrace($"A SocketException occured with {remoteEndPoint}. ({((SocketException)e.InnerException).SocketErrorCode})", stopwatch);

                                break;
                            }
                        }

                        Logger.LogError("An exception occured in the client handler:  " + e.SafeToString(), stopwatch);

                        try
                        {
                            client.Client.Shutdown(SocketShutdown.Both);
                            client.Close();

                            Logger.LogTrace($"The connection to {client.Client.RemoteEndPoint} has been closed ordinarily.", stopwatch);
                        }
                        catch { };
                    }

                    break;
                }

                if (bytes == 0)
                {
                    break;
                }

                try
                {
                    string      msg_ = enc.GetString(msg, 0, bytes);
                    HttpRequest htp  = HttpRequest.Constructor(ref msg_, lastmsg, stream);
                    htp.TcpClient = client;

                    byte[] buffer;

                    try
                    {
                        if (htp.IsIncompleteRequest)
                        {
                            lastmsg = msg_;
                        }
                        else if (htp.RequestUrl == "")
                        {
                            lastmsg = null;

                            HttpResponse htp_ = new HttpResponse(null, Master.GetErrorMsg(
                                                                     "Error 501: Not Implemented",
                                                                     "<p>The Feature that you were trying to use is not yet implemented.</p>" +
#if DEBUG
                                                                     "<p>The Package you were sending:<br><div style='font-family:\"Consolas\",monospace;font-size: 13;color:#4C4C4C;'>" +
                                                                     msg_.Replace("\r\n", "<br>") +
#endif
                                                                     "</div></p>"))
                            {
                                Status = "501 Not Implemented"
                            };

                            buffer = htp_.GetPackage();
                            stream.Write(buffer, 0, buffer.Length);

                            Logger.LogInformation("Client requested an empty URL. We sent Error 501.", stopwatch);
                        }
                        else
                        {
                            lastmsg = null;
                            HttpResponse response = null;

                            try
                            {
                                response = RequestHandler.GetResponse(htp);

                                if (response == null)
                                {
                                    goto InvalidResponse;
                                }

                                buffer = response.GetPackage();
                                stream.Write(buffer, 0, buffer.Length);

                                continue;
                            }
                            catch (ThreadAbortException)
                            {
                                try
                                {
                                    stream.Close();
                                }
                                catch { }

                                return;
                            }
                            catch (WebSocketManagementOvertakeFlagException)
                            {
                                return;
                            }
                            catch (Exception e)
                            {
                                HttpResponse htp_ = new HttpResponse(null, Master.GetErrorMsg(
                                                                         "Error 500: Internal Server Error",
                                                                         "<p>An Exception occured while processing the response.</p><br><br><div style='font-family:\"Consolas\",monospace;font-size: 13;color:#4C4C4C;'>"
                                                                         + GetErrorMsg(e, SessionData.CurrentSession, msg_).Replace("\r\n", "<br>").Replace(" ", "&nbsp;") + "</div><br>"
                                                                         + "</div></p>"))
                                {
                                    Status = "500 Internal Server Error"
                                };

                                buffer = htp_.GetPackage();
                                stream.Write(buffer, 0, buffer.Length);

                                Logger.LogWarning($"Client requested '{htp.RequestUrl}'. {e.GetType()} thrown.\n" + e.SafeToString(), stopwatch);

                                ServerHandler.LogMessage($"Client requested '{htp.RequestUrl}'. {e.GetType()} thrown.\n" + e.SafeToString(), stopwatch);

                                continue;
                            }


InvalidResponse:

                            if (htp.RequestUrl.EndsWith("/"))
                            {
                                buffer = new HttpResponse(null, Master.GetErrorMsg(
                                                              "Error 403: Forbidden",
                                                              "<p>The Requested URL cannot be delivered due to insufficient priveleges.</p>" +
#if DEBUG
                                                              "<p>The Package you were sending:<br><div style='font-family:\"Consolas\",monospace;font-size: 13;color:#4C4C4C;'>" +
                                                              msg_.Replace("\r\n", "<br>") +
#endif
                                                              "</div></p>"))
                                {
                                    Status = "403 Forbidden"
                                }.GetPackage();
                            }
                            else
                            {
                                buffer = new HttpResponse(null, Master.GetErrorMsg(
                                                              "Error 404: Page Not Found",
                                                              "<p>The URL you requested did not match any page or file on the server.</p>" +
#if DEBUG
                                                              "<p>The Package you were sending:<br><div style='font-family:\"Consolas\",monospace;font-size: 13;color:#4C4C4C;'>" +
                                                              msg_.Replace("\r\n", "<br>") +
#endif
                                                              "</div></p>"))
                                {
                                    Status = "404 File Not Found"
                                }.GetPackage();
                            }

                            stream.Write(buffer, 0, buffer.Length);

                            Logger.LogInformation("Client requested the URL '" + htp.RequestUrl + "' which couldn't be found on the server. Retrieved Error 403/404.", stopwatch);
                        }
                    }
                    catch (Exception e)
                    {
                        Logger.LogError("An error occurred in the client handler: " + e.SafeToString(), stopwatch);
                    }
                }
                catch (ThreadAbortException)
                {
                    try
                    {
                        stream.Close();
                    }
                    catch { }

                    return;
                }
                catch (Exception e)
                {
                    Logger.LogError("An error occurred in the client handler: " + e.SafeToString(), stopwatch);
                }
            }
        }