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
0e2621a7d2
12 changed files with 456 additions and 4254 deletions
269
muninn_daemon.c
Normal file
269
muninn_daemon.c
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
#include "ngx_event.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);
|
||||
|
||||
// request state machine
|
||||
static void mun_request_parse(ngx_connection_t *c);
|
||||
|
||||
|
||||
static ngx_int_t mun_daemon_dns_connection_pool_ct = MUN_DEFAULT_CONN_POOL_SZ;
|
||||
|
||||
/* TODO: (in muninn.h)
|
||||
* need a global tree structure for storing records.
|
||||
* should store both nameservers, empty non-leaves, and leaf node DNS records.
|
||||
*
|
||||
* if possible some text hashing function for fast lookup.
|
||||
*
|
||||
* cache lookup should return closest matching record in tree
|
||||
*
|
||||
* data structure needs to be atomic
|
||||
*
|
||||
* STORE IN SHARED MEMORY
|
||||
*/
|
||||
|
||||
/* TODO: (in muninn.h)
|
||||
* mun_dns_request should store queue of resources (mun_dns_requests) it depends on
|
||||
* mun_dns_request should store an array of mun_dns_requests that depend on it
|
||||
* mun_dns_request should store the handler of the next phase to call
|
||||
* mun_dns_request should have an event in it whos handler calls stored phase of request
|
||||
* mun_dns_request should store an error counter
|
||||
* mun_dns_request should store the result of a record cache lookup
|
||||
*/
|
||||
|
||||
// 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 },
|
||||
|
||||
// TODO: shared memory size cap
|
||||
// TODO: dns resource retry limit
|
||||
|
||||
ngx_null_command
|
||||
};
|
||||
|
||||
static ngx_core_module_t ngx_muninn_daemon_module_ctx = {
|
||||
ngx_string("muninn_daemon"), NULL, NULL,
|
||||
/* TODO:
|
||||
* 1. init shm somewhere in here
|
||||
*/
|
||||
};
|
||||
|
||||
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, // TODO: make bootstrapping request on a single worker here
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NGX_MODULE_V1_PADDING
|
||||
};
|
||||
|
||||
|
||||
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_request_parse;
|
||||
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");
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
static void mun_request_parse(ngx_connection_t *c) {
|
||||
/* TODO:
|
||||
* 1. init new pool
|
||||
* 2. init new request obj
|
||||
* 3. track request source in request object here
|
||||
* 4. parse requested DNS resource
|
||||
* 5. put a new event in the dns request (handler = cache lookup handler)
|
||||
* 6. event->data = mun_dns_request
|
||||
* 7. post this event
|
||||
*/
|
||||
}
|
||||
|
||||
// TODO: put this decl into muninn.h
|
||||
void mun_dns_cache_lookup(ngx_event_t *ev) {
|
||||
/* TODO: request cache lookup handler
|
||||
* if hit, clear dependencies and set request next handler to postpone phase
|
||||
* if miss next handler is request records fetch phase AND attach cache returned closest node to tree
|
||||
* reschedule our request event.
|
||||
*/
|
||||
}
|
||||
|
||||
// TODO: put this decl into muninn.h
|
||||
void mun_dns_prep_record_fetch(ngx_event_t *ev) {
|
||||
/* TODO: request record(s) prep fetch
|
||||
* find closest neighbor in request struct and figure out all resources we are missing
|
||||
* initialize linked requests for all dependencies.
|
||||
* each linked request should store a reference to this one as a dependent.
|
||||
* their handlers should all be set to fetch record (next)
|
||||
*
|
||||
* set this request next phase to postpone phase
|
||||
* dont reschedule.
|
||||
*/
|
||||
}
|
||||
|
||||
// TODO: put this decl into muninn.h
|
||||
void mun_dns_record_fetch(ngx_event_t *ev) {
|
||||
/* TODO: fetch record phase
|
||||
* open a UDP connection or whatever the fuck to some godawful NS and get
|
||||
* the actual record.
|
||||
* finally store the record in the cache.
|
||||
*
|
||||
* next phase is postpone phase.
|
||||
* do reschedule.
|
||||
*/
|
||||
}
|
||||
|
||||
// TODO: put this decl into muninn.h
|
||||
void mun_postpone_request(ngx_event_t *ev) {
|
||||
/* TODO: POSTPONE PHASE FOR LINKED REQUESTS
|
||||
* IFF there are still linked requests we depend on then return.
|
||||
* if there are requests depending on us then post their events now.
|
||||
* remove ourselves from their dependency linkedlist.
|
||||
* next phase is teardown, reschedule.
|
||||
*
|
||||
* if we have a request source (client wants to know) then set next to output phase
|
||||
* call output phase without rescheduling.
|
||||
*/
|
||||
}
|
||||
|
||||
// TODO: put this decl into muninn.h
|
||||
void mun_dns_record_response(ngx_event_t *ev) {
|
||||
/* TODO: output phase
|
||||
* write the records to client.
|
||||
* next phase is teardown.
|
||||
* reschedule.
|
||||
*/
|
||||
}
|
||||
|
||||
// TODO: put this decl into muninn.h
|
||||
void mun_handle_request_error(ngx_event_t *ev) {
|
||||
/* TODO: error handler phase
|
||||
* if dependent request then try to restart request processing for this.
|
||||
* (increment error counter in mun_dns_request)
|
||||
* if error counter >= max then set dependent request error counter the same
|
||||
* AND set dependent request phase handler to error handler
|
||||
* AND schedule dependent request
|
||||
* return without reschedule
|
||||
*
|
||||
* otherwise attempt retry
|
||||
* if not retriable then send some DNS error IDK
|
||||
* loop over dependencies and set their handlers to teardown.
|
||||
* MUST REMOVE THEM FROM QUEUE IF POSTED
|
||||
* re-schedule them all with teardown handlers.
|
||||
* set next phase to teardown. DONT reschedule.
|
||||
*/
|
||||
}
|
||||
|
||||
// TODO: put this decl into muninn.h
|
||||
void mun_request_teardown(ngx_event_t *ev) {
|
||||
/* TODO: teardown phase
|
||||
* if dependencies then return awaiting full teardown
|
||||
*
|
||||
* if dependent request then remove ourselves from their dependencies
|
||||
* and schedule dependent request event
|
||||
*
|
||||
* log teardown
|
||||
* delete our pool
|
||||
*/
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue