blob: d3f16d6d340e0dad12ba82c6fd8a786be4c46602 [file] [log] [blame] [raw]
/*
Edit this file to add any command line argument handling and core setup concerns
(i.e. replacing the default pub/sub engine with a Redis engine).
*/
/* declared here, implemented in setup.h */
void setup_network_services(void);
/* declared here, implemented in setup.h */
#include "main.h"
#include "fio_cli_helper.h"
#include "redis_engine.h"
#include <string.h>
const int ARGC;
char const **ARGV;
int VERBOSE = 0;
const char *HTTP_PUBLIC_FOLDER;
const char *HTTP_PORT;
const char *HTTP_ADDRESS;
unsigned long HTTP_BODY_LIMIT;
unsigned char HTTP_TIMEOUT;
unsigned long WEBSOCKET_MSG_LIMIT;
unsigned char WEBSOCKET_PING_INTERVAL;
static char tmp_url_parsing[1024];
/*
clang-format off
Available command line flags:
-p <port> : defaults port 3000.
-t <threads> : number of threads per process, defaults to 0 (automatic CPU core test/set).
-w <processes> : number of processes, defaults to 0 (automatic CPU core test/set).
-v : request verbosity (logging).
-r <address> <port> : a spece delimited couplet for the Redis address and port for pub/sub.
-k <0..255> : HTTP keep-alive timeout. default (0) reverts to ~5 seconds.
-ping <0..255> : websocket ping interval. default (0) reverts to ~40 seconds.
-public <folder> : public folder, for static file service. default (NULL) disables static file service.
-maxbd <Mb> : HTTP upload limit. default to ~50Mb.
-maxms <Kb> : incoming websocket message size limit. default to ~250Kb.
-? : print command line options.
clang-format on
*/
int main(int argc, char const *argv[]) {
{
/* setup global access to ARGC and ARGV */
int *tmp = (int *)&ARGC;
*tmp = argc;
ARGV = argv;
}
const char *redis_address = NULL;
const char *redis_port = NULL;
const char *redis_password = NULL;
uint32_t threads = 0;
uint32_t workers = 0;
/* **** Environmental defaults **** */
if (getenv("PORT"))
HTTP_PORT = getenv("PORT");
if (getenv("ADDRESS"))
HTTP_ADDRESS = getenv("ADDRESS");
if (getenv("HTTP_PUBLIC_FOLDER"))
HTTP_PUBLIC_FOLDER = getenv("HTTP_PUBLIC_FOLDER");
/* parse the Redis URL to manage redis pub/sub */
if (getenv("REDIS_URL")) {
/* We assume a format such as redis://user:password@example.com:6379/ */
size_t l = strlen(getenv("REDIS_URL"));
if (l < 1024) {
strcpy(tmp_url_parsing, getenv("REDIS_URL"));
int flag = 0;
for (size_t i = 0; i < l; i++) {
if (tmp_url_parsing[i] == ':' && tmp_url_parsing[i + 1] == '/' &&
tmp_url_parsing[i + 2] == '/') {
redis_address = tmp_url_parsing + i + 2;
i += 2;
} else if (tmp_url_parsing[i] == ':') {
tmp_url_parsing[i] = 0;
if (redis_address)
redis_port = tmp_url_parsing + i + 1;
} else if (tmp_url_parsing[i] == '@' && flag == 0) {
/* there was a password involved */
flag = 1;
redis_password = redis_port;
redis_address = NULL;
} else if (tmp_url_parsing[i] == '/')
flag = 1;
}
}
}
/* **** Command line arguments **** */
fio_cli_start(argc, argv, NULL);
fio_cli_accept_num("port p", "port number to listen to. defaults port 3000");
fio_cli_accept_num("workers w", "number of processes to use.");
fio_cli_accept_num("threads t", "number of threads per process.");
fio_cli_accept_bool("log v", "request verbosity (logging).");
fio_cli_accept_str("public www", "public folder, for static file service.");
fio_cli_accept_num("keep-alive k", "HTTP keep-alive timeout (0..255). "
"default: ~5s");
fio_cli_accept_num("ping", "websocket ping interval (0..255). "
"default: ~40s");
fio_cli_accept_num("max-body maxbd", "HTTP upload limit. default: ~50Mb");
fio_cli_accept_num("max-message maxms",
"incoming websocket message size limit. "
"default: ~250Kb");
fio_cli_accept_str("redis-address ra", "an optional Redis server's address.");
fio_cli_accept_str("redis-port rp",
"an optional Redis server's port. default: 6379");
fio_cli_accept_str("redis-password rpw", "Redis password, if any.");
if (fio_cli_get_str("p"))
HTTP_PORT = fio_cli_get_str("p");
if (fio_cli_get_str("www")) {
HTTP_PUBLIC_FOLDER = fio_cli_get_str("www");
}
if (fio_cli_get_str("t"))
threads = fio_cli_get_int("t");
if (fio_cli_get_str("w"))
workers = fio_cli_get_int("w");
VERBOSE = fio_cli_get_int("v");
if (fio_cli_get_str("redis"))
redis_address = fio_cli_get_str("redis");
if (fio_cli_get_str("redis-port"))
redis_port = fio_cli_get_str("redis-port");
if (fio_cli_get_str("redis-port"))
redis_password = fio_cli_get_str("redis-password");
HTTP_TIMEOUT = fio_cli_get_int("keep-alive");
WEBSOCKET_PING_INTERVAL = fio_cli_get_int("ping");
if (fio_cli_get_int("maxbd"))
HTTP_BODY_LIMIT = fio_cli_get_int("maxbd");
if (fio_cli_get_int("maxms"))
WEBSOCKET_MSG_LIMIT = fio_cli_get_int("maxms");
if (!HTTP_PORT)
HTTP_PORT = "3000";
/* **** actual code **** */
/* set Redis pub/sub if requested */
if (redis_address) {
PUBSUB_DEFAULT_ENGINE =
redis_engine_create(.address = redis_address, .port = redis_port,
.auth = redis_password, .ping_interval = 40);
if (!PUBSUB_DEFAULT_ENGINE) {
perror("\nERROR: couldn't initialize Redis engine.\n");
exit(-2);
}
}
/* initialize network services */
setup_network_services();
/* start facil */
facil_run(.threads = threads, .processes = workers);
/* clean up Redis, if exists */
if (PUBSUB_DEFAULT_ENGINE != PUBSUB_CLUSTER_ENGINE) {
redis_engine_destroy(PUBSUB_DEFAULT_ENGINE);
PUBSUB_DEFAULT_ENGINE = PUBSUB_CLUSTER_ENGINE;
}
return 0;
}