Skip to content

Commit 438caae

Browse files
committed
net_imap: Skip generate_mailbox_name for exclusive proxying sessions.
When sending untagged FETCH, EXISTS, etc. responses, we call generate_mailbox_name to generate the name of a mailbox as it would appear for a user (to handle shared/public mailboxes that may have different names for different users). If a user has a lot of exclusive proxying connections, we generate the mailbox name for that user each loop iteration, but then when we call imap_notify_applicable, the answer will be "no" because exclusively proxying sessions don't create NOTIFY watches locally. As an optimization, we can therefore simply skip that session entirely if it's exclusively proxying. Also indicate in the "imap sessions" CLI command if a session is exclusively proxying. Previously the output reported "No" since imap->client is not set, but this is incorrect. We now use the dedicated flag to distinguish between exclusively proxying sessions and normal sessions that just happen to have a proxying client in the foreground. LBBS-140 #close
1 parent 6cb9fa0 commit 438caae

3 files changed

Lines changed: 20 additions & 1 deletion

File tree

nets/net_imap.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ static int cli_imap_sessions(struct bbs_cli_args *a)
260260
}
261261
}
262262
bbs_dprintf(a->fdout, "%4u %14p %4s %7s %11s %-28s %s\n",
263-
imap->node->id, imap, BBS_YN(imap->idle), imap->client ? "Yes" : "No", S_IF(mbox_name), S_IF(imap->folder), S_IF(imap->clientid));
263+
imap->node->id, imap, BBS_YN(imap->idle), imap->exclusiveproxy ? "Excl." : imap->client ? "Yes" : "No", S_IF(mbox_name), S_IF(imap->folder), S_IF(imap->clientid));
264264
}
265265
RWLIST_UNLOCK(&sessions);
266266
return 0;
@@ -502,6 +502,9 @@ void send_untagged_fetch(struct imap_session *imap, const char *maildir, int seq
502502
if (s == imap) { /* Skip if the update was caused by the client. The STORE handler already sent a response to this client if needed. */
503503
continue;
504504
}
505+
if (s->exclusiveproxy) {
506+
continue; /* Skip if this IMAP session is exclusively proxying */
507+
}
505508
/* imap->folder is maybe not the same name for s.
506509
* We convert the maildir path to the name for s, though this is a little bit roundabout.
507510
* Would be easier if generate_status could accept a maildir as well instead of just a name.
@@ -559,6 +562,9 @@ static void send_untagged_expunge(struct bbs_node *node, struct mailbox *mbox, c
559562
if (s->node == node && silent) {
560563
continue;
561564
}
565+
if (s->exclusiveproxy) {
566+
continue; /* Skip if this IMAP session is exclusively proxying */
567+
}
562568
/* We can't pass the mailbox name into send_untagged_expunge anyways,
563569
* because mailbox names might be different for different users (e.g. Other Users) */
564570
if (generate_mailbox_name(s, maildir, mboxname, sizeof(mboxname))) {
@@ -637,6 +643,10 @@ static void send_untagged_exists(struct bbs_node *node, struct mailbox *mbox, co
637643
char mboxname[256];
638644
const char *fetchargs = NULL;
639645

646+
if (s->exclusiveproxy) {
647+
continue; /* Skip if this IMAP session is exclusively proxying */
648+
}
649+
640650
if (generate_mailbox_name(s, maildir, mboxname, sizeof(mboxname))) {
641651
continue;
642652
}
@@ -715,6 +725,9 @@ static void send_untagged_list(struct bbs_node *node, enum mailbox_event_type ty
715725
/* RFC 5465 Section 5: avoid notifying client if this was caused by that client */
716726
continue;
717727
}
728+
if (s->exclusiveproxy) {
729+
continue; /* Skip if this IMAP session is exclusively proxying */
730+
}
718731

719732
/* Mailbox names could be different for different users, so need to do per session, not just once */
720733
if (generate_mailbox_name(s, maildir, newdir, sizeof(newdir))) {
@@ -767,6 +780,9 @@ static void send_untagged_uidvalidity(struct mailbox *mbox, const char *maildir,
767780
/* Notify anyone watching this mailbox, specifically the INBOX. */
768781
RWLIST_RDLOCK(&sessions);
769782
RWLIST_TRAVERSE(&sessions, s, entry) {
783+
if (s->exclusiveproxy) {
784+
continue; /* Skip if this IMAP session is exclusively proxying */
785+
}
770786
if (s->mbox != mbox || strcmp(s->dir, maildir)) {
771787
continue;
772788
}

nets/net_imap/imap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ struct imap_session {
9090
unsigned int innew:1; /* So we can use the same callback for both new and cur */
9191
unsigned int readonly:1; /* SELECT vs EXAMINE */
9292
unsigned int inauth:1;
93+
unsigned int exclusiveproxy:1; /* Whether this connection is exclusively proxying to another IMAP server */
9394
unsigned int idle:1; /* Whether IDLE is active */
9495
unsigned int dnd:1; /* Do Not Disturb: Whether client is executing a FETCH, STORE, or SEARCH command (EXPUNGE responses are not allowed). XXX Unused? */
9596
unsigned int pending:1; /* Delayed output is pending in pfd pipe */

nets/net_imap/imap_client.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,6 +1240,7 @@ int imap_proxy_remote_mailbox_exclusively(struct imap_session *imap, const char
12401240
}
12411241
}
12421242

1243+
imap->exclusiveproxy = 1;
12431244
bbs_verb(4, "Beginning exclusively proxied session with remote mailbox '%s'\n", name);
12441245

12451246
/* The client expects a CAPABILITY response after authenticating successfully,
@@ -1312,6 +1313,7 @@ int imap_proxy_remote_mailbox_exclusively(struct imap_session *imap, const char
13121313
}
13131314

13141315
cleanup:
1316+
imap->exclusiveproxy = 0;
13151317
imap_client_unlink(imap, client);
13161318
return -1;
13171319
}

0 commit comments

Comments
 (0)