diff options
author | Omar Polo <op@omarpolo.com> | 2021-05-09 18:23:36 +0000 |
---|---|---|
committer | Omar Polo <op@omarpolo.com> | 2021-05-09 18:23:36 +0000 |
commit | 8ad1c570242cd93f0802931621b49b2510b338e7 (patch) | |
tree | 361394003bca869780ace3a3391ff13b2439a6e2 /gmid.h | |
parent | 50310aff335912edde625a5cde3729e34783fd7c (diff) |
fastcgi: a first implementation
Not production-ready yet, but it's a start.
This adds a third ``backend'' for gmid: until now there it served
local files or CGI scripts, now FastCGI applications too.
FastCGI is meant to be an improvement over CGI: instead of exec'ing a
script for every request, it allows to open a single connection to an
``application'' and send the requests/receive the responses over that
socket using a simple binary protocol.
At the moment gmid supports three different methods of opening a
fastcgi connection:
- local unix sockets, with: fastcgi "/path/to/sock"
- network sockets, with: fastcgi tcp "host" [port]
port defaults to 9000 and can be either a string or a number
- subprocess, with: fastcgi spawn "/path/to/program"
the fastcgi protocol is done over the executed program stdin
of these, the last is only for testing and may be removed in the
future.
P.S.: the fastcgi rule is per-location of course :)
Diffstat (limited to 'gmid.h')
-rw-r--r-- | gmid.h | 54 |
1 files changed, 54 insertions, 0 deletions
@@ -26,6 +26,7 @@ #include <netinet/in.h> #include <dirent.h> +#include <event.h> #include <limits.h> #include <netdb.h> #include <signal.h> @@ -55,8 +56,24 @@ #define DOMAIN_NAME_LEN (253+1) #define LABEL_LEN (63+1) +#define FCGI_MAX 32 #define PROC_MAX 16 +struct fcgi { + int id; + char *path; + char *port; + char *prog; + int fd; + struct event e; + +#define FCGI_OFF 0 +#define FCGI_INFLIGHT 1 +#define FCGI_READY 2 + int s; +}; +extern struct fcgi fcgi[FCGI_MAX]; + TAILQ_HEAD(lochead, location); struct location { const char *match; @@ -69,6 +86,7 @@ struct location { int strip; X509_STORE *reqca; int disable_log; + int fcgi; const char *dir; int dirfd; @@ -157,6 +175,14 @@ struct parser { const char *err; }; +struct mbuf { + size_t len; + size_t off; + TAILQ_ENTRY(mbuf) mbufs; + char data[]; +}; +TAILQ_HEAD(mbufhead, mbuf); + struct client; typedef void (imsg_handlerfn)(struct imsgbuf*, struct imsg*, size_t); @@ -171,6 +197,7 @@ typedef void (*statefn)(int, short, void*); * 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 @@ -180,6 +207,10 @@ typedef void (*statefn)(int, short, void*); * * 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 * @@ -193,21 +224,33 @@ struct client { char req[GEMINI_URL_LEN]; 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; + int code; const char *meta; int fd, pfd; struct dirent **dir; int dirlen, diroff; + int fcgi; /* big enough to store STATUS + SPACE + META + CRLF */ char sbuf[1029]; ssize_t len, off; + struct mbufhead mbufhead; + struct sockaddr_storage addr; struct vhost *host; /* host they're talking to */ }; +extern struct client clients[MAX_USERS]; + struct cgireq { char buf[GEMINI_URL_LEN]; @@ -248,6 +291,8 @@ enum { enum imsg_type { IMSG_CGI_REQ, IMSG_CGI_RES, + IMSG_FCGI_REQ, + IMSG_FCGI_FD, IMSG_LOG, IMSG_QUIT, }; @@ -298,11 +343,16 @@ const char *vhost_default_mime(struct vhost*, const char*); const char *vhost_index(struct vhost*, const char*); int vhost_auto_index(struct vhost*, const char*); int vhost_block_return(struct vhost*, const char*, int*, const char**); +int vhost_fastcgi(struct vhost*, const char*); int vhost_dirfd(struct vhost*, const char*); int vhost_strip(struct vhost*, const char*); X509_STORE *vhost_require_ca(struct vhost*, const char*); int vhost_disable_log(struct vhost*, const char*); + void mark_nonblock(int); +void start_reply(struct client*, int, const char*); +void close_conn(int, short, void*); +struct client *try_client_by_id(int); void loop(struct tls*, int, int, struct imsgbuf*); /* dirs.c */ @@ -325,6 +375,10 @@ int send_fd(int, int); int recv_fd(int); int executor_main(struct imsgbuf*); +/* fcgi.c */ +void handle_fcgi(int, short, void*); +void send_fcgi_req(struct fcgi*, struct client*); + /* sandbox.c */ void sandbox_server_process(void); void sandbox_executor_process(void); |