diff --git a/src/config_parser.rl b/src/config_parser.rl index 7407dd9..02002b5 100644 --- a/src/config_parser.rl +++ b/src/config_parser.rl @@ -2,7 +2,7 @@ #include "condition.h" #include "config_parser.h" -#if 1 +#if 0 #define _printf(fmt, ...) g_print(fmt, __VA_ARGS__) #else #define _printf(fmt, ...) /* */ @@ -46,7 +46,7 @@ action integer { value *o; - guint i = 0; + gint64 i = 0; for (gchar *c = ctx->mark; c < fpc; c++) i = i * 10 + *c - 48; @@ -55,7 +55,7 @@ /* push value onto stack */ g_queue_push_head(ctx->option_stack, o); - _printf("got integer %d in line %zd\n", i, ctx->line); + _printf("got integer %" G_GINT64_FORMAT " in line %zd\n", i, ctx->line); } action integer_suffix { @@ -69,10 +69,12 @@ if (g_str_equal(str->str, "kbyte")) o->data.number *= 1024; else if (g_str_equal(str->str, "mbyte")) o->data.number *= 1024 * 1024; else if (g_str_equal(str->str, "gbyte")) o->data.number *= 1024 * 1024 * 1024; + else if (g_str_equal(str->str, "tbyte")) o->data.number *= 1024 * 1024 * 1024 * G_GINT64_CONSTANT(1024); else if (g_str_equal(str->str, "kbit")) o->data.number *= 1000; else if (g_str_equal(str->str, "mbit")) o->data.number *= 1000 * 1000; else if (g_str_equal(str->str, "gbit")) o->data.number *= 1000 * 1000 * 1000; + else if (g_str_equal(str->str, "tbit")) o->data.number *= 1000 * 1000 * 1000 * G_GINT64_CONSTANT(1000); else if (g_str_equal(str->str, "min")) o->data.number *= 60; else if (g_str_equal(str->str, "hours")) o->data.number *= 60 * 60; @@ -81,12 +83,6 @@ g_string_free(str, TRUE); _printf("got int with suffix: %" G_GINT64_FORMAT "\n", o->data.number); - - /* make sure there was no overflow that led to negative numbers */ - if (o->data.number < 0) { - log_warning(srv, NULL, "integer value overflowed in line %zd of %s", ctx->line, ctx->filename); - return FALSE; - } } action string { @@ -414,6 +410,7 @@ if (t == NULL) { log_warning(srv, NULL, "unknown variable '%s'", o->data.string->str); + value_free(o); return FALSE; } @@ -424,6 +421,7 @@ gchar *env = getenv(o->data.string->str + 4); if (env == NULL) { log_error(srv, NULL, "unknown environment variable: %s", o->data.string->str + 4); + value_free(o); return FALSE; } @@ -532,6 +530,7 @@ if (ctx->in_setup_block) { /* we are in the setup { } block, call setups and don't append to action list */ if (!call_setup(srv, name->data.string->str, NULL)) { + value_free(name); return FALSE; } } @@ -539,14 +538,16 @@ al = g_queue_peek_head(ctx->action_list_stack); a = create_action(srv, name->data.string->str, NULL); - if (a == NULL) + if (a == NULL) { + value_free(name); return FALSE; + } g_array_append_val(al->data.list, a); } - - value_free(name); } + + value_free(name); } action function_param { @@ -565,22 +566,32 @@ if (g_str_equal(name->data.string->str, "include")) { if (val->type != VALUE_STRING) { log_warning(srv, NULL, "include directive takes a string as parameter, %s given", value_type_string(val->type)); + value_free(name); + value_free(val); return FALSE; } - if (!config_parser_file(srv, ctx_stack, val->data.string->str)) + if (!config_parser_file(srv, ctx_stack, val->data.string->str)) { + value_free(name); + value_free(val); return FALSE; + } value_free(val); } else if (g_str_equal(name->data.string->str, "include_shell")) { if (val->type != VALUE_STRING) { log_warning(srv, NULL, "include_shell directive takes a string as parameter, %s given", value_type_string(val->type)); + value_free(name); + value_free(val); return FALSE; } - if (!config_parser_shell(srv, ctx_stack, val->data.string->str)) + if (!config_parser_shell(srv, ctx_stack, val->data.string->str)) { + value_free(name); + value_free(val); return FALSE; + } value_free(val); } @@ -599,6 +610,7 @@ if (ctx->in_setup_block) { /* we are in the setup { } block, call setups and don't append to action list */ if (!call_setup(srv, name->data.string->str, val)) { + value_free(name); value_free(val); return FALSE; } @@ -609,8 +621,10 @@ a = create_action(srv, name->data.string->str, val); value_free(val); - if (a == NULL) + if (a == NULL) { + value_free(name); return FALSE; + } g_array_append_val(al->data.list, a); } @@ -861,7 +875,7 @@ # basic types boolean = ( 'true' | 'false' ) %boolean; integer_suffix_bytes = ( 'byte' | 'kbyte' | 'mbyte' | 'gbyte' | 'tbyte' | 'pbyte' ); - integer_suffix_bits = ( 'bit' | 'kbit' | 'mbit' | 'gbit' ); + integer_suffix_bits = ( 'bit' | 'kbit' | 'mbit' | 'gbit' | 'tbit' | 'pbit' ); integer_suffix_seconds = ( 'sec' | 'min' | 'hours' | 'days' ); integer_suffix = ( integer_suffix_bytes | integer_suffix_bits | integer_suffix_seconds ) >mark %integer_suffix; integer = ( ('0' | ( [1-9] [0-9]* )) %integer (ws? integer_suffix)? ); diff --git a/src/log.c b/src/log.c index 9499c11..a7b5f2b 100644 --- a/src/log.c +++ b/src/log.c @@ -448,6 +448,8 @@ void log_thread_finish(server *srv) { } void log_thread_wakeup(server *srv) { + if (!g_atomic_int_get(&srv->logs.thread_alive)) + log_thread_start(srv); log_entry_t *e; e = g_slice_new0(log_entry_t); diff --git a/src/plugin_core.c b/src/plugin_core.c index 1600d14..bb35f52 100644 --- a/src/plugin_core.c +++ b/src/plugin_core.c @@ -299,19 +299,46 @@ static action* core_blank(server *srv, plugin* p, value *val) { static gboolean core_listen(server *srv, plugin* p, value *val) { guint32 ipv4; guint8 ipv6[16]; + GString *ipstr; + guint16 port = 80; UNUSED(p); + if (val->type != VALUE_STRING) { ERROR(srv, "%s", "listen expects a string as parameter"); return FALSE; } - if (parse_ipv4(val->data.string->str, &ipv4, NULL)) { + if (val->data.string->str[0] == '[') { + /* ipv6 with port */ + gchar *pos = g_strrstr(val->data.string->str, "]"); + if (NULL == pos) { + ERROR(srv, "%s", "listen: bogus ipv6 format"); + return FALSE; + } + if (pos[1] == ':') { + port = atoi(&pos[2]); + } + ipstr = g_string_new_len(&val->data.string->str[1], pos - &val->data.string->str[1]); + } else { + /* no brackets, search for :port */ + gchar *pos = g_strrstr(val->data.string->str, ":"); + if (NULL != pos) { + ipstr = g_string_new_len(val->data.string->str, pos - val->data.string->str); + port = atoi(&pos[1]); + } else { + /* no port, just plain ipv4 or ipv6 address */ + ipstr = g_string_new_len(GSTR_LEN(val->data.string)); + } + } + + if (parse_ipv4(ipstr->str, &ipv4, NULL)) { int s, v; struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = ipv4; - addr.sin_port = htons(8080); + addr.sin_port = htons(port); + g_string_free(ipstr, TRUE); if (-1 == (s = socket(AF_INET, SOCK_STREAM, 0))) { ERROR(srv, "Couldn't open socket: %s", g_strerror(errno)); return FALSE; @@ -333,19 +360,20 @@ static gboolean core_listen(server *srv, plugin* p, value *val) { return FALSE; } server_listen(srv, s); - TRACE(srv, "listen to ipv4: '%s'", inet_ntoa(*(struct in_addr*)&ipv4)); + TRACE(srv, "listen to ipv4: '%s' port: %d", inet_ntoa(*(struct in_addr*)&ipv4), port); #ifdef HAVE_IPV6 - } else if (parse_ipv6(val->data.string->str, ipv6, NULL)) { + } else if (parse_ipv6(ipstr->str, ipv6, NULL)) { /* TODO: IPv6 */ + g_string_free(ipstr, TRUE); ERROR(srv, "%s", "IPv6 not supported yet"); return FALSE; #endif } else { - ERROR(srv, "Invalid ip: '%s'", val->data.string->str); + ERROR(srv, "Invalid ip: '%s'", ipstr->str); + g_string_free(ipstr, TRUE); return FALSE; } - TRACE(srv, "will listen to '%s'", val->data.string->str); return TRUE; } diff --git a/src/server.c b/src/server.c index a48809f..0255e18 100644 --- a/src/server.c +++ b/src/server.c @@ -291,13 +291,13 @@ void server_stop(server *srv) { server_socket *sock = g_array_index(srv->sockets, server_socket*, i); ev_io_stop(srv->main_worker->loop, &sock->watcher); } - } - /* stop all workers */ - for (i = 0; i < srv->worker_count; i++) { - worker *wrk; - wrk = g_array_index(srv->workers, worker*, i); - worker_stop(srv->main_worker, wrk); + /* stop all workers */ + for (i = 0; i < srv->worker_count; i++) { + worker *wrk; + wrk = g_array_index(srv->workers, worker*, i); + worker_stop(srv->main_worker, wrk); + } } log_thread_wakeup(srv);