mirror of
https://github.com/brazilofmux/tinymux
synced 2026-08-13 00:23:11 -04:00
High: - H-4: Session token TTL (session_token_ttl, default 24h) and rotation on re-authentication. Expired tokens rejected in findByPersistId. - H-5: gRPC TLS support via grpc_tls_cert/grpc_tls_key config options. Warning logged when using insecure credentials. Medium: - M-1: Replace deprecated getpass() with termios echo-disable on POSIX - M-3: O(1) findByPersistId via unordered_map persistIdIndex_ - M-4: Account creation rate-limited to 2/hour per IP - M-6: strerror_r portability guard for GNU vs XSI semantics - M-7: GMCP cache capped at 64 packages per session - M-8: OutputItem::render uses heap buffer (4x input + 256) instead of fixed 8000-byte stack buffer Low: - L-3: SIGHUP log rotation via logReopen() (for logrotate integration) - L-4: Remove dead stub files front_door.cpp/h, back_door.cpp/h - L-5: Adaptive event loop poll: 10ms when active, ramps to 100ms idle Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
99 lines
2.4 KiB
C++
99 lines
2.4 KiB
C++
#include "hydra_log.h"
|
|
#include <cstdarg>
|
|
#include <cstdio>
|
|
#include <ctime>
|
|
#include <mutex>
|
|
|
|
static FILE* s_logFile = nullptr;
|
|
static LogLevel s_logLevel = LogLevel::Info;
|
|
static std::mutex s_logMutex;
|
|
static std::string s_logPath;
|
|
|
|
static LogLevel parseLevel(const std::string& level) {
|
|
if (level == "debug") return LogLevel::Debug;
|
|
if (level == "info") return LogLevel::Info;
|
|
if (level == "warn") return LogLevel::Warn;
|
|
if (level == "error") return LogLevel::Error;
|
|
return LogLevel::Info;
|
|
}
|
|
|
|
static const char* levelString(LogLevel level) {
|
|
switch (level) {
|
|
case LogLevel::Debug: return "DEBUG";
|
|
case LogLevel::Info: return "INFO";
|
|
case LogLevel::Warn: return "WARN";
|
|
case LogLevel::Error: return "ERROR";
|
|
}
|
|
return "INFO";
|
|
}
|
|
|
|
bool logInit(const std::string& filePath, const std::string& level) {
|
|
s_logLevel = parseLevel(level);
|
|
s_logPath = filePath;
|
|
|
|
if (filePath.empty() || filePath == "-") {
|
|
s_logFile = stderr;
|
|
return true;
|
|
}
|
|
|
|
s_logFile = fopen(filePath.c_str(), "a");
|
|
if (!s_logFile) {
|
|
fprintf(stderr, "HYDRA: cannot open log file: %s\n", filePath.c_str());
|
|
s_logFile = stderr;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void logShutdown() {
|
|
if (s_logFile && s_logFile != stderr) {
|
|
fclose(s_logFile);
|
|
}
|
|
s_logFile = nullptr;
|
|
}
|
|
|
|
void logReopen() {
|
|
std::lock_guard<std::mutex> lock(s_logMutex);
|
|
if (s_logPath.empty() || s_logFile == stderr) return;
|
|
|
|
FILE* newFile = fopen(s_logPath.c_str(), "a");
|
|
if (newFile) {
|
|
if (s_logFile && s_logFile != stderr) {
|
|
fclose(s_logFile);
|
|
}
|
|
s_logFile = newFile;
|
|
}
|
|
// If fopen fails, keep the old file handle
|
|
}
|
|
|
|
void logMessage(LogLevel level, const char* fmt, ...) {
|
|
if (level < s_logLevel) return;
|
|
if (!s_logFile) return;
|
|
|
|
time_t now = time(nullptr);
|
|
struct tm tm;
|
|
#if defined(_WIN32)
|
|
_localtime64_s(&tm, &now);
|
|
#else
|
|
localtime_r(&now, &tm);
|
|
#endif
|
|
|
|
char timebuf[32];
|
|
strftime(timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S", &tm);
|
|
|
|
std::lock_guard<std::mutex> lock(s_logMutex);
|
|
|
|
fprintf(s_logFile, "%s [%s] ", timebuf, levelString(level));
|
|
|
|
va_list args;
|
|
va_start(args, fmt);
|
|
vfprintf(s_logFile, fmt, args);
|
|
va_end(args);
|
|
|
|
fprintf(s_logFile, "\n");
|
|
fflush(s_logFile);
|
|
}
|
|
|
|
void hydraGanlLogCallback(const char* message) {
|
|
logMessage(LogLevel::Debug, "GANL: %s", message);
|
|
}
|