/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: Runtime.hpp Date: 2021-6-9 Author: Reece ***/ #pragma once #if defined(AURORA_ENGINE_KERNEL_STATIC) #define AUKN_SYM #else #if defined(AURORA_ENGINE_KERNEL_EXPORT) #define AUKN_SYM AURORA_SYMBOL_EXPORT #else #define AUKN_SYM AURORA_SYMBOL_IMPORT #endif #endif #include #if defined(_AUHAS_FMT) #include #include #include #include #endif #if !defined(_AUHAS_UUID) #error Missing stduuid library #endif #include #define AUKN_SHARED_API(name, type, ...) AU_SHARED_API_EX(AUKN_SYM, name, type, ## __VA_ARGS__) #if defined(_AURORA_RUNTIME_BUILD_API_INTERFACES) #define AUKN_INTERFACE AUI_INTERFACE_IMPL #define AUKN_INTERFACE_EXT AUI_INTERFACE_EXT_IMPL #else #define AUKN_INTERFACE AUI_INTERFACE_FWD #define AUKN_INTERFACE_EXT AUI_INTERFACE_EXT_FWD #endif #include "Memory/Memory.hpp" #include "Console/Console.hpp" #include "Logging/Logging.hpp" #include "Crypto/Crypto.hpp" #include "Compression/Compression.hpp" #include "Data/Data.hpp" #include "Debug/Debug.hpp" #include "Hashing/Hashing.hpp" #include "HWInfo/HWInfo.hpp" #include "IO/IO.hpp" #include "Time/Time.hpp" #include "Locale/Locale.hpp" #include "Parse/Parse.hpp" #include "Process/Process.hpp" #include "Registry/Registry.hpp" #include "RNG/RNG.hpp" #include "Telemetry/Telemetery.hpp" #include "Threading/Threading.hpp" #include "Async/Async.hpp" #include "Processes/Processes.hpp" #include "IO/Loop/Loop.hpp" #include "IO/IPC/IPC.hpp" #include "SWInfo/SWInfo.hpp" #include "Exit/Exit.hpp" #include "CmdLine/CmdLine.hpp" #include "Utility/RateLimiter.hpp" #include "Memory/_ByteBuffer.hpp" namespace AuAsync = Aurora::Async; namespace AuBuild = Aurora::Build; namespace AuCompression = Aurora::Compression; namespace AuConsole = Aurora::Console; namespace AuCmdLine = Aurora::CmdLine; namespace AuCrypto = Aurora::Crypto; namespace AuData = Aurora::Data; namespace AuDebug = Aurora::Debug; namespace AuThreading = Aurora::Threading; namespace AuThreadPrimitives = Aurora::Threading::Primitives; namespace AuThreads = Aurora::Threading::Threads; namespace AuHwInfo = Aurora::HWInfo; namespace AuSwInfo = Aurora::SWInfo; namespace AuIO = Aurora::IO; namespace AuIOFS = Aurora::IO::FS; namespace AuIONet = Aurora::IO::Net; namespace AuIOIPC = Aurora::IO::IPC; namespace AuIOLoop = Aurora::IO::Loop; // Legacy shorthands; wont deprecate namespace AuIPC = Aurora::IO::IPC; namespace AuLoop = Aurora::IO::Loop; namespace AuNet = Aurora::IO::Net; namespace AuFS = Aurora::IO::FS; namespace AuRng = Aurora::RNG; namespace AuLocale = Aurora::Locale; namespace AuParse = Aurora::Parse; namespace AuProcess = Aurora::Process; namespace AuProcesses = Aurora::Processes; namespace AuTelemetry = Aurora::Telemetry; namespace AuTime = Aurora::Time; namespace AuTypes = Aurora::Types; namespace AuLog = Aurora::Logging; namespace AuMemory = Aurora::Memory; namespace AuHashing = Aurora::Hashing; namespace AuExit = Aurora::Exit; using AuWorkerId_t = AuAsync::WorkerId_t; using AuWorkerPId_t = AuAsync::WorkerPId_t; using AuByteBuffer = AuMemory::ByteBuffer; using AuMemoryViewRead = AuMemory::MemoryViewRead; using AuMemoryViewWrite = AuMemory::MemoryViewWrite; using AuMemoryViewStreamRead = AuMemory::MemoryViewStreamRead; using AuMemoryViewStreamWrite = AuMemory::MemoryViewStreamWrite; static bool AuIsThreadRunning() { return !AuThreads::GetThread()->Exiting(); } static inline void AuDebugBreak() { AuDebug::DebugBreak(); } namespace Aurora { // The following configuration structures are a mess you probably wont need to think about for a while. // Let's assume it's safe to move onto some other for now, alright? struct LocalLogInfo { bool enableLogging { true }; AuUInt32 maxSizeMB { 128 * 1024 * 1024 }; // these numbers feel insane, but at least we have a max threshold int maxLogs { 1024 * 2 }; // by default, we neither leak disk space or waste opportunities of being able to dig through old data int maxLogsBeforeCompress { 16 }; // #if defined(SHIP) bool writeLogsToUserDir { true }; // use user directory #else bool writeLogsToUserDir { false }; // use cwd #endif }; // TODO: this struct is mostly placeholder BS struct TelemetryConfigDoc { LocalLogInfo localLogging; bool enabled {false}; AuString address; AuUInt16 port {45069}; AuString serviceIdnt {"7b5f7a54-7122-4489-ac1a-3d75884b307e"}; bool wantsActiveMonitoring {false}; bool privacyConsoleLog[255] {}; }; struct TelemetryConfig { bool readModNameJsonConfig {}; TelemetryConfigDoc defaultConfig; }; // TODO: this struct is mostly placeholder BS struct SocketConsole { bool enableLogging {false}; bool binaryProto {false}; AuString path; //AuIONet::ConnectionEndpoint net; }; struct ConsoleConfig { /// Enables Aurora::Console::xxxStd functions; defer to enableStdXX for default logger behaviour bool enableStdPassthrough {false}; /// Enables standard, debug, and GUI consoles bool enableConsole {true}; /// Attempt to force a terminal emulator host under graphical subsystems bool forceConsoleWindow {}; /// Attempt to force a GUI console under command line targets bool forceToolKitWindow {}; /// In conjunction with enableStdPassthrough, Aurora::Console::ReadStd reads a binary stream /// In conjunction with !enableStdPassthrough, enables stdin cmd processing, otherwise disables stdin input bool enableStdIn {true}; /// In conjunction with enableStdPassthrough, enables Aurora::Console::WriteStd to write binary, otherwise enables the console logger /// In conjunction with !enableStdPassthrough, enables stdout logging bool enableStdOut {true}; /// Use WxWidgets when possible bool enableWxWidgets {true}; /// Delegate stdout writes to loops -> recommended for servers bool asyncWrite {true}; /// Async debug log bool asyncVSLog {false}; /// Should stdout print the full date or a mere HH MM SS prefix? bool bStdOutShortTime { false }; /// bool bStdOutUseLocalTime { true }; #if 1 /// FIO config LocalLogInfo fio; #endif AuString titleBrand = "Aurora SDK Sample"; AuString supportPublic {"https://git.reece.sx/AuroraSupport/AuroraRuntime/issues"}; AuString supportInternal {"https://jira.reece.sx"}; bool consoleTTYHasPerAppHistory {true}; }; struct LoggerConfig { /// FIO config LocalLogInfo fileConfiguration; /// Socket config SocketConsole socketConfiguration; }; struct CryptoConfig { /// Defer to the rationales in the implementation bool allowChineseCerts {false}; /// Defer to the rationales in the implementation bool allowRussianCerts {true}; // TODO: we have no live or cached builtin CRL and CA retrieval and storage /// WIP bool allowHTTPRetrievalOfCerts {true}; /// bool enablePinning {true}; /// // TODO: these placeholder bits will be made redundant once AuCrypto is overhauled AuList blacklistedCerts{}; AuList whitelistedCerts{}; }; struct AsyncConfig { bool enableSchedularThread {true}; // turn this off to make your application lighter-weight; turn this on for higher performance (+expensive) scheduling bool enableSysPumpFreqnecy {false}; // turn this on to enable an async apps singleton threadpool to SysPump on worker id zero. Alternatively, use SetMainThreadForSysPumpScheduling once you have a thread pool and worker id. AuUInt32 threadPoolDefaultStackSize {}; AuUInt32 schedularFrequency {2}; // * 0.5 or 1 MS depending on the platform AuUInt32 sysPumpFrequency {25}; // x amount of schedularFrequencys }; struct FIOConfig { /// You can bypass branding by assigning an empty string to 'defaultBrand' AuString defaultBrand = "Aurora SDK Sample"; bool bForceOverlappedUtilsToDelegatedThreadPool { false }; AuUInt32 uOverlappedUtilsThreadPoolSize { 2 }; // note: this does not relate to the overlapped aio apis }; // these threads are only spawned as a fallback for AuFS::Overlapped*** apis struct DebugConfig { /** * @brief Precache/initialize symbols for printable stack traces under binaries not intended for shipping to consumers * * @warning true will result in artificially high commit charge under certain monitoring applications as application databases are * precached into memory. these maps shouldn't be duplicated across processes (if the kernel plays nice). regardless, * end users shouldn't see the hit. in the best case scenario, this serves as a quality of life upgrade for stage/debug * binaries that want real time stack traces with file locations cached. noting that this isn't optional for stage win32 * builds with live exception traces with line info. in the future, debug tools should be able to parse telemetry dumps, though. */ bool bNonshipPrecachesSymbols { true }; /** * @brief Activates the internal AddVectoredExceptionHandler handler. Might conflict with DRM and other debugging utilities */ bool bEnableWin32RootExceptionHandler { true }; /** * @brief */ bool bEnableInjectedExceptionHandler { true }; /** * @brief Raises a SysPanic in place of returning null over all allocators. This includes C++ containers which *should* be configured to use our overloaded allocators (compile ./Source/Alloc.cpp & link in with your application/library). * If you're one of those people who don't like the idea of raising out of memory exceptions, and therefore compile without exceptions, this is an alternative this allows for exceptions to remain enabled for truly exceptional behaviour * IE: we're fucked. Lets see if we can restart the root tick, at the risk of unaccounted for behaviour, because crashing over a STL parse exception or something stupid in that ballpark would be a really terrible **[end]user**-experience. */ bool bIsMemoryErrorFatal { false }; /** * @brief */ bool bIsExceptionThrowFatal { false }; bool bPrintExceptionStackTracesOut { true }; bool bIsApplicationClientSoftwareOnJitteryMemorySystem { false }; // enable me to enable padding from system out of memory conditions. // the catch: usually this memory is reserved for exit callbacks, internal low memory conditions, error reporting, and the like. // // generally you should not exploit this without ** acknowledging this thread-local condition via AuDebug::[Add/Dec]MemoryCrunch. ** ( << tl;dr: recommended way of accessing this memory) // // setting this flag enables debug buffer memory to be used at any point during any threads execution - the moment mimalloc runs // out of pre-reserved and system mappable memory. i wouldn't use this for anything except monolithic client/user-facing applications // that are likely to run on low resource systems (low spec or heavy app), with untested/uncaught C++ allocations splattered everywhere. // this could be VERY useful to end users who are running into `bIsMemoryErrorFatal` crashes. AuUInt32 uDebugMemoryReserveSize { 3 * 1024 * 1024 }; /* nowdays: a single v8 isolate is low sub-tens MB of memory, executable file sizes are low mbs, image sizes are much larger. forget small low-footprint vms of flex and bison yesteryear. 3MB given our heavyish standard footprint already is probably fine. how much memory do Java heap+JIT engines sink just to boot again? this'll allow us to high tens of KBs of malicous strings, overhead for doing telemetry/(structured ???)logging, overhead to stack traces, module cache, etc. i'm sure it'll also be enough to give back to the user, if need be. @warning: 0 = 3 * 1024 * 1024 */ }; struct RuntimeStartInfo { ConsoleConfig console; CryptoConfig crypto; TelemetryConfig telemetry; AsyncConfig async; FIOConfig fio; DebugConfig debug; bool bFIODisableBatching {true}; bool bIOLinuxHasProcIpcPerms {false}; }; /** * @brief Initializes Aurora Runtime for the first and only time * @return */ AUKN_SYM void RuntimeStart(const RuntimeStartInfo &info); /** * @brief Querys the state of the DLL or Static Library * @return true after at least one RuntimeStart */ AUKN_SYM bool RuntimeHasStarted(); /** * @brief You have **one** opportunity to swap the system locality before it locked * This can be used by platform gems to align the runtime language and decimal dot notation to a given locality * @return */ AUKN_SYM void RuntimeOverloadLocality(const AuPair &locality); /** * @brief Cleans up Aurora Runtime regardless of the count of calls to RuntimeShutdown or RuntimeStart * @return */ AUKN_SYM void RuntimeShutdown(); /** * @brief Single threaded main pump for GUI applications polling for non-async subsystem callbacks * @return */ AUKN_SYM void RuntimeSysPump(); }