* For certain IMAP outputs (such as BODYSTRUCTURE), buffer all output until
authorArt Cancro <ajc@citadel.org>
Thu, 6 Nov 2003 04:25:30 +0000 (04:25 +0000)
committerArt Cancro <ajc@citadel.org>
Thu, 6 Nov 2003 04:25:30 +0000 (04:25 +0000)
  we've got the whole thing, then spew it all at once to avoid lots of
  tiny TCP packets.
* New API calls buffer_output() (to start buffering) and unbuffer_output()
  (to dump the buffer and stop buffering) are available to do this.

citadel/ChangeLog
citadel/imap_fetch.c
citadel/server.h
citadel/sysdep.c
citadel/sysdep_decls.h
citadel/user_ops.c

index 0c152ba717b51ad3aa564e7714a5794611c91e67..13d0a4d62955019181bdf757043eb6da0fb7d2e3 100644 (file)
@@ -1,4 +1,11 @@
  $Log$
+ Revision 611.1  2003/11/06 04:25:30  ajc
+ * For certain IMAP outputs (such as BODYSTRUCTURE), buffer all output until
+   we've got the whole thing, then spew it all at once to avoid lots of
+   tiny TCP packets.
+ * New API calls buffer_output() (to start buffering) and unbuffer_output()
+   (to dump the buffer and stop buffering) are available to do this.
+
  Revision 611.0  2003/10/21 04:20:41  ajc
  * THIS IS 6.11
 
@@ -5055,3 +5062,4 @@ Sat Jul 11 00:20:48 EDT 1998 Nathan Bryant <bryant@cs.usm.maine.edu>
 
 Fri Jul 10 1998 Art Cancro <ajc@uncensored.citadel.org>
        * Initial CVS import
+
index 0c9af927b584b066a49ecc4a75386c8a0b098c16..d3254473e71a134cf95693e59a7a265f75a86e45 100644 (file)
@@ -773,14 +773,20 @@ void imap_do_fetch_msg(int seq, struct CtdlMessage *msg,
                                        1, msg);
                }
                else if (!strcasecmp(itemlist[i], "BODYSTRUCTURE")) {
+                       buffer_output();
                        imap_fetch_bodystructure(IMAP->msgids[seq-1],
                                        itemlist[i], msg);
+                       unbuffer_output();
                }
                else if (!strcasecmp(itemlist[i], "ENVELOPE")) {
+                       buffer_output();
                        imap_fetch_envelope(IMAP->msgids[seq-1], msg);
+                       unbuffer_output();
                }
                else if (!strcasecmp(itemlist[i], "FLAGS")) {
+                       buffer_output();
                        imap_fetch_flags(seq-1);
+                       unbuffer_output();
                }
                else if (!strcasecmp(itemlist[i], "INTERNALDATE")) {
                        imap_fetch_internaldate(msg);
index e8cebf98d80f921339f2607abac63f380fb18112..4b9a3ffe8ca09d2d1e419a4e548e98703abfdf0a 100644 (file)
@@ -130,6 +130,10 @@ struct CitContext {
        int redirect_ssl;
 #endif
 
+       int buffering;
+       char *output_buffer;    /* hold output for one big dump */
+       int buffer_len;
+
        /* A linked list of all express messages sent to us. */
        struct ExpressMessage *FirstExpressMessage;
        int disable_exp;        /* Set to 1 to disable incoming pages */
index 988acd9dc8ae5fffa6d11248999d39b38f71e8b2..9ec508e087021882395e0b09ecb894e5d02796f9 100644 (file)
@@ -484,6 +484,33 @@ DONE:      ++num_sessions;
 }
 
 
+/*
+ * buffer_output() ... tell client_write to buffer all output until
+ *                     instructed to dump it all out later
+ */
+void buffer_output(void) {
+       if (CC->buffering == 0) {
+               CC->buffering = 1;
+               CC->buffer_len = 0;
+               CC->output_buffer = mallok(SIZ);
+       }
+}
+
+/*
+ * unbuffer_output()  ...  dump out all that output we've been buffering.
+ */
+void unbuffer_output(void) {
+       if (CC->buffering == 1) {
+               CC->buffering = 0;
+               client_write(CC->output_buffer, CC->buffer_len);
+               phree(CC->output_buffer);
+               CC->output_buffer = NULL;
+               CC->buffer_len = 0;
+       }
+}
+
+
+
 /*
  * client_write()   ...    Send binary data to the client.
  */
@@ -492,6 +519,7 @@ void client_write(char *buf, int nbytes)
        int bytes_written = 0;
        int retval;
        int sock;
+       int old_buffer_len = 0;
 
        if (CC->redirect_fp != NULL) {
                fwrite(buf, nbytes, 1, CC->redirect_fp);
@@ -505,6 +533,17 @@ void client_write(char *buf, int nbytes)
                sock = CC->client_socket;
        }
 
+       /* If we're buffering for later, do that now. */
+       if (CC->buffering) {
+               old_buffer_len = CC->buffer_len;
+               CC->buffer_len += nbytes;
+               CC->output_buffer = reallok(CC->output_buffer, CC->buffer_len);
+               memcpy(&CC->output_buffer[old_buffer_len], buf, nbytes);
+               return;
+       }
+
+       /* Ok, at this point we're not buffering.  Go ahead and write. */
+
 #ifdef HAVE_OPENSSL
        if (CC->redirect_ssl) {
                client_write_ssl(buf, nbytes);
index 406e8f68924cbcfb7747663bd62988cacdf6340a..c7870e63e55e39d16658406c498d0f92aa1ed943 100644 (file)
@@ -20,6 +20,8 @@ int ig_uds_server(char *sockpath, int queue_len);
 inline struct CitContext *MyContext (void);
 struct CitContext *CreateNewContext (void);
 void InitMyContext (struct CitContext *con);
+void buffer_output(void);
+void unbuffer_output(void);
 void client_write (char *buf, int nbytes);
 int client_read_to (char *buf, int bytes, int timeout);
 int client_read (char *buf, int bytes);
index 69f45a64dfd53fddecfda227608e22b17c7d4404..93957ce2938a65a651a5dd3193a9e7e39ec521f6 100644 (file)
@@ -532,6 +532,11 @@ void logout(struct CitContext *who)
 
        /* Do modular stuff... */
        PerformSessionHooks(EVT_LOGOUT);
+
+       /* Free any output buffers */
+       if (who->output_buffer != NULL) {
+               unbuffer_output();
+       }
 }
 
 #ifdef ENABLE_CHKPWD