Commit Diff


commit - 0d7a38c4ce99cf5367a242d0a1d41b51d4a742e8
commit + 9862b637c2aa97e7e8d148ae9c3f92d0ca758fa7
blob - ab19646ef28f0d0c0d7c5a4ab18e94d2353629cc
blob + 13d49e238fe9957f5d2580fda736d3f50e949676
--- gmid.c
+++ gmid.c
@@ -569,51 +569,86 @@ send_dir(char *path, struct pollfd *fds, struct client
 }
 
 void
-handle(struct pollfd *fds, struct client *client)
+handle_handshake(struct pollfd *fds, struct client *c)
 {
+	switch (tls_handshake(c->ctx)) {
+	case 0:  /* success */
+	case -1: /* already handshaked */
+		break;
+	case TLS_WANT_POLLIN:
+		fds->events = POLLIN;
+		return;
+	case TLS_WANT_POLLOUT:
+		fds->events = POLLOUT;
+		return;
+	default:
+		/* unreachable */
+		abort();
+	}
+
+	/* TODO: check SNI here */
+	logs(LOG_DEBUG, c, "client wanted to talk to: %s", tls_conn_servername(c->ctx));
+
+	c->state = S_OPEN;
+	handle_open_conn(fds, c);
+}
+
+void
+handle_open_conn(struct pollfd *fds, struct client *c)
+{
 	char buf[GEMINI_URL_LEN];
-	const char *parse_err;
+	const char *parse_err = "invalid request";
 	struct iri iri;
 
-	switch (client->state) {
-	case S_OPEN:
-		bzero(buf, GEMINI_URL_LEN);
-		switch (tls_read(client->ctx, buf, sizeof(buf)-1)) {
-		case -1:
-			LOGE(client, "tls_read: %s", tls_error(client->ctx));
-			goodbye(fds, client);
+	bzero(buf, sizeof(buf));
+
+	switch (tls_read(c->ctx, buf, sizeof(buf)-1)) {
+	case -1:
+		LOGE(c, "tls_read: %s", tls_error(c->ctx));
+		goodbye(fds, c);
+		return;
+
+	case TLS_WANT_POLLIN:
+		fds->events = POLLIN;
+		return;
+
+	case TLS_WANT_POLLOUT:
+		fds->events = POLLOUT;
+		return;
+	}
+
+	if (!trim_req_iri(buf) || !parse_iri(buf, &iri, &parse_err)) {
+		if (!start_reply(fds, c, BAD_REQUEST, parse_err))
 			return;
+		goodbye(fds, c);
+		return;
+	}
 
-		case TLS_WANT_POLLIN:
-			fds->events = POLLIN;
+	if (strcmp(iri.schema, "gemini")) {
+		if (!start_reply(fds, c, PROXY_REFUSED, "won't proxy request"))
 			return;
+		goodbye(fds, c);
+		return;
+	}
 
-		case TLS_WANT_POLLOUT:
-			fds->events = POLLOUT;
-			return;
-		}
+	LOGI(c, "GET %s%s%s",
+		*iri.path ? iri.path : "/",
+		*iri.query ? "?" : "",
+		*iri.query ? iri.query : "");
 
-		parse_err = "invalid request";
-		if (!trim_req_iri(buf) || !parse_iri(buf, &iri, &parse_err)) {
-			if (!start_reply(fds, client, BAD_REQUEST, parse_err))
-				return;
-			goodbye(fds, client);
-			return;
-		}
+	send_file(iri.path, iri.query, fds, c);
+}
 
-		if (strcmp(iri.schema, "gemini")) {
-			if (!start_reply(fds, client, PROXY_REFUSED, "won't proxy request"))
-				return;
-			goodbye(fds, client);
-			return;
-		}
-
-		LOGI(client, "GET %s%s%s",
-		    *iri.path ? iri.path : "/",
-		    *iri.query ? "?" : "",
-		    *iri.query ? iri.query : "");
+void
+handle(struct pollfd *fds, struct client *client)
+{
+	switch (client->state) {
+	case S_HANDSHAKE:
+		handle_handshake(fds, client);
+		break;
 
-		send_file(iri.path, iri.query, fds, client);
+	case S_OPEN:
+                handle_open_conn(fds, client);
 		break;
 
 	case S_INITIALIZING:
@@ -738,7 +773,7 @@ do_accept(int sock, struct tls *ctx, struct pollfd *fd
 			fds[i].fd = fd;
 			fds[i].events = POLLIN;
 
-			clients[i].state = S_OPEN;
+			clients[i].state = S_HANDSHAKE;
 			clients[i].fd = -1;
 			clients[i].child = -1;
 			clients[i].buf = MAP_FAILED;
blob - e145d1a626088989b5738e140f7480da9c5fac93
blob + 570d38cc4b4fc4d38bcdf32cd7af64ceed755f42
--- gmid.h
+++ gmid.h
@@ -51,6 +51,7 @@
 #define MAX_USERS	64
 
 enum {
+	S_HANDSHAKE,
 	S_OPEN,
 	S_INITIALIZING,
 	S_SENDING,
@@ -111,6 +112,8 @@ void		 cgi_poll_on_client(struct pollfd*, struct clien
 void		 handle_cgi(struct pollfd*, struct client*);
 void		 send_file(char*, char*, struct pollfd*, struct client*);
 void		 send_dir(char*, struct pollfd*, struct client*);
+void		 handle_handshake(struct pollfd*, struct client*);
+void		 handle_open_conn(struct pollfd*, struct client*);
 void		 handle(struct pollfd*, struct client*);
 
 void		 mark_nonblock(int);