WIP: request and connection machine
Just need a simple request logging phase to wrap this up Signed-off-by: Ava Affine <ava@sunnypup.io>
This commit is contained in:
parent
19fafc6a8c
commit
19cb63b614
12 changed files with 1180 additions and 605 deletions
3
.clangd
Normal file
3
.clangd
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
CompileFlags:
|
||||||
|
Compiler: gcc
|
||||||
|
Add: ["-xc", "-std=c2x"]
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -1,3 +1,5 @@
|
||||||
libmuninn.so
|
libmuninn.so
|
||||||
libmuninn.dylib
|
libmuninn.dylib
|
||||||
nginx/.cache
|
nginx/.cache
|
||||||
|
.cache
|
||||||
|
mun_pfx
|
||||||
|
|
|
||||||
13
Makefile
13
Makefile
|
|
@ -10,23 +10,22 @@ ifneq ($(MUNINN_NGINX_DEBUG),)
|
||||||
MUNINN_NGINX_DEBUG="--with-debug"
|
MUNINN_NGINX_DEBUG="--with-debug"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CURDIR = $(.CURDIR)
|
.PHONY: all clean
|
||||||
|
|
||||||
.PHONY: all clean build
|
|
||||||
|
|
||||||
all: nginx/objs/nginx
|
all: nginx/objs/nginx
|
||||||
|
|
||||||
nginx/objs/Makefile:
|
nginx/objs/Makefile: config Makefile
|
||||||
|
make clean
|
||||||
cd $(NGINX_SOURCE_DIR) && \
|
cd $(NGINX_SOURCE_DIR) && \
|
||||||
./auto/configure \
|
./auto/configure \
|
||||||
$(MUNINN_NGINX_DEBUG) \
|
$(MUNINN_NGINX_DEBUG) \
|
||||||
--with-http_ssl_module \
|
--with-http_ssl_module \
|
||||||
--with-compat \
|
--with-compat \
|
||||||
--add-module=$(.CURDIR)
|
--add-module=$(shell pwd)
|
||||||
|
|
||||||
nginx/objs/nginx: nginx/objs/Makefile
|
nginx/objs/nginx: nginx/objs/Makefile muninn_core.c muninn_daemon.c muninn.h
|
||||||
$(MUNIN_BEAR) make -C $(NGINX_SOURCE_DIR)
|
$(MUNIN_BEAR) make -C $(NGINX_SOURCE_DIR)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
make -C $(NGINX_SOURCE_DIR) clean
|
-make -C $(NGINX_SOURCE_DIR) clean
|
||||||
|
|
||||||
|
|
|
||||||
60
README.md
60
README.md
|
|
@ -22,13 +22,65 @@ The loose plan to implement Muninn is as follows:
|
||||||
9. Muninn can identify as authoritatively owning a certain DN (and Peers abide).
|
9. Muninn can identify as authoritatively owning a certain DN (and Peers abide).
|
||||||
10. Something other than logging is done for conflicts over who owns what DN
|
10. Something other than logging is done for conflicts over who owns what DN
|
||||||
|
|
||||||
Currently Muninn is on phase 2.
|
Currently Muninn is working on phase 3.
|
||||||
|
|
||||||
## Building Muninn
|
## Building Muninn
|
||||||
simply run `make`.
|
Muninn is implemented as a statically linked NGINX Module. The output of the
|
||||||
|
provided build process is an NGINX binary that contains Muninn functionality. To
|
||||||
|
build Muninn simply run `make`. The resulting binary will be in the build tree
|
||||||
|
at `$(pwd)/nginx/objs/nginx`.
|
||||||
|
|
||||||
## Running Muninn
|
## Running Muninn
|
||||||
TODO
|
Muninn may be ran in any way which NGINX is currently run. See the configuration
|
||||||
|
section for more details. To add Muninn to an existing running NGINX simply
|
||||||
|
compile Muninn, copy the output binary over your NGINX executable, and follow
|
||||||
|
the existing NGINX binary upgrade process.
|
||||||
|
|
||||||
## Configuring Muninn
|
## Configuring Muninn
|
||||||
TODO
|
Muninn uses an NGINX global configuration block similar to the existing NGINX
|
||||||
|
HTTP module. To configure Muninn begin a standard NGINX configuration and open
|
||||||
|
a Muninn block:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
error_log /dev/stdout info;
|
||||||
|
pid /tmp/munin_pid;
|
||||||
|
daemon off;
|
||||||
|
|
||||||
|
events {}
|
||||||
|
|
||||||
|
muninn {
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To serve DNS over UDP on port 53 add a `dns_listener` directive like below.
|
||||||
|
Currently Muninn only supports UDP, but plans to provide for TCP and DoH as
|
||||||
|
development progresses.
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
error_log /dev/stdout info;
|
||||||
|
pid /tmp/munin_pid;
|
||||||
|
daemon off;
|
||||||
|
|
||||||
|
events {}
|
||||||
|
|
||||||
|
muninn {
|
||||||
|
dns_listen 0.0.0.0:53;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The default Muninn DNS over UDP server provides for 1024 simultaneous
|
||||||
|
connections. To change this add the `dns_connection_pool_count` like so:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
error_log /dev/stdout info;
|
||||||
|
pid /tmp/munin_pid;
|
||||||
|
daemon off;
|
||||||
|
|
||||||
|
events {}
|
||||||
|
|
||||||
|
muninn {
|
||||||
|
dns_listen 0.0.0.0:53;
|
||||||
|
dns_connection_pool_count 24;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
16
config
16
config
|
|
@ -1,5 +1,15 @@
|
||||||
ngx_module_name=muninn
|
ngx_module_type=CORE
|
||||||
ngx_module_srcs="$ngx_addon_dir/muninn.c"
|
ngx_module_name=ngx_muninn_core_module
|
||||||
ngx_module_link=YES
|
ngx_module_srcs="$ngx_addon_dir/muninn_core.c"
|
||||||
|
ngx_module_link=ADDON
|
||||||
|
|
||||||
. auto/module
|
. auto/module
|
||||||
|
|
||||||
|
ngx_module_type=CORE
|
||||||
|
ngx_module_name=ngx_muninn_daemon_module
|
||||||
|
ngx_module_srcs="$ngx_addon_dir/muninn_daemon.c"
|
||||||
|
ngx_module_link=ADDON
|
||||||
|
|
||||||
|
. auto/module
|
||||||
|
|
||||||
|
ngx_addon_name="muninn"
|
||||||
|
|
|
||||||
27
muninn.c
27
muninn.c
|
|
@ -1,27 +0,0 @@
|
||||||
#include <ngx_config.h>
|
|
||||||
#include <ngx_core.h>
|
|
||||||
|
|
||||||
static ngx_command_t ngx_muninn_commands[] = {};
|
|
||||||
|
|
||||||
static ngx_core_module_t ngx_muninn_module_ctx = {
|
|
||||||
ngx_string("muninn"),
|
|
||||||
NULL, // create conf
|
|
||||||
NULL // init conf
|
|
||||||
};
|
|
||||||
|
|
||||||
ngx_module_t ngx_muninn_core_module = {
|
|
||||||
NGX_MODULE_V1,
|
|
||||||
&ngx_muninn_module_ctx, /* module context */
|
|
||||||
ngx_muninn_commands, /* module directives */
|
|
||||||
NGX_CORE_MODULE, /* module type */
|
|
||||||
NULL, /* init master */
|
|
||||||
NULL, /* init module */
|
|
||||||
NULL, /* init process */
|
|
||||||
NULL, /* init thread */
|
|
||||||
NULL, /* exit thread */
|
|
||||||
NULL, /* exit process */
|
|
||||||
NULL, /* exit master */
|
|
||||||
NGX_MODULE_V1_PADDING
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
18
muninn.h
Normal file
18
muninn.h
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
#include <ngx_config.h>
|
||||||
|
#include <ngx_core.h>
|
||||||
|
#include <ngx_event.h>
|
||||||
|
|
||||||
|
#define NGX_MUNINN_MODULE 0x42000000
|
||||||
|
#define NGX_MUNINN_CONF 0x00000086
|
||||||
|
|
||||||
|
#define MUN_DNS_LEGACY_UDP_SZ 512
|
||||||
|
#define MUN_DEFAULT_CONN_POOL_SZ 1024
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ngx_uint_t read_state, finalized;
|
||||||
|
ngx_chain_t *in, *out, *read_cur;
|
||||||
|
//ngx_pool_t *pool; use conn->pool;
|
||||||
|
//ngx_log_t *log; use conn->log;
|
||||||
|
ngx_connection_t *conn;
|
||||||
|
} mun_dns_request;
|
||||||
55
muninn_core.c
Normal file
55
muninn_core.c
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
#include "muninn.h"
|
||||||
|
|
||||||
|
|
||||||
|
static char *mun_conf_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
|
||||||
|
static void *mun_core_create_conf(ngx_cycle_t *cycle);
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_command_t ngx_muninn_core_commands[] = {
|
||||||
|
{ ngx_string("muninn"),
|
||||||
|
NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
|
||||||
|
mun_conf_server,
|
||||||
|
0, 0, NULL },
|
||||||
|
|
||||||
|
ngx_null_command
|
||||||
|
};
|
||||||
|
|
||||||
|
static ngx_core_module_t ngx_muninn_core_module_ctx = {
|
||||||
|
ngx_string("muninn_core"),
|
||||||
|
mun_core_create_conf,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
ngx_module_t ngx_muninn_core_module = {
|
||||||
|
NGX_MODULE_V1,
|
||||||
|
&ngx_muninn_core_module_ctx,
|
||||||
|
ngx_muninn_core_commands,
|
||||||
|
NGX_CORE_MODULE,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NGX_MODULE_V1_PADDING
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void *mun_core_create_conf(ngx_cycle_t *cycle) {
|
||||||
|
ngx_int_t *conf;
|
||||||
|
if (!(conf = ngx_pcalloc(cycle->pool, sizeof(ngx_int_t))))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *mun_conf_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {
|
||||||
|
if (!conf) return "no conf";
|
||||||
|
if (**(ngx_int_t **) conf) return "duplicate block";
|
||||||
|
|
||||||
|
**(ngx_int_t **)conf = 1;
|
||||||
|
cf->module_type = NGX_MUNINN_MODULE;
|
||||||
|
cf->cmd_type = NGX_MUNINN_CONF;
|
||||||
|
return ngx_conf_parse(cf, NULL);
|
||||||
|
}
|
||||||
362
muninn_daemon.c
Normal file
362
muninn_daemon.c
Normal file
|
|
@ -0,0 +1,362 @@
|
||||||
|
#include "ngx_conf_file.h"
|
||||||
|
#ifdef __clang__
|
||||||
|
#pragma clang diagnostic ignored "-Wdangling-else"
|
||||||
|
#else
|
||||||
|
#pragma GCC diagnostic ignored "-Wdangling-else"
|
||||||
|
#pragma GCC diagnostic ignored "-Wmultistatement-macros"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "muninn.h"
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
|
||||||
|
// Configuration functions
|
||||||
|
static char *mun_conf_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
|
||||||
|
static char *mun_conf_connection_ct(ngx_conf_t *cf, ngx_command_t *c, void *v);
|
||||||
|
|
||||||
|
// Connection lifecycle
|
||||||
|
static void mun_init_connection(ngx_connection_t *c);
|
||||||
|
static void mun_close_connection(ngx_connection_t *c);
|
||||||
|
static void mun_handle_conn_readable(ngx_event_t *ev);
|
||||||
|
static void mun_handle_conn_writeable(ngx_event_t *ev);
|
||||||
|
|
||||||
|
// Request lifecycle functions
|
||||||
|
static ngx_int_t mun_log_request(mun_dns_request *r);
|
||||||
|
|
||||||
|
// connection pool flag stored here
|
||||||
|
static ngx_int_t mun_daemon_dns_connection_pool_ct = MUN_DEFAULT_CONN_POOL_SZ;
|
||||||
|
|
||||||
|
|
||||||
|
// Module definitions
|
||||||
|
static ngx_command_t ngx_muninn_daemon_commands[] = {
|
||||||
|
{ ngx_string("dns_listen"),
|
||||||
|
NGX_MUNINN_CONF|NGX_DIRECT_CONF|NGX_CONF_1MORE,
|
||||||
|
mun_conf_listen,
|
||||||
|
0, 0, NULL },
|
||||||
|
|
||||||
|
{ ngx_string("dns_connection_pool_count"),
|
||||||
|
NGX_MUNINN_CONF|NGX_DIRECT_CONF|NGX_CONF_1MORE,
|
||||||
|
mun_conf_connection_ct,
|
||||||
|
0, 0, NULL },
|
||||||
|
|
||||||
|
ngx_null_command
|
||||||
|
};
|
||||||
|
|
||||||
|
static ngx_core_module_t ngx_muninn_daemon_module_ctx = {
|
||||||
|
ngx_string("muninn_daemon"), NULL, NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
ngx_module_t ngx_muninn_daemon_module = {
|
||||||
|
NGX_MODULE_V1,
|
||||||
|
&ngx_muninn_daemon_module_ctx,
|
||||||
|
ngx_muninn_daemon_commands,
|
||||||
|
NGX_MUNINN_MODULE,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NGX_MODULE_V1_PADDING
|
||||||
|
};
|
||||||
|
|
||||||
|
// Muninn request handling state machine
|
||||||
|
static ngx_int_t (*mun_read_handler_list[])(mun_dns_request *) = {
|
||||||
|
mun_log_request, // test req state machine logging handler
|
||||||
|
// TODO: request parsing
|
||||||
|
// TODO: request logging
|
||||||
|
// TODO: request cache lookup
|
||||||
|
// TODO: request record(s) fetch
|
||||||
|
// TODO: request response generation
|
||||||
|
// TODO: error handling phase
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ADJACENCY LIST
|
||||||
|
* This matrix defines the entire request processing state machine and changes
|
||||||
|
* All numbers in this list should correspond to mun_read_handler_list indexes
|
||||||
|
* The entries in this list are linked to their same index in the handler list
|
||||||
|
*
|
||||||
|
* Entries:
|
||||||
|
* { NGX_OK next handler - intended to indidicate phase is complete
|
||||||
|
* NGX_ERROR next handler - intended to trap error states
|
||||||
|
* NGX_BUSY next handler - intended to trap waiting state
|
||||||
|
* NGX_DECLINED next handler } intended to trap service refusal
|
||||||
|
*
|
||||||
|
* Other handler returns:
|
||||||
|
* NGX_DONE: this return code means a request is ready to be finalized
|
||||||
|
* nothing further will be returned.
|
||||||
|
* NGX_AGAIN: this return code causes same function to be called again.
|
||||||
|
* primarily used when more input needed than what is available.
|
||||||
|
* NGX_ABORT: this return code causes all further action to stop for request
|
||||||
|
*
|
||||||
|
* For more information, see how this is used in mun_handle_conn_readable
|
||||||
|
*/
|
||||||
|
static ngx_uint_t mun_read_handler_adjacency[][4] = {
|
||||||
|
{0, 0, 0, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static char *mun_conf_connection_ct(
|
||||||
|
ngx_conf_t *cf,
|
||||||
|
ngx_command_t *cmd,
|
||||||
|
void *conf
|
||||||
|
) {
|
||||||
|
ngx_int_t argc = cf->args->nelts;
|
||||||
|
ngx_str_t *argv = cf->args->elts;
|
||||||
|
ngx_int_t num;
|
||||||
|
|
||||||
|
if (argc < 1) {
|
||||||
|
ngx_conf_log_error(NGX_LOG_ERR, cf, 0,
|
||||||
|
"dns_connection_pool_count requires at least one argument");
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((num = ngx_atoi(argv[1].data, argv[1].len)) == NGX_ERROR) {
|
||||||
|
ngx_conf_log_error(NGX_LOG_ERR, cf, 0,
|
||||||
|
"invalid integer passed to dns_connection_pool_count");
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num < 1) {
|
||||||
|
ngx_conf_log_error(NGX_LOG_ERR, cf, 0,
|
||||||
|
"dns_connection_pool_count must be set to at least 1");
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
mun_daemon_dns_connection_pool_ct = num;
|
||||||
|
return NGX_CONF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *mun_conf_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *in) {
|
||||||
|
ngx_url_t *u;
|
||||||
|
ngx_int_t argc;
|
||||||
|
ngx_str_t *argv;
|
||||||
|
ngx_listening_t *listening;
|
||||||
|
|
||||||
|
argc = cf->args->nelts;
|
||||||
|
argv = cf->args->elts;
|
||||||
|
|
||||||
|
if (argc < 1) {
|
||||||
|
ngx_conf_log_error(NGX_LOG_ERR, cf, 0,
|
||||||
|
"dns_listen needs at least one argument");
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(u = ngx_pcalloc(cf->pool, sizeof(ngx_url_t)))) return NGX_CONF_ERROR;
|
||||||
|
|
||||||
|
u->url = argv[1];
|
||||||
|
u->listen = 1;
|
||||||
|
u->default_port = 53;
|
||||||
|
if (ngx_parse_url(cf->pool, u) != NGX_OK) {
|
||||||
|
if (u->err) {
|
||||||
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
|
"%s in \"%V\" of the \"dns_listen\" directive",
|
||||||
|
u->err, &u->url);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
listening = ngx_create_listening(cf, (struct sockaddr *) &u->sockaddr,
|
||||||
|
u->socklen);
|
||||||
|
if (!listening) return NGX_CONF_ERROR;
|
||||||
|
|
||||||
|
listening->addr_ntop = 1;
|
||||||
|
listening->pool_size = mun_daemon_dns_connection_pool_ct;
|
||||||
|
listening->handler = mun_init_connection;
|
||||||
|
listening->logp = cf->log;
|
||||||
|
listening->log.data = &listening->addr_text;
|
||||||
|
listening->log.handler = ngx_accept_log_error;
|
||||||
|
listening->sndbuf = 1;
|
||||||
|
listening->rcvbuf = 1;
|
||||||
|
listening->backlog = mun_daemon_dns_connection_pool_ct * 2;
|
||||||
|
listening->protocol = IPPROTO_UDP;
|
||||||
|
listening->type = SOCK_DGRAM;
|
||||||
|
|
||||||
|
// listener added to cycle at creation
|
||||||
|
ngx_conf_log_error(NGX_LOG_NOTICE, cf, 0, "muninn DNS server enabled");
|
||||||
|
|
||||||
|
fprintf(stdout, "MUNINN DNS ON");
|
||||||
|
|
||||||
|
return NGX_CONF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mun_init_connection(ngx_connection_t *c) {
|
||||||
|
mun_dns_request *r;
|
||||||
|
|
||||||
|
if (!(r = ngx_pcalloc(c->pool, sizeof(mun_dns_request)))) {
|
||||||
|
mun_close_connection(c);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->data = r;
|
||||||
|
c->log->connection = c->number;
|
||||||
|
c->log_error = NGX_ERROR_INFO;
|
||||||
|
|
||||||
|
c->read->handler = mun_handle_conn_readable;
|
||||||
|
c->write->handler = mun_handle_conn_writeable;
|
||||||
|
|
||||||
|
if (c->read->ready) ngx_post_event(c->read, &ngx_posted_events)
|
||||||
|
|
||||||
|
ngx_log_error(NGX_LOG_NOTICE, c->log, 0, "muninn: new request accepted");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mun_close_connection(ngx_connection_t *c) {
|
||||||
|
c->destroyed = 1;
|
||||||
|
ngx_close_connection(c);
|
||||||
|
ngx_destroy_pool(c->pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mun_handle_conn_readable(ngx_event_t *ev) {
|
||||||
|
ngx_connection_t *c;
|
||||||
|
mun_dns_request *r;
|
||||||
|
ngx_chain_t *cur;
|
||||||
|
ngx_int_t ret, idx, space, filled;
|
||||||
|
|
||||||
|
c = ev->data;
|
||||||
|
r = c->data;
|
||||||
|
ret = 0;
|
||||||
|
filled = 0;
|
||||||
|
|
||||||
|
if (r && r->finalized) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, c->log, 0,
|
||||||
|
"muninn: read called for finalized request");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ev->timedout) {
|
||||||
|
// TODO: handle timedout according to DNS proto
|
||||||
|
mun_close_connection(c);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!r->in) {
|
||||||
|
if (!(r->in = ngx_alloc_chain_link(c->pool))) {
|
||||||
|
ret = NGX_ERROR;
|
||||||
|
goto content;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(r->in->buf = ngx_create_temp_buf(c->pool,
|
||||||
|
MUN_DNS_LEGACY_UDP_SZ))) {
|
||||||
|
ret = NGX_ERROR;
|
||||||
|
goto content;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur = r->in;
|
||||||
|
cur->buf->last_buf = 1;
|
||||||
|
cur->next = NULL;
|
||||||
|
space = MUN_DNS_LEGACY_UDP_SZ;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
for (cur = r->in; cur && !cur->buf->last_buf; cur = cur->next) {}
|
||||||
|
if (!cur) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, r->conn->log, 0,
|
||||||
|
"muninn: failed to find next buffer to read into");
|
||||||
|
}
|
||||||
|
space = cur->buf->end - cur->buf->last;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!r->read_cur) {
|
||||||
|
r->read_cur = r->in;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
filled = c->recv(c, cur->buf->last, space);
|
||||||
|
if (c->read->error || c->read->eof) {
|
||||||
|
// TODO: log
|
||||||
|
ret = NGX_ERROR;
|
||||||
|
goto content;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filled == space) {
|
||||||
|
cur->buf->last_buf = 0;
|
||||||
|
if (!(cur = (cur->next = ngx_alloc_chain_link(c->pool))) ||
|
||||||
|
!(cur->buf = ngx_create_temp_buf(c->pool,
|
||||||
|
MUN_DNS_LEGACY_UDP_SZ)) ||
|
||||||
|
!(space = MUN_DNS_LEGACY_UDP_SZ)) break;
|
||||||
|
|
||||||
|
cur->next = NULL;
|
||||||
|
cur->buf->last_buf = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
content:
|
||||||
|
if (!ret) ret = mun_read_handler_list[r->read_state](r);
|
||||||
|
idx = mun_read_handler_adjacency[r->read_state][0 - ret];
|
||||||
|
r->read_state = idx;
|
||||||
|
|
||||||
|
switch (ret) {
|
||||||
|
case NGX_OK:
|
||||||
|
// we could still have read data to process in next stage
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NGX_ERROR:
|
||||||
|
case NGX_BUSY:
|
||||||
|
case NGX_DECLINED:
|
||||||
|
ngx_post_event(c->write, &ngx_posted_events);
|
||||||
|
/* fallthrough */
|
||||||
|
case NGX_ABORT:
|
||||||
|
case NGX_AGAIN:
|
||||||
|
return;
|
||||||
|
|
||||||
|
case NGX_DONE:
|
||||||
|
// TODO: perform request finalization
|
||||||
|
r->finalized = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_post_event(ev, &ngx_posted_events);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mun_handle_conn_writeable(ngx_event_t *ev) {
|
||||||
|
ngx_chain_t *tmp;
|
||||||
|
ngx_connection_t *c;
|
||||||
|
mun_dns_request *r;
|
||||||
|
|
||||||
|
c = ev->data;
|
||||||
|
r = c->data;
|
||||||
|
tmp = r->out;
|
||||||
|
|
||||||
|
/* this event posted for one of two reasons:
|
||||||
|
* 1. mun_handle_request_read has reached end of request processing
|
||||||
|
* 2. socket newly available after incomplete write
|
||||||
|
*/
|
||||||
|
|
||||||
|
// write wouldnt work here anyways. event will retrigger when ready
|
||||||
|
if (!ev->ready) return;
|
||||||
|
|
||||||
|
if (!r->out) {
|
||||||
|
ngx_log_debug(NGX_LOG_ALERT, r->conn->log, 0,
|
||||||
|
"muninn: request processed but no output");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
r->out = c->send_chain(c, tmp, MUN_DNS_LEGACY_UDP_SZ);
|
||||||
|
for (/* tmp */; tmp != r->out; tmp = tmp->next) {
|
||||||
|
if (tmp->buf->pos == tmp->buf->last) ngx_free_chain(c->pool, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// request lifecycle complete condition
|
||||||
|
if (!r->out) return mun_close_connection(c);
|
||||||
|
|
||||||
|
// event will retrigger when write possible
|
||||||
|
if (!ev->ready) return;
|
||||||
|
|
||||||
|
// more can be written but we want to yield to other events on task loop
|
||||||
|
ngx_post_event(ev, &ngx_posted_events);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t mun_log_request(mun_dns_request *r) {
|
||||||
|
ngx_log_error(NGX_LOG_INFO, r->conn->log, 0,
|
||||||
|
"muninn: request state machine entered");
|
||||||
|
|
||||||
|
return NGX_DONE;
|
||||||
|
}
|
||||||
9
snippets/muninn-test.conf
Normal file
9
snippets/muninn-test.conf
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
error_log info;
|
||||||
|
pid /tmp/munin_pid;
|
||||||
|
|
||||||
|
events {}
|
||||||
|
|
||||||
|
muninn {
|
||||||
|
dns_connection_pool_count 5;
|
||||||
|
dns_listen 0.0.0.0:8053;
|
||||||
|
}
|
||||||
20
snippets/test-muninn.sh
Executable file
20
snippets/test-muninn.sh
Executable file
|
|
@ -0,0 +1,20 @@
|
||||||
|
#!/bin/zsh
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
alias muninn="nginx/objs/nginx -p $(pwd)/mun_pfx -c muninn-test.conf"
|
||||||
|
|
||||||
|
# step 1: build
|
||||||
|
make all -j24
|
||||||
|
|
||||||
|
# step 2: set up test pfx
|
||||||
|
mkdir -p $(pwd)/mun_pfx/logs/
|
||||||
|
cp $(pwd)/snippets/muninn-test.conf mun_pfx/
|
||||||
|
|
||||||
|
# step 3: test configuration
|
||||||
|
muninn -T
|
||||||
|
|
||||||
|
#step 4: test runtime
|
||||||
|
muninn
|
||||||
|
sleep 1
|
||||||
|
muninn -s quit
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue