Compare commits
3 Commits
e44b7d0e5f
...
8e0477c34b
| Author | SHA1 | Date |
|---|---|---|
|
|
8e0477c34b | |
|
|
dde83584a7 | |
|
|
3aa0ace863 |
|
|
@ -0,0 +1,47 @@
|
||||||
|
#ifndef LNM_LOG
|
||||||
|
#define LOG
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "lnm/common.h"
|
||||||
|
|
||||||
|
typedef struct lnm_logger lnm_logger;
|
||||||
|
|
||||||
|
typedef enum lnm_log_level {
|
||||||
|
lnm_log_level_debug = 0,
|
||||||
|
lnm_log_level_info,
|
||||||
|
lnm_log_level_notice,
|
||||||
|
lnm_log_level_warning,
|
||||||
|
lnm_log_level_error,
|
||||||
|
lnm_log_level_critical
|
||||||
|
} lnm_log_level;
|
||||||
|
|
||||||
|
extern const char *lnm_log_level_names[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the global logger.
|
||||||
|
*/
|
||||||
|
lnm_err lnm_log_init_global();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register stdout as one of the streams for the global logger.
|
||||||
|
*/
|
||||||
|
lnm_err lnm_log_register_stdout(lnm_log_level level);
|
||||||
|
|
||||||
|
void lnm_log(lnm_log_level level, const char *section, const char *fmt, ...)
|
||||||
|
__attribute__((format(printf, 3, 4)));
|
||||||
|
|
||||||
|
#define lnm_ldebug(section, fmt, ...) \
|
||||||
|
lnm_log(lnm_log_level_debug, section, fmt, __VA_ARGS__)
|
||||||
|
#define lnm_linfo(section, fmt, ...) \
|
||||||
|
lnm_log(lnm_log_level_info, section, fmt, __VA_ARGS__)
|
||||||
|
#define lnm_lnotice(section, fmt, ...) \
|
||||||
|
lnm_log(lnm_log_level_notice, section, fmt, __VA_ARGS__)
|
||||||
|
#define lnm_lwarning(section, fmt, ...) \
|
||||||
|
lnm_log(lnm_log_level_warning, section, fmt, __VA_ARGS__)
|
||||||
|
#define lnm_lerror(section, fmt, ...) \
|
||||||
|
lnm_log(lnm_log_level_error, section, fmt, __VA_ARGS__)
|
||||||
|
#define lnm_lcritical(section, fmt, ...) \
|
||||||
|
lnm_log(lnm_log_level_critical, section, fmt, __VA_ARGS__)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef LNM_LOG_INTERNAL
|
||||||
|
#define LNM_LOG_INTERNAL
|
||||||
|
|
||||||
|
#include "lnm/log.h"
|
||||||
|
|
||||||
|
typedef enum lnm_logger_stream_type {
|
||||||
|
lnm_logger_stream_type_file = 0
|
||||||
|
} lnm_logger_stream_type;
|
||||||
|
|
||||||
|
typedef struct lnm_logger_stream {
|
||||||
|
void *ptr;
|
||||||
|
lnm_logger_stream_type type;
|
||||||
|
lnm_log_level level;
|
||||||
|
} lnm_logger_stream;
|
||||||
|
|
||||||
|
struct lnm_logger {
|
||||||
|
struct {
|
||||||
|
lnm_logger_stream **arr;
|
||||||
|
size_t len;
|
||||||
|
} streams;
|
||||||
|
};
|
||||||
|
|
||||||
|
lnm_err lnm_logger_stream_register(lnm_logger *logger,
|
||||||
|
lnm_logger_stream *stream);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -6,9 +6,12 @@
|
||||||
#include "lnm/http/loop.h"
|
#include "lnm/http/loop.h"
|
||||||
#include "lnm/http/loop_internal.h"
|
#include "lnm/http/loop_internal.h"
|
||||||
#include "lnm/http/req.h"
|
#include "lnm/http/req.h"
|
||||||
|
#include "lnm/log.h"
|
||||||
#include "lnm/loop.h"
|
#include "lnm/loop.h"
|
||||||
#include "lnm/loop_internal.h"
|
#include "lnm/loop_internal.h"
|
||||||
|
|
||||||
|
static const char *section = "http";
|
||||||
|
|
||||||
/* static const lnm_http_loop_state lnm_http_loop_state_first_req =
|
/* static const lnm_http_loop_state lnm_http_loop_state_first_req =
|
||||||
* lnm_http_loop_state_parse_req; */
|
* lnm_http_loop_state_parse_req; */
|
||||||
static const lnm_http_loop_state lnm_http_loop_state_first_res =
|
static const lnm_http_loop_state lnm_http_loop_state_first_res =
|
||||||
|
|
@ -29,10 +32,15 @@ void lnm_http_loop_process_parse_req(lnm_http_conn *conn) {
|
||||||
// If the request is already the size of the read buffer, we close the
|
// If the request is already the size of the read buffer, we close the
|
||||||
// request. Otherwise, we wait for anything read
|
// request. Otherwise, we wait for anything read
|
||||||
if (conn->r.size - conn->r.read == LNM_LOOP_BUF_SIZE) {
|
if (conn->r.size - conn->r.read == LNM_LOOP_BUF_SIZE) {
|
||||||
|
lnm_linfo(section, "Received request larger than buffer (%i bytes)",
|
||||||
|
LNM_LOOP_BUF_SIZE);
|
||||||
|
|
||||||
conn->state = lnm_loop_state_end;
|
conn->state = lnm_loop_state_end;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case lnm_http_parse_err_invalid:
|
case lnm_http_parse_err_invalid:
|
||||||
|
lnm_linfo(section, "%s", "Received invalid request");
|
||||||
|
|
||||||
conn->state = lnm_loop_state_end;
|
conn->state = lnm_loop_state_end;
|
||||||
break;
|
break;
|
||||||
case lnm_http_parse_err_unknown_method:
|
case lnm_http_parse_err_unknown_method:
|
||||||
|
|
@ -40,6 +48,10 @@ void lnm_http_loop_process_parse_req(lnm_http_conn *conn) {
|
||||||
ctx->state = lnm_http_loop_state_first_res;
|
ctx->state = lnm_http_loop_state_first_res;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lnm_linfo(section, "%s %.*s HTTP/1.%i",
|
||||||
|
lnm_http_method_names[ctx->req.method], (int)ctx->req.path.len,
|
||||||
|
ctx->req.path.s, ctx->req.minor_version);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lnm_http_loop_process_route(lnm_http_conn *conn) {
|
void lnm_http_loop_process_route(lnm_http_conn *conn) {
|
||||||
|
|
@ -163,6 +175,13 @@ void lnm_http_loop_state_process_add_headers(lnm_http_conn *conn) {
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (res->status == 0) {
|
||||||
|
res->status = lnm_http_status_ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
lnm_linfo(section, "%i %s", res->status,
|
||||||
|
lnm_http_status_names[res->status / 100 - 1][res->status % 100]);
|
||||||
|
|
||||||
ctx->state = lnm_http_loop_state_write_status_line;
|
ctx->state = lnm_http_loop_state_write_status_line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -172,10 +191,6 @@ void lnm_http_loop_process_write_status_line(lnm_http_conn *conn) {
|
||||||
lnm_http_loop_ctx *ctx = conn->ctx;
|
lnm_http_loop_ctx *ctx = conn->ctx;
|
||||||
lnm_http_res *res = &ctx->res;
|
lnm_http_res *res = &ctx->res;
|
||||||
|
|
||||||
if (res->status == 0) {
|
|
||||||
res->status = lnm_http_status_ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *response_type_name =
|
const char *response_type_name =
|
||||||
lnm_http_status_names[res->status / 100 - 1][res->status % 100];
|
lnm_http_status_names[res->status / 100 - 1][res->status % 100];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "lnm/common.h"
|
||||||
|
#include "lnm/log_internal.h"
|
||||||
|
|
||||||
|
const char *lnm_log_level_names[] = {"DEBUG ", "INFO ", "NOTICE ",
|
||||||
|
"WARNING ", "ERROR ", "CRITICAL"};
|
||||||
|
|
||||||
|
lnm_logger *global_logger = NULL;
|
||||||
|
|
||||||
|
lnm_err lnm_log_init_global() {
|
||||||
|
global_logger = calloc(1, sizeof(lnm_logger));
|
||||||
|
|
||||||
|
return global_logger == NULL ? lnm_err_failed_alloc : lnm_err_ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
lnm_err lnm_logger_stream_register(lnm_logger *logger,
|
||||||
|
lnm_logger_stream *stream) {
|
||||||
|
lnm_logger_stream **new =
|
||||||
|
logger->streams.len == 0
|
||||||
|
? malloc(sizeof(lnm_logger_stream *))
|
||||||
|
: realloc(logger->streams.arr,
|
||||||
|
(logger->streams.len + 1) * sizeof(lnm_logger_stream *));
|
||||||
|
|
||||||
|
if (new == NULL) {
|
||||||
|
return lnm_err_failed_alloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
new[logger->streams.len] = stream;
|
||||||
|
logger->streams.arr = new;
|
||||||
|
logger->streams.len++;
|
||||||
|
|
||||||
|
return lnm_err_ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
lnm_err lnm_log_register_stdout(lnm_log_level level) {
|
||||||
|
lnm_logger_stream *stream = malloc(sizeof(lnm_logger_stream));
|
||||||
|
|
||||||
|
if (stream == NULL) {
|
||||||
|
return lnm_err_failed_alloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream->type = lnm_logger_stream_type_file;
|
||||||
|
stream->ptr = stdout;
|
||||||
|
stream->level = level;
|
||||||
|
|
||||||
|
LNM_RES2(lnm_logger_stream_register(global_logger, stream), free(stream));
|
||||||
|
|
||||||
|
return lnm_err_ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lnm_vlog(lnm_log_level level, const char *section, const char *fmt,
|
||||||
|
va_list ap) {
|
||||||
|
char date_str[32];
|
||||||
|
|
||||||
|
time_t now = time(NULL);
|
||||||
|
strftime(date_str, sizeof(date_str) - 1, "%Y-%m-%d %H:%M:%S",
|
||||||
|
localtime(&now));
|
||||||
|
|
||||||
|
for (size_t i = 0; i < global_logger->streams.len; i++) {
|
||||||
|
lnm_logger_stream *stream = global_logger->streams.arr[i];
|
||||||
|
|
||||||
|
if (level < stream->level) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (stream->type) {
|
||||||
|
case lnm_logger_stream_type_file:
|
||||||
|
fprintf(stream->ptr, "[%s][%s][%s] ", date_str,
|
||||||
|
lnm_log_level_names[level], section);
|
||||||
|
vfprintf(stream->ptr, fmt, ap);
|
||||||
|
fprintf(stream->ptr, "\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void lnm_log(lnm_log_level level, const char *section, const char *fmt, ...) {
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
lnm_vlog(level, section, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
@ -6,8 +6,11 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "lnm/common.h"
|
#include "lnm/common.h"
|
||||||
|
#include "lnm/log.h"
|
||||||
#include "lnm/loop_internal.h"
|
#include "lnm/loop_internal.h"
|
||||||
|
|
||||||
|
static const char *section = "loop";
|
||||||
|
|
||||||
lnm_err lnm_loop_init(lnm_loop **out, void *gctx,
|
lnm_err lnm_loop_init(lnm_loop **out, void *gctx,
|
||||||
lnm_err (*ctx_init)(void **out, void *gctx),
|
lnm_err (*ctx_init)(void **out, void *gctx),
|
||||||
void (*ctx_free)(void *ctx),
|
void (*ctx_free)(void *ctx),
|
||||||
|
|
@ -34,6 +37,8 @@ lnm_err lnm_loop_accept(lnm_loop *l) {
|
||||||
int conn_fd = accept(l->listen_fd, NULL, NULL);
|
int conn_fd = accept(l->listen_fd, NULL, NULL);
|
||||||
|
|
||||||
if (conn_fd < 0) {
|
if (conn_fd < 0) {
|
||||||
|
lnm_lcritical(section, "accept failed: %i", conn_fd);
|
||||||
|
|
||||||
return lnm_err_failed_network;
|
return lnm_err_failed_network;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -72,6 +77,8 @@ lnm_err lnm_loop_accept(lnm_loop *l) {
|
||||||
|
|
||||||
l->conns.open++;
|
l->conns.open++;
|
||||||
|
|
||||||
|
lnm_ldebug(section, "connection opened with fd %i", conn_fd);
|
||||||
|
|
||||||
return lnm_err_ok;
|
return lnm_err_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -130,6 +137,8 @@ lnm_err lnm_loop_run(lnm_loop *l) {
|
||||||
poll_args[0].fd = l->listen_fd;
|
poll_args[0].fd = l->listen_fd;
|
||||||
poll_args[0].events = POLLIN;
|
poll_args[0].events = POLLIN;
|
||||||
|
|
||||||
|
lnm_linfo(section, "started on fd %i", l->listen_fd);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
nfds_t poll_args_len = 1;
|
nfds_t poll_args_len = 1;
|
||||||
|
|
||||||
|
|
@ -171,6 +180,8 @@ lnm_err lnm_loop_run(lnm_loop *l) {
|
||||||
close(conn->fd);
|
close(conn->fd);
|
||||||
|
|
||||||
l->conns.open--;
|
l->conns.open--;
|
||||||
|
lnm_ldebug(section, "connection closed with fd %i", conn->fd);
|
||||||
|
|
||||||
lnm_loop_conn_free(l, conn);
|
lnm_loop_conn_free(l, conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "lnm/http/consts.h"
|
#include "lnm/http/consts.h"
|
||||||
#include "lnm/http/loop.h"
|
#include "lnm/http/loop.h"
|
||||||
#include "lnm/loop.h"
|
#include "lnm/loop.h"
|
||||||
|
#include "lnm/log.h"
|
||||||
#include "lsm/store.h"
|
#include "lsm/store.h"
|
||||||
|
|
||||||
#include "lander.h"
|
#include "lander.h"
|
||||||
#include "log.h"
|
|
||||||
|
|
||||||
static const char index_page[] =
|
static const char index_page[] =
|
||||||
"<!DOCTYPE html>\n"
|
"<!DOCTYPE html>\n"
|
||||||
|
|
@ -39,7 +40,7 @@ lnm_http_step_err lander_get_redirect(lnm_http_conn *conn) {
|
||||||
// This shouldn't be able to happen
|
// This shouldn't be able to happen
|
||||||
if (lsm_entry_attr_get(&url_attr_val, c_ctx->entry, lander_attr_type_url) !=
|
if (lsm_entry_attr_get(&url_attr_val, c_ctx->entry, lander_attr_type_url) !=
|
||||||
lsm_error_ok) {
|
lsm_error_ok) {
|
||||||
error("Entry of type redirect detected without URL attribute");
|
lnm_lerror("lander", "%s", "Entry of type redirect detected without URL attribute");
|
||||||
|
|
||||||
ctx->res.status = lnm_http_status_internal_server_error;
|
ctx->res.status = lnm_http_status_internal_server_error;
|
||||||
lsm_entry_close(c_ctx->entry);
|
lsm_entry_close(c_ctx->entry);
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "lnm/loop.h"
|
#include "lnm/loop.h"
|
||||||
#include "lsm/store.h"
|
#include "lsm/store.h"
|
||||||
|
|
||||||
#include "lander.h"
|
#include "lander.h"
|
||||||
#include "log.h"
|
|
||||||
|
|
||||||
static void randomize_key(char *key, int len) {
|
static void randomize_key(char *key, int len) {
|
||||||
size_t charset_len = strlen(lander_key_charset);
|
size_t charset_len = strlen(lander_key_charset);
|
||||||
|
|
|
||||||
31
src/log.c
31
src/log.c
|
|
@ -1,31 +0,0 @@
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include "log.h"
|
|
||||||
|
|
||||||
const char *log_level_names[] = {"DEBUG", "INFO ", "WARN ", "ERROR",
|
|
||||||
"CRITICAL"};
|
|
||||||
|
|
||||||
log_level _log_level = log_level_debug;
|
|
||||||
|
|
||||||
void _lander_log(log_level level, FILE *f, const char *fmt, ...) {
|
|
||||||
if (level < _log_level) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log to stdout by default
|
|
||||||
f = (f == NULL) ? stdout : f;
|
|
||||||
|
|
||||||
char date_str[32];
|
|
||||||
|
|
||||||
time_t now = time(NULL);
|
|
||||||
strftime(date_str, sizeof(date_str) - 1, "%Y-%m-%d %H:%M:%S",
|
|
||||||
localtime(&now));
|
|
||||||
fprintf(f, "[%s][%s] ", date_str, log_level_names[level]);
|
|
||||||
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, fmt);
|
|
||||||
vfprintf(f, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
fprintf(f, "\n");
|
|
||||||
}
|
|
||||||
18
src/main.c
18
src/main.c
|
|
@ -3,6 +3,7 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include "lnm/http/loop.h"
|
#include "lnm/http/loop.h"
|
||||||
|
#include "lnm/log.h"
|
||||||
|
|
||||||
#include "lander.h"
|
#include "lander.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
@ -61,7 +62,8 @@ lnm_http_loop *loop_init(lander_gctx *gctx, const char *api_key) {
|
||||||
#define ENV(var, env_var) \
|
#define ENV(var, env_var) \
|
||||||
const char *var = getenv(env_var); \
|
const char *var = getenv(env_var); \
|
||||||
if (var == NULL) { \
|
if (var == NULL) { \
|
||||||
critical(1, "Missing environment variable %s", env_var); \
|
lnm_lcritical("main", "Missing environment variable %s", env_var); \
|
||||||
|
exit(1); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ENV_OPT(var, env_var, default) \
|
#define ENV_OPT(var, env_var, default) \
|
||||||
|
|
@ -71,9 +73,11 @@ lnm_http_loop *loop_init(lander_gctx *gctx, const char *api_key) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
setvbuf(stdout, NULL, _IONBF, 0);
|
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
|
|
||||||
|
lnm_log_init_global();
|
||||||
|
lnm_log_register_stdout(lnm_log_level_debug);
|
||||||
|
|
||||||
ENV(api_key, "LANDER_API_KEY");
|
ENV(api_key, "LANDER_API_KEY");
|
||||||
ENV_OPT(port_str, "LANDER_PORT", "18080");
|
ENV_OPT(port_str, "LANDER_PORT", "18080");
|
||||||
ENV_OPT(data_dir_s, "LANDER_DATA_DIR", ".");
|
ENV_OPT(data_dir_s, "LANDER_DATA_DIR", ".");
|
||||||
|
|
@ -81,7 +85,8 @@ int main() {
|
||||||
int port = atoi(port_str);
|
int port = atoi(port_str);
|
||||||
|
|
||||||
if (port <= 0 || port >= 1 << 16) {
|
if (port <= 0 || port >= 1 << 16) {
|
||||||
critical(1, "Invalid TCP port %s", port_str);
|
lnm_lcritical("main", "Invalid TCP port %s", port_str);
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
lander_gctx *c_gctx = lander_gctx_init();
|
lander_gctx *c_gctx = lander_gctx_init();
|
||||||
|
|
@ -90,13 +95,14 @@ int main() {
|
||||||
lsm_str *data_dir;
|
lsm_str *data_dir;
|
||||||
lsm_str_init_copy(&data_dir, (char *)data_dir_s);
|
lsm_str_init_copy(&data_dir, (char *)data_dir_s);
|
||||||
|
|
||||||
info("Initializing store from path '%s'", data_dir_s);
|
lnm_linfo("main", "Initializing store from path '%s'", data_dir_s);
|
||||||
|
|
||||||
if (lsm_store_load(&c_gctx->store, data_dir) != lsm_error_ok) {
|
if (lsm_store_load(&c_gctx->store, data_dir) != lsm_error_ok) {
|
||||||
critical(2, "Failed to load existing store.");
|
lnm_lcritical("main", "%s", "Failed to load existing store.");
|
||||||
}
|
}
|
||||||
|
|
||||||
info("Store loaded containing %lu entries", lsm_store_size(c_gctx->store));
|
lnm_linfo("main", "Store loaded containing %lu entries",
|
||||||
|
lsm_store_size(c_gctx->store));
|
||||||
lnm_http_loop *hl = loop_init(c_gctx, api_key);
|
lnm_http_loop *hl = loop_init(c_gctx, api_key);
|
||||||
lnm_http_loop_run(hl, port);
|
lnm_http_loop_run(hl, port);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue