help-gsasl
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] Improve application data throughput


From: Enrico Scholz
Subject: [PATCH] Improve application data throughput
Date: Wed, 14 Oct 2009 09:59:58 +0200

This patch allows application data from the remote site to be read in
larger hunks.  Old code read only one character and passed this to the
gnutls and gsasl methods. This results (for STARTTLS) in long

| write(1, "X-Bugzilla-Reason: Reporter\r\n"..., 29) = 29
| poll([{fd=0, events=POLLIN}, {fd=3, events=POLLIN}], 2, -1) = 1 ([{fd=3, 
revents=POLLIN}])
| ... [80 lines] ...
| poll([{fd=0, events=POLLIN}, {fd=3, events=POLLIN}], 2, -1) = 1 ([{fd=3, 
revents=POLLIN}])

operations where gnutls_record_recv() was called > 80 times which lead
to a high CPU load.  As I tunnel my IMAP connection with 'gsasl' this is
an important issue for me.

This patch allocates a larger buffer so that gnutls_record_recv() is
called only once per TLS record.

There was added an overflow check too which assumes 1MiB as maximum size
for a GSASL message.   This value is a blind guess; please adjust when
specifications require a higher value.

I see only one problem with the patch:  when remote site stops sending
in the middle of a TLS record, the 'gsasl' application will hang in
gnutls_record_recv() forever.

Signed-off-by: Enrico Scholz <address@hidden>
---
 src/gsasl.c |   17 ++++++++++++-----
 1 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/src/gsasl.c b/src/gsasl.c
index b65bd79..5bcbc18 100644
--- a/src/gsasl.c
+++ b/src/gsasl.c
@@ -30,6 +30,8 @@ bool using_tls = false;
 #endif
 
 #define MAX_LINE_LENGTH BUFSIZ
+#define INPUT_BUFSIZE  BUFSIZ
+#define MAX_INPUT_SIZE 0x100000
 
 struct gengetopt_args_info args_info;
 int sockfd = 0;
@@ -795,26 +797,31 @@ main (int argc, char *argv[])
                  ssize_t len;
                  char *tmp;
 
-                 tmp = realloc (sockbuf, sockpos + 1);
+                 tmp = realloc (sockbuf, sockpos + INPUT_BUFSIZE);
                  if (!tmp)
                    error (EXIT_FAILURE, errno, "realloc");
                  sockbuf = tmp;
 
 #ifdef HAVE_LIBGNUTLS
                  if (using_tls)
-                   len = gnutls_record_recv (session, &sockbuf[sockpos], 1);
+                   len = gnutls_record_recv (session, &sockbuf[sockpos],
+                                             INPUT_BUFSIZE);
                  else
 #endif
-                   len = recv (sockfd, &sockbuf[sockpos], 1, 0);
+                   len = recv (sockfd, &sockbuf[sockpos], INPUT_BUFSIZE, 0);
                  if (len <= 0)
                    break;
 
-                 sockpos++;
+                 sockpos += len;
 
                  res = gsasl_decode (xctx, sockbuf, sockpos,
                                      &out, &output_len);
-                 if (res == GSASL_NEEDS_MORE)
+                 if (res == GSASL_NEEDS_MORE) {
+                   if (sockpos > MAX_INPUT_SIZE)
+                     error (EXIT_FAILURE, 0,
+                            _("SASL record too large: %zu\n"), sockpos);
                    continue;
+                 }
                  if (res != GSASL_OK)
                    break;
 
-- 
1.6.2.5





reply via email to

[Prev in Thread] Current Thread [Next in Thread]