Simplify list_all handling. Send an imsg for each msg instead of
authorSunil Nimmagadda <sunil@nimmagadda.net>
Tue, 01 Apr 2014 16:15:19 +0500
changeset 2 6e7b98264ea2
parent 1 f50606f97adf
child 3 a32da8616e0e
Simplify list_all handling. Send an imsg for each msg instead of consolidating into one imsg. We are no longer limited by MAX_IMSGSIZE. End of list is signalled by sending an imsg with hash as "" or sz as 0.
maildrop.c
pop3d.h
session.c
--- a/maildrop.c	Thu Mar 27 09:57:27 2014 +0500
+++ b/maildrop.c	Tue Apr 01 16:15:19 2014 +0500
@@ -38,9 +38,8 @@
 static void dele(struct imsgev *, struct imsg *, struct m_backend *);
 static void rset(struct imsgev *, struct imsg *, struct m_backend *);
 static void list(struct imsgev *, struct imsg *, struct m_backend *);
-static void list_all(struct imsgev *, struct imsg *, struct m_backend *, int);
+static void list_all(struct imsgev *, struct imsg *, struct m_backend *);
 static void do_list(unsigned int, size_t *, char *, size_t);
-static void *do_list_all(int, size_t *);
 static struct m_backend *m_backend_lookup(enum m_type);
 static void sig_handler(int, short, void *);
 static void needfd(struct imsgev *);
