commit - 1e7591a9220359bc646562b161719d406cbbc267
commit + 112802ea3116b6e11a70d6060e6e238495498bbc
blob - 5d4becfadf20bfc62c907d4ff56193abad4314ec
blob + e2a5e5e6d5cb982b5f412f0713f562c86f0e8387
--- gmid.h
+++ gmid.h
const char *err;
};
-enum {
- S_HANDSHAKE,
- S_OPEN,
- S_INITIALIZING,
- S_SENDING_FILE,
- S_SENDING_DIR,
- S_SENDING_CGI,
- S_CLOSING,
-};
+struct client;
+typedef void (*statefn)(struct pollfd*, struct client*);
+
struct client {
struct tls *ctx;
char req[GEMINI_URL_LEN];
struct iri iri;
char domain[DOMAIN_NAME_LEN];
- int state, next;
+ statefn state, next;
int code;
const char *meta;
int fd, waiting_on_child;
void handle_handshake(struct pollfd*, struct client*);
void handle_open_conn(struct pollfd*, struct client*);
void start_reply(struct pollfd*, struct client*, int, const char*);
+void handle_start_reply(struct pollfd*, struct client*);
void start_cgi(const char*, const char*, struct pollfd*, struct client*);
void send_file(struct pollfd*, struct client*);
void open_dir(struct pollfd*, struct client*);
void handle_cgi(struct pollfd*, struct client*);
void close_conn(struct pollfd*, struct client*);
void do_accept(int, struct tls*, struct pollfd*, struct client*);
-void handle(struct pollfd*, struct client*);
void loop(struct tls*, int, int);
/* ex.c */
blob - 30f413c685dc2e63601f4fc5428bdad8875bec86
blob + 2f8112db514c87161d2be9c4b42b56bf72f3a4cc
--- server.c
+++ server.c
return;
}
c->i = c->buf;
- c->next = S_SENDING_FILE;
+ c->next = send_file;
start_reply(fds, c, SUCCESS, mime(c->host, c->iri.path));
}
/* h->domain != NULL ? h->domain : "(null)"); */
if (h->domain != NULL) {
- c->state = S_OPEN;
+ c->state = handle_open_conn;
c->host = h;
handle_open_conn(fds, c);
return;
void
start_reply(struct pollfd *pfd, struct client *c, int code, const char *meta)
{
+ c->code = code;
+ c->meta = meta;
+ c->state = handle_start_reply;
+ c->state(pfd, c);
+}
+
+void
+handle_start_reply(struct pollfd *pfd, struct client *c)
+{
char buf[1030]; /* status + ' ' + max reply len + \r\n\0 */
const char *lang;
size_t len;
- c->code = code;
- c->meta = meta;
- c->state = S_INITIALIZING;
-
lang = vhost_lang(c->host, c->iri.path);
- snprintf(buf, sizeof(buf), "%d ", code);
- strlcat(buf, meta, sizeof(buf));
- if (!strcmp(meta, "text/gemini") && lang != NULL) {
+ snprintf(buf, sizeof(buf), "%d ", c->code);
+ strlcat(buf, c->meta, sizeof(buf));
+ if (!strcmp(c->meta, "text/gemini") && lang != NULL) {
strlcat(buf, "; lang=", sizeof(buf));
strlcat(buf, lang, sizeof(buf));
}
/* advance the state machine */
c->state = c->next;
- handle(pfd, c);
+ c->state(pfd, c);
}
void
start_reply(fds, c, TEMP_FAILURE, "internal server error");
return;
}
- c->state = S_SENDING_CGI;
+ c->state = handle_cgi;
cgi_poll_on_child(fds, c);
c->code = -1;
/* handle_cgi(fds, c); */
{
ssize_t ret, len;
- /* ensure the correct state */
- c->state = S_SENDING_FILE;
-
len = (c->buf + c->len) - c->i;
while (len > 0) {
}
c->fd = dirfd;
- c->next = S_SENDING_DIR;
+ c->next = send_directory_listing;
if ((c->dir = fdopendir(c->fd)) == NULL) {
LOGE(c, "can't fdopendir(%d) (vhost:%s) %s: %s",
void
close_conn(struct pollfd *pfd, struct client *c)
{
- c->state = S_CLOSING;
+ c->state = close_conn;
switch (tls_close(c->ctx)) {
case TLS_WANT_POLLIN:
fds[i].fd = fd;
fds[i].events = POLLIN;
- clients[i].state = S_HANDSHAKE;
- clients[i].next = S_SENDING_FILE;
+ clients[i].state = handle_handshake;
+ clients[i].next = send_file;
clients[i].fd = -1;
clients[i].waiting_on_child = 0;
clients[i].buf = MAP_FAILED;
}
close(fd);
-}
-
-void
-handle(struct pollfd *fds, struct client *client)
-{
- switch (client->state) {
- case S_HANDSHAKE:
- handle_handshake(fds, client);
- break;
-
- case S_OPEN:
- handle_open_conn(fds, client);
- break;
-
- case S_INITIALIZING:
- start_reply(fds, client, client->code, client->meta);
- break;
-
- case S_SENDING_FILE:
- send_file(fds, client);
- break;
-
- case S_SENDING_DIR:
- send_directory_listing(fds, client);
- break;
-
- case S_SENDING_CGI:
- handle_cgi(fds, client);
- break;
-
- case S_CLOSING:
- close_conn(fds, client);
- break;
-
- default:
- /* unreachable */
- abort();
- }
}
void
else if (fds[i].fd == sock6)
do_accept(sock6, ctx, fds, clients);
else
- handle(&fds[i], &clients[i]);
+ clients[i].state(&fds[i], &clients[i]);
}
}
}