diff --git a/core/headers/services.h b/core/headers/services.h index 84b8a2b..5b521eb 100644 --- a/core/headers/services.h +++ b/core/headers/services.h @@ -9,29 +9,33 @@ #include "../src/headers/bdd_event.h" #include "../src/headers/bdd_service.h" #include "../src/headers/bdd_name_descs.h" +#include "../src/headers/bdd_cont.h" +#include "../src/headers/bdd_shutdown_status.h" +#include "../src/headers/bidirectiond_n_io.h" struct bdd_conversation; __attribute__((warn_unused_result)) ssize_t bdd_io_read( struct bdd_conversation *conversation, - uint8_t io_id, + bdd_io_id io_id, void *buf, ssize_t sz ); __attribute__((warn_unused_result)) ssize_t bdd_io_write( struct bdd_conversation *conversation, - uint8_t io_id, + bdd_io_id io_id, void *buf, ssize_t sz ); -bool bdd_connect(struct bdd_conversation *conversation, int address_family, struct sockaddr *addr, socklen_t addrlen); -bool bdd_prep_ssl( +bool bdd_io_obtain(struct bdd_conversation *conversation, bdd_io_id *io_id) +bool bdd_io_connect(struct bdd_conversation *conversation, bdd_io_id io_id, struct sockaddr *addr, socklen_t addrlen); +bool bdd_io_prep_ssl( struct bdd_conversation *conversation, char *ssl_name, char *alp ); -void bdd_set_associated( +void bdd_io_set_associated( struct bdd_conversation *conversation, void *data, void (*destructor)(void *) @@ -45,6 +49,6 @@ bool bdd_name_descs_add_service_instance( const void **instance_info ); -bool bdd_io_shutdown(struct bdd_conversation *conversation, uint8_t io_id); +enum bdd_shutdown_status bdd_io_shutdown(struct bdd_conversation *conversation, bdd_io_id io_id); #endif diff --git a/core/src/accept.c b/core/src/accept.c index cb5e01b..51b9759 100644 --- a/core/src/accept.c +++ b/core/src/accept.c @@ -263,7 +263,7 @@ enum bdd_cont bdd_connect_continue(struct bdd_io *io) { } void bdd_accept(struct bdd_worker_data *worker_data) { - struct bdd_conversation *conversation = bdd_conversation_obtain(); + struct bdd_conversation *conversation = bdd_conversation_obtain(worker_data->epoll_fd); if (conversation == NULL) { return; } diff --git a/core/src/conversations.c b/core/src/conversations.c index 7a19456..fa3bf92 100644 --- a/core/src/conversations.c +++ b/core/src/conversations.c @@ -12,6 +12,7 @@ #include "headers/conversations.h" #include "headers/bdd_service.h" #include "headers/bdd_io.h" +#include "headers/bdd_event.h" void *bdd_get_associated(struct bdd_conversation *conversation) { return conversation->aopn.associated.data; @@ -39,13 +40,13 @@ int bdd_conversation_id(struct bdd_conversation *conversation) { return (((char *)conversation - (char *)(bdd_gv.conversations)) / sizeof(struct bdd_conversation)); } -struct bdd_ev *bdd_ev(struct bdd_conversation *conversation, typeof(BIDIRECTIOND_N_IO) idx) { +struct bdd_ev *bdd_ev(struct bdd_conversation *conversation, bdd_io_id idx) { if (idx >= conversation->n_ev) { abort(); } return &(((struct bdd_ev *)&(conversation->io_array[BIDIRECTIOND_N_IO]))[idx]); } -typeof(BIDIRECTIOND_N_IO) bdd_n_ev(struct bdd_conversation *conversation) { +bdd_io_id bdd_n_ev(struct bdd_conversation *conversation) { return conversation->n_ev; } @@ -84,7 +85,7 @@ struct bdd_conversation *bdd_conversation_obtain(int epoll_fd) { conversation->aopn.pn.cstr_protocol_name = NULL; return conversation; } -void bdd_conversation_discard(struct bdd_conversation *conversation, int epoll_fd) { +void bdd_conversation_discard(struct bdd_conversation *conversation) { if (conversation->state == bdd_conversation_established) { bdd_set_associated(conversation, NULL, NULL); } diff --git a/core/src/headers/accept.h b/core/src/headers/accept.h index b4f5dd9..28275d9 100644 --- a/core/src/headers/accept.h +++ b/core/src/headers/accept.h @@ -2,16 +2,11 @@ #define bidirectiond_core__accept__h #include +#include "bdd_cont.h" struct bdd_conversation; struct bdd_io; -enum bdd_cont { - bdd_cont_discard, - bdd_cont_inprogress, - bdd_cont_established, -}; - int bdd_alpn_cb( SSL *client_ssl, const unsigned char **out, diff --git a/core/src/headers/bdd_cont.h b/core/src/headers/bdd_cont.h new file mode 100644 index 0000000..012b95b --- /dev/null +++ b/core/src/headers/bdd_cont.h @@ -0,0 +1,10 @@ +#ifndef bidirectiond_core__bdd_cont__h +#define bidirectiond_core__bdd_contt__h + +enum bdd_cont { + bdd_cont_discard, + bdd_cont_inprogress, + bdd_cont_established, +}; + +#endif diff --git a/core/src/headers/bdd_event.h b/core/src/headers/bdd_event.h index c370a51..5141ef3 100644 --- a/core/src/headers/bdd_event.h +++ b/core/src/headers/bdd_event.h @@ -6,7 +6,7 @@ #define bdd_ev_removed 4 struct bdd_ev { - enum bdd_ev ev; + uint8_t events; uint8_t io_id; }; diff --git a/core/src/headers/bdd_service.h b/core/src/headers/bdd_service.h index 022c460..ec3e5fd 100644 --- a/core/src/headers/bdd_service.h +++ b/core/src/headers/bdd_service.h @@ -8,7 +8,7 @@ struct bdd_conversation; struct bdd_name_descs; struct bdd_service { - void (*handle_events)(struct bdd_conversation *conversation, uint8_t io_id, uint8_t events); + void (*handle_events)(struct bdd_conversation *conversation); bool (*conversation_init)( struct bdd_conversation *conversation, diff --git a/core/src/headers/bidirectiond_n_io.h b/core/src/headers/bidirectiond_n_io.h new file mode 100644 index 0000000..79c6086 --- /dev/null +++ b/core/src/headers/bidirectiond_n_io.h @@ -0,0 +1,6 @@ +#ifndef BIDIRECTIOND_N_IO +#define BIDIRECTIOND_N_IO 2 +#endif +#ifndef bdd_io_id +#define bdd_io_id typeof(BIDIRECTIOND_N_IO) +#endif diff --git a/core/src/headers/conversations.h b/core/src/headers/conversations.h index b9957a1..b87f7bb 100644 --- a/core/src/headers/conversations.h +++ b/core/src/headers/conversations.h @@ -8,6 +8,8 @@ #include #include "bdd_io.h" +#include "bdd_shutdown_status.h" +#include "bidirectiond_n_io.h" struct bdd_service; struct bdd_io; @@ -39,10 +41,10 @@ struct bdd_conversation { struct bdd_io *io_array; - typeof(BIDIRECTIOND_N_IO) n_connecting; - typeof(BIDIRECTIOND_N_IO) n_in_epoll_with_events; + bdd_io_id n_connecting; + bdd_io_id n_in_epoll_with_events; - typeof(BIDIRECTIOND_N_IO) n_ev; + bdd_io_id n_ev; union { struct bdd_associated associated; @@ -70,12 +72,19 @@ enum bdd_conversation_init_status bdd_conversation_init( int bdd_io_fd(struct bdd_io *io); struct bdd_conversation *bdd_conversation_obtain(int epoll_fd); void bdd_conversation_discard(struct bdd_conversation *conversation); -typeof(BIDIRECTIOND_N_IO) bdd_io_obtain(struct bdd_conversation *conversation); void bdd_io_discard(struct bdd_io *io); -typeof(BIDIRECTIOND_N_IO) bdd_io_id(struct bdd_io *io); -struct bdd_io *bdd_io(struct bdd_conversation *conversation, typeof(BIDIRECTIOND_N_IO) io_id); +bdd_io_id bdd_io_id_of(struct bdd_io *io); +struct bdd_io *bdd_io(struct bdd_conversation *conversation, bdd_io_id io_id); enum bdd_shutdown_status bdd_ssl_shutdown_continue(struct bdd_io *io); +void bdd_io_epoll_mod(struct bdd_io *io, uint32_t add_events, uint32_t remove_events, bool edge_trigger); +void bdd_io_epoll_add(struct bdd_io *io); +void bdd_io_epoll_remove(struct bdd_io *io); +bool bdd_io_hup(struct bdd_io *io, bool rdhup); +void bdd_io_state(struct bdd_io *io, enum bdd_io_state new_state); + +struct bdd_ev *bdd_ev(struct bdd_conversation *conversation, bdd_io_id io_id); + #endif diff --git a/core/src/instance.c b/core/src/instance.c index 8a6b8aa..ca6474e 100644 --- a/core/src/instance.c +++ b/core/src/instance.c @@ -111,7 +111,8 @@ void bdd_destroy(void) { ++idx ) { struct bdd_conversation *conversation = &(bdd_gv.conversations[idx]); - bdd_conversation_discard(conversation, -1); + conversation->epoll_fd = -1; + bdd_conversation_discard(conversation); } free(bdd_gv.conversations); diff --git a/core/src/io.c b/core/src/io.c index 2213d91..bcf4ce4 100644 --- a/core/src/io.c +++ b/core/src/io.c @@ -14,13 +14,14 @@ #include "headers/conversations.h" #include "headers/bdd_service.h" #include "headers/bdd_io.h" +#include "headers/bidirectiond_n_io.h" -typeof(BIDIRECTIOND_N_IO) bdd_io_id(struct bdd_io *io) { +bdd_io_id bdd_io_id_of(struct bdd_io *io) { struct bdd_conversation *conversation = io->conversation; return (((char *)io - (char *)conversation->io_array) / sizeof(struct bdd_io)); } -struct bdd_io *bdd_io(struct bdd_conversation *conversation, typeof(BIDIRECTIOND_N_IO) io_id) { +struct bdd_io *bdd_io(struct bdd_conversation *conversation, bdd_io_id io_id) { if (conversation == NULL || io_id >= BIDIRECTIOND_N_IO) { return NULL; } @@ -36,14 +37,14 @@ int bdd_io_fd(struct bdd_io *io) { } } -void bdd_io_epoll_mod(struct bdd_io *io, uint32_t remove_flags, uint32_t add_flags, bool edge_trigger) { +void bdd_io_epoll_mod(struct bdd_io *io, uint32_t add_events, uint32_t remove_events, bool edge_trigger) { uint32_t old_events = io->epoll_events; - io->epoll_events &= ~remove_flags; + io->epoll_events &= ~remove_events; if (io->rdhup) { - add_flags &= ~EPOLLIN; + add_events &= ~EPOLLIN; } io->epoll_events |= add_events; - if (io->edge_trigger) { + if (edge_trigger) { io->epoll_events |= EPOLLET; } else { io->epoll_events &= ~EPOLLET; @@ -54,7 +55,7 @@ void bdd_io_epoll_mod(struct bdd_io *io, uint32_t remove_flags, uint32_t add_fla } #endif if (io->in_epoll) { - if (((old_events & ~EPOLLET) == 0) { + if ((old_events & ~EPOLLET) == 0) { if ((io->epoll_events & ~EPOLLET) != 0) { io->conversation->n_in_epoll_with_events += 1; } @@ -87,7 +88,7 @@ void bdd_io_epoll_add(struct bdd_io *io) { } void bdd_io_epoll_remove(struct bdd_io *io) { - if (!io->in_epoll) { + if (!io->in_epoll || io->conversation->epoll_fd < 0) { return; } io->in_epoll = 0; @@ -114,8 +115,8 @@ void bdd_io_state(struct bdd_io *io, enum bdd_io_state new_state) { if (state == bdd_io_connecting) { if (conversation->n_connecting) { - for (typeof(BIDIRECTIOND_N_IO) idx = 0; idx <= conversation->n_servers; ++idx) { - struct bdd_io *idx_io = bdd_io(idx); + for (bdd_io_id idx = 0; idx < BIDIRECTIOND_N_IO; ++idx) { + struct bdd_io *idx_io = bdd_io(conversation, idx); if (idx_io == io || (idx_io->state != bdd_io_est && idx_io->state != bdd_io_ssl_shutting)) { continue; } @@ -134,8 +135,8 @@ void bdd_io_state(struct bdd_io *io, enum bdd_io_state new_state) { if (new_state == bdd_io_connecting) { if (conversation->n_connecting == 0) { - for (typeof(BIDIRECTIOND_N_IO) idx = 0; idx <= conversation->n_servers; ++idx) { - struct bdd_io *idx_io = bdd_io(idx); + for (bdd_io_id idx = 0; idx < BIDIRECTIOND_N_IO; +idx) { + struct bdd_io *idx_io = bdd_io(conversation, idx); if (idx_io == io || idx_io->state == bdd_io_connecting) { continue; } @@ -147,24 +148,24 @@ void bdd_io_state(struct bdd_io *io, enum bdd_io_state new_state) { } } conversation->n_connecting += 1; - bdd_io_epoll_mod(idx_io, 0, EPOLLIN | EPOLLOUT, true); - bdd_io_epoll_add(idx_io); + bdd_io_epoll_mod(io, 0, EPOLLIN | EPOLLOUT, true); + bdd_io_epoll_add(io); } else if (new_state == bdd_io_est) { uint32_t epollin = EPOLLIN; if (io->rdhup) { epollin = 0; } - bdd_io_epoll_mod(idx_io, EPOLLOUT, epollin, false); + bdd_io_epoll_mod(io, EPOLLOUT, epollin, false); if (conversation->n_connecting == 0) { - bdd_io_epoll_add(idx_io); + bdd_io_epoll_add(io); } else { - bdd_io_epoll_remove(idx_io); + bdd_io_epoll_remove(io); } } else if (new_state == bdd_io_ssl_shutting) { - bdd_io_epoll_mod(idx_io, 0, EPOLLOUT, false); - bdd_io_epoll_add(idx_io); + bdd_io_epoll_mod(io, 0, EPOLLOUT, false); + bdd_io_epoll_add(io); } else { - bdd_io_epoll_remove(idx_io); + bdd_io_epoll_remove(io); } return; @@ -173,7 +174,7 @@ void bdd_io_state(struct bdd_io *io, enum bdd_io_state new_state) { // returns the number of bytes read (where 0 is a possible value), returns -3 on rdhup, returns -2 if IO discarded, returns -1 on err, __attribute__((warn_unused_result)) ssize_t bdd_io_read( struct bdd_conversation *conversation, - typeof(BIDIRECTIOND_N_IO) io_id, + bdd_io_id io_id, void *buf, ssize_t sz ) { @@ -205,7 +206,7 @@ __attribute__((warn_unused_result)) ssize_t bdd_io_read( } else if (err == SSL_ERROR_WANT_WRITE) { abort(); // fuck re-negotiation } else if (err == SSL_ERROR_ZERO_RETURN /* received close_notify */) { - if (bdd_io_set_hup(io, true)) { + if (bdd_io_hup(io, true)) { bdd_io_discard(io); return -2; } @@ -234,7 +235,7 @@ __attribute__((warn_unused_result)) ssize_t bdd_io_read( return -2; } if (r == 0) { - if (bdd_io_set_hup(io, true)) { + if (bdd_io_hup(io, true)) { bdd_io_discard(io); return -2; } @@ -247,7 +248,7 @@ __attribute__((warn_unused_result)) ssize_t bdd_io_read( // returns the number of bytes written, returns -2 if IO discarded, returns -1 on err __attribute__((warn_unused_result)) ssize_t bdd_io_write( struct bdd_conversation *conversation, - typeof(BIDIRECTIOND_N_IO) io_id, + bdd_io_id io_id, void *buf, ssize_t sz ) { @@ -279,7 +280,7 @@ __attribute__((warn_unused_result)) ssize_t bdd_io_write( bdd_io_epoll_mod(io, 0, EPOLLOUT, false); return 0; } - if (bdd_io_set_hup(io, false)) { + if (bdd_io_hup(io, false)) { return -2; } return -1; @@ -294,7 +295,7 @@ __attribute__((warn_unused_result)) ssize_t bdd_io_write( bdd_io_epoll_mod(io, 0, EPOLLOUT, false); return 0; } - if (bdd_io_set_hup(io, false)) { + if (bdd_io_hup(io, false)) { return -2; } return -1; @@ -306,6 +307,18 @@ __attribute__((warn_unused_result)) ssize_t bdd_io_write( return r; } +bool bdd_io_obtain(struct bdd_conversation *conversation, bdd_io_id *io_id) { + for (size_t idx = 0; idx < BIDIRECTIOND_N_IO; ++idx) { + struct bdd_io *io = &(conversation->io_array[idx]); + if (io->state == bdd_io_unused) { + bdd_io_state(io, bdd_io_obtained); + *io_id = (bdd_io_id)idx; + return true; + } + } + return false; +} + enum bdd_shutdown_status bdd_ssl_shutdown_continue(struct bdd_io *io) { int r = SSL_shutdown(io->io.ssl); if (r < 0) { @@ -323,7 +336,7 @@ enum bdd_shutdown_status bdd_ssl_shutdown_continue(struct bdd_io *io) { return bdd_shutdown_complete; } -enum bdd_shutdown_status bdd_io_shutdown(struct bdd_conversation *conversation, typeof(BIDIRECTIOND_N_IO) io_id) { +enum bdd_shutdown_status bdd_io_shutdown(struct bdd_conversation *conversation, bdd_io_id io_id) { struct bdd_io *io = bdd_io(conversation, io_id); if (io == NULL) { fputs("programming error: bdd_io_shutdown called with invalid arguments\n", stderr); @@ -335,11 +348,9 @@ enum bdd_shutdown_status bdd_io_shutdown(struct bdd_conversation *conversation, } if (io->ssl) { - bdd_io_state(io, bdd_io_ssl_shutdown); - if (bdd_io_shutdown_continue(io)): { - case (bdd_shutdown_inprogress): { - return bdd_shutdown_inprogress; - } + bdd_io_state(io, bdd_io_ssl_shutting); + if (bdd_ssl_shutdown_continue(io) == bdd_shutdown_inprogress) { + return bdd_shutdown_inprogress; } } else { shutdown(bdd_io_fd(io), SHUT_WR); @@ -366,7 +377,7 @@ void bdd_io_discard(struct bdd_io *io) { io->ssl && io->rdhup && io->wrhup && - (SSL_get_shutdown(io->io.ssl) & SSL_SENT_SHUT) + (SSL_get_shutdown(io->io.ssl) & SSL_SENT_SHUTDOWN) ) { SSL_shutdown(io->io.ssl); shutdown(fd, SHUT_WR); @@ -379,8 +390,8 @@ void bdd_io_discard(struct bdd_io *io) { return; } -bool bdd_io_prep_ssl(struct bdd_conversation *conversation, typeof(BIDIRECTIOND_N_IO) io_id, char *ssl_name, char *alp) { - struct bdd_io *io = bdd_io(conversation, io); +bool bdd_io_prep_ssl(struct bdd_conversation *conversation, bdd_io_id io_id, char *ssl_name, char *alp) { + struct bdd_io *io = bdd_io(conversation, io_id); if (io == NULL || io->state != bdd_io_obtained) { fputs("programming error: bdd_io_prep_ssl called with an io_id which is in an invalid state\n", stderr); abort(); @@ -439,11 +450,11 @@ bool bdd_io_prep_ssl(struct bdd_conversation *conversation, typeof(BIDIRECTIOND_ enum bdd_cont bdd_io_connect( struct bdd_conversation *conversation, - typeof(BIDIRECTIOND_N_IO) io_id, + bdd_io_id io_id, struct sockaddr *sockaddr, socklen_t addrlen ) { - struct bdd_io *io = bdd_io(conversation, io); + struct bdd_io *io = bdd_io(conversation, io_id); if (io == NULL || (io->state != bdd_io_obtained && io->state != bdd_io_prepd_ssl)) { fputs("programming error: bdd_io_connect called with an io_id which is in an invalid state\n", stderr); abort(); diff --git a/core/src/serve.c b/core/src/serve.c index 59da5d3..4bc29b4 100644 --- a/core/src/serve.c +++ b/core/src/serve.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include "headers/instance.h" @@ -15,71 +16,11 @@ #include "headers/unlikely.h" #include "headers/bdd_event.h" #include "headers/bdd_io.h" +#include "headers/bidirectiond_n_io.h" #include "headers/bdd_service.h" #include "headers/bdd_stop.h" - -enum handle_io_status { - handle_io_discard, - handle_io_hup, - handle_io_lt, -}; -static enum handle_io_status handle_io(struct bdd_io *io, uint32_t revents) { - struct bdd_conversation *conversation = io->conversation; - unsigned char bdd_revents = 0; - - if (revents & EPOLLERR) { - io->state = BDD_IO_ERR; - } else if (io->state == BDD_IO_SSL_SHUTTING) { - if (bdd_ssl_shutdown_continue(io) == bdd_cont_discard) { - io->state = BDD_IO_ERR; - } - } - if ((revents & EPOLLIN) && !io->rdhup) { - bdd_revents |= BDDEV_IN; - } - if (revents & EPOLLOUT) { - if (io->state == bdd_io_est) { - bdd_revents |= bdd_ev_out; - bdd_io_epoll_flags(io, EPOLLOUT, 0); - } else if (io->state == BDD_IO_SSL_SHUTTING) { - switch (bdd_ssl_shutdown_continue(io)) { - case (bdd_cont_established): { - bdd_io_epoll_flags(io, EPOLLOUT, 0); - break; - } - case (bdd_cont_discard): { - bdd_io_epoll_remove(io); - break; - } - } - } else { - abort(); - } - } - if (io->state == BDD_IO_ERR) { - bdd_revents |= BDDEV_NOOUT; - } - - if (bdd_revents & ~BDDEV_NOOUT) { - conversation->sosi.service->handle_events(conversation, bdd_io_id(conversation, io), bdd_revents); - } - - assert(conversation->client.state >= bdd_io_est); - - if (conversation->client.state >= bdd_io_err) { - // discard conversation - } - - if ( - (( - conversation->client.rdhup && - !(conversation->client.epoll_flags & EPOLLOUT) - ) || !conversation->client.in_epoll) && - conversation->n_servers_in_epoll == 0 - ) { - abort(); - } -} +#include "headers/bdd_event.h" +#include "headers/bdd_shutdown_status.h" static void process_link(struct bdd_conversation **list, struct bdd_conversation *conversation) { if (conversation->n_ev == 1) { @@ -129,16 +70,14 @@ void *bdd_serve(struct bdd_worker_data *worker_data) { } switch (conversation->state) { case (bdd_conversation_accept): { - switch (bdd_accept_continue(conversation)) { - case (bdd_cont_discard): { - bdd_conversation_discard(conversation, epoll_fd); - } + if (bdd_accept_continue(conversation) == bdd_cont_discard) { + bdd_conversation_discard(conversation); } break; } case (bdd_conversation_established): { struct bdd_ev *ev = bdd_ev(conversation, conversation->n_ev++); - ev->io_id = bdd_io_id(io); + ev->io_id = bdd_io_id_of(io); ev->events = ( (event->events & EPOLLIN ? bdd_ev_in : 0) | (event->events & EPOLLOUT ? bdd_ev_out : 0) |