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(" ", " ") + "</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(" ", " ") + "</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); } } }