@@ -188,7 +187,6 @@
 session_imsgev(struct imsgev *iev, int code, struct imsg *imsg)
 {
 	struct m_backend	*mb = iev->data;
-	int			uidl = 0;		
 
 	switch (code) {
 	case IMSGEV_IMSG:
@@ -208,11 +206,8 @@
 		case IMSG_MAILDROP_LIST:
 			list(iev, imsg, mb);
 			break;
-		case IMSG_MAILDROP_UIDLALL:
-			uidl = 1;
-			/* FALLTHROUGH */
 		case IMSG_MAILDROP_LISTALL:
-			list_all(iev, imsg, mb, uidl);
+			list_all(iev, imsg, mb);
 			break;
 		default:
 			logit(LOG_DEBUG, "%s: unexpected imsg %u",
@@ -312,16 +307,37 @@
 }
 
 static void
-list_all(struct imsgev *iev, struct imsg *imsg, struct m_backend *mb, int uidl)
+list_all(struct imsgev *iev, struct imsg *imsg, struct m_backend *mb)
 {
-	void	*res;
-	size_t	sz;
+	struct list_res	res;
+	size_t		i;
+	int		*uidl = imsg->data;
+
+	for (i = 0; i < m.nmsgs; i++) {
+		if (m.msgs_index[i]->flags & F_DELE)
+			continue;
 
-	res = do_list_all(uidl, &sz);
-	/* XXX watchout for sz > MAX_IMSGSIZE */
-	imsgev_xcompose(iev,
-	    (uidl) ? IMSG_MAILDROP_UIDLALL : IMSG_MAILDROP_LISTALL,
-	    imsg->hdr.peerid, 0, -1, res, sz, "maildrop_list");
+		res.idx = i;
+		res.uidl = *uidl;
+		if (*uidl) {
+			strlcpy(res.u.hash, m.msgs_index[i]->hash,
+			    sizeof(res.u.hash));
+		} else
+			res.u.sz = m.msgs_index[i]->sz;
+		
+		imsgev_xcompose(iev, IMSG_MAILDROP_LISTALL,
+		    imsg->hdr.peerid, 0, -1, &res, sizeof(res),
+		    "maildrop_list");
+	}
+	
+	/* terminal sentinel: hash = "" and sz = 0 */
+	if (*uidl)
+		strlcpy(res.u.hash, "", sizeof(res.u.hash));
+	else
+		res.u.sz = 0;
+
+	imsgev_xcompose(iev, IMSG_MAILDROP_LISTALL, imsg->hdr.peerid,
+	    0, -1, &res, sizeof(res), "maildrop_list");
 }
 
 static void
@@ -337,43 +353,6 @@
 	strlcpy(hash, m.msgs_index[idx]->hash, hash_sz);
 }
 
-static void *
-do_list_all(int uidl, size_t *sz)
-{
-	size_t	i, j, *nsz = NULL;
-	char	*nhash = NULL;
-
-	if (uidl) {
-		nhash = xcalloc(m.nmsgs, SHA1_DIGEST_STRING_LENGTH, "list_all");
-	} else
-		nsz = xcalloc(m.nmsgs, sizeof(size_t), "list_all");
-
-	for (i = 0; i < m.nmsgs; i++) {
-			
-		if (uidl) {
-			j = i * SHA1_DIGEST_STRING_LENGTH;
-			if (m.msgs_index[i]->flags & F_DELE)
-				nhash[j] = '\0';
-			else
-				strlcpy(nhash + j, m.msgs_index[i]->hash,
-			    	    SHA1_DIGEST_STRING_LENGTH);
-		} else {
-			if (m.msgs_index[i]->flags & F_DELE)
-				nsz[i] = 0;
-			else
-				nsz[i] = m.msgs_index[i]->sz;
-		}
-	}
-
-	if (uidl) {
-		*sz = m.nmsgs * SHA1_DIGEST_STRING_LENGTH;
-		return (nhash);
-	} else {
-		*sz = m.nmsgs * sizeof(size_t);
-		return (nsz);
-	}
-}
-
 static void
 needfd(struct imsgev *iev)
 {
--- a/pop3d.h	Thu Mar 27 09:57:27 2014 +0500
+++ b/pop3d.h	Tue Apr 01 16:15:19 2014 +0500
@@ -36,7 +36,6 @@
 	IMSG_MAILDROP_RSET,
 	IMSG_MAILDROP_LIST,
 	IMSG_MAILDROP_LISTALL,
-	IMSG_MAILDROP_UIDLALL,
 	IMSG_MAILDROP_UPDATE
 };
 
--- a/session.c	Thu Mar 27 09:57:27 2014 +0500
+++ b/session.c	Tue Apr 01 16:15:19 2014 +0500
@@ -85,7 +85,7 @@
 static void handle_retr(struct session *, struct imsg *);
 static void handle_dele(struct session *, struct imsg *);
 static void handle_list(struct session *, struct imsg *);
-static void handle_list_all(struct session *, struct imsg *, int);
+static void handle_list_all(struct session *, struct imsg *);
 static void handle_update(struct session *, struct imsg *);
 static void needfd(struct imsgev *);
 static void pop3_debug(char *, ...);
@@ -417,9 +417,10 @@
 static void
 get_list_all(struct session *s, int uidl)
 {
-	imsgev_xcompose(&s->iev_maildrop,
-	    (uidl) ? IMSG_MAILDROP_UIDLALL : IMSG_MAILDROP_LISTALL,
-	    s->id, 0, -1, NULL, 0, "list_all");
+	io_pause(&s->io, IO_PAUSE_IN);
+	session_reply(s, "+OK");
+	imsgev_xcompose(&s->iev_maildrop, IMSG_MAILDROP_LISTALL,
+	    s->id, 0, -1, &uidl, sizeof(uidl), "list_all");
 }
 
 static void
@@ -443,7 +444,6 @@
 maildrop_imsgev(struct imsgev *iev, int code, struct imsg *imsg)
 {
 	struct session	key, *r;
-	int		uidl = 0;
 
 	switch (code) {
 	case IMSGEV_IMSG:
@@ -470,11 +470,8 @@
 		case IMSG_MAILDROP_LIST:
 			handle_list(r, imsg);
 			break;
-		case IMSG_MAILDROP_UIDLALL:
-			uidl = 1;
-			/* FALLTHROUGH */
 		case IMSG_MAILDROP_LISTALL:
-			handle_list_all(r, imsg, uidl);
+			handle_list_all(r, imsg);
 			break;
 		case IMSG_MAILDROP_UPDATE:
 			handle_update(r, imsg);
@@ -602,36 +599,28 @@
 	io_set_write(&s->io);
 }
 
-/* DELEted msg's hash and sz will be zero, ignore them */
+/* List terminal is indicated by hash being empty string or sz = 0 */
 static void
-handle_list_all(struct session *s, struct imsg *imsg, int uidl)
+handle_list_all(struct session *s, struct imsg *imsg)
 {
-	char 	*nhash = NULL;
-	size_t	datalen, i, item_sz, j, nitems, *nsz = NULL;
+	struct list_res	*res = imsg->data;
 
-	datalen = imsg->hdr.len - sizeof(imsg->hdr);
-	item_sz = (uidl) ? SHA1_DIGEST_STRING_LENGTH : sizeof(size_t);
-	nitems = datalen / item_sz;
-	if (uidl)
-		nhash = imsg->data;
+	if (res->uidl)
+		if (strlen(res->u.hash))
+			session_reply(s, "%s", res->u.hash);
+		else 
+			goto end;
 	else
-		nsz = imsg->data;
+		if (res->u.sz)
+			session_reply(s, "%zu", res->u.sz);
+		else
+			goto end;
 
-	session_reply(s, "+OK");
-	for (i = 0; i < nitems; i++) {
-		if (uidl) {
-			j = i * SHA1_DIGEST_STRING_LENGTH;
-			if (nhash[j])
-				session_reply(s, "%zu %s", i + 1, nhash + j);
-		} else {
-			if (nsz[i])
-				session_reply(s, "%zu %zu", i + 1, nsz[i]);
-		}
-	}
-
+	return;
+end:
 	session_reply(s, ".");
 	io_set_write(&s->io);
-
+	io_resume(&s->io, IO_PAUSE_IN);
 }
 
 static void