aboutsummaryrefslogtreecommitdiff
path: root/gmid.h
diff options
context:
space:
mode:
authorOmar Polo <op@omarpolo.com>2021-10-02 17:20:56 +0000
committerOmar Polo <op@omarpolo.com>2021-10-02 17:20:56 +0000
commitefe7d180292726775fb3ae5e6af593490a264c60 (patch)
treefb80d8c133a34cea6cce5be538202aad76a6729e /gmid.h
parent403c42204182515d7281d8c11084eef596f8a6ee (diff)
new I/O handling on top of bufferevents
This is a big change in how gmid handles I/O. Initially we used a hand-written loop over poll(2), that then was evolved into something powered by libevent basic API. This meant that there were a lot of small "asynchronous" function that did one step, eventually scheduling the re-execution, that called each others in a chain. The new implementation revolves completely around libevent' bufferevents. It's more clear, as everything is implemented around the client_read and client_write functions. There is still space for improvements, like adding timeouts for one, but it's solid enough to be committed as is and then further improved.
Diffstat (limited to 'gmid.h')
-rw-r--r--gmid.h69
1 files changed, 21 insertions, 48 deletions
diff --git a/gmid.h b/gmid.h
index d0b17bd..8e3f308 100644
--- a/gmid.h
+++ b/gmid.h
@@ -185,60 +185,33 @@ struct parser {
const char *err;
};
-struct mbuf {
- size_t len;
- size_t off;
- TAILQ_ENTRY(mbuf) mbufs;
- char data[];
-};
-TAILQ_HEAD(mbufhead, mbuf);
-
typedef void (imsg_handlerfn)(struct imsgbuf*, struct imsg*, size_t);
-typedef void (*statefn)(int, short, void*);
+enum {
+ REQUEST_UNDECIDED,
+ REQUEST_FILE,
+ REQUEST_DIR,
+ REQUEST_CGI,
+ REQUEST_FCGI,
+ REQUEST_DONE,
+};
+
+#define IS_INTERNAL_REQUEST(x) ((x) != REQUEST_CGI && (x) != REQUEST_FCGI)
-/*
- * DFA: handle_handshake is the initial state, close_conn the final.
- * Sometimes we have an enter_* function to handle the state switch.
- *
- * handle_handshake -> handle_open_conn
- * handle_handshake -> close_conn // on err
- *
- * handle_open_conn -> handle_cgi_reply // via open_file/dir/...
- * handle_open_conn -> send_fcgi_req // via apply_fastcgi, IMSG_FCGI_FD
- * handle_open_conn -> handle_dirlist // ...same
- * handle_open_conn -> send_file // ...same
- * handle_open_conn -> start_reply // on error
- *
- * handle_cgi_reply -> handle_cgi // after logging the CGI reply
- * handle_cgi_reply -> start_reply // on error
- *
- * handle_cgi -> close_conn
- *
- * send_fcgi_req -> copy_mbuf // via handle_fcgi
- * handle_fcgi -> close_all // on error
- * copy_mbuf -> close_conn // on success/error
- *
- * handle_dirlist -> send_directory_listing
- * handle_dirlist -> close_conn // on error
- *
- * send_directory_listing -> close_conn
- *
- * send_file -> close_conn
- */
struct client {
int id;
struct tls *ctx;
- char req[GEMINI_URL_LEN];
+ char *req;
struct iri iri;
char domain[DOMAIN_NAME_LEN];
- /*
- * start_reply uses this to know what function call after the
- * reply. It's also used as sentinel value in fastcgi to know
- * if the server has closed the request.
- */
- statefn next;
+ struct bufferevent *bev;
+
+ int type;
+
+ struct bufferevent *cgibev;
+
+ char *header;
int code;
const char *meta;
@@ -251,8 +224,6 @@ struct client {
char sbuf[1029];
ssize_t len, off;
- struct mbufhead mbufhead;
-
struct sockaddr_storage addr;
struct vhost *host; /* host they're talking to */
size_t loc; /* location matched */
@@ -356,8 +327,9 @@ X509_STORE *vhost_require_ca(struct vhost*, const char*);
int vhost_disable_log(struct vhost*, const char*);
void mark_nonblock(int);
+void client_write(struct bufferevent *, void *);
void start_reply(struct client*, int, const char*);
-void close_conn(int, short, void*);
+void client_close(struct client *);
struct client *try_client_by_id(int);
void loop(struct tls*, int, int, struct imsgbuf*);
@@ -382,6 +354,7 @@ int recv_fd(int);
int executor_main(struct imsgbuf*);
/* fcgi.c */
+void fcgi_abort_request(struct client *);
void fcgi_close_backend(struct fcgi *);
void fcgi_read(struct bufferevent *, void *);
void fcgi_write(struct bufferevent *, void *);