From 18c08e8d9300b84128fbc225e3b0b2f08667b296 Mon Sep 17 00:00:00 2001 From: Aleksy Grabowski Date: Fri, 3 May 2024 08:08:58 +0200 Subject: [PATCH] Compile on GNU Hurd --- Makefile | 12 ++-- autoresponder.c | 15 +++-- frob.h | 6 +- fsm/frontend.rl | 27 ++++----- fsm/wireprotocol.rl | 13 ++-- log.c | 3 - log.h | 1 + main.c | 11 ++-- multitasking/sigio.c | 117 +++++++++++++++++++++++------------- multitasking/suspendables.c | 3 +- serialization.c | 1 + utils.c | 2 + utils.h | 3 + 13 files changed, 128 insertions(+), 86 deletions(-) diff --git a/Makefile b/Makefile index e7e799f..5f714ee 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,7 @@ CPPFLAGS_cc = $(CPPFLAGS_gcc) CPPFLAGS ?= $(CPPFLAGS_$(CC)) CPPFLAGS += -I$(PROJECT_DIR) -I$(PROJECT_DIR)multitasking CPPFLAGS += -D_GNU_SOURCE +CPPFLAGS += -DCORO_UCONTEXT #CPPFLAGS += -DNDEBUG # Disable all logs #CPPFLAGS += -DNO_LOGS_ON_STDERR @@ -30,7 +31,7 @@ CFLAGS += $(call if_coverage,--coverage) # TODO: Remove those warnings only for generated files CFLAGS += -Wno-implicit-fallthrough -Wno-unused-const-variable -Wno-sign-compare -Wno-unused-variable -Wno-unused-parameter TARGET_ARCH := -mtune=native -march=native -LDLIBS := +#LDLIBS := -lpthread LDFLAGS ?= -flto LDFLAGS += $(call if_coverage,--coverage) @@ -38,7 +39,7 @@ LDFLAGS += $(call if_coverage,--coverage) # Project configuration ######################################################## RL_C := wireprotocol.c frontend.c header.c body.c attrs.c frame.c RL_O := $(RL_C:.c=.o) -CFILES := main.c log.c utils.c serialization.c autoresponder.c sighandler.c controller.c ucspi.c s6notify.c +CFILES := main.c log.c utils.c serialization.c autoresponder.c controller.c ucspi.c s6notify.c OFILES := $(RL_O) $(CFILES:.c=.o) UT_C := ut.c serialization.c log.c utils.c contextring.c UT_O := $(UT_C:.c=.o) header.o body.o frame.o attrs.o @@ -57,9 +58,10 @@ vpath %.rl $(PROJECT_DIR)fsm vpath %.c $(PROJECT_DIR) $(addprefix $(PROJECT_DIR),multitasking multitasking/coro) vpath %.t $(PROJECT_DIR) vpath %.txt $(PROJECT_DIR) +vpath %.tcl $(PROJECT_DIR) # Public targets ############################################################### -all: frob ut +all: dir-pipe-client dir-ut index: tags cscope.out test: test-unit test-functional test-random clean: @@ -70,7 +72,9 @@ clang-analyze: $(ALL_PLIST) tcp-server: frob | d5.txt s6-tcpserver -vd -b2 0.0.0.0 5002 s6-tcpserver-access -t200 -v3 -rp -B "Welcome!\r\n" $(realpath $<) 1000 $| tcp-client: frob | d5.txt - s6-tcpclient -rv localhost 5002 rlwrap ./$< 1000 $| 2>&1 | s6-tai64n | s6-tai64nlocal + s6-tcpclient -rv localhost 5002 ./$< 1000 $| +pipe-client: frob | d5.txt gent1.tcl + $(word 2,$|) | ./$< 1000 $(word 1,$|) tls-server: frob server.cer server.key | d5.txt env -i PATH=/bin CERTFILE=$(word 2,$^) KEYFILE=$(word 3,$^) s6-tlsserver 0.0.0.0 6666 $(realpath $<) -f $(word 1,$^) tls-client: frob server.cer | d5.txt diff --git a/autoresponder.c b/autoresponder.c index 7336930..b4f239f 100644 --- a/autoresponder.c +++ b/autoresponder.c @@ -67,12 +67,14 @@ int autoresponder(const struct autoresponder_args* const args) { }, .parameters = load_d5_from_file(args->d5_path) }; - const unsigned char* p; + char buf[1024]; + const unsigned char* p = buf; ssize_t bytes; unsigned char rsp_buf[1024]; - /* - while ((bytes = sus_borrow(args->in, (void**)&p)) >= 0) { - //LOGDXP(char tmp[4*bytes], "Received %zd bytes: %s", bytes, PRETTY(p, p + bytes, tmp)); + LOGDX("reading on %d, writting to %d", args->in, args->out); + while ((bytes = sio_read(args->in, buf, sizeof buf)) >= 0) { + p = buf; + LOGDXP(char tmp[4*bytes], "Received %zd bytes: %s", bytes, PRETTY(p, p + bytes, tmp)); if (bytes > 1) { const struct frob_msg msg = xparse_message(bytes - 1, p + 1); const struct frob_msg response = { @@ -87,13 +89,10 @@ int autoresponder(const struct autoresponder_args* const args) { if (w < 0) { LOGEX("Message skipped"); } else { - sus_write(args->out, rsp_buf, w); + sio_write(args->out, rsp_buf, w); LOGDXP(char tmp[4*w], "← % 4zd %s", sizeof w, PRETTY(rsp_buf, rsp_buf + w, tmp)); } } - //LOGDX("Returning buffer"); - sus_return(args->in, p, bytes); } - */ return -1; } diff --git a/frob.h b/frob.h index 71bdcfd..b7fe485 100644 --- a/frob.h +++ b/frob.h @@ -287,6 +287,9 @@ static_assert(sizeof (struct frob_msg) % 16 == 0, "Message shall fit into 16-byt struct fsm_frontend_foreign_args { int cs; + const int infd; + const int foreign_out; + const int to_autoresponder; }; struct fsm_frontend_internal_args { @@ -299,6 +302,7 @@ struct fsm_frontend_timer_args { struct fsm_wireformat_args { const int infd; + const int outfd; }; struct autoresponder_args { @@ -317,7 +321,7 @@ struct s6_notify_args { const int fd; }; -int fsm_wireformat(void*); +int fsm_wireformat(const struct fsm_wireformat_args*); int fsm_frontend_foreign(struct fsm_frontend_foreign_args*); int fsm_frontend_internal(struct fsm_frontend_internal_args*); int fsm_frontend_timer(struct fsm_frontend_timer_args*); diff --git a/fsm/frontend.rl b/fsm/frontend.rl index b3d0b3b..5af9411 100644 --- a/fsm/frontend.rl +++ b/fsm/frontend.rl @@ -3,7 +3,6 @@ #include "log.h" #include "utils.h" #include -#include #include static int cs; @@ -31,15 +30,15 @@ static int cs; acknak = 0x15; } action Send { - if (sio_write(6, &acknak, 1) != 1) { + if (sio_write(a->foreign_out, &acknak, 1) != 1) { LOGE("write"); fbreak; } LOGDXP(char tmp[4*1], "← % 4d %s", 1, PRETTY(&acknak, &acknak + 1, tmp)); } action Process { - LOGDXP(char tmp[4*(pe-p)], "Lending %zd bytes: %s", pe - p, PRETTY((unsigned char*)p, (unsigned char*)pe, tmp)); - //sus_lend(1, pe - p, (char*)p);// TODO: Remove this cast + LOGDXP(char tmp[4*(pe-p)], "to_autoresponder %zd bytes: %s", pe - p, PRETTY((unsigned char*)p, (unsigned char*)pe, tmp)); + sio_write(a->to_autoresponder, p, pe - p); } action Forward { if (sio_write(forwarded_fd, p, pe - p) != pe - p) { @@ -67,7 +66,7 @@ static bool is_idempotent(const char* const msg) { } */ -static int fsm_exec(const char* p, const char* const pe) { +static int fsm_exec(struct fsm_frontend_foreign_args* const a, const char* p, const char* const pe) { unsigned char acknak; %% write exec; return -1; @@ -76,25 +75,21 @@ static int fsm_exec(const char* p, const char* const pe) { __attribute__((constructor)) void fsm_frontend_init() { (void)frontend_en_main, (void)frontend_error, (void)frontend_first_final; - set_nonblocking(6); %% write init; } int fsm_frontend_foreign(struct fsm_frontend_foreign_args* const a) { (void)a; ssize_t bytes; - const char* p; - /* - while ((bytes = sus_borrow(0, (void**)&p)) >= 0) { + char buf[1024]; + const char* p = buf; + while ((bytes = sio_read(a->infd, buf, sizeof buf)) > 0) { LOGDX("Received %zd bytes", bytes); - const char* const pe = p + bytes; - fsm_exec(p, pe); - sus_return(0, p, bytes); + const char* const pe = (p = buf) + bytes; + fsm_exec(a, p, pe); } - if (bytes < 0) - LOGE("Closing fronted"); - sus_disable(1); - */ + LOGE("Closing fronted"); + close(a->infd); return -1; } diff --git a/fsm/wireprotocol.rl b/fsm/wireprotocol.rl index 48f8c32..de9841c 100644 --- a/fsm/wireprotocol.rl +++ b/fsm/wireprotocol.rl @@ -18,9 +18,11 @@ } action LRC_Check { if (lrc != fc) { - //sus_lend(0, 1, "\x03"); + LOGDX("@@@ NOK"); + sio_write(args->outfd, "\x03", 1); } else { - //sus_lend(0, fpc - start, buf); + LOGDX("@@@ OK"); + sio_write(args->outfd, buf, fpc - start); } } action Frame_Start { @@ -33,7 +35,7 @@ %% write data; -int fsm_wireformat(void*) { +int fsm_wireformat(const struct fsm_wireformat_args* const args) { unsigned char* start = NULL; char lrc; ssize_t bytes; @@ -41,16 +43,13 @@ int fsm_wireformat(void*) { int cs; unsigned char* p = buf, * pe = p; %% write init; - set_nonblocking(6); - while ((bytes = sio_read(6, buf, sizeof buf)) > 0) { + while ((bytes = sio_read(args->infd, buf, sizeof buf)) > 0) { pe = (p = buf) + bytes; LOGDXP(char tmp[4*bytes], "→ % 4zd %s", bytes, PRETTY(p, pe, tmp)); %% write exec; } if (bytes < 0) LOGE("read"); - close(7); LOGIX("FSM state: current/entry/error/final %d/%d/%d/%d", cs, wireformat_en_main, wireformat_error, wireformat_first_final); - //sus_disable(0); return cs == wireformat_error ? -1 : 0; } diff --git a/log.c b/log.c index 31d4345..c30ba16 100644 --- a/log.c +++ b/log.c @@ -8,9 +8,6 @@ const char* g_errname; #endif void init_log(void) { -#ifdef NO_LOGS_ON_STDERR - xfclose(stderr); -#endif } char* to_printable(const unsigned char* const p, const unsigned char* const pe, diff --git a/log.h b/log.h index 1fb3472..d0d9010 100644 --- a/log.h +++ b/log.h @@ -23,6 +23,7 @@ * * PostScriptum ,Prefix,Level ,Method,Prologue,Epilogue,Message */ #define LOGDXP(P, ...) LOG( ,"D" ,DEBUG ,warnx ,P , ,##__VA_ARGS__) +#define LOGDP(P, ...) LOG( ,"D" ,DEBUG ,warn ,P , ,##__VA_ARGS__) #define LOGDX(...) LOG( ,"D" ,DEBUG ,warnx , , ,##__VA_ARGS__) #define LOGD(...) LOG( ,"D" ,DEBUG ,warn , , ,##__VA_ARGS__) #define LOGIX(...) LOG( ,"I" ,INFO ,warnx , , ,##__VA_ARGS__) diff --git a/main.c b/main.c index afb1b4a..33fff03 100644 --- a/main.c +++ b/main.c @@ -5,6 +5,7 @@ #include #include #include +#include static void adjust_rlimit(void) { // This will force syscalls that allocate file descriptors to fail if it @@ -24,16 +25,16 @@ int main(const int ac, const char* av[static const ac]) { adjust_rlimit(); int fd_fo_main = STDOUT_FILENO, fd_fi_main = STDIN_FILENO; ucsp_info_and_adjust_fds(&fd_fo_main, &fd_fi_main); + set_nonblocking(fd_fi_main); + set_nonblocking(fd_fo_main); struct sus_registation_form tasks[] = { - sus_registration(fsm_wireformat, fd_fi_main), - sus_registration(fsm_frontend_foreign), + sus_registration(fsm_wireformat, .infd = fd_fi_main), + sus_registration(fsm_frontend_foreign, .foreign_out = fd_fo_main), sus_registration(fsm_frontend_timer), - sus_registration(autoresponder, av[2], 1, fd_fo_main), + sus_registration(autoresponder, .d5_path = av[2], .out = fd_fo_main), sus_registration(s6_notify, -1), sus_registration(controller), }; - set_nonblocking(fd_fo_main); - set_nonblocking(fd_fi_main); if (sig_runall(lengthof(tasks), &tasks) != 0) EXITF("Can't start"); int ret = 0; diff --git a/multitasking/sigio.c b/multitasking/sigio.c index eae2032..069a24a 100644 --- a/multitasking/sigio.c +++ b/multitasking/sigio.c @@ -21,53 +21,54 @@ static struct coro_context s_end; static siginfo_t s_si; static char* events_tostring(const size_t size, char buf[static const size], const short e) { + assert(!(e & ~0x37FF)); FILE* const s = fmemopen(buf, size, "w"); xfprintf(s, "0x%04hx", e); +# if 0 + if (e & POLLRDHUP) + xfputs(" RDHUP", s); + if (e & POLLREMOVE) + xfputs(" REMOVE", s); + if (e & POLLMSG) + xfputs(" MSG", s); +# endif # ifdef _XOPEN_SOURCE - if (e & POLLRDNORM) - xfputs(" IN", s); + if (e & POLLWRBAND) + xfputs(" XOUTPRI", s); if (e & POLLWRNORM) - xfputs(" OUT", s); + xfputs(" XOUT", s); if (e & POLLRDBAND) - xfputs(" INPRI", s); - if (e & POLLWRBAND) - xfputs(" OUTPRI", s); -# else - if (e & POLLIN) - xfputs(" IN", s); - if (e & POLLPRI) - xfputs(" PRI", s); - if (e & POLLOUT) - xfputs(" OUT", s); -# endif -# ifdef _GNU_SOURCE - if (e & POLLMSG) - xfputs(" MSG", s); - if (e & POLLREMOVE) - xfputs(" REMOVE", s); - if (e & POLLRDHUP) - xfputs(" RDHUP", s); + xfputs(" XINPRI", s); + if (e & POLLRDNORM) + xfputs(" XIN", s); # endif - if (e & POLLERR) - xfputs(" ERR", s); - if (e & POLLHUP) - xfputs(" HUP", s); if (e & POLLNVAL) xfputs(" NVAL", s); + if (e & POLLHUP) + xfputs(" HUP", s); + if (e & POLLERR) + xfputs(" ERR", s); + if (e & POLLOUT) + xfputs(" OUT", s); + if (e & POLLPRI) + xfputs(" PRI", s); + if (e & POLLIN) + xfputs(" IN", s); xfclose(s); return buf; } -static int suspend_poll(const int fd, const short nevents) { - LOGDXP(char tmp[8], "fd: %d, nevents: %s", fd, events_tostring(sizeof tmp, tmp, nevents)); +static int suspend_poll(const int fd, const short wants) { + LOGDP(char tmp[32], "fd:%d fcntl:%#x wants:%s", fd, fcntl(fd, F_GETFL), events_tostring(sizeof tmp, tmp, wants)); if (is_fd_bad(fd)) return -1; assert(fcntl(fd, F_GETFL) & O_NONBLOCK); - assert(fcntl(fd, F_GETFL) & O_ASYNC); +# if 0 assert(fcntl(fd, F_GETOWN) == getpid()); assert(fcntl(fd, F_GETSIG) == SIGPOLL); - assert(nevents & (POLLIN | POLLOUT)); - while (s_si.si_signo != SIGPOLL || s_si.si_fd != fd || s_si.si_band & nevents) { + assert(fcntl(fd, F_GETFL) & O_ASYNC); +# endif + while (s_si.si_signo != SIGPOLL || /* s_si.si_fd != fd || */ !(s_si.si_band & wants)) { if (s_current->visited > 100) return errno = EDEADLK, -1; const char* const name = s_current->name; @@ -79,15 +80,48 @@ static int suspend_poll(const int fd, const short nevents) { } ssize_t sio_read(const int fd, void* const data, const size_t size) { - if (suspend_poll(fd, POLLOUT) < 0) - return -1; - return read(fd, data, size); + LOGDX("> %s fd:%d", s_current->name, fd); + ssize_t res; + while ((res = read(fd, data, size)) < 0) { + switch (errno) { + case EINTR: + continue; + case EAGAIN: + if (suspend_poll(fd, POLLIN | POLLRDNORM) < 0) { + return -1; + } + break; + default: + return -1; + } + } + LOGDX("< %s res:%zd", s_current->name, res); + return res; } ssize_t sio_write(const int fd, const void* const data, const size_t size) { - if (suspend_poll(fd, POLLIN) < 0) - return -1; - return write(fd, data, size); + LOGDX("> %s fd:%d", s_current->name, fd); + ssize_t res; + while ((res = write(fd, data, size)) < 0) { + switch (errno) { + case EINTR: + continue; + case EAGAIN: + if (suspend_poll(fd, POLLOUT | POLLWRNORM) < 0) { + return -1; + } + break; + default: + return -1; + } + } + LOGDX("< %s res:%zd", s_current->name, res); + return res; +} + +ssize_t sio_memwrite(int id, const void* const data, const size_t size) { + const void* const buf = xmalloc(size); + return -1; } // Transfer to scheduler and forget about current coroutine @@ -109,9 +143,9 @@ static void starter(struct sus_registation_form* const reg) { int sig_runall(const size_t length, struct sus_registation_form (* const h)[length]) { assert(h); - close(STDIN_FILENO); int ret = -1; - struct coro_stuff stuff[length] = {}; + struct coro_stuff stuff[length]; + memset(stuff, 0, length); coro_create(&s_end, NULL, NULL, NULL, 0); for (size_t i = 0; i < length; i++) { if (!coro_stack_alloc(&stuff[i].stack, (*h)[i].stack_size)) @@ -127,14 +161,15 @@ int sig_runall(const size_t length, struct sus_registation_form (* const h)[leng for (size_t i = 0; i < lengthof(blocked_signals); i++) sigaddset(&s, blocked_signals[i]); xsigprocmask(SIG_BLOCK, &s, NULL); - const struct timespec timeout = { .tv_sec = 10, .tv_nsec = 0 }; + const struct timespec timeout = { .tv_sec = 100, .tv_nsec = 0 }; do { for (; s_current; s_current = s_current ? s_current->next : NULL) coro_transfer(&s_end, s_current->ctx); + LOGDX("waiting for I/O..."); const int sig = xsigtimedwait(&s, &s_si, &timeout); if (s_si.si_signo == SIGPOLL) - LOGDXP(char tmp[16], "signal %02d: %s (fd: %d band: %s)", - sig, strsignal(sig), s_si.si_fd, events_tostring(sizeof tmp, tmp, s_si.si_band)); + LOGDXP(char tmp[32], "signal %02d: %s (v: %d band: %s)", + sig, strsignal(sig), s_si.si_value.sival_int, events_tostring(sizeof tmp, tmp, s_si.si_band)); else psiginfo(&s_si, NULL); s_current = s_waiting; diff --git a/multitasking/suspendables.c b/multitasking/suspendables.c index fe4e2f7..f0da59c 100644 --- a/multitasking/suspendables.c +++ b/multitasking/suspendables.c @@ -235,7 +235,8 @@ int sus_ioloop(struct sus_ioloop_args* const args) { int sus_runall(const size_t length, struct sus_registation_form (* const h)[length]) { assert(h); int ret = -1; - struct coro_stuff stuff[length] = {}; + struct coro_stuff stuff[length]; + memset(stuff, 0, length); coro_create(&s_end, NULL, NULL, NULL, 0); for (size_t i = 0; i < length; i++) { if (!coro_stack_alloc(&stuff[i].stack, (*h)[i].stack_size)) diff --git a/serialization.c b/serialization.c index b26f120..0c28fd9 100644 --- a/serialization.c +++ b/serialization.c @@ -18,6 +18,7 @@ enum FrobDeviceType: serialize_integer,\ enum FrobTransactionType: serialize_trx_type,\ enum FrobTransactionStatus: serialize_integer,\ + enum __error_t_codes: serialize_integer,\ const char*: serialize_string,\ const unsigned char*: xsnprint_hex,\ bool: serialize_boolean,\ diff --git a/utils.c b/utils.c index 8a47115..95a9f5c 100644 --- a/utils.c +++ b/utils.c @@ -17,10 +17,12 @@ void set_nonblocking(const int fd) { EXITF("fcntl F_GETFL"); if (fcntl(fd, F_SETFL, flags | O_NONBLOCK | O_ASYNC) == -1) EXITF("fcntl F_SETFL O_NONBLOCK | O_ASYNC"); +# if 0 if (fcntl(fd, F_SETOWN, getpid()) == -1) EXITF("fcntl F_SETOWN"); if (fcntl(fd, F_SETSIG, SIGPOLL) == -1) EXITF("fcntl F_SETSIG"); +# endif } bool is_fd_bad(const int fd) { diff --git a/utils.h b/utils.h index 6ace75e..be29f97 100644 --- a/utils.h +++ b/utils.h @@ -66,6 +66,9 @@ #define xsigtimedwait(...) XCALL(sigtimedwait, __VA_ARGS__) #define xfprintf(...) XCALL(fprintf, __VA_ARGS__) +#define xlseek(...) XCALL(lseek, __VA_ARGS__) +#define xpipe2(...) XCALL(pipe2, __VA_ARGS__) +#define xftruncate(...) XCALL(truncate, __VA_ARGS__) #define xfputs(...) XCALL(fputs, __VA_ARGS__) #define xfflush(...) XCALL(fflush, __VA_ARGS__) #define xsigprocmask(...) XCALL(sigprocmask, __VA_ARGS__)