aboutsummaryrefslogtreecommitdiff
path: root/gmid.h
diff options
context:
space:
mode:
authorOmar Polo <op@omarpolo.com>2021-05-09 18:23:36 +0000
committerOmar Polo <op@omarpolo.com>2021-05-09 18:23:36 +0000
commit8ad1c570242cd93f0802931621b49b2510b338e7 (patch)
tree361394003bca869780ace3a3391ff13b2439a6e2 /gmid.h
parent50310aff335912edde625a5cde3729e34783fd7c (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.h54
1 files changed, 54 insertions, 0 deletions
diff --git a/gmid.h b/gmid.h
index 752653a..c97fd23 100644
--- a/gmid.h
+++ b/gmid.h
@@ -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);