From 9a76381d5a868d57a9f4e557a21c7e6a9dcae516 Mon Sep 17 00:00:00 2001 From: Sunil Nimmagadda Date: Tue, 1 Apr 2014 16:14:49 +0500 Subject: 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 | 85 +++++++++++++++++++++++--------------------------------------- pop3d.h | 1 - session.c | 53 ++++++++++++++++----------------------- 3 files changed, 53 insertions(+), 86 deletions(-) diff --git a/maildrop.c b/maildrop.c index 634fa3f..ce242f9 100644 --- a/maildrop.c +++ b/maildrop.c @@ -38,9 +38,8 @@ static void retr(struct imsgev *, struct imsg *, struct m_backend *); 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 @@ static void 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 @@ session_imsgev(struct imsgev *iev, int code, struct imsg *imsg) 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 @@ list(struct imsgev *iev, struct imsg *imsg, struct m_backend *mb) } 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; - - 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"); + 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.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 @@ do_list(unsigned int idx, size_t *sz, char *hash, size_t hash_sz) 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) { diff --git a/pop3d.h b/pop3d.h index 3035795..15b9b09 100644 --- a/pop3d.h +++ b/pop3d.h @@ -36,7 +36,6 @@ enum imsg_type { IMSG_MAILDROP_RSET, IMSG_MAILDROP_LIST, IMSG_MAILDROP_LISTALL, - IMSG_MAILDROP_UIDLALL, IMSG_MAILDROP_UPDATE }; diff --git a/session.c b/session.c index 77402a3..a042f58 100644 --- a/session.c +++ b/session.c @@ -85,7 +85,7 @@ static void handle_init(struct session *, struct imsg *); 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 @@ trans_command(struct session *s, int cmd, char *args) 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 @@ static void 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 @@ maildrop_imsgev(struct imsgev *iev, int code, struct imsg *imsg) 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 @@ handle_list(struct session *s, struct imsg *imsg) 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; - - 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]); - } - } + if (res->u.sz) + session_reply(s, "%zu", res->u.sz); + else + goto end; + return; +end: session_reply(s, "."); io_set_write(&s->io); - + io_resume(&s->io, IO_PAUSE_IN); } static void -- cgit v1.2.3