struct imclient, outbuf

Patrick Welche prlw1 at newn.cam.ac.uk
Fri Apr 4 14:42:25 EST 2003


In trying to figure out what is going on in imclient_write, I simplified
struct imclient, and moved from pointers to indices - a matter of taste,
I know, but it seems the reply buffer is handled that way..
(One could also s/writelen/imclient->outlen/g)

Cheers,

Patrick


Index: imclient.c
===================================================================
RCS file: /cvs/src/cyrus/lib/imclient.c,v
retrieving revision 1.77
diff -u -r1.77 imclient.c
--- imclient.c	13 Feb 2003 20:15:40 -0000	1.77
+++ imclient.c	4 Apr 2003 19:37:33 -0000
@@ -120,9 +120,7 @@
 
     /* Data to be output to server */
     char outbuf[IMCLIENT_BUFSIZE];
-    char *outptr;
-    size_t outleft;
-    char *outstart;
+    size_t outlen;
 
     /* Replies being received from server */
     char *replybuf;
@@ -263,8 +261,10 @@
     (*imclient)->saslconn = NULL;
     (*imclient)->saslcompleted = 0;
     (*imclient)->servername = xstrdup(hp->h_name);
-    (*imclient)->outptr = (*imclient)->outstart = (*imclient)->outbuf;
-    (*imclient)->outleft = (*imclient)->maxplain = sizeof((*imclient)->outbuf);
+    (*imclient)->outlen = 0;
+    (*imclient)->replylen = 0;
+    (*imclient)->alloc_replybuf = 0;
+	(*imclient)->maxplain = sizeof((*imclient)->outbuf);
     (*imclient)->interact_results = NULL;
     imclient_addcallback(*imclient,
 		 "", 0, (imclient_proc_t *) 0, (void *)0,
@@ -626,41 +625,50 @@
  */
 void imclient_write(struct imclient *imclient, const char *s, size_t len)
 {
+	size_t outleft;
+
     assert(imclient);
     assert(s);
     
-    /* If no data pending for output, reset the buffer */
-    if (imclient->outptr == imclient->outstart) {
-	imclient->outstart = imclient->outptr = imclient->outbuf;
-	imclient->outleft = imclient->maxplain;
-    }
-
+	outleft = imclient->maxplain - imclient->outlen;
     /* While we don't have room to buffer all the output */
-    while (len > imclient->outleft) {
-	/* Copy as much data as will fit in output buffer */
-	memcpy(imclient->outptr, s, imclient->outleft);
-	imclient->outptr += imclient->outleft;
-	s += imclient->outleft;
-	len -= imclient->outleft;
-	imclient->outleft = 0;
-
-	/* Process events until output buffer is flushed */
-	while (imclient->outptr != imclient->outstart) {
-	    imclient_processoneevent(imclient);
-	}
-
-	/* Reset the buffer */
-	imclient->outstart = imclient->outptr = imclient->outbuf;
-	imclient->outleft = imclient->maxplain;
+    while (len > outleft) {
+		/* Copy as much data as will fit in output buffer */
+		memcpy(imclient->outbuf+imclient->outlen, s, outleft);
+		imclient->outlen += outleft;
+		s += outleft;
+		len -= outleft;
+
+		/* Process events until output buffer is flushed */
+		while (imclient->outlen) {
+	    	imclient_processoneevent(imclient);
+		} /* Should only be called once. If not, then not all plain text
+		   * was successfully writen in non sasl case
+           */
+		outleft = imclient->maxplain; /*  - imclient->outlen; == 0 */
     }
 
     /* Copy remaining data to output buffer */
-    memcpy(imclient->outptr, s, len);
-    imclient->outptr += len;
-    imclient->outleft -= len;
+    memcpy(imclient->outbuf+imclient->outlen, s, len);
+    imclient->outlen += len;
 }
 
 /*
+ * http://bugzilla.andrew.cmu.edu/show_bug.cgi?id=333
+ *
+ * Opened: 2000-10-13 00:02
+ * 
+ * imclient doesn't correctly parse literals.  this will bite any
+ * serious imclient application that consistently fetches things with
+ * literals.
+ * 
+ * imclient.c, around line 730, uses the variable 'len' in a place
+ * where it clearly isn't applicable.  this is the heart of the bug,
+ * but we need to fix it so that literals that don't end lines are
+ * still handled correctly.
+ */
+
+/*
  * On the connection 'imclient', handle the input 'buf' of size 'len'
  * from the server.  Invoke callbacks as appropriate.
  */
@@ -1006,13 +1014,13 @@
     assert(imclient);
 
     for (;;) {
-	writelen = imclient->outptr - imclient->outstart;
+	writelen = imclient->outlen;
 
 	if ((imclient->saslcompleted==1) && (writelen>0)) {
 	    unsigned int cryptlen=0;
 	    const char *cryptptr=NULL;
 
-	  if (sasl_encode(imclient->saslconn, imclient->outstart, writelen,
+	  if (sasl_encode(imclient->saslconn, imclient->outbuf, writelen,
 			  &cryptptr,&cryptlen)!=SASL_OK)
 	  {
 	      /* XXX encoding error */
@@ -1032,7 +1040,7 @@
 #endif /* HAVE_SSL */
 	  	  
 	  if (n > 0) {	    
-	    imclient->outstart += writelen;
+	    imclient->outlen = 0; /* what if cryptlen != n ? */
 	    return;
 	  }
 
@@ -1047,17 +1055,17 @@
 #ifdef HAVE_SSL
 	  if (imclient->tls_on==1)
 	  {
-	    n = SSL_write(imclient->tls_conn, imclient->outstart, writelen);
+	    n = SSL_write(imclient->tls_conn, imclient->outbuf, writelen);
 	  } else {
-	    n = write(imclient->fd, imclient->outstart, writelen);
+	    n = write(imclient->fd, imclient->outbuf, writelen);
 	  }
 #else  /* HAVE_SSL */
-	  n = write(imclient->fd, imclient->outstart, writelen);
+	  n = write(imclient->fd, imclient->outbuf, writelen);
 #endif /* HAVE_SSL */
 
 
 	    if (n > 0) {
-		imclient->outstart += n;
+		imclient->outlen -= n;
 		return;
 	    }
 	    /* XXX Also EPIPE & the like? */




More information about the Info-cyrus mailing list