Commit Diff


commit - 0388b56b659378d06da4d3ae5b44ec1b11d53374
commit + b148be7145ec930043173b11be95bf6327d3b598
blob - c734a08cba71dcbc23e29f39560ebcd7f0b1045f
blob + 12dcebeabdf586f349249dc3b68d24d87de134e4
--- telescope.c
+++ telescope.c
@@ -110,16 +110,11 @@ const char *err_pages[70] = {
 
 static void		 die(void) __attribute__((__noreturn__));
 static struct tab	*tab_by_id(uint32_t);
-static void		 handle_imsg_err(struct imsg *, size_t);
-static void		 handle_imsg_check_cert(struct imsg *, size_t);
+static void		 handle_imsg_check_cert(struct imsg *);
 static void		 handle_check_cert_user_choice(int, struct tab *);
 static void		 handle_maybe_save_new_cert(int, struct tab *);
-static void		 handle_imsg_got_code(struct imsg *, size_t);
-static void		 handle_imsg_got_meta(struct imsg *, size_t);
 static void		 handle_maybe_save_page(int, struct tab *);
 static void		 handle_save_page_path(const char *, struct tab *);
-static void		 handle_imsg_buf(struct imsg *, size_t);
-static void		 handle_imsg_eof(struct imsg *, size_t);
 static void		 handle_dispatch_imsg(int, short, void *);
 static void		 load_about_url(struct tab *, const char *);
 static void		 load_file_url(struct tab *, const char *);
@@ -147,15 +142,6 @@ static const struct proto {
 	{NULL, NULL, NULL},
 };
 
-static imsg_handlerfn *handlers[] = {
-	[IMSG_ERR] = handle_imsg_err,
-	[IMSG_CHECK_CERT] = handle_imsg_check_cert,
-	[IMSG_GOT_CODE] = handle_imsg_got_code,
-	[IMSG_GOT_META] = handle_imsg_got_meta,
-	[IMSG_BUF] = handle_imsg_buf,
-	[IMSG_EOF] = handle_imsg_eof,
-};
-
 static struct ohash	certs;
 
 static void __attribute__((__noreturn__))
@@ -175,40 +161,22 @@ tab_by_id(uint32_t id)
 	}
 
 	return NULL;
-}
-
-static void
-handle_imsg_err(struct imsg *imsg, size_t datalen)
-{
-	struct tab	*tab;
-	char		*page;
-
-	if ((tab = tab_by_id(imsg->hdr.peerid)) == NULL)
-		return;
-
-	page = imsg->data;
-	page[datalen-1] = '\0';
-
-	if (asprintf(&page, "# Error loading %s\n\n> %s\n",
-	    hist_cur(tab->hist), page) == -1)
-		die();
-	load_page_from_str(tab, page);
-	free(page);
 }
 
 static void
