forked from Telodendria/Telodendria
Add a global log configuration.
This is the easiest and cleanest way to get logging into some of the fundamental APIs, such as the database and TLS APIs. We don't want to have to pass logging functions to those, but they can safely use the global logging configuration.
This commit is contained in:
parent
8782aa046d
commit
f3c4c0ac65
13 changed files with 207 additions and 142 deletions
41
TODO.txt
41
TODO.txt
|
@ -6,52 +6,63 @@ Key:
|
|||
[ ] Not Started
|
||||
[x] Done
|
||||
[~] In Progress
|
||||
[!] Won't Fix
|
||||
[!] Won't Do
|
||||
|
||||
Milestone: v0.3.0
|
||||
-----------------
|
||||
|
||||
[~] Stream API
|
||||
[x] Stream API
|
||||
[x] Implementation
|
||||
[x] Convert all code that deals with I/O
|
||||
[!] Multi-output (proof of concept)
|
||||
[!] Memory streams (proof of concept)
|
||||
[~] TLS
|
||||
[ ] SOCKS
|
||||
[x] TLS
|
||||
[!] SOCKS
|
||||
[x] Move/convert UtilStreamCopy()
|
||||
[ ] Io man page
|
||||
[ ] Stream man page
|
||||
[ ] Tls man page
|
||||
[~] HTTP Client API
|
||||
[x] HTTP Client API
|
||||
[x] Document HttpParseHeaders()
|
||||
[ ] HttpClient man page
|
||||
[ ] Uri man page
|
||||
[x] Test on other platforms
|
||||
[x] Option to pretty-print Json
|
||||
[x] Document JsonEncode() and JsonEncodeValue()
|
||||
[ ] Update man page for td
|
||||
[x] Document Telodendria and Main
|
||||
[ ] Document tt and http-debug-server
|
||||
|
||||
[x] Simple command line tool to make matrix requests
|
||||
[x] Built on HTTP client API
|
||||
[x] http man page
|
||||
[~] Simple command line tool for working with JSON
|
||||
[x] Simple command line tool for working with JSON
|
||||
[x] Pretty-print Json
|
||||
[x] Query fields for use in shell scripts.
|
||||
[x] Encode user-provided JSON strings
|
||||
[x] json man page
|
||||
[ ] Update man pages for tp and send-patch
|
||||
|
||||
[x] Global log object
|
||||
- So we don't have to pass LogConfig around everywhere
|
||||
- Also allows debug and error logging in other APIs
|
||||
[ ] Proper HTTP request router
|
||||
- Support regex matching
|
||||
|
||||
[ ] Move configuration to database
|
||||
[ ] Initial configuration
|
||||
[ ] If no config, create one-time use registration token that
|
||||
grants user admin privileges.
|
||||
[ ] /_telodendria/admin/config endpoint
|
||||
[ ] Refactor TelodendriaConfig to just Config (ConfigLock() and ConfigUnlock())
|
||||
[ ] Make 'listen' directive in config an array of objects
|
||||
- Each object has port, threads, maxConnections
|
||||
- If tls is given, it can be null, false, or an object with cert and key
|
||||
[ ] Pass TLS certs and keys into HttpServer
|
||||
|
||||
[ ] Documentation
|
||||
[ ] Io
|
||||
[ ] Stream
|
||||
[ ] Tls
|
||||
[ ] HttpClient
|
||||
[ ] Uri
|
||||
[ ] td
|
||||
[ ] tt
|
||||
[ ] http-debug-server
|
||||
[ ] tp
|
||||
[ ] send-patch
|
||||
[ ] Log
|
||||
|
||||
[~] Client-Server API
|
||||
[x] 4: Token-based user registration
|
||||
|
|
45
src/Log.c
45
src/Log.c
|
@ -45,6 +45,8 @@ struct LogConfig
|
|||
pthread_mutex_t lock;
|
||||
};
|
||||
|
||||
LogConfig *globalConfig = NULL;
|
||||
|
||||
LogConfig *
|
||||
LogConfigCreate(void)
|
||||
{
|
||||
|
@ -68,6 +70,17 @@ LogConfigCreate(void)
|
|||
return config;
|
||||
}
|
||||
|
||||
LogConfig *
|
||||
LogConfigGlobal(void)
|
||||
{
|
||||
if (!globalConfig)
|
||||
{
|
||||
globalConfig = LogConfigCreate();
|
||||
}
|
||||
|
||||
return globalConfig;
|
||||
}
|
||||
|
||||
void
|
||||
LogConfigFlagClear(LogConfig * config, int flags)
|
||||
{
|
||||
|
@ -111,6 +124,11 @@ LogConfigFree(LogConfig * config)
|
|||
|
||||
StreamClose(config->out);
|
||||
Free(config);
|
||||
|
||||
if (config == globalConfig)
|
||||
{
|
||||
globalConfig = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -202,12 +220,11 @@ LogConfigUnindent(LogConfig * config)
|
|||
}
|
||||
|
||||
void
|
||||
Log(LogConfig * config, int level, const char *msg,...)
|
||||
Logv(LogConfig * config, int level, const char *msg, va_list argp)
|
||||
{
|
||||
size_t i;
|
||||
int doColor;
|
||||
char indicator;
|
||||
va_list argp;
|
||||
|
||||
/*
|
||||
* Only proceed if we have a config and its log level is set to a
|
||||
|
@ -232,9 +249,7 @@ Log(LogConfig * config, int level, const char *msg,...)
|
|||
{
|
||||
/* No further print logic is needed; syslog will handle it all
|
||||
* for us. */
|
||||
va_start(argp, msg);
|
||||
vsyslog(level, msg, argp);
|
||||
va_end(argp);
|
||||
pthread_mutex_unlock(&config->lock);
|
||||
return;
|
||||
}
|
||||
|
@ -345,12 +360,30 @@ Log(LogConfig * config, int level, const char *msg,...)
|
|||
StreamPutc(config->out, ' ');
|
||||
}
|
||||
|
||||
va_start(argp, msg);
|
||||
StreamVprintf(config->out, msg, argp);
|
||||
StreamPutc(config->out, '\n');
|
||||
va_end(argp);
|
||||
|
||||
StreamFlush(config->out);
|
||||
|
||||
pthread_mutex_unlock(&config->lock);
|
||||
}
|
||||
|
||||
void
|
||||
LogTo(LogConfig *config, int level, const char *fmt, ...)
|
||||
{
|
||||
va_list argp;
|
||||
|
||||
va_start(argp, fmt);
|
||||
Logv(config, level, fmt, argp);
|
||||
va_end(argp);
|
||||
}
|
||||
|
||||
extern void
|
||||
Log(int level, const char *fmt, ...)
|
||||
{
|
||||
va_list argp;
|
||||
|
||||
va_start(argp, fmt);
|
||||
Logv(LogConfigGlobal(), level, fmt, argp);
|
||||
va_end(argp);
|
||||
}
|
||||
|
|
140
src/Main.c
140
src/Main.c
|
@ -63,7 +63,6 @@ typedef enum ArgFlag
|
|||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
LogConfig *lc;
|
||||
int exit = EXIT_SUCCESS;
|
||||
|
||||
/* Arg parsing */
|
||||
|
@ -90,17 +89,15 @@ main(int argc, char **argv)
|
|||
|
||||
memset(&matrixArgs, 0, sizeof(matrixArgs));
|
||||
|
||||
lc = LogConfigCreate();
|
||||
|
||||
if (!lc)
|
||||
if (!LogConfigGlobal())
|
||||
{
|
||||
printf("Fatal error: unable to allocate memory for logger.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
MemoryHook(TelodendriaMemoryHook, lc);
|
||||
MemoryHook(TelodendriaMemoryHook, NULL);
|
||||
|
||||
TelodendriaPrintHeader(lc);
|
||||
TelodendriaPrintHeader();
|
||||
|
||||
while ((opt = getopt(argc, argv, "f:Vvn")) != -1)
|
||||
{
|
||||
|
@ -128,7 +125,7 @@ main(int argc, char **argv)
|
|||
|
||||
if (flags & ARG_VERBOSE)
|
||||
{
|
||||
LogConfigLevelSet(lc, LOG_DEBUG);
|
||||
LogConfigLevelSet(LogConfigGlobal(), LOG_DEBUG);
|
||||
}
|
||||
|
||||
if (flags & ARG_VERSION)
|
||||
|
@ -138,7 +135,7 @@ main(int argc, char **argv)
|
|||
|
||||
if (!configArg)
|
||||
{
|
||||
Log(lc, LOG_ERR, "No configuration file specified.");
|
||||
Log(LOG_ERR, "No configuration file specified.");
|
||||
exit = EXIT_FAILURE;
|
||||
goto finish;
|
||||
}
|
||||
|
@ -153,25 +150,25 @@ main(int argc, char **argv)
|
|||
configFile = StreamOpen(configArg, "r");
|
||||
if (!configFile)
|
||||
{
|
||||
Log(lc, LOG_ERR, "Unable to open configuration file '%s' for reading.", configArg);
|
||||
Log(LOG_ERR, "Unable to open configuration file '%s' for reading.", configArg);
|
||||
exit = EXIT_FAILURE;
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
|
||||
Log(lc, LOG_NOTICE, "Processing configuration file '%s'.", configArg);
|
||||
Log(LOG_NOTICE, "Processing configuration file '%s'.", configArg);
|
||||
|
||||
config = JsonDecode(configFile);
|
||||
StreamClose(configFile);
|
||||
|
||||
if (!config)
|
||||
{
|
||||
Log(lc, LOG_ERR, "Syntax error in configuration file.");
|
||||
Log(LOG_ERR, "Syntax error in configuration file.");
|
||||
exit = EXIT_FAILURE;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
tConfig = TelodendriaConfigParse(config, lc);
|
||||
tConfig = TelodendriaConfigParse(config, LogConfigGlobal());
|
||||
JsonFree(config);
|
||||
|
||||
if (!tConfig)
|
||||
|
@ -182,13 +179,13 @@ main(int argc, char **argv)
|
|||
|
||||
if (flags & ARG_CONFIGTEST)
|
||||
{
|
||||
Log(lc, LOG_INFO, "Configuration is OK.");
|
||||
Log(LOG_INFO, "Configuration is OK.");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!tConfig->logTimestamp || strcmp(tConfig->logTimestamp, "default") != 0)
|
||||
{
|
||||
LogConfigTimeStampFormatSet(lc, tConfig->logTimestamp);
|
||||
LogConfigTimeStampFormatSet(LogConfigGlobal(), tConfig->logTimestamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -198,24 +195,24 @@ main(int argc, char **argv)
|
|||
|
||||
if (tConfig->flags & TELODENDRIA_LOG_COLOR)
|
||||
{
|
||||
LogConfigFlagSet(lc, LOG_FLAG_COLOR);
|
||||
LogConfigFlagSet(LogConfigGlobal(), LOG_FLAG_COLOR);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogConfigFlagClear(lc, LOG_FLAG_COLOR);
|
||||
LogConfigFlagClear(LogConfigGlobal(), LOG_FLAG_COLOR);
|
||||
}
|
||||
|
||||
LogConfigLevelSet(lc, flags & ARG_VERBOSE ? LOG_DEBUG : tConfig->logLevel);
|
||||
LogConfigLevelSet(LogConfigGlobal(), flags & ARG_VERBOSE ? LOG_DEBUG : tConfig->logLevel);
|
||||
|
||||
if (chdir(tConfig->dataDir) != 0)
|
||||
{
|
||||
Log(lc, LOG_ERR, "Unable to change into data directory: %s.", strerror(errno));
|
||||
Log(LOG_ERR, "Unable to change into data directory: %s.", strerror(errno));
|
||||
exit = EXIT_FAILURE;
|
||||
goto finish;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lc, LOG_DEBUG, "Changed working directory to: %s", tConfig->dataDir);
|
||||
Log(LOG_DEBUG, "Changed working directory to: %s", tConfig->dataDir);
|
||||
}
|
||||
|
||||
|
||||
|
@ -225,22 +222,22 @@ main(int argc, char **argv)
|
|||
|
||||
if (!logFile)
|
||||
{
|
||||
Log(lc, LOG_ERR, "Unable to open log file for appending.");
|
||||
Log(LOG_ERR, "Unable to open log file for appending.");
|
||||
exit = EXIT_FAILURE;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
Log(lc, LOG_INFO, "Logging to the log file. Check there for all future messages.");
|
||||
LogConfigOutputSet(lc, logFile);
|
||||
Log(LOG_INFO, "Logging to the log file. Check there for all future messages.");
|
||||
LogConfigOutputSet(LogConfigGlobal(), logFile);
|
||||
}
|
||||
else if (tConfig->flags & TELODENDRIA_LOG_STDOUT)
|
||||
{
|
||||
Log(lc, LOG_DEBUG, "Already logging to standard output.");
|
||||
Log(LOG_DEBUG, "Already logging to standard output.");
|
||||
}
|
||||
else if (tConfig->flags & TELODENDRIA_LOG_SYSLOG)
|
||||
{
|
||||
Log(lc, LOG_INFO, "Logging to the syslog. Check there for all future messages.");
|
||||
LogConfigFlagSet(lc, LOG_FLAG_SYSLOG);
|
||||
Log(LOG_INFO, "Logging to the syslog. Check there for all future messages.");
|
||||
LogConfigFlagSet(LogConfigGlobal(), LOG_FLAG_SYSLOG);
|
||||
|
||||
openlog("telodendria", LOG_PID | LOG_NDELAY, LOG_DAEMON);
|
||||
/* Always log everything, because the Log API will control what
|
||||
|
@ -249,28 +246,27 @@ main(int argc, char **argv)
|
|||
}
|
||||
else
|
||||
{
|
||||
Log(lc, LOG_ERR, "Unknown logging method in flags: '%d'", tConfig->flags);
|
||||
Log(lc, LOG_ERR, "This is a programmer error; please report it.");
|
||||
Log(LOG_ERR, "Unknown logging method in flags: '%d'", tConfig->flags);
|
||||
Log(LOG_ERR, "This is a programmer error; please report it.");
|
||||
exit = EXIT_FAILURE;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
Log(lc, LOG_DEBUG, "Configuration:");
|
||||
LogConfigIndent(lc);
|
||||
Log(lc, LOG_DEBUG, "Listen On: %d", tConfig->listenPort);
|
||||
Log(lc, LOG_DEBUG, "Server Name: %s", tConfig->serverName);
|
||||
Log(lc, LOG_DEBUG, "Base URL: %s", tConfig->baseUrl);
|
||||
Log(lc, LOG_DEBUG, "Identity Server: %s", tConfig->identityServer);
|
||||
Log(lc, LOG_DEBUG, "Run As: %s:%s", tConfig->uid, tConfig->gid);
|
||||
Log(lc, LOG_DEBUG, "Data Directory: %s", tConfig->dataDir);
|
||||
Log(lc, LOG_DEBUG, "Threads: %d", tConfig->threads);
|
||||
Log(lc, LOG_DEBUG, "Max Connections: %d", tConfig->maxConnections);
|
||||
Log(lc, LOG_DEBUG, "Max Cache: %ld", tConfig->maxCache);
|
||||
Log(lc, LOG_DEBUG, "Flags: %x", tConfig->flags);
|
||||
LogConfigUnindent(lc);
|
||||
Log(LOG_DEBUG, "Configuration:");
|
||||
LogConfigIndent(LogConfigGlobal());
|
||||
Log(LOG_DEBUG, "Listen On: %d", tConfig->listenPort);
|
||||
Log(LOG_DEBUG, "Server Name: %s", tConfig->serverName);
|
||||
Log(LOG_DEBUG, "Base URL: %s", tConfig->baseUrl);
|
||||
Log(LOG_DEBUG, "Identity Server: %s", tConfig->identityServer);
|
||||
Log(LOG_DEBUG, "Run As: %s:%s", tConfig->uid, tConfig->gid);
|
||||
Log(LOG_DEBUG, "Data Directory: %s", tConfig->dataDir);
|
||||
Log(LOG_DEBUG, "Threads: %d", tConfig->threads);
|
||||
Log(LOG_DEBUG, "Max Connections: %d", tConfig->maxConnections);
|
||||
Log(LOG_DEBUG, "Max Cache: %ld", tConfig->maxCache);
|
||||
Log(LOG_DEBUG, "Flags: %x", tConfig->flags);
|
||||
LogConfigUnindent(LogConfigGlobal());
|
||||
|
||||
/* Arguments to pass into the HTTP handler */
|
||||
matrixArgs.lc = lc;
|
||||
matrixArgs.config = tConfig;
|
||||
|
||||
/* Bind the socket before possibly dropping permissions */
|
||||
|
@ -278,13 +274,13 @@ main(int argc, char **argv)
|
|||
tConfig->maxConnections, MatrixHttpHandler, &matrixArgs);
|
||||
if (!httpServer)
|
||||
{
|
||||
Log(lc, LOG_ERR, "Unable to create HTTP server on port %d: %s",
|
||||
Log(LOG_ERR, "Unable to create HTTP server on port %d: %s",
|
||||
tConfig->listenPort, strerror(errno));
|
||||
exit = EXIT_FAILURE;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
Log(lc, LOG_DEBUG, "Running as uid:gid: %d:%d.", getuid(), getgid());
|
||||
Log(LOG_DEBUG, "Running as uid:gid: %d:%d.", getuid(), getgid());
|
||||
|
||||
if (tConfig->uid && tConfig->gid)
|
||||
{
|
||||
|
@ -293,18 +289,18 @@ main(int argc, char **argv)
|
|||
|
||||
if (!userInfo || !groupInfo)
|
||||
{
|
||||
Log(lc, LOG_ERR, "Unable to locate the user/group specified in the configuration.");
|
||||
Log(LOG_ERR, "Unable to locate the user/group specified in the configuration.");
|
||||
exit = EXIT_FAILURE;
|
||||
goto finish;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lc, LOG_DEBUG, "Found user/group information using getpwnam() and getgrnam().");
|
||||
Log(LOG_DEBUG, "Found user/group information using getpwnam() and getgrnam().");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lc, LOG_DEBUG, "No user/group info specified in the config.");
|
||||
Log(LOG_DEBUG, "No user/group info specified in the config.");
|
||||
}
|
||||
|
||||
if (getuid() == 0)
|
||||
|
@ -313,35 +309,35 @@ main(int argc, char **argv)
|
|||
{
|
||||
if (setgid(groupInfo->gr_gid) != 0 || setuid(userInfo->pw_uid) != 0)
|
||||
{
|
||||
Log(lc, LOG_ERR, "Unable to set process uid/gid.");
|
||||
Log(LOG_ERR, "Unable to set process uid/gid.");
|
||||
exit = EXIT_FAILURE;
|
||||
goto finish;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lc, LOG_DEBUG, "Set uid/gid to %s:%s.", tConfig->uid, tConfig->gid);
|
||||
Log(LOG_DEBUG, "Set uid/gid to %s:%s.", tConfig->uid, tConfig->gid);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lc, LOG_WARNING, "We are running as root, and we are not dropping to another user");
|
||||
Log(lc, LOG_WARNING, "because none was specified in the configuration file.");
|
||||
Log(lc, LOG_WARNING, "This is probably a security issue.");
|
||||
Log(LOG_WARNING, "We are running as root, and we are not dropping to another user");
|
||||
Log(LOG_WARNING, "because none was specified in the configuration file.");
|
||||
Log(LOG_WARNING, "This is probably a security issue.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lc, LOG_WARNING, "Not setting root directory, because we are not root.");
|
||||
Log(LOG_WARNING, "Not setting root directory, because we are not root.");
|
||||
|
||||
if (tConfig->uid && tConfig->gid)
|
||||
{
|
||||
if (getuid() != userInfo->pw_uid || getgid() != groupInfo->gr_gid)
|
||||
{
|
||||
Log(lc, LOG_WARNING, "Not running as the uid/gid specified in the configuration.");
|
||||
Log(LOG_WARNING, "Not running as the uid/gid specified in the configuration.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lc, LOG_DEBUG, "Running as the uid/gid specified in the configuration.");
|
||||
Log(LOG_DEBUG, "Running as the uid/gid specified in the configuration.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -359,18 +355,16 @@ main(int argc, char **argv)
|
|||
|
||||
if (!tConfig->maxCache)
|
||||
{
|
||||
Log(lc, LOG_WARNING, "Database caching is disabled.");
|
||||
Log(lc, LOG_WARNING,
|
||||
"If this is not what you intended, check the config file");
|
||||
Log(lc, LOG_WARNING,
|
||||
"and ensure that maxCache is a valid number of bytes.");
|
||||
Log(LOG_WARNING, "Database caching is disabled.");
|
||||
Log(LOG_WARNING, "If this is not what you intended, check the config file");
|
||||
Log(LOG_WARNING, "and ensure that maxCache is a valid number of bytes.");
|
||||
}
|
||||
|
||||
matrixArgs.db = DbOpen(".", tConfig->maxCache);
|
||||
|
||||
if (!matrixArgs.db)
|
||||
{
|
||||
Log(lc, LOG_ERR, "Unable to open data directory as a database.");
|
||||
Log(LOG_ERR, "Unable to open data directory as a database.");
|
||||
exit = EXIT_FAILURE;
|
||||
goto finish;
|
||||
}
|
||||
|
@ -378,28 +372,28 @@ main(int argc, char **argv)
|
|||
cron = CronCreate(60 * 1000); /* 1-minute tick */
|
||||
if (!cron)
|
||||
{
|
||||
Log(lc, LOG_ERR, "Unable to set up job scheduler.");
|
||||
Log(LOG_ERR, "Unable to set up job scheduler.");
|
||||
exit = EXIT_FAILURE;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
Log(lc, LOG_DEBUG, "Registering jobs...");
|
||||
Log(LOG_DEBUG, "Registering jobs...");
|
||||
|
||||
CronEvery(cron, 30 * 60 * 1000, (JobFunc *) UiaCleanup, &matrixArgs);
|
||||
|
||||
Log(lc, LOG_NOTICE, "Starting job scheduler...");
|
||||
Log(LOG_NOTICE, "Starting job scheduler...");
|
||||
CronStart(cron);
|
||||
|
||||
Log(lc, LOG_NOTICE, "Starting server...");
|
||||
Log(LOG_NOTICE, "Starting server...");
|
||||
|
||||
if (!HttpServerStart(httpServer))
|
||||
{
|
||||
Log(lc, LOG_ERR, "Unable to start HTTP server.");
|
||||
Log(LOG_ERR, "Unable to start HTTP server.");
|
||||
exit = EXIT_FAILURE;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
Log(lc, LOG_INFO, "Listening on port: %d", tConfig->listenPort);
|
||||
Log(LOG_INFO, "Listening on port: %d", tConfig->listenPort);
|
||||
|
||||
sigAction.sa_handler = TelodendriaSignalHandler;
|
||||
sigfillset(&sigAction.sa_mask);
|
||||
|
@ -407,7 +401,7 @@ main(int argc, char **argv)
|
|||
|
||||
if (sigaction(SIGINT, &sigAction, NULL) < 0)
|
||||
{
|
||||
Log(lc, LOG_ERR, "Unable to install signal handler.");
|
||||
Log(LOG_ERR, "Unable to install signal handler.");
|
||||
exit = EXIT_FAILURE;
|
||||
goto finish;
|
||||
}
|
||||
|
@ -417,18 +411,18 @@ main(int argc, char **argv)
|
|||
HttpServerJoin(httpServer);
|
||||
|
||||
finish:
|
||||
Log(lc, LOG_NOTICE, "Shutting down...");
|
||||
Log(LOG_NOTICE, "Shutting down...");
|
||||
if (httpServer)
|
||||
{
|
||||
HttpServerFree(httpServer);
|
||||
Log(lc, LOG_DEBUG, "Freed HTTP Server.");
|
||||
Log(LOG_DEBUG, "Freed HTTP Server.");
|
||||
}
|
||||
|
||||
if (cron)
|
||||
{
|
||||
CronStop(cron);
|
||||
CronFree(cron);
|
||||
Log(lc, LOG_DEBUG, "Stopped and freed job scheduler.");
|
||||
Log(LOG_DEBUG, "Stopped and freed job scheduler.");
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -442,11 +436,9 @@ finish:
|
|||
|
||||
DbClose(matrixArgs.db);
|
||||
|
||||
LogConfigTimeStampFormatSet(lc, NULL);
|
||||
TelodendriaConfigFree(tConfig);
|
||||
|
||||
|
||||
Log(lc, LOG_DEBUG, "Exiting with code '%d'.", exit);
|
||||
Log(LOG_DEBUG, "Exiting with code '%d'.", exit);
|
||||
|
||||
/*
|
||||
* Uninstall the memory hook because it uses the Log
|
||||
|
@ -455,7 +447,7 @@ finish:
|
|||
*/
|
||||
MemoryHook(NULL, NULL);
|
||||
|
||||
LogConfigFree(lc);
|
||||
LogConfigFree(LogConfigGlobal());
|
||||
|
||||
/* Standard error should never have been opened, but just in case
|
||||
* it was, this doesn't hurt anything. */
|
||||
|
|
10
src/Matrix.c
10
src/Matrix.c
|
@ -38,7 +38,6 @@ void
|
|||
MatrixHttpHandler(HttpServerContext * context, void *argp)
|
||||
{
|
||||
MatrixHttpHandlerArgs *args = (MatrixHttpHandlerArgs *) argp;
|
||||
LogConfig *lc = args->lc;
|
||||
Stream *stream;
|
||||
HashMap *response = NULL;
|
||||
|
||||
|
@ -52,12 +51,10 @@ MatrixHttpHandler(HttpServerContext * context, void *argp)
|
|||
|
||||
requestPath = HttpRequestPath(context);
|
||||
|
||||
Log(lc, LOG_INFO, "%s %s",
|
||||
Log(LOG_INFO, "%s %s",
|
||||
HttpRequestMethodToString(HttpRequestMethodGet(context)),
|
||||
requestPath);
|
||||
|
||||
LogConfigIndent(lc);
|
||||
|
||||
HttpResponseStatus(context, HTTP_OK);
|
||||
HttpResponseHeader(context, "Server", "Telodendria/" TELODENDRIA_VERSION);
|
||||
|
||||
|
@ -78,7 +75,7 @@ MatrixHttpHandler(HttpServerContext * context, void *argp)
|
|||
HttpResponseStatus(context, HTTP_NO_CONTENT);
|
||||
HttpSendHeaders(context);
|
||||
|
||||
goto finish;
|
||||
return;
|
||||
}
|
||||
|
||||
pathParts = MATRIX_PATH_CREATE();
|
||||
|
@ -146,9 +143,6 @@ MatrixHttpHandler(HttpServerContext * context, void *argp)
|
|||
}
|
||||
|
||||
MATRIX_PATH_FREE(pathParts);
|
||||
|
||||
finish:
|
||||
LogConfigUnindent(lc);
|
||||
}
|
||||
|
||||
HashMap *
|
||||
|
|
|
@ -45,7 +45,6 @@ ROUTE_IMPL(RouteRefresh, args)
|
|||
char *deviceId;
|
||||
|
||||
Db *db = args->matrixArgs->db;
|
||||
LogConfig *lc = args->matrixArgs->lc;
|
||||
|
||||
User *user = NULL;
|
||||
DbRef *rtRef = NULL;
|
||||
|
@ -96,9 +95,9 @@ ROUTE_IMPL(RouteRefresh, args)
|
|||
|
||||
if (!oAtRef)
|
||||
{
|
||||
Log(lc, LOG_ERR, "Refresh token '%s' points to an access token that doesn't exist.",
|
||||
Log(LOG_ERR, "Refresh token '%s' points to an access token that doesn't exist.",
|
||||
refreshToken);
|
||||
Log(lc, LOG_WARNING, "This refresh token will be deleted.");
|
||||
Log(LOG_WARNING, "This refresh token will be deleted.");
|
||||
HttpResponseStatus(args->context, HTTP_INTERNAL_SERVER_ERROR);
|
||||
response = MatrixErrorCreate(M_UNKNOWN);
|
||||
|
||||
|
@ -114,9 +113,9 @@ ROUTE_IMPL(RouteRefresh, args)
|
|||
user = UserLock(db, JsonValueAsString(HashMapGet(DbJson(oAtRef), "user")));
|
||||
if (!user)
|
||||
{
|
||||
Log(lc, LOG_ERR, "Access token '%s' points to a user that doesn't exist.",
|
||||
Log(LOG_ERR, "Access token '%s' points to a user that doesn't exist.",
|
||||
oldAccessToken);
|
||||
Log(lc, LOG_WARNING, "This access token will be deleted.");
|
||||
Log(LOG_WARNING, "This access token will be deleted.");
|
||||
HttpResponseStatus(args->context, HTTP_INTERNAL_SERVER_ERROR);
|
||||
response = MatrixErrorCreate(M_UNKNOWN);
|
||||
|
||||
|
|
|
@ -66,7 +66,6 @@ ROUTE_IMPL(RouteRegister, args)
|
|||
char *fullUsername;
|
||||
|
||||
Db *db = args->matrixArgs->db;
|
||||
LogConfig *lc = args->matrixArgs->lc;
|
||||
|
||||
User *user = NULL;
|
||||
|
||||
|
@ -249,7 +248,7 @@ ROUTE_IMPL(RouteRegister, args)
|
|||
Free(loginInfo);
|
||||
}
|
||||
|
||||
Log(lc, LOG_INFO, "Registered user '%s'", UserGetName(user));
|
||||
Log(LOG_INFO, "Registered user '%s'", UserGetName(user));
|
||||
|
||||
UserUnlock(user);
|
||||
finish:
|
||||
|
|
|
@ -67,9 +67,10 @@ const char
|
|||
void
|
||||
TelodendriaMemoryHook(MemoryAction a, MemoryInfo * i, void *args)
|
||||
{
|
||||
LogConfig *lc = (LogConfig *) args;
|
||||
char *action;
|
||||
|
||||
(void) args;
|
||||
|
||||
switch (a)
|
||||
{
|
||||
case MEMORY_ALLOCATE:
|
||||
|
@ -89,7 +90,7 @@ TelodendriaMemoryHook(MemoryAction a, MemoryInfo * i, void *args)
|
|||
break;
|
||||
}
|
||||
|
||||
Log(lc, a == MEMORY_BAD_POINTER ? LOG_WARNING : LOG_DEBUG,
|
||||
Log(a == MEMORY_BAD_POINTER ? LOG_WARNING : LOG_DEBUG,
|
||||
"%s:%d: %s %lu bytes of memory at %p.",
|
||||
MemoryInfoGetFile(i), MemoryInfoGetLine(i),
|
||||
action, MemoryInfoGetSize(i),
|
||||
|
@ -171,25 +172,25 @@ TelodendriaGenerateMemReport(void)
|
|||
}
|
||||
|
||||
void
|
||||
TelodendriaPrintHeader(LogConfig * lc)
|
||||
TelodendriaPrintHeader(void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < TELODENDRIA_LOGO_HEIGHT; i++)
|
||||
{
|
||||
Log(lc, LOG_INFO, "%s", TelodendriaLogo[i]);
|
||||
Log(LOG_INFO, "%s", TelodendriaLogo[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < TELODENDRIA_HEADER_HEIGHT; i++)
|
||||
{
|
||||
Log(lc, LOG_INFO, "%s", TelodendriaHeader[i]);
|
||||
Log(LOG_INFO, "%s", TelodendriaHeader[i]);
|
||||
}
|
||||
|
||||
Log(lc, LOG_INFO, "Telodendria v" TELODENDRIA_VERSION);
|
||||
Log(lc, LOG_INFO, "");
|
||||
Log(lc, LOG_INFO,
|
||||
Log(LOG_INFO, "Telodendria v" TELODENDRIA_VERSION);
|
||||
Log(LOG_INFO, "");
|
||||
Log(LOG_INFO,
|
||||
"Copyright (C) 2023 Jordan Bancino <@jordan:bancino.net>");
|
||||
Log(lc, LOG_INFO,
|
||||
Log(LOG_INFO,
|
||||
"Documentation/Support: https://telodendria.io");
|
||||
Log(lc, LOG_INFO, "");
|
||||
Log(LOG_INFO, "");
|
||||
}
|
||||
|
|
|
@ -38,17 +38,17 @@
|
|||
value = HashMapGet(config, key); \
|
||||
if (!value) \
|
||||
{ \
|
||||
Log(lc, LOG_ERR, "Missing required " key " directive."); \
|
||||
Log(LOG_ERR, "Missing required " key " directive."); \
|
||||
goto error; \
|
||||
} \
|
||||
if (JsonValueType(value) == JSON_NULL) \
|
||||
{ \
|
||||
Log(lc, LOG_ERR, "Missing value for " key " directive."); \
|
||||
Log(LOG_ERR, "Missing value for " key " directive."); \
|
||||
goto error; \
|
||||
} \
|
||||
if (JsonValueType(value) != type) \
|
||||
{ \
|
||||
Log(lc, LOG_ERR, "Expected " key " to be of type " #type); \
|
||||
Log(LOG_ERR, "Expected " key " to be of type " #type); \
|
||||
goto error; \
|
||||
}
|
||||
|
||||
|
@ -61,14 +61,14 @@
|
|||
{ \
|
||||
if (JsonValueType(value) != JSON_STRING) \
|
||||
{ \
|
||||
Log(lc, LOG_ERR, "Expected " key " to be of type JSON_STRING"); \
|
||||
Log(LOG_ERR, "Expected " key " to be of type JSON_STRING"); \
|
||||
goto error; \
|
||||
} \
|
||||
into = StrDuplicate(JsonValueAsString(value)); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
Log(lc, LOG_INFO, "Using default value " #default " for " key "."); \
|
||||
Log(LOG_INFO, "Using default value " #default " for " key "."); \
|
||||
into = default ? StrDuplicate(default) : NULL; \
|
||||
}
|
||||
|
||||
|
@ -78,14 +78,14 @@
|
|||
{ \
|
||||
if (JsonValueType(value) != JSON_INTEGER) \
|
||||
{ \
|
||||
Log(lc, LOG_ERR, "Expected " key " to be of type JSON_INTEGER"); \
|
||||
Log(LOG_ERR, "Expected " key " to be of type JSON_INTEGER"); \
|
||||
goto error; \
|
||||
} \
|
||||
into = JsonValueAsInteger(value); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
Log(lc, LOG_INFO, "Using default value " #default " for " key "."); \
|
||||
Log(LOG_INFO, "Using default value " #default " for " key "."); \
|
||||
into = default; \
|
||||
}
|
||||
|
||||
|
@ -128,7 +128,7 @@ ConfigParseLog(LogConfig * lc, TelodendriaConfig * tConfig, HashMap * config)
|
|||
}
|
||||
else
|
||||
{
|
||||
Log(lc, LOG_ERR, "Invalid value for log.output: '%s'.", str);
|
||||
Log(LOG_ERR, "Invalid value for log.output: '%s'.", str);
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -156,7 +156,7 @@ ConfigParseLog(LogConfig * lc, TelodendriaConfig * tConfig, HashMap * config)
|
|||
}
|
||||
else
|
||||
{
|
||||
Log(lc, LOG_ERR, "Invalid value for log.level: '%s'.", tConfig->logLevel);
|
||||
Log(LOG_ERR, "Invalid value for log.level: '%s'.", tConfig->logLevel);
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -175,7 +175,7 @@ ConfigParseLog(LogConfig * lc, TelodendriaConfig * tConfig, HashMap * config)
|
|||
{
|
||||
if (JsonValueType(value) != JSON_BOOLEAN)
|
||||
{
|
||||
Log(lc, LOG_ERR, "Expected type JSON_BOOLEAN for log.color.");
|
||||
Log(LOG_ERR, "Expected type JSON_BOOLEAN for log.color.");
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -222,11 +222,11 @@ TelodendriaConfigParse(HashMap * config, LogConfig * lc)
|
|||
}
|
||||
else
|
||||
{
|
||||
Log(lc, LOG_WARNING, "Base URL not specified. Assuming it's 'https://%s'.", tConfig->serverName);
|
||||
Log(LOG_WARNING, "Base URL not specified. Assuming it's 'https://%s'.", tConfig->serverName);
|
||||
tConfig->baseUrl = Malloc(strlen(tConfig->serverName) + 10);
|
||||
if (!tConfig->baseUrl)
|
||||
{
|
||||
Log(lc, LOG_ERR, "Error allocating memory for default config value 'baseUrl'.");
|
||||
Log(LOG_ERR, "Error allocating memory for default config value 'baseUrl'.");
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -247,8 +247,8 @@ TelodendriaConfigParse(HashMap * config, LogConfig * lc)
|
|||
}
|
||||
else
|
||||
{
|
||||
Log(lc, LOG_ERR, "Config directive 'runAs' should be a JSON object");
|
||||
Log(lc, LOG_ERR, "that contains a 'uid' and 'gid'.");
|
||||
Log(LOG_ERR, "Config directive 'runAs' should be a JSON object");
|
||||
Log(LOG_ERR, "that contains a 'uid' and 'gid'.");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#if TLS_IMPL == TLS_LIBRESSL
|
||||
|
||||
#include <Memory.h>
|
||||
#include <Log.h>
|
||||
|
||||
#include <tls.h> /* LibreSSL TLS */
|
||||
|
||||
typedef struct LibreSSLCookie
|
||||
|
@ -77,6 +79,11 @@ TlsInitClient(int fd, const char *serverName)
|
|||
error:
|
||||
if (cookie->ctx)
|
||||
{
|
||||
if (tls_error(cookie->ctx))
|
||||
{
|
||||
Log(LOG_ERR, "TlsInitClient(): %s", tls_error(cookie->ctx));
|
||||
}
|
||||
|
||||
tls_free(cookie->ctx);
|
||||
}
|
||||
|
||||
|
@ -135,11 +142,20 @@ TlsInitServer(int fd, const char *crt, const char *key)
|
|||
error:
|
||||
if (cookie->ctx)
|
||||
{
|
||||
if (tls_error(cookie->ctx))
|
||||
{
|
||||
Log(LOG_ERR, "TlsInitServer(): %s", tls_error(cookie->ctx));
|
||||
}
|
||||
tls_free(cookie->ctx);
|
||||
}
|
||||
|
||||
if (cookie->cctx)
|
||||
{
|
||||
if (tls_error(cookie->cctx))
|
||||
{
|
||||
Log(LOG_ERR, "TlsInitServer(): %s", tls_error(cookie->cctx));
|
||||
}
|
||||
|
||||
tls_free(cookie->cctx);
|
||||
}
|
||||
|
||||
|
@ -157,16 +173,28 @@ ssize_t
|
|||
TlsRead(void *cookie, void *buf, size_t nBytes)
|
||||
{
|
||||
LibreSSLCookie *tls = cookie;
|
||||
ssize_t ret = tls_read(tls->cctx ? tls->cctx : tls->ctx, buf, nBytes);
|
||||
|
||||
return tls_read(tls->cctx ? tls->cctx : tls->ctx, buf, nBytes);
|
||||
if (ret == -1)
|
||||
{
|
||||
Log(LOG_ERR, "TlsRead(): %s", tls_error(tls->cctx ? tls->cctx : tls->ctx));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
TlsWrite(void *cookie, void *buf, size_t nBytes)
|
||||
{
|
||||
LibreSSLCookie *tls = cookie;
|
||||
ssize_t ret = tls_write(tls->cctx ? tls->cctx : tls->ctx, buf, nBytes);
|
||||
|
||||
return tls_write(tls->cctx ? tls->cctx : tls->ctx, buf, nBytes);
|
||||
if (ret == -1)
|
||||
{
|
||||
Log(LOG_ERR, "TlsWrite(): %s", tls_error(tls->cctx ? tls->cctx : tls->ctx));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -491,7 +491,7 @@ UiaCleanup(MatrixHttpHandlerArgs * args)
|
|||
Array *sessions = DbList(args->db, 1, "user_interactive");
|
||||
size_t i;
|
||||
|
||||
Log(args->lc, LOG_DEBUG, "User Interactive Auth sessions: %lu",
|
||||
Log(LOG_DEBUG, "User Interactive Auth sessions: %lu",
|
||||
ArraySize(sessions));
|
||||
for (i = 0; i < ArraySize(sessions); i++)
|
||||
{
|
||||
|
@ -502,7 +502,7 @@ UiaCleanup(MatrixHttpHandlerArgs * args)
|
|||
|
||||
if (!ref)
|
||||
{
|
||||
Log(args->lc, LOG_ERR, "Unable to lock uia %s for inspection.",
|
||||
Log(LOG_ERR, "Unable to lock uia %s for inspection.",
|
||||
session);
|
||||
continue;
|
||||
}
|
||||
|
@ -515,7 +515,7 @@ UiaCleanup(MatrixHttpHandlerArgs * args)
|
|||
{
|
||||
DbUnlock(args->db, ref);
|
||||
DbDelete(args->db, 2, "user_interactive", session);
|
||||
Log(args->lc, LOG_DEBUG, "Deleted session %s", session);
|
||||
Log(LOG_DEBUG, "Deleted session %s", session);
|
||||
}
|
||||
|
||||
DbUnlock(args->db, ref);
|
||||
|
|
|
@ -39,6 +39,9 @@ typedef struct LogConfig LogConfig;
|
|||
extern LogConfig *
|
||||
LogConfigCreate(void);
|
||||
|
||||
extern LogConfig *
|
||||
LogConfigGlobal(void);
|
||||
|
||||
extern void
|
||||
LogConfigFree(LogConfig *);
|
||||
|
||||
|
@ -67,6 +70,12 @@ extern void
|
|||
LogConfigTimeStampFormatSet(LogConfig *, char *);
|
||||
|
||||
extern void
|
||||
Log(LogConfig *, int, const char *,...);
|
||||
Logv(LogConfig *, int, const char *, va_list);
|
||||
|
||||
extern void
|
||||
LogTo(LogConfig *, int, const char *,...);
|
||||
|
||||
extern void
|
||||
Log(int, const char *, ...);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -69,7 +69,6 @@ typedef enum MatrixError
|
|||
|
||||
typedef struct MatrixHttpHandlerArgs
|
||||
{
|
||||
LogConfig *lc;
|
||||
TelodendriaConfig *config;
|
||||
Db *db;
|
||||
} MatrixHttpHandlerArgs;
|
||||
|
|
|
@ -46,6 +46,6 @@ extern void
|
|||
TelodendriaGenerateMemReport(void);
|
||||
|
||||
extern void
|
||||
TelodendriaPrintHeader(LogConfig *);
|
||||
TelodendriaPrintHeader(void);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue