Skip to content

Commit

Permalink
net_imap: Truly parallelize remote LIST command.
Browse files Browse the repository at this point in the history
The LIST command for remote mailboxes was set up
using the parallel framework, but the client
was set up synchronously before a job was created
for it, which was rather silly as TCP and IMAP setup
do not take a trivial amount of time. This is now
moved to inside the job itself, and the LIST response
for client proxies no longer has serial bottlenecks.
  • Loading branch information
InterLinked1 committed Jul 15, 2023
1 parent c23bd05 commit fc58472
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 15 deletions.
2 changes: 0 additions & 2 deletions nets/net_imap/imap_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,6 @@ int imap_poll(struct imap_session *imap, int ms, struct imap_client **clientout)
goto cleanup;
}

bbs_debug(5, "Polling %lu fd%s for IMAP session %p\n", numfds, ESS(numfds), imap);

for (;;) {
int pres, i = 0;
pfds[i].events = POLLIN;
Expand Down
48 changes: 35 additions & 13 deletions nets/net_imap/imap_client_list.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,12 +233,23 @@ static int remote_list(struct imap_client *client, struct list_command *lcmd, co
}

struct remote_list_info {
struct imap_client *client;
struct list_command *lcmd;
const char *prefix;
struct imap_session *imap;
char *server;
char data[];
};

static void remote_list_destroy(void *data)
{
struct remote_list_info *r = data;
if (!strlen_zero(r->server)) {
bbs_memzero(r->server, strlen(r->server)); /* Contains password */
}
free(r->server);
free(r);
}

static void *remote_list_dup(void *data)
{
size_t prefixlen;
Expand All @@ -252,26 +263,40 @@ static void *remote_list_dup(void *data)
}
strcpy(r->data, orig->prefix); /* Safe */
r->prefix = r->data;
r->client = orig->client;
r->lcmd = orig->lcmd;
r->imap = orig->imap;

/* Allocate this separately, so that we can destroy it securely */
r->server = strdup(orig->server);
if (ALLOC_FAILURE(r->server)) {
free(r);
return NULL;
}
return r;
}

static int remote_list_cb(void *data)
{
struct remote_list_info *r = data;
struct imap_client *client = imap_client_get_by_url(r->imap, r->prefix, r->server);
bbs_memzero(r->server, strlen(r->server)); /* Contains password */
/* Marshall arguments and execute */
return remote_list(r->client, r->lcmd, r->prefix);
return remote_list(client, r->lcmd, r->prefix);
}

static int remote_list_parallel(struct imap_parallel *p, const char *restrict prefix, struct imap_client *client, struct list_command *lcmd)
static int remote_list_parallel(struct imap_parallel *p, const char *restrict prefix, struct list_command *lcmd, struct imap_session *imap, const char *server)
{
struct remote_list_info rinfo; /* No memset needed */

rinfo.client = client;
rinfo.lcmd = lcmd;
rinfo.prefix = prefix;
return imap_client_parallel_schedule_task(p, prefix, &rinfo, remote_list_cb, remote_list_dup, free);
rinfo.imap = imap;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-qual"
/* This variable will not be modified, but since the dynamic version allocates and frees it, the type cannot be const */
rinfo.server = (char*) server;
#pragma GCC diagnostic pop
return imap_client_parallel_schedule_task(p, prefix, &rinfo, remote_list_cb, remote_list_dup, remote_list_destroy);
}

/*! \brief Mutex to prevent recursion */
Expand Down Expand Up @@ -323,7 +348,6 @@ int list_virtual(struct imap_session *imap, struct list_command *lcmd)
/* Note that we cache all the directories on all servers at once, since we truncate the file. */
while ((fgets(line, sizeof(line), fp))) {
char *prefix, *server;
struct imap_client *client;

l++;
server = line;
Expand All @@ -332,12 +356,10 @@ int list_virtual(struct imap_session *imap, struct list_command *lcmd)
continue; /* Skip commented lines */
}

client = imap_client_get_by_url(imap, prefix, server);
bbs_memzero(server, strlen(server)); /* Contains password */
if (!client) {
continue;
}
remote_list_parallel(&p, prefix, client, lcmd);
/* We don't actually create the client here,
* since TCP and IMAP setup time takes a while,
* we do it inside the job itself! */
remote_list_parallel(&p, prefix, lcmd, imap, server);
}
fclose(fp);

Expand Down

0 comments on commit fc58472

Please sign in to comment.