-handle_imsg_check_cert(struct imsg *imsg, size_t datalen)
+handle_imsg_check_cert(struct imsg *imsg)
 {
 	const char		*hash, *host, *port;
 	int			 tofu_res;
 	struct tofu_entry	*e;
 	struct tab		*tab;
+	size_t			 datalen;
 
-	hash = imsg->data;
-	if (hash[datalen-1] != '\0')
+	if ((hash = imsg_borrow_str(imsg)) == NULL)
 		abort();
+	datalen = strlen(hash);
 
-	if ((tab = tab_by_id(imsg->hdr.peerid)) == NULL)
+	if ((tab = tab_by_id(imsg_get_id(imsg))) == NULL)
 		return;
 
 	if (tab->proxy != NULL) {
@@ -358,35 +326,10 @@ normalize_code(int n)
 }
 
 static void
-handle_imsg_got_code(struct imsg *imsg, size_t datalen)
+handle_request_response(struct tab *tab)
 {
-	struct tab	*tab;
-
-	if ((tab = tab_by_id(imsg->hdr.peerid)) == NULL)
-		return;
-
-	if (imsg_get_data(imsg, &tab->code, sizeof(tab->code)) == -1)
-		die();
-
-	tab->code = normalize_code(tab->code);
-	if (tab->code != 30 && tab->code != 31)
-		tab->redirect_count = 0;
-}
-
-static void
-handle_imsg_got_meta(struct imsg *imsg, size_t datalen)
-{
-	struct tab	*tab;
 	char		 buf[128];
 
-	if ((tab = tab_by_id(imsg->hdr.peerid)) == NULL)
-		return;
-
-	if (sizeof(tab->meta) <= datalen)
-		die();
-
-	memcpy(tab->meta, imsg->data, datalen);
-
 	if (tab->code < 10) {	/* internal errors */
 		load_page_from_str(tab, err_pages[tab->code]);
 	} else if (tab->code < 20) {	/* 1x */
@@ -480,69 +423,127 @@ handle_save_page_path(const char *path, struct tab *ta
 }
 
 static void
-handle_imsg_buf(struct imsg *imsg, size_t datalen)
+handle_dispatch_imsg(int fd, short event, void *data)
 {
-	struct tab	*tab = NULL;
-	struct download	*d = NULL;
+	struct imsgev	*iev = data;
+	struct imsgbuf	*imsgbuf = &iev->ibuf;
+	struct imsg	 imsg;
+	struct tab	*tab;
+	struct download	*d;
+	const char	*str, *h;
+	char		*page;
+	ssize_t		 n;
 
-	if ((tab = tab_by_id(imsg->hdr.peerid)) == NULL &&
-	    (d = download_by_id(imsg->hdr.peerid)) == NULL)
-		return;
-
-	if (tab != NULL) {
-		if (!parser_parse(tab, imsg->data, datalen))
-			die();
-		ui_on_tab_refresh(tab);
-	} else {
-		d->bytes += datalen;
-		write(d->fd, imsg->data, datalen);
-		ui_on_download_refresh();
+	if (event & EV_READ) {
+		if ((n = imsg_read(imsgbuf)) == -1 && errno != EAGAIN)
+			err(1, "imsg_read");
+		if (n == 0)
+			err(1, "connection closed");
 	}
-}
+	if (event & EV_WRITE) {
+		if ((n = msgbuf_write(&imsgbuf->w)) == -1 && errno != EAGAIN)
+			err(1, "msgbuf_write");
+		if (n == 0)
+			err(1, "connection closed");
+	}
 
-static void
-handle_imsg_eof(struct imsg *imsg, size_t datalen)
-{
-	struct tab	*tab = NULL;
-	struct download	*d = NULL;
-	const char	*h;
+	for (;;) {
+		if ((n = imsg_get(imsgbuf, &imsg)) == -1)
+			err(1, "imsg_get");
+		if (n == 0)
+			break;
 
-	if ((tab = tab_by_id(imsg->hdr.peerid)) == NULL &&
-	    (d = download_by_id(imsg->hdr.peerid)) == NULL)
-		return;
+		switch (imsg_get_type(&imsg)) {
+		case IMSG_ERR:
+			if ((tab = tab_by_id(imsg_get_id(&imsg))) == NULL)
+				break;
+			if ((str = imsg_borrow_str(&imsg)) == NULL)
+				die();
+			if (asprintf(&page, "# Error loading %s\n\n> %s\n",
+			    hist_cur(tab->hist), str) == -1)
+				die();
+			load_page_from_str(tab, page);
+			free(page);
+			break;
+		case IMSG_CHECK_CERT:
+			handle_imsg_check_cert(&imsg);
+			break;
+		case IMSG_GOT_CODE:
+			if ((tab = tab_by_id(imsg_get_id(&imsg))) == NULL)
+				break;
+			if (imsg_get_data(&imsg, &tab->code, sizeof(tab->code))
+			    == -1)
+				die();
+			tab->code = normalize_code(tab->code);
+			if (tab->code != 30 && tab->code != 31)
+				tab->redirect_count = 0;
+			break;
+		case IMSG_GOT_META:
+			if ((tab = tab_by_id(imsg_get_id(&imsg))) == NULL)
+				break;
+			if ((str = imsg_borrow_str(&imsg)) == NULL)
+				die();
+			if (strlcpy(tab->meta, str, sizeof(tab->meta)) >=
+			    sizeof(tab->meta))
+				die();
+			handle_request_response(tab);
+			break;
+		case IMSG_BUF:
+			if ((tab = tab_by_id(imsg_get_id(&imsg))) == NULL &&
+			    ((d = download_by_id(imsg_get_id(&imsg)))) == NULL)
+				return;
 
-	if (tab != NULL) {
-		if (!parser_free(tab))
-			die();
-		h = hist_cur(tab->hist);
-		if (!strncmp(h, "gemini://", 9) ||
-		    !strncmp(h, "gopher://", 9) ||
-		    !strncmp(h, "finger://", 9))
-			mcache_tab(tab);
+			if (tab) {
+				if (!parser_parse(tab, imsg.data,
+				    imsg_get_len(&imsg)))
+					die();
+				ui_on_tab_refresh(tab);
+			} else {
+				size_t datalen = imsg_get_len(&imsg);
 
-		/*
-		 * Gemini is handled as soon as a 2x reply is got.
-		 */
-		if (!strncmp(h, "finger://", 9) ||
-		    !strncmp(h, "gopher://", 9))
-			history_add(h);
+				d->bytes += datalen;
+				write(d->fd, imsg.data, datalen);
+				ui_on_download_refresh();
+			}
+			break;
+		case IMSG_EOF:
+			if ((tab = tab_by_id(imsg_get_id(&imsg))) == NULL &&
+			    ((d = download_by_id(imsg_get_id(&imsg)))) == NULL)
+				return;
 
-		ui_on_tab_refresh(tab);
-		ui_on_tab_loaded(tab);
-	} else {
-		close(d->fd);
-		d->fd = -1;
-		ui_on_download_refresh();
-	}
-}
-
-static void
-handle_dispatch_imsg(int fd, short ev, void *d)
-{
-	struct imsgev	*iev = d;
+			if (tab != NULL) {
+				if (!parser_free(tab))
+					die();
+				h = hist_cur(tab->hist);
+				if (!strncmp(h, "gemini://", 9) ||
+				    !strncmp(h, "gopher://", 9) ||
+				    !strncmp(h, "finger://", 9))
+					mcache_tab(tab);
 
-	if (dispatch_imsg(iev, ev, handlers, sizeof(handlers)) == -1)
-		err(1, "connection closed");
+				/*
+				 * Gemini is handled as soon as a 2x
+				 * reply is got.
+				 */
+				if (!strncmp(h, "finger://", 9) ||
+				    !strncmp(h, "gopher://", 9))
+					history_add(h);
+
+				ui_on_tab_refresh(tab);
+				ui_on_tab_loaded(tab);
+			} else {
+				close(d->fd);
+				d->fd = -1;
+				ui_on_download_refresh();
+			}
+			break;
+		default:
+			errx(1, "got unknown imsg %d", imsg_get_type(&imsg));
+		}
+
+		imsg_free(&imsg);
+	}
+
+	imsg_event_add(iev);
 }
 
 static void
blob - acb3a2423988a8d005fdc3feb99dc4e6348683c0
blob + d458841d901c12576f9fe2ae79944071f1fe6e1d
--- telescope.h
+++ telescope.h
@@ -128,8 +128,6 @@ typedef void	(*parserinit)(struct parser *);
 typedef int	(*parsechunkfn)(struct parser *, const char *, size_t);
 typedef int	(*parserfreefn)(struct parser *);
 typedef int	(*parserserial)(struct parser *, FILE *);
-
-typedef void (imsg_handlerfn)(struct imsg*, size_t);
 
 struct parser {
 	const char	*name;
blob - a78de2d3db7f7b2d79d10c46adc1229c634d5ca7
blob + d8ae654a86abc0e7d06b67c2ba08298611206206
--- utils.c
+++ utils.c
@@ -83,47 +83,6 @@ imsg_event_add(struct imsgev *iev)
 }
 
 int
-dispatch_imsg(struct imsgev *iev, short event, imsg_handlerfn **handlers,
-    size_t size)
-{
-	struct imsgbuf	*ibuf;
-	struct imsg	 imsg;
-	size_t		 datalen, i;
-	ssize_t		 n;
-
-	ibuf = &iev->ibuf;
-
-	if (event & EV_READ) {
-		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
-			err(1, "imsg_read error");
-		if (n == 0)
-			return -1;
-	}
-	if (event & EV_WRITE) {
-		if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
-			err(1, "msgbuf_write");
-		if (n == 0)
-			return -1;
-	}
-
-	for (;;) {
-		if ((n = imsg_get(ibuf, &imsg)) == -1)
-			_exit(1);
-		if (n == 0)
-			break;
-		datalen = IMSG_DATA_SIZE(imsg);
-		i = imsg.hdr.type;
-		if (i > (size / sizeof(imsg_handlerfn*)) || handlers[i] == NULL)
-			abort();
-		handlers[i](&imsg, datalen);
-		imsg_free(&imsg);
-	}
-
-	imsg_event_add(iev);
-	return 0;
-}
-
-int
 imsg_compose_event(struct imsgev *iev, uint16_t type, uint32_t peerid,
     pid_t pid, int fd, const void *data, uint16_t datalen)
 {
@@ -136,6 +95,22 @@ imsg_compose_event(struct imsgev *iev, uint16_t type, 
 	return ret;
 }
 
+char *
+imsg_borrow_str(struct imsg *imsg)
+{
+	struct ibuf	 ibuf;
+	char		*data;
+	size_t		 len;
+
+	if (imsg_get_ibuf(imsg, &ibuf) == -1 ||
+	    (data = ibuf_data(&ibuf)) == NULL ||
+	    (len = ibuf_size(&ibuf)) == 0 ||
+	    data[len - 1] != '\0')
+		return NULL;
+
+	return data;
+}
+
 void *
 hash_alloc(size_t len, void *d)
 {
blob - 588673966051ca334bb6556f4e9054308ee8bc64
blob + e9b8386cca41a5b753e80548cde2f3725c2a5bd2
--- utils.h
+++ utils.h
@@ -24,9 +24,10 @@ int		 unicode_isspace(uint32_t);
 int		 unicode_isgraph(uint32_t);
 
 void		 imsg_event_add(struct imsgev *);
-int		 dispatch_imsg(struct imsgev *, short, imsg_handlerfn **, size_t);
 int		 imsg_compose_event(struct imsgev *, uint16_t, uint32_t, pid_t, int, const void *, uint16_t);
 
+char		*imsg_borrow_str(struct imsg *);
+
 void		*hash_alloc(size_t, void *);
 void		*hash_calloc(size_t, size_t, void *);
 void		 hash_free(void *, void *);