forked from Telodendria/Telodendria
Add support for spinning up multiple HTTP servers.
This is useful for having a TLS and a non-TLS version port, like Synapse. I verified that the multiple-servers does in fact work as intended, although the TLS server part is broken; I must be doing something incorrectly with LibreSSL in setting up the server.
This commit is contained in:
parent
2fab7b55fe
commit
2441f07848
15 changed files with 311 additions and 90 deletions
4
TODO.txt
4
TODO.txt
|
@ -38,10 +38,10 @@ Milestone: v0.3.0
|
|||
[x] Global log object
|
||||
- So we don't have to pass LogConfig around everywhere
|
||||
- Also allows debug and error logging in other APIs
|
||||
[ ] Make 'listen' directive in config an array of objects
|
||||
[x] 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
|
||||
[x] Pass TLS certs and keys into HttpServer
|
||||
[ ] Move configuration to database
|
||||
[ ] Initial configuration
|
||||
[ ] If no config, create one-time use registration token that
|
||||
|
|
|
@ -1,14 +1,19 @@
|
|||
{
|
||||
"serverName": "localhost",
|
||||
"baseUrl": "http://localhost:8008",
|
||||
"dataDir": "./data",
|
||||
"federation": true,
|
||||
"registration": true,
|
||||
"threads": 2,
|
||||
"log": {
|
||||
"output": "stdout",
|
||||
"level": "debug",
|
||||
"timestampFormat": "none",
|
||||
"color": true
|
||||
}
|
||||
"log": {
|
||||
"output": "stdout",
|
||||
"color": true,
|
||||
"timestampFormat": "none",
|
||||
"level": "debug"
|
||||
},
|
||||
"dataDir": "./data",
|
||||
"listen": [
|
||||
{
|
||||
"port": 8008,
|
||||
"tls": false
|
||||
}
|
||||
],
|
||||
"registration": true,
|
||||
"serverName": "localhost",
|
||||
"baseUrl": "http:\/\/localhost:8008",
|
||||
"federation": true
|
||||
}
|
||||
|
|
|
@ -1,13 +1,25 @@
|
|||
{
|
||||
"serverName": "example.com",
|
||||
"baseUrl": "https://matrix.example.com",
|
||||
"identityServer": "https://identity.example.com",
|
||||
"dataDir": "/var/telodendria",
|
||||
"federation": true,
|
||||
"registration": false,
|
||||
"threads": 4,
|
||||
"maxCache": 512000000,
|
||||
"log": {
|
||||
"output": "file"
|
||||
"log": {
|
||||
"output": "file"
|
||||
},
|
||||
"dataDir": "/var/telodendria",
|
||||
"listen": [
|
||||
{
|
||||
"port": 8008,
|
||||
"tls": false
|
||||
},
|
||||
{
|
||||
"port": 8448,
|
||||
"tls": {
|
||||
"cert": "telodendria.crt",
|
||||
"key": "telodendria.key"
|
||||
}
|
||||
}
|
||||
],
|
||||
"serverName": "example.com",
|
||||
"identityServer": "https://identity.example.com",
|
||||
"baseUrl": "https://matrix.example.com",
|
||||
"registration": false,
|
||||
"federation": true,
|
||||
"maxCache": 512000000
|
||||
}
|
||||
|
|
|
@ -164,7 +164,7 @@ ArrayInsert(Array * array, size_t index, void *value)
|
|||
}
|
||||
|
||||
extern void *
|
||||
ArraySet(Array * array, size_t index, void * value)
|
||||
ArraySet(Array * array, size_t index, void *value)
|
||||
{
|
||||
void *oldValue;
|
||||
|
||||
|
|
131
src/Config.c
131
src/Config.c
|
@ -29,6 +29,7 @@
|
|||
#include <Array.h>
|
||||
#include <Str.h>
|
||||
#include <Db.h>
|
||||
#include <HttpServer.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
@ -89,7 +90,7 @@
|
|||
into = default; \
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
ConfigParseRunAs(Config * tConfig, HashMap * config)
|
||||
{
|
||||
JsonValue *value;
|
||||
|
@ -105,7 +106,109 @@ error:
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
ConfigParseListen(Config * tConfig, Array * listen)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!ArraySize(listen))
|
||||
{
|
||||
Log(LOG_ERR, "Listen array cannot be empty; you must specify at least");
|
||||
Log(LOG_ERR, "one listener.");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!tConfig->servers)
|
||||
{
|
||||
tConfig->servers = ArrayCreate();
|
||||
if (!tConfig->servers)
|
||||
{
|
||||
Log(LOG_ERR, "Unable to allocate memory for listener configurations.");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ArraySize(listen); i++)
|
||||
{
|
||||
JsonValue *val = ArrayGet(listen, i);
|
||||
HashMap *obj;
|
||||
HttpServerConfig *serverCfg = Malloc(sizeof(HttpServerConfig));
|
||||
|
||||
if (!serverCfg)
|
||||
{
|
||||
Log(LOG_ERR, "Unable to allocate memory for listener configuration.");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (JsonValueType(val) != JSON_OBJECT)
|
||||
{
|
||||
Log(LOG_ERR, "Invalid value in listener array.");
|
||||
Log(LOG_ERR, "All listeners must be objects.");
|
||||
goto error;
|
||||
}
|
||||
|
||||
obj = JsonValueAsObject(val);
|
||||
|
||||
serverCfg->port = JsonValueAsInteger(HashMapGet(obj, "port"));
|
||||
serverCfg->threads = JsonValueAsInteger(HashMapGet(obj, "threads"));
|
||||
serverCfg->maxConnections = JsonValueAsInteger(HashMapGet(obj, "maxConnections"));
|
||||
|
||||
if (!serverCfg->port)
|
||||
{
|
||||
Log(LOG_WARNING, "No or invalid port specified, listener will be ignored.");
|
||||
Free(serverCfg);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!serverCfg->threads)
|
||||
{
|
||||
Log(LOG_DEBUG, "No or invalid number of threads specified for listener.");
|
||||
Log(LOG_DEBUG, "Using default, which may be subject to change.");
|
||||
serverCfg->threads = 4;
|
||||
}
|
||||
|
||||
if (!serverCfg->maxConnections)
|
||||
{
|
||||
Log(LOG_DEBUG, "No or invalid number of maximum connections specified.");
|
||||
Log(LOG_DEBUG, "Using default, which may be subject to change.");
|
||||
serverCfg->maxConnections = 32;
|
||||
}
|
||||
|
||||
val = HashMapGet(obj, "tls");
|
||||
if ((JsonValueType(val) == JSON_BOOLEAN && !JsonValueAsBoolean(val)) || JsonValueType(val) == JSON_NULL)
|
||||
{
|
||||
serverCfg->flags = HTTP_FLAG_NONE;
|
||||
serverCfg->tlsCert = NULL;
|
||||
serverCfg->tlsKey = NULL;
|
||||
}
|
||||
else if (JsonValueType(val) != JSON_OBJECT)
|
||||
{
|
||||
Log(LOG_ERR, "Invalid value for listener.tls. It must be an object.");
|
||||
goto error;
|
||||
}
|
||||
else
|
||||
{
|
||||
serverCfg->flags = HTTP_FLAG_TLS;
|
||||
|
||||
obj = JsonValueAsObject(val);
|
||||
serverCfg->tlsCert = StrDuplicate(JsonValueAsString(HashMapGet(obj, "cert")));
|
||||
serverCfg->tlsKey = StrDuplicate(JsonValueAsString(HashMapGet(obj, "key")));
|
||||
|
||||
if (!serverCfg->tlsCert || !serverCfg->tlsKey)
|
||||
{
|
||||
Log(LOG_ERR, "TLS cert and key must both be valid file names.");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
ArrayAdd(tConfig->servers, serverCfg);
|
||||
}
|
||||
|
||||
return 1;
|
||||
error:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ConfigParseLog(Config * tConfig, HashMap * config)
|
||||
{
|
||||
JsonValue *value;
|
||||
|
@ -210,7 +313,11 @@ ConfigParse(HashMap * config)
|
|||
|
||||
memset(tConfig, 0, sizeof(Config));
|
||||
|
||||
CONFIG_OPTIONAL_INTEGER(tConfig->listenPort, "listen", 8008);
|
||||
CONFIG_REQUIRE("listen", JSON_ARRAY);
|
||||
if (!ConfigParseListen(tConfig, JsonValueAsArray(value)))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
CONFIG_REQUIRE("serverName", JSON_STRING);
|
||||
CONFIG_COPY_STRING(tConfig->serverName);
|
||||
|
@ -256,8 +363,6 @@ ConfigParse(HashMap * config)
|
|||
CONFIG_REQUIRE("dataDir", JSON_STRING);
|
||||
CONFIG_COPY_STRING(tConfig->dataDir);
|
||||
|
||||
CONFIG_OPTIONAL_INTEGER(tConfig->threads, "threads", 1);
|
||||
CONFIG_OPTIONAL_INTEGER(tConfig->maxConnections, "maxConnections", 32);
|
||||
CONFIG_OPTIONAL_INTEGER(tConfig->maxCache, "maxCache", 0);
|
||||
|
||||
CONFIG_REQUIRE("federation", JSON_BOOLEAN);
|
||||
|
@ -303,5 +408,21 @@ ConfigFree(Config * tConfig)
|
|||
|
||||
Free(tConfig->logTimestamp);
|
||||
|
||||
if (tConfig->servers)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < ArraySize(tConfig->servers); i++)
|
||||
{
|
||||
HttpServerConfig *serverCfg = ArrayGet(tConfig->servers, i);
|
||||
|
||||
Free(serverCfg->tlsCert);
|
||||
Free(serverCfg->tlsKey);
|
||||
Free(serverCfg);
|
||||
}
|
||||
|
||||
ArrayFree(tConfig->servers);
|
||||
}
|
||||
|
||||
Free(tConfig);
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <Array.h>
|
||||
#include <Util.h>
|
||||
#include <Tls.h>
|
||||
#include <Log.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
|
@ -48,20 +49,13 @@ static const char ENABLE = 1;
|
|||
|
||||
struct HttpServer
|
||||
{
|
||||
HttpServerConfig config;
|
||||
int sd;
|
||||
unsigned int nThreads;
|
||||
unsigned int maxConnections;
|
||||
pthread_t socketThread;
|
||||
int flags;
|
||||
char *tlsCrt;
|
||||
char *tlsKey;
|
||||
|
||||
volatile unsigned int stop:1;
|
||||
volatile unsigned int isRunning:1;
|
||||
|
||||
HttpHandler *requestHandler;
|
||||
void *handlerArgs;
|
||||
|
||||
Queue *connQueue;
|
||||
pthread_mutex_t connQueueMutex;
|
||||
|
||||
|
@ -234,7 +228,7 @@ HttpResponseStatus(HttpServerContext * c, HttpStatus status)
|
|||
}
|
||||
|
||||
HttpStatus
|
||||
HttpResponseStatusGet(HttpServerContext *c)
|
||||
HttpResponseStatusGet(HttpServerContext * c)
|
||||
{
|
||||
if (!c)
|
||||
{
|
||||
|
@ -291,19 +285,23 @@ DequeueConnection(HttpServer * server)
|
|||
}
|
||||
|
||||
HttpServer *
|
||||
HttpServerCreate(int flags, unsigned short port, unsigned int nThreads, unsigned int maxConnections,
|
||||
HttpHandler * requestHandler, void *handlerArgs)
|
||||
HttpServerCreate(HttpServerConfig * config)
|
||||
{
|
||||
HttpServer *server;
|
||||
struct sockaddr_in sa;
|
||||
|
||||
if (!requestHandler)
|
||||
if (!config)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!config->handler)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef TLS_IMPL
|
||||
if (flags & HTTP_FLAG_TLS)
|
||||
if (config->flags & HTTP_FLAG_TLS)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
@ -317,7 +315,7 @@ HttpServerCreate(int flags, unsigned short port, unsigned int nThreads, unsigned
|
|||
|
||||
memset(server, 0, sizeof(HttpServer));
|
||||
|
||||
server->flags = flags;
|
||||
server->config = *config;
|
||||
|
||||
server->threadPool = ArrayCreate();
|
||||
if (!server->threadPool)
|
||||
|
@ -325,7 +323,7 @@ HttpServerCreate(int flags, unsigned short port, unsigned int nThreads, unsigned
|
|||
goto error;
|
||||
}
|
||||
|
||||
server->connQueue = QueueCreate(maxConnections);
|
||||
server->connQueue = QueueCreate(config->maxConnections);
|
||||
if (!server->connQueue)
|
||||
{
|
||||
goto error;
|
||||
|
@ -363,7 +361,7 @@ HttpServerCreate(int flags, unsigned short port, unsigned int nThreads, unsigned
|
|||
memset(&sa, 0, sizeof(struct sockaddr_in));
|
||||
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = htons(port);
|
||||
sa.sin_port = htons(config->port);
|
||||
sa.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
if (bind(server->sd, (struct sockaddr *) & sa, sizeof(sa)) < 0)
|
||||
|
@ -371,15 +369,11 @@ HttpServerCreate(int flags, unsigned short port, unsigned int nThreads, unsigned
|
|||
goto error;
|
||||
}
|
||||
|
||||
if (listen(server->sd, maxConnections) < 0)
|
||||
if (listen(server->sd, config->maxConnections) < 0)
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
server->nThreads = nThreads;
|
||||
server->maxConnections = maxConnections;
|
||||
server->requestHandler = requestHandler;
|
||||
server->handlerArgs = handlerArgs;
|
||||
server->stop = 0;
|
||||
server->isRunning = 0;
|
||||
|
||||
|
@ -410,6 +404,17 @@ error:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
HttpServerConfig *
|
||||
HttpServerConfigGet(HttpServer * server)
|
||||
{
|
||||
if (!server)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &server->config;
|
||||
}
|
||||
|
||||
void
|
||||
HttpServerFree(HttpServer * server)
|
||||
{
|
||||
|
@ -561,7 +566,7 @@ HttpServerWorkerThread(void *args)
|
|||
goto internal_error;
|
||||
}
|
||||
|
||||
server->requestHandler(context, server->handlerArgs);
|
||||
server->config.handler(context, server->config.handlerArgs);
|
||||
|
||||
HttpServerContextFree(context);
|
||||
fp = NULL; /* The above call will close this
|
||||
|
@ -603,7 +608,7 @@ HttpServerEventThread(void *args)
|
|||
pollFds[0].fd = server->sd;
|
||||
pollFds[0].events = POLLIN;
|
||||
|
||||
for (i = 0; i < server->nThreads; i++)
|
||||
for (i = 0; i < server->config.threads; i++)
|
||||
{
|
||||
HttpServerWorkerThreadArgs *workerThread = Malloc(sizeof(HttpServerWorkerThreadArgs));
|
||||
|
||||
|
@ -657,9 +662,9 @@ HttpServerEventThread(void *args)
|
|||
}
|
||||
|
||||
#ifdef TLS_IMPL
|
||||
if (server->flags & HTTP_FLAG_TLS)
|
||||
if (server->config.flags & HTTP_FLAG_TLS)
|
||||
{
|
||||
fp = TlsServerStream(connFd, server->tlsCrt, server->tlsKey);
|
||||
fp = TlsServerStream(connFd, server->config.tlsCert, server->config.tlsKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -681,7 +686,7 @@ HttpServerEventThread(void *args)
|
|||
pthread_mutex_unlock(&server->connQueueMutex);
|
||||
}
|
||||
|
||||
for (i = 0; i < server->nThreads; i++)
|
||||
for (i = 0; i < server->config.threads; i++)
|
||||
{
|
||||
HttpServerWorkerThreadArgs *workerThread = ArrayGet(server->threadPool, i);
|
||||
|
||||
|
|
|
@ -369,7 +369,7 @@ Logv(LogConfig * config, int level, const char *msg, va_list argp)
|
|||
}
|
||||
|
||||
void
|
||||
LogTo(LogConfig *config, int level, const char *fmt, ...)
|
||||
LogTo(LogConfig * config, int level, const char *fmt,...)
|
||||
{
|
||||
va_list argp;
|
||||
|
||||
|
@ -379,7 +379,7 @@ LogTo(LogConfig *config, int level, const char *fmt, ...)
|
|||
}
|
||||
|
||||
extern void
|
||||
Log(int level, const char *fmt, ...)
|
||||
Log(int level, const char *fmt,...)
|
||||
{
|
||||
va_list argp;
|
||||
|
||||
|
|
95
src/Main.c
95
src/Main.c
|
@ -43,6 +43,7 @@
|
|||
#include <Db.h>
|
||||
#include <Cron.h>
|
||||
#include <Uia.h>
|
||||
#include <Util.h>
|
||||
|
||||
static Array *httpServers = NULL;
|
||||
|
||||
|
@ -61,6 +62,7 @@ TelodendriaSignalHandler(int signalNo)
|
|||
for (i = 0; i < ArraySize(httpServers); i++)
|
||||
{
|
||||
HttpServer *server = ArrayGet(httpServers, i);
|
||||
|
||||
HttpServerStop(server);
|
||||
}
|
||||
}
|
||||
|
@ -239,6 +241,7 @@ main(int argc, char **argv)
|
|||
{
|
||||
Log(LOG_ERR, "Unable to open log file for appending.");
|
||||
exit = EXIT_FAILURE;
|
||||
tConfig->flags &= CONFIG_LOG_STDOUT;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
@ -269,14 +272,11 @@ main(int argc, char **argv)
|
|||
|
||||
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());
|
||||
|
@ -292,19 +292,60 @@ main(int argc, char **argv)
|
|||
goto finish;
|
||||
}
|
||||
|
||||
/* Bind the socket before possibly dropping permissions */
|
||||
server = HttpServerCreate(HTTP_FLAG_NONE, tConfig->listenPort, tConfig->threads,
|
||||
tConfig->maxConnections, MatrixHttpHandler, &matrixArgs);
|
||||
if (!server)
|
||||
/* Bind servers before possibly dropping permissions. */
|
||||
for (i = 0; i < ArraySize(tConfig->servers); i++)
|
||||
{
|
||||
Log(LOG_ERR, "Unable to create HTTP server on port %d: %s",
|
||||
tConfig->listenPort, strerror(errno));
|
||||
HttpServerConfig *serverCfg = ArrayGet(tConfig->servers, i);
|
||||
|
||||
Log(LOG_DEBUG, "HTTP listener: %lu", i);
|
||||
LogConfigIndent(LogConfigGlobal());
|
||||
Log(LOG_DEBUG, "Port: %hu", serverCfg->port);
|
||||
Log(LOG_DEBUG, "Threads: %u", serverCfg->threads);
|
||||
Log(LOG_DEBUG, "Max Connections: %u", serverCfg->maxConnections);
|
||||
Log(LOG_DEBUG, "Flags: %d", serverCfg->flags);
|
||||
Log(LOG_DEBUG, "TLS Cert: %s", serverCfg->tlsCert);
|
||||
Log(LOG_DEBUG, "TLS Key: %s", serverCfg->tlsKey);
|
||||
LogConfigUnindent(LogConfigGlobal());
|
||||
|
||||
serverCfg->handler = MatrixHttpHandler;
|
||||
serverCfg->handlerArgs = &matrixArgs;
|
||||
|
||||
if (serverCfg->flags & HTTP_FLAG_TLS)
|
||||
{
|
||||
if (!UtilLastModified(serverCfg->tlsCert))
|
||||
{
|
||||
Log(LOG_ERR, "%s: %s", strerror(errno), serverCfg->tlsCert);
|
||||
exit = EXIT_FAILURE;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!UtilLastModified(serverCfg->tlsKey))
|
||||
{
|
||||
Log(LOG_ERR, "%s: %s", strerror(errno), serverCfg->tlsKey);
|
||||
exit = EXIT_FAILURE;
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
|
||||
server = HttpServerCreate(serverCfg);
|
||||
if (!server)
|
||||
{
|
||||
Log(LOG_ERR, "Unable to create HTTP server on port %d: %s",
|
||||
serverCfg->port, strerror(errno));
|
||||
|
||||
exit = EXIT_FAILURE;
|
||||
goto finish;
|
||||
}
|
||||
ArrayAdd(httpServers, server);
|
||||
}
|
||||
|
||||
if (!ArraySize(httpServers))
|
||||
{
|
||||
Log(LOG_ERR, "No valid HTTP listeners specified in the configuration.");
|
||||
exit = EXIT_FAILURE;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
ArrayAdd(httpServers, server);
|
||||
|
||||
Log(LOG_DEBUG, "Running as uid:gid: %d:%d.", getuid(), getgid());
|
||||
|
||||
if (tConfig->uid && tConfig->gid)
|
||||
|
@ -375,7 +416,6 @@ main(int argc, char **argv)
|
|||
tConfig->uid = NULL;
|
||||
tConfig->gid = NULL;
|
||||
|
||||
|
||||
if (!tConfig->maxCache)
|
||||
{
|
||||
Log(LOG_WARNING, "Database caching is disabled.");
|
||||
|
@ -391,6 +431,10 @@ main(int argc, char **argv)
|
|||
exit = EXIT_FAILURE;
|
||||
goto finish;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(LOG_DEBUG, "Opened database.");
|
||||
}
|
||||
|
||||
cron = CronCreate(60 * 1000); /* 1-minute tick */
|
||||
if (!cron)
|
||||
|
@ -411,21 +455,24 @@ main(int argc, char **argv)
|
|||
|
||||
for (i = 0; i < ArraySize(httpServers); i++)
|
||||
{
|
||||
HttpServerConfig *serverCfg;
|
||||
|
||||
server = ArrayGet(httpServers, i);
|
||||
serverCfg = HttpServerConfigGet(server);
|
||||
|
||||
if (!HttpServerStart(server))
|
||||
{
|
||||
Log(LOG_ERR, "Unable to start HTTP server %lu.", i);
|
||||
Log(LOG_ERR, "Unable to start HTTP server %lu on port %hu.", i, serverCfg->port);
|
||||
exit = EXIT_FAILURE;
|
||||
goto finish;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(LOG_DEBUG, "Started HTTP server %lu.", i);
|
||||
Log(LOG_INFO, "Listening on port: %hu", serverCfg->port);
|
||||
}
|
||||
}
|
||||
|
||||
Log(LOG_INFO, "Listening on port: %d", tConfig->listenPort);
|
||||
|
||||
sigAction.sa_handler = TelodendriaSignalHandler;
|
||||
sigfillset(&sigAction.sa_mask);
|
||||
|
@ -437,6 +484,10 @@ main(int argc, char **argv)
|
|||
exit = EXIT_FAILURE;
|
||||
goto finish;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(LOG_DEBUG, "Installed SIGINT signal handler.");
|
||||
}
|
||||
|
||||
/* Block this thread until the servers are terminated by a signal
|
||||
* handler */
|
||||
|
@ -444,6 +495,7 @@ main(int argc, char **argv)
|
|||
{
|
||||
server = ArrayGet(httpServers, i);
|
||||
HttpServerJoin(server);
|
||||
Log(LOG_DEBUG, "Joined HTTP server %lu.", i);
|
||||
}
|
||||
|
||||
finish:
|
||||
|
@ -452,11 +504,14 @@ finish:
|
|||
{
|
||||
for (i = 0; i < ArraySize(httpServers); i++)
|
||||
{
|
||||
Log(LOG_DEBUG, "Freeing HTTP server %lu...", i);
|
||||
server = ArrayGet(httpServers, i);
|
||||
HttpServerStop(server);
|
||||
HttpServerFree(server);
|
||||
Log(LOG_DEBUG, "Freed HTTP server %lu.", i);
|
||||
}
|
||||
ArrayFree(httpServers);
|
||||
Log(LOG_DEBUG, "Freed HTTP servers array.");
|
||||
}
|
||||
|
||||
if (cron)
|
||||
|
@ -466,16 +521,8 @@ finish:
|
|||
Log(LOG_DEBUG, "Stopped and freed job scheduler.");
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're not logging to standard output, then we can close it. Otherwise,
|
||||
* if we are logging to stdout, LogConfigFree() will close it for us.
|
||||
*/
|
||||
if (tConfig && !(tConfig->flags & CONFIG_LOG_STDOUT))
|
||||
{
|
||||
StreamClose(StreamStdout());
|
||||
}
|
||||
|
||||
DbClose(matrixArgs.db);
|
||||
Log(LOG_DEBUG, "Closed database.");
|
||||
|
||||
ConfigFree(tConfig);
|
||||
|
||||
|
@ -498,6 +545,8 @@ finish:
|
|||
* memory should be allocated. */
|
||||
TelodendriaGenerateMemReport();
|
||||
|
||||
/* Free any leaked memory now, just in case the operating system
|
||||
* we're running on won't do it for us. */
|
||||
MemoryFreeAll();
|
||||
return exit;
|
||||
}
|
||||
|
|
|
@ -119,21 +119,25 @@ TlsInitServer(int fd, const char *crt, const char *key)
|
|||
|
||||
if (tls_config_set_cert_file(cookie->cfg, crt) == -1)
|
||||
{
|
||||
Log(LOG_ERR, "Error with certificate file.");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (tls_config_set_key_file(cookie->cfg, key) == -1)
|
||||
{
|
||||
Log(LOG_ERR, "Error with key file.");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (tls_configure(cookie->ctx, cookie->cfg) == -1)
|
||||
{
|
||||
Log(LOG_ERR, "Error configuring context.");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (tls_accept_socket(cookie->ctx, &cookie->cctx, fd) == -1)
|
||||
{
|
||||
Log(LOG_ERR, "Error accepting socket.");
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
|
|
@ -205,7 +205,7 @@ UiaStageBuild(char *type, HashMap * params)
|
|||
|
||||
int
|
||||
UiaComplete(Array * flows, HttpServerContext * context, Db * db,
|
||||
HashMap * request, HashMap ** response, Config * config)
|
||||
HashMap * request, HashMap ** response, Config * config)
|
||||
{
|
||||
JsonValue *val;
|
||||
HashMap *auth;
|
||||
|
|
|
@ -43,7 +43,7 @@ extern int
|
|||
ArrayInsert(Array *, size_t, void *);
|
||||
|
||||
extern void *
|
||||
ArraySet(Array *, size_t, void *);
|
||||
ArraySet(Array *, size_t, void *);
|
||||
|
||||
extern int
|
||||
ArrayAdd(Array *, void *);
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include <Log.h>
|
||||
#include <HashMap.h>
|
||||
#include <Array.h>
|
||||
|
||||
typedef enum ConfigFlag
|
||||
{
|
||||
|
@ -48,15 +49,14 @@ typedef struct Config
|
|||
char *gid;
|
||||
char *dataDir;
|
||||
|
||||
unsigned short listenPort;
|
||||
unsigned int flags;
|
||||
unsigned int threads;
|
||||
unsigned int maxConnections;
|
||||
|
||||
size_t maxCache;
|
||||
|
||||
char *logTimestamp;
|
||||
int logLevel;
|
||||
|
||||
Array *servers;
|
||||
} Config;
|
||||
|
||||
extern Config *
|
||||
|
@ -65,4 +65,4 @@ extern Config *
|
|||
extern void
|
||||
ConfigFree(Config *);
|
||||
|
||||
#endif /* TELODENDRIA_CONFIG_H */
|
||||
#endif /* TELODENDRIA_CONFIG_H */
|
||||
|
|
|
@ -36,8 +36,25 @@ typedef struct HttpServer HttpServer;
|
|||
typedef struct HttpServerContext HttpServerContext;
|
||||
typedef void (HttpHandler) (HttpServerContext *, void *);
|
||||
|
||||
typedef struct HttpServerConfig
|
||||
{
|
||||
unsigned short port;
|
||||
unsigned int threads;
|
||||
unsigned int maxConnections;
|
||||
|
||||
int flags;
|
||||
char *tlsCert;
|
||||
char *tlsKey;
|
||||
|
||||
HttpHandler *handler;
|
||||
void *handlerArgs;
|
||||
} HttpServerConfig;
|
||||
|
||||
extern HttpServer *
|
||||
HttpServerCreate(int, unsigned short, unsigned int, unsigned int, HttpHandler *, void *);
|
||||
HttpServerCreate(HttpServerConfig *);
|
||||
|
||||
extern HttpServerConfig *
|
||||
HttpServerConfigGet(HttpServer *);
|
||||
|
||||
extern void
|
||||
HttpServerFree(HttpServer *);
|
||||
|
|
|
@ -76,6 +76,6 @@ extern void
|
|||
LogTo(LogConfig *, int, const char *,...);
|
||||
|
||||
extern void
|
||||
Log(int, const char *, ...);
|
||||
Log(int, const char *,...);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -73,8 +73,16 @@ int
|
|||
main(void)
|
||||
{
|
||||
struct sigaction sa;
|
||||
HttpServerConfig cfg;
|
||||
|
||||
server = HttpServerCreate(HTTP_FLAG_NONE, 8008, 1, 1, HttpHandle, NULL);
|
||||
cfg.flags = HTTP_FLAG_NONE;
|
||||
cfg.port = 8008;
|
||||
cfg.threads = 1;
|
||||
cfg.maxConnections = 1;
|
||||
cfg.handler = HttpHandle;
|
||||
cfg.handlerArgs = NULL;
|
||||
|
||||
server = HttpServerCreate(&cfg);
|
||||
if (!HttpServerStart(server))
|
||||
{
|
||||
StreamPuts(StreamStderr(), "Unable to start HTTP server.\n");
|
||||
|
|
Loading…
Reference in a new issue