commit-mailutils
[Top][All Lists]
Advanced

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

[SCM] GNU Mailutils branch, stream-cleanup, updated. rel-2_1-111-g286657


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, stream-cleanup, updated. rel-2_1-111-g286657e
Date: Sun, 29 Aug 2010 21:09:23 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Mailutils".

http://git.savannah.gnu.org/cgit/mailutils.git/commit/?id=286657e78705d061fc68c000cd3823608c522c04

The branch, stream-cleanup has been updated
       via  286657e78705d061fc68c000cd3823608c522c04 (commit)
       via  f4e67b5e949b324617b7c737d63455f0c0da1371 (commit)
      from  f1625c353026c160c8db18ac9a4bd3bd35df150c (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 286657e78705d061fc68c000cd3823608c522c04
Author: Sergey Poznyakoff <address@hidden>
Date:   Mon Aug 30 00:08:31 2010 +0300

    Re-implement server TLS support.
    
    STLS in pop3d is already working.
    
    * include/mailutils/sys/tls-stream.h: New header.
    * include/mailutils/tls.h (mu_tls_stream_create)
    (mu_tls_stream_create_client)
    (mu_tls_stream_create_client_from_tcp): Remove.
    (mu_tls_server_stream_create, mu_tls_client_stream_create): New
    protos.
    * libmu_auth/tls.c: Rewrite.
    
    * imap4d/util.c: Use mu_tls_server_stream_create.
    * libproto/pop/mbox.c: Use mu_tls_server_stream_create/
    mu_tls_client_stream_create.
    * libproto/pop/pop3_stls.c: Use mu_tls_client_stream_create.
    * libproto/imap/folder.c: Use mu_tls_client_stream_create.
    
    * pop3d/capa.c (pop3d_capa): CAPA is allowed in both states.
    * pop3d/extra.c (pop3d_setio): Rewrite.

commit f4e67b5e949b324617b7c737d63455f0c0da1371
Author: Sergey Poznyakoff <address@hidden>
Date:   Sun Aug 29 18:01:27 2010 +0300

    amd, pop3d: bugfixes.
    
    * mailbox/amd.c (amd_body_stream_readdelim): Fix the logic.
    * mailbox/message.c (_message_stream_seek): Fix seeks in
    backward direction.
    * pop3d/top.c: Fix output of the body.

-----------------------------------------------------------------------

Summary of changes:
 imap4d/util.c                                      |    2 +-
 include/mailutils/sys/Makefile.am                  |    1 +
 .../sys/{message_stream.h => tls-stream.h}         |   53 ++-
 include/mailutils/tls.h                            |   11 +-
 libmu_auth/tls.c                                   |  541 +++++++++++---------
 libproto/imap/folder.c                             |    6 +-
 libproto/pop/mbox.c                                |   14 +-
 libproto/pop/pop3_stls.c                           |    4 +-
 mailbox/amd.c                                      |   36 +-
 mailbox/message.c                                  |   12 +-
 pop3d/capa.c                                       |    3 -
 pop3d/extra.c                                      |   28 +-
 pop3d/top.c                                        |    6 +-
 13 files changed, 393 insertions(+), 324 deletions(-)
 copy include/mailutils/sys/{message_stream.h => tls-stream.h} (53%)

diff --git a/imap4d/util.c b/imap4d/util.c
index 26a1a8d..2947823 100644
--- a/imap4d/util.c
+++ b/imap4d/util.c
@@ -893,7 +893,7 @@ imap4d_init_tls_server ()
   mu_stream_t stream;
   int rc;
  
-  rc = mu_tls_stream_create (&stream, istream, ostream, 0);
+  rc = mu_tls_server_stream_create (&stream, istream, ostream, 0);
   if (rc)
     return 0;
 
diff --git a/include/mailutils/sys/Makefile.am 
b/include/mailutils/sys/Makefile.am
index 79d94cd..34f995b 100644
--- a/include/mailutils/sys/Makefile.am
+++ b/include/mailutils/sys/Makefile.am
@@ -34,5 +34,6 @@ sysinclude_HEADERS = \
  streamref.h\
  streamtrans.h\
  stream.h\
+ tls-stream.h\
  pop3.h\
  nntp.h
diff --git a/include/mailutils/sys/message_stream.h 
b/include/mailutils/sys/tls-stream.h
similarity index 53%
copy from include/mailutils/sys/message_stream.h
copy to include/mailutils/sys/tls-stream.h
index 381e7c9..8a903b9 100644
--- a/include/mailutils/sys/message_stream.h
+++ b/include/mailutils/sys/tls-stream.h
@@ -1,5 +1,5 @@
 /* GNU Mailutils -- a suite of utilities for electronic mail
-   Copyright (C) 2009 Free Software Foundation, Inc.
+   Copyright (C) 2010 Free Software Foundation, Inc.
 
    This library is free software; you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
@@ -14,35 +14,44 @@
    You should have received a copy of the GNU Lesser General Public License
    along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
 
-#ifndef _MAILUTILS_SYS_MESSAGE_STREAM_H
-#define _MAILUTILS_SYS_MESSAGE_STREAM_H
+#ifndef _MAILUTILS_SYS_TLS_STREAM_H
+# define _MAILUTILS_SYS_TLS_STREAM_H
 
-#include <mailutils/sys/stream.h>
+# include <mailutils/types.h>
+# include <mailutils/stream.h>
+# include <mailutils/sys/stream.h>
 
-struct _mu_message_stream
+enum _mu_tls_stream_state
+  {
+    state_init,
+    state_open,
+    state_closed,
+    state_destroyed
+  };
+
+struct _mu_tls_io_stream
 {
   struct _mu_stream stream;
-  mu_stream_t transport;  /* Actual stream */
-  mu_off_t offset;
-
-  char *envelope;
-  size_t envelope_length; 
-  char *from;
-  char *date;
-  size_t mark_offset;  /* Offset of the header separator */
-  size_t mark_length;  /* Length of the header separator (not counting the
-                         newline) */
-  mu_off_t body_start;
-  mu_off_t body_end;
+  mu_stream_t transport;
+  struct _mu_tls_stream *up;
 };
 
-struct _mu_body_stream
+struct _mu_tls_stream
 {
   struct _mu_stream stream;
-  mu_off_t offset;
-  struct _mu_message_stream *message_stream;
+  enum _mu_tls_stream_state state;
+  gnutls_session session;
+  int tls_err;
+  mu_stream_t transport[2];
 };
 
-#endif
-
+struct _mu_tls_stream_s
+{
+  struct _mu_stream stream;
+  enum _mu_tls_stream_state state;
+  gnutls_session session;
+  int tls_err;
+  mu_stream_t transport;
+};
 
+#endif
diff --git a/include/mailutils/tls.h b/include/mailutils/tls.h
index 9848f82..856e474 100644
--- a/include/mailutils/tls.h
+++ b/include/mailutils/tls.h
@@ -36,15 +36,12 @@ struct mu_tls_module_config
 
 extern int mu_tls_module_init (enum mu_gocs_op, void *);
 
-extern int mu_tls_stream_create (mu_stream_t *stream, 
-                                mu_stream_t strin, mu_stream_t strout,
-                                int flags);
-extern int mu_tls_stream_create_client (mu_stream_t *stream,
+extern int mu_tls_server_stream_create (mu_stream_t *stream, 
+                                       mu_stream_t strin, mu_stream_t strout,
+                                       int flags);
+extern int mu_tls_client_stream_create (mu_stream_t *stream,
                                        mu_stream_t strin, mu_stream_t strout,
                                        int flags);
-extern int mu_tls_stream_create_client_from_tcp (mu_stream_t *stream,
-                                                mu_stream_t tcp_str,
-                                                int flags);
 
 extern int mu_check_tls_environment (void);
 extern int mu_init_tls_libs (void);
diff --git a/libmu_auth/tls.c b/libmu_auth/tls.c
index 5ce9bc7..7dff478 100644
--- a/libmu_auth/tls.c
+++ b/libmu_auth/tls.c
@@ -35,8 +35,6 @@
 #include <mailutils/stream.h>
 #include <mailutils/errno.h>
 
-#include <lbuf.h>
-
 struct mu_tls_module_config mu_tls_module_config = { 1, NULL, NULL, NULL };
   
 int
@@ -48,7 +46,7 @@ mu_tls_module_init (enum mu_gocs_op op, void *data)
       if (data)
        memcpy (&mu_tls_module_config, data, sizeof mu_tls_module_config);
       break;
-
+      
     case mu_gocs_op_flush:
 #ifdef WITH_TLS
       mu_init_tls_libs ();
@@ -61,6 +59,7 @@ mu_tls_module_init (enum mu_gocs_op op, void *data)
 #ifdef WITH_TLS
 
 #include <gnutls/gnutls.h>
+#include <mailutils/sys/tls-stream.h>
 
 #define DH_BITS 768
 
@@ -170,7 +169,7 @@ mu_tls_begin (void *iodata,
   for (i = 0; keywords[i]; i++)
     {
       switch (i)
-      {
+       {
         case 0:
           /*
            *  Send STLS/STARTTLS
@@ -190,10 +189,10 @@ mu_tls_begin (void *iodata,
            }
 
           stream_ctl (iodata, &oldstr, NULL);
-          status = mu_tls_stream_create_client_from_tcp (&newstr, oldstr, 0);
+          status = mu_tls_client_stream_create (&newstr, oldstr, oldstr, 0);
           if (status != 0)
            {
-             mu_error ("mu_tls_begin: mu_tls_stream_create_client_from_tcp 
(0): %s",
+             mu_error ("mu_tls_begin: mu_tls_client_stream_create(0): %s",
                        mu_strerror (status));
              return status;
            }
@@ -228,124 +227,67 @@ mu_tls_begin (void *iodata,
            }
           break;
           
-      default:
-       return 1;
-      }
+       default:
+         return 1;
+       }
     }
   return 0;
 }
-
+
 /* ************************* TLS Stream Support **************************** */
 
-enum tls_stream_state {
-  state_init,
-  state_open,
-  state_closed,
-  state_destroyed
-};
-
-struct _tls_stream {
-  mu_stream_t strin;  /* Input stream */
-  mu_stream_t strout; /* Output stream */ 
-  int last_err;
-  struct _line_buffer *lb;
-  enum tls_stream_state state;
-  gnutls_session session;
-};
-
-
-static void
-_tls_destroy (mu_stream_t stream)
+static int
+_tls_io_close (mu_stream_t stream)
 {
-  struct _tls_stream *s = mu_stream_get_owner (stream);
-  int flags;
+  struct _mu_tls_io_stream *sp = (struct _mu_tls_io_stream *) stream;
   
-  if (x509_cred)
-    gnutls_certificate_free_credentials (x509_cred);
-  if (s->session && s->state == state_closed)
-    {
-      gnutls_deinit (s->session);
-      s->state = state_destroyed;
-    }
-  _auth_lb_destroy (&s->lb);
+  if (!(sp->stream.flags & MU_STREAM_NO_CLOSE))
+    return mu_stream_close (sp->transport);
+  return 0;
+}
 
-  mu_stream_get_flags (stream, &flags);
-  if (!(flags & MU_STREAM_NO_CLOSE))
-    {
-      int same_stream = s->strin == s->strout;
-      mu_stream_destroy (&s->strin, mu_stream_get_owner (s->strin));
-      if (!same_stream)
-       mu_stream_destroy (&s->strout, mu_stream_get_owner (s->strout));
-    }
-  free (s);
+static void
+_tls_io_done (struct _mu_stream *stream)
+{
+  struct _mu_tls_io_stream *sp = (struct _mu_tls_io_stream *) stream;
+  if (!(sp->stream.flags & MU_STREAM_NO_CLOSE))
+    mu_stream_unref (sp->transport);
 }
-    
+
 static int
-_tls_read (mu_stream_t stream, char *optr, size_t osize,
-          mu_off_t offset, size_t *nbytes)
+_tls_io_flush (struct _mu_stream *stream)
 {
-  struct _tls_stream *s = mu_stream_get_owner (stream);
-  int rc;
-  
-  if (!stream || s->state != state_open)
-    return EINVAL;
-  rc = gnutls_record_recv (s->session, optr, osize);
-  if (rc >= 0)
-    {
-      *nbytes = rc;
-      return 0;
-    }
-  s->last_err = rc;
-  return EIO;
+  struct _mu_tls_io_stream *sp = (struct _mu_tls_io_stream *) stream;
+  return mu_stream_flush (sp->transport);
 }
 
 static int
-_tls_readline (mu_stream_t stream, char *optr, size_t osize,
-               mu_off_t offset, size_t *nbytes)
+_tls_io_read (struct _mu_stream *stream, char *buf, size_t bufsize,
+             size_t *pnread)
 {
-  struct _tls_stream *s = mu_stream_get_owner (stream);
+  struct _mu_tls_io_stream *sp = (struct _mu_tls_io_stream *) stream;
   int rc;
-  char *ptr;
-  size_t rdsize;
   
-  if (!stream || s->state != state_open || osize < 2)
+  if (sp->up->state != state_open)
     return EINVAL;
-
-  if (_auth_lb_level (s->lb) == 0)
+  rc = gnutls_record_recv (sp->up->session, buf, bufsize);
+  if (rc >= 0)
     {
-      ptr = optr;
-      rdsize = 0;
-      do
-       {
-         rc = gnutls_record_recv (s->session, ptr + rdsize, osize - rdsize);
-         if (rc < 0)
-           {
-             s->last_err = rc;
-             return EIO;
-           }
-         rdsize += rc;
-       }
-      while (osize > rdsize && rc > 0 && ptr[rdsize-1] != '\n');
-      
-      _auth_lb_grow (s->lb, ptr, rdsize);
+      *pnread = rc;
+      return 0;
     }
-  
-  osize--; /* Allow for terminating zero */
-  rdsize = _auth_lb_readline (s->lb, optr, osize);
-  optr[rdsize] = 0;
-  if (nbytes)
-    *nbytes = rdsize;
-  return 0;
+  sp->up->tls_err = rc;
+  return EIO;
 }
 
 static int
-_tls_write (mu_stream_t stream, const char *iptr, size_t isize,
-           mu_off_t offset, size_t *nbytes)
+_tls_io_write (struct _mu_stream *stream, const char *buf, size_t bufsize,
+           size_t *pnwrite)
 {
-  struct _tls_stream *s = mu_stream_get_owner (stream);
+  struct _mu_tls_io_stream *sp = (struct _mu_tls_io_stream *) stream;
   int rc;
   
-  if (!stream || s->state != state_open)
+  if (sp->up->state != state_open)
     return EINVAL;
 
   /* gnutls_record_send() docs say:
@@ -356,53 +298,103 @@ _tls_write (mu_stream_t stream, const char *iptr, size_t 
isize,
        corrupted and the connection will be terminated. */
     
   do
-    rc = gnutls_record_send (s->session, iptr, isize);
+    rc = gnutls_record_send (sp->up->session, buf, bufsize);
   while (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN);
 
   if (rc < 0)
     {
-      s->last_err = rc;
+      sp->up->tls_err = rc;
       return EIO;
     }
 
-  if (nbytes)
-    *nbytes = rc;
+  *pnwrite = rc;
 
   return 0;
 }
 
 static int
-_tls_flush (mu_stream_t stream)
+_tls_rd_wait (struct _mu_stream *stream, int *pflags, struct timeval *tvp)
 {
-  struct _tls_stream *s = mu_stream_get_owner (stream);
-  return mu_stream_flush (s->strout);
+  struct _mu_tls_io_stream *sp = (struct _mu_tls_io_stream *) stream;
+  int rc = EINVAL;
+  
+  if (*pflags == MU_STREAM_READY_RD)
+    rc = mu_stream_wait (sp->transport, pflags, tvp);
+  return rc;
 }
 
 static int
-_tls_close (mu_stream_t stream)
+_tls_wr_wait (struct _mu_stream *stream, int *pflags, struct timeval *tvp)
 {
-  struct _tls_stream *s = mu_stream_get_owner (stream);
-  int flags;
+  struct _mu_tls_io_stream *sp = (struct _mu_tls_io_stream *) stream;
+  int rc = EINVAL;
   
-  if (s->session && s->state == state_open)
+  if (*pflags == MU_STREAM_READY_WR)
+    rc = mu_stream_wait (sp->transport, pflags, tvp);
+  return rc;
+}
+
+static int
+_tls_io_ioctl (struct _mu_stream *stream, int op, void *arg)
+{
+  struct _mu_tls_io_stream *sp = (struct _mu_tls_io_stream *) stream;
+  mu_transport_t *ptrans;
+
+  switch (op)
+    {
+    case MU_IOCTL_GET_TRANSPORT:
+      if (!arg)
+       return EINVAL;
+      ptrans = arg;
+      ptrans[0] = (mu_transport_t) sp->transport;
+      ptrans[1] = NULL;
+      break;
+
+    default:
+      return EINVAL;
+    }
+  return 0;
+}
+
+static int
+_mu_tls_io_stream_create (mu_stream_t *pstream,
+                         mu_stream_t transport, int flags,
+                         struct _mu_tls_stream *master)
+{
+  struct _mu_tls_io_stream *sp;
+
+  sp = (struct _mu_tls_io_stream *)
+    _mu_stream_create (sizeof (*sp),
+                      flags & (MU_STREAM_RDWR | MU_STREAM_NO_CLOSE));
+  if (!sp)
+    return ENOMEM;
+
+  if (flags & MU_STREAM_READ)
     {
-      gnutls_bye (s->session, GNUTLS_SHUT_RDWR);
-      s->state = state_closed;
+      sp->stream.read = _tls_io_read; 
+      sp->stream.wait = _tls_rd_wait;
+      mu_stream_set_buffer ((mu_stream_t) sp, mu_buffer_full, 1024);
     }
-  
-  mu_stream_get_flags (stream, &flags);
-  if (!(flags & MU_STREAM_NO_CLOSE))
+  else
     {
-      mu_stream_close (s->strin);
-      if (s->strin != s->strout)
-       mu_stream_close (s->strout);
+      sp->stream.write = _tls_io_write;
+      sp->stream.wait = _tls_wr_wait;
+      mu_stream_set_buffer ((mu_stream_t) sp, mu_buffer_line, 1024);
     }
+  sp->stream.flush = _tls_io_flush;
+  sp->stream.close = _tls_io_close;
+  sp->stream.done = _tls_io_done; 
+  sp->stream.ctl = _tls_io_ioctl;
+  /* FIXME:
+     sp->stream.error_string = _tls_error_string;*/
+
+  sp->transport = transport;
+  sp->up = master;
+  *pstream = (mu_stream_t) sp;
   return 0;
 }
 
 
-/* Push & pull functions */
-
 static ssize_t
 _tls_stream_pull (gnutls_transport_ptr fd, void *buf, size_t size)
 {
@@ -424,7 +416,7 @@ _tls_stream_push (gnutls_transport_ptr fd, const void *buf, 
size_t size)
   mu_stream_t stream = fd;
   int rc;
 
-  rc = mu_stream_write (stream, buf, size);
+  rc = mu_stream_write (stream, buf, size, &size);
   if (rc)
     {
       mu_error ("_tls_stream_push: %s", mu_strerror (rc)); /* FIXME */
@@ -435,14 +427,14 @@ _tls_stream_push (gnutls_transport_ptr fd, const void 
*buf, size_t size)
 }
 
 
-
 static int
-_tls_open (mu_stream_t stream)
+_tls_server_open (mu_stream_t stream)
 {
-  struct _tls_stream *s = mu_stream_get_owner (stream);
+  struct _mu_tls_stream *sp = (struct _mu_tls_stream *) stream;
   int rc = 0;
+  mu_transport_t transport[2];
   
-  if (!stream || s->state != state_init)
+  if (!stream || sp->state != state_init)
     return EINVAL;
 
   gnutls_certificate_allocate_credentials (&x509_cred);
@@ -451,40 +443,41 @@ _tls_open (mu_stream_t stream)
     gnutls_certificate_set_x509_trust_file (x509_cred,
                                            mu_tls_module_config.ssl_cafile,
                                            GNUTLS_X509_FMT_PEM);
-
+  
   rc = gnutls_certificate_set_x509_key_file (x509_cred,
                                             mu_tls_module_config.ssl_cert, 
                                             mu_tls_module_config.ssl_key,
                                             GNUTLS_X509_FMT_PEM);
   if (rc < 0)
     {
-      s->last_err = rc;
+      sp->tls_err = rc;
       return EIO;
     }
   
   generate_dh_params ();
   gnutls_certificate_set_dh_params (x509_cred, dh_params);
 
-  s->session = initialize_tls_session ();
-  gnutls_transport_set_ptr2 (s->session,
-                            (gnutls_transport_ptr) s->strin,
-                            (gnutls_transport_ptr) s->strout);
-  gnutls_transport_set_pull_function (s->session, _tls_stream_pull);
-  gnutls_transport_set_push_function (s->session, _tls_stream_push);
+  sp->session = initialize_tls_session ();
+  mu_stream_ioctl (stream, MU_IOCTL_GET_TRANSPORT, transport);
+  gnutls_transport_set_ptr2 (sp->session,
+                            (gnutls_transport_ptr) transport[0],
+                            (gnutls_transport_ptr) transport[1]);
+  gnutls_transport_set_pull_function (sp->session, _tls_stream_pull);
+  gnutls_transport_set_push_function (sp->session, _tls_stream_push);
   
-  rc = gnutls_handshake (s->session);
+  rc = gnutls_handshake (sp->session);
   if (rc < 0)
     {
-      gnutls_deinit (s->session);
-      s->last_err = rc;
+      gnutls_deinit (sp->session);
+      sp->tls_err = rc;
       return EIO;
     }
-  s->state = state_open;
+  sp->state = state_open;
   return 0;
 }
 
 static int
-prepare_client_session (struct _tls_stream *s)
+prepare_client_session (struct _mu_tls_stream *sp)
 {
   int rc;
   static int protocol_priority[] = {GNUTLS_TLS1, GNUTLS_SSL3, 0};
@@ -495,12 +488,12 @@ prepare_client_session (struct _tls_stream *s)
   static int comp_priority[] = {GNUTLS_COMP_NULL, 0};
   static int mac_priority[] = {GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0};
 
-  gnutls_init (&s->session, GNUTLS_CLIENT);
-  gnutls_protocol_set_priority (s->session, protocol_priority);
-  gnutls_cipher_set_priority (s->session, cipher_priority);
-  gnutls_compression_set_priority (s->session, comp_priority);
-  gnutls_kx_set_priority (s->session, kx_priority);
-  gnutls_mac_set_priority (s->session, mac_priority);
+  gnutls_init (&sp->session, GNUTLS_CLIENT);
+  gnutls_protocol_set_priority (sp->session, protocol_priority);
+  gnutls_cipher_set_priority (sp->session, cipher_priority);
+  gnutls_compression_set_priority (sp->session, comp_priority);
+  gnutls_kx_set_priority (sp->session, kx_priority);
+  gnutls_mac_set_priority (sp->session, mac_priority);
 
   gnutls_certificate_allocate_credentials (&x509_cred);
   if (mu_tls_module_config.ssl_cafile)
@@ -510,44 +503,44 @@ prepare_client_session (struct _tls_stream *s)
                                                   GNUTLS_X509_FMT_PEM);
       if (rc < 0)
        {
-         s->last_err = rc;
+         sp->tls_err = rc;
          return -1;
        }
     }
 
-  gnutls_credentials_set (s->session, GNUTLS_CRD_CERTIFICATE, x509_cred);
+  gnutls_credentials_set (sp->session, GNUTLS_CRD_CERTIFICATE, x509_cred);
 
-  gnutls_transport_set_ptr2 (s->session,
-                            (gnutls_transport_ptr) s->strin,
-                            (gnutls_transport_ptr) s->strout);
-  gnutls_transport_set_pull_function (s->session, _tls_stream_pull);
-  gnutls_transport_set_push_function (s->session, _tls_stream_push);
+  gnutls_transport_set_ptr2 (sp->session,
+                            (gnutls_transport_ptr) sp->transport[0],
+                            (gnutls_transport_ptr) sp->transport[1]);
+  gnutls_transport_set_pull_function (sp->session, _tls_stream_pull);
+  gnutls_transport_set_push_function (sp->session, _tls_stream_push);
       
   return 0;
 }
-  
+
 static int
-_tls_open_client (mu_stream_t stream)
+_tls_client_open (mu_stream_t stream)
 {
-  struct _tls_stream *s = mu_stream_get_owner (stream);
+  struct _mu_tls_stream *sp = (struct _mu_tls_stream *) stream;
   int rc = 0;
   
-  switch (s->state)
+  switch (sp->state)
     {
     case state_closed:
       gnutls_certificate_free_credentials (x509_cred);
-      if (s->session)
-       gnutls_deinit (s->session);
+      if (sp->session)
+       gnutls_deinit (sp->session);
       /* FALLTHROUGH */
       
     case state_init:
-      prepare_client_session (s);
-      rc = gnutls_handshake (s->session);
+      prepare_client_session (sp);
+      rc = gnutls_handshake (sp->session);
       if (rc < 0)
        {
-         s->last_err = rc;
-         gnutls_deinit (s->session);
-         s->state = state_init;
+         sp->tls_err = rc;
+         gnutls_deinit (sp->session);
+         sp->state = state_init;
          return MU_ERR_FAILURE;
        }
       break;
@@ -557,133 +550,181 @@ _tls_open_client (mu_stream_t stream)
     }
 
   /* FIXME: if (ssl_cafile) verify_certificate (s->session); */
-  s->state = state_open;
+  sp->state = state_open;
   return 0;
 }
 
-int
-_tls_strerror (mu_stream_t stream, const char **pstr)
+static int
+_tls_read (struct _mu_stream *str, char *buf, size_t bufsize,
+          size_t *pnread)
 {
-  struct _tls_stream *s = mu_stream_get_owner (stream);
-  *pstr = gnutls_strerror (s->last_err);
-  return 0;
+  struct _mu_tls_stream *sp = (struct _mu_tls_stream *)str;
+  return mu_stream_read (sp->transport[0], buf, bufsize, pnread);
 }
 
-int
-_tls_get_transport2 (mu_stream_t stream,
-                    mu_transport_t *pin, mu_transport_t *pout)
+static int
+_tls_write (struct _mu_stream *str, const char *buf, size_t bufsize,
+           size_t *pnwrite)
 {
-  struct _tls_stream *s = mu_stream_get_owner (stream);
-  *pin = (mu_transport_t) s->strin;
-  *pout = (mu_transport_t) s->strout;
-  return 0;
+  struct _mu_tls_stream *sp = (struct _mu_tls_stream *)str;
+  return mu_stream_write (sp->transport[1], buf, bufsize, pnwrite);
 }
 
-int
-_tls_wait (mu_stream_t stream, int *pflags, struct timeval *tvp)
+static int
+_tls_ioctl (struct _mu_stream *stream, int op, void *arg)
 {
-  struct _tls_stream *s = mu_stream_get_owner (stream);
-  if ((*pflags & (MU_STREAM_READY_RD|MU_STREAM_READY_WR))
-      == (MU_STREAM_READY_RD|MU_STREAM_READY_WR))
-    return EINVAL; /* Sorry, can't wait for both input and output. */
-  if (*pflags & MU_STREAM_READY_RD)
-    return mu_stream_wait (s->strin, pflags, tvp);
-  if (*pflags & MU_STREAM_READY_WR)
-    return mu_stream_wait (s->strout, pflags, tvp);
-  return EINVAL;
-}
+  struct _mu_tls_stream *sp = (struct _mu_tls_stream *) stream;
+  mu_transport_t *ptrans, trans[2];
 
-/* FIXME: if strin == strout sequential reads may intefere with
-   sequential writes (they would share stream->offset). This should
-   be fixed either in stream.c or here. In particular,
-   mu_tls_stream_create_client will malfunction */
-int
-mu_tls_stream_create (mu_stream_t *stream,
-                     mu_stream_t strin, mu_stream_t strout, int flags)
-{
-  struct _tls_stream *s;
-  int rc;
+  switch (op)
+    {
+    case MU_IOCTL_GET_TRANSPORT:
+      if (!arg)
+       return EINVAL;
+      ptrans = arg;
+      mu_stream_ioctl (sp->transport[0], MU_IOCTL_GET_TRANSPORT, trans);
+      ptrans[0] = trans[0];
+      mu_stream_ioctl (sp->transport[1], MU_IOCTL_GET_TRANSPORT, trans);
+      ptrans[1] = trans[0];
+      break;
 
-  if (stream == NULL)
-    return MU_ERR_OUT_PTR_NULL;
+    default:
+      return EINVAL;
+    }
+  return 0;
+}
 
-  s = calloc (1, sizeof (*s));
-  if (s == NULL)
-    return ENOMEM;
+static int
+_tls_wait (struct _mu_stream *stream, int *pflags, struct timeval *tvp)
+{
+  struct _mu_tls_stream *sp = (struct _mu_tls_stream *) stream;
+  int rc = EINVAL;
+  
+  if (*pflags == MU_STREAM_READY_RD)
+    rc = mu_stream_wait (sp->transport[0], pflags, tvp);
+  else if (*pflags == MU_STREAM_READY_WR)
+    rc = mu_stream_wait (sp->transport[1], pflags, tvp);
+  return rc;
+}
 
-  s->strin = strin;
-  s->strout = strout;
+static int
+_tls_flush (struct _mu_stream *stream)
+{
+  struct _mu_tls_stream *sp = (struct _mu_tls_stream *) stream;
+  return mu_stream_flush (sp->transport[1]);
+}
 
-  rc = mu_stream_create (stream, flags|MU_STREAM_NO_CHECK, s);
-  if (rc)
+static int
+_tls_close (mu_stream_t stream)
+{
+  struct _mu_tls_stream *sp = (struct _mu_tls_stream *) stream;
+  
+  if (sp->session && sp->state == state_open)
     {
-      free (s);
-      return rc;
+      gnutls_bye (sp->session, GNUTLS_SHUT_RDWR);
+      sp->state = state_closed;
     }
-
-  mu_stream_set_open (*stream, _tls_open, s);
-  mu_stream_set_close (*stream, _tls_close, s);
-  mu_stream_set_read (*stream, _tls_read, s);
-  mu_stream_set_readline (*stream, _tls_readline, s);
-  mu_stream_set_write (*stream, _tls_write, s);
-  mu_stream_set_flush (*stream, _tls_flush, s);
-  mu_stream_set_destroy (*stream, _tls_destroy, s);
-  mu_stream_set_strerror (*stream, _tls_strerror, s);
-  mu_stream_set_get_transport2 (*stream, _tls_get_transport2, s);
-  mu_stream_set_wait (*stream, _tls_wait, s);
-  _auth_lb_create (&s->lb);
   
-  s->state = state_init;
+  if (!(sp->stream.flags & MU_STREAM_NO_CLOSE))
+    {
+      mu_stream_close (sp->transport[0]);
+      mu_stream_close (sp->transport[1]);
+    }
   return 0;
 }
 
-int
-mu_tls_stream_create_client (mu_stream_t *stream,
-                            mu_stream_t strin, mu_stream_t strout, int flags)
+static void
+_tls_done (struct _mu_stream *stream)
 {
-  struct _tls_stream *s;
-  int rc;
+  struct _mu_tls_stream *sp = (struct _mu_tls_stream *) stream;
+  
+  if (x509_cred)
+    gnutls_certificate_free_credentials (x509_cred);
+  if (sp->session && sp->state == state_closed)
+    {
+      gnutls_deinit (sp->session);
+      sp->state = state_destroyed;
+    }
 
-  if (stream == NULL)
-    return MU_ERR_OUT_PTR_NULL;
+  if (!(sp->stream.flags & MU_STREAM_NO_CLOSE))
+    {
+      mu_stream_unref (sp->transport[0]);
+      mu_stream_unref (sp->transport[1]);
+    }
+}
 
-  s = calloc (1, sizeof (*s));
-  if (s == NULL)
+static int
+_mu_tls_stream_create (mu_stream_t *pstream,
+                      int (*openfn) (mu_stream_t stream),
+                      mu_stream_t strin, mu_stream_t strout, int flags)
+{
+  struct _mu_tls_stream *sp;
+  int noclose = flags & MU_STREAM_NO_CLOSE;
+  int rc;
+  
+  sp = (struct _mu_tls_stream *)
+    _mu_stream_create (sizeof (*sp),
+                      MU_STREAM_RDWR | noclose);
+  if (!sp)
     return ENOMEM;
 
-  s->strin = strin;
-  s->strout = strout;
-  
-  rc = mu_stream_create (stream, flags|MU_STREAM_NO_CHECK, s);
+  sp->stream.read = _tls_read; 
+  sp->stream.write = _tls_write;
+  sp->stream.flush = _tls_flush;
+  sp->stream.open = openfn; 
+  sp->stream.close = _tls_close;
+  sp->stream.done = _tls_done; 
+  sp->stream.ctl = _tls_ioctl;
+  sp->stream.wait = _tls_wait;
+  /* FIXME:
+     sp->stream.error_string = _tls_error_string;*/
+
+  if (!noclose && strin == strout)
+    mu_stream_ref (strin);
+
+  mu_stream_set_buffer (strin, mu_buffer_none, 0);
+  mu_stream_set_buffer (strout, mu_buffer_none, 0);
+  rc = _mu_tls_io_stream_create (&sp->transport[0], strin,
+                                MU_STREAM_READ | noclose, sp);
   if (rc)
     {
-      free (s);
+      free (sp);
+      return rc;
+    }
+      
+  rc = _mu_tls_io_stream_create (&sp->transport[1], strout,
+                                MU_STREAM_WRITE | noclose, sp);
+  if (rc)
+    {
+      free (sp);
+      free (sp->transport[0]);
       return rc;
     }
-
-  mu_stream_set_open (*stream, _tls_open_client, s);
-  mu_stream_set_close (*stream, _tls_close, s);
-  mu_stream_set_read (*stream, _tls_read, s);
-  mu_stream_set_readline (*stream, _tls_readline, s);
-  mu_stream_set_write (*stream, _tls_write, s);
-  mu_stream_set_flush (*stream, _tls_flush, s);
-  mu_stream_set_destroy (*stream, _tls_destroy, s);
-  mu_stream_set_strerror (*stream, _tls_strerror, s);
-  mu_stream_set_get_transport2 (*stream, _tls_get_transport2, s);
-  mu_stream_set_wait (*stream, _tls_wait, s);
-  _auth_lb_create (&s->lb);
   
-  s->state = state_init;
+  mu_stream_set_buffer ((mu_stream_t) sp, mu_buffer_line, 1024);
+  *pstream = (mu_stream_t) sp;
   return 0;
 }
 
 int
-mu_tls_stream_create_client_from_tcp (mu_stream_t *stream, mu_stream_t tcp_str,
-                                     int flags)
+mu_tls_server_stream_create (mu_stream_t *pstream,
+                            mu_stream_t strin, mu_stream_t strout, int flags)
+{
+  return _mu_tls_stream_create (pstream,
+                               _tls_server_open,
+                               strin, strout, flags);
+}
+
+int
+mu_tls_client_stream_create (mu_stream_t *pstream,
+                            mu_stream_t strin, mu_stream_t strout, int flags)
 {
-  return mu_tls_stream_create_client (stream, tcp_str, tcp_str, flags);
+  return _mu_tls_stream_create (pstream,
+                               _tls_client_open,
+                               strin, strout, flags);
 }
 
+
 #endif /* WITH_TLS */
 
 /* EOF */
diff --git a/libproto/imap/folder.c b/libproto/imap/folder.c
index 77e7919..e974ced 100644
--- a/libproto/imap/folder.c
+++ b/libproto/imap/folder.c
@@ -688,10 +688,12 @@ folder_imap_open (mu_folder_t folder, int flags)
              CHECK_EAGAIN (f_imap, status);
              CHECK_ERROR_CLOSE (folder, f_imap, status);
 
-             status = mu_tls_stream_create_client_from_tcp (&newstr, 
folder->stream, 0);
+             status = mu_tls_client_stream_create (&newstr, 
+                                                   folder->stream,
+                                                   folder->stream, 0);
              if (status != 0)
                {
-                 mu_error ("folder_imap_open: 
mu_tls_stream_create_client_from_tcp: %s",
+                 mu_error ("folder_imap_open: mu_tls_client_stream_create: %s",
                            mu_strerror (status));
                  return status;
                }
diff --git a/libproto/pop/mbox.c b/libproto/pop/mbox.c
index a9e28d5..b9a21d6 100644
--- a/libproto/pop/mbox.c
+++ b/libproto/pop/mbox.c
@@ -824,8 +824,11 @@ pop_open (mu_mailbox_t mbox, int flags)
       /* Create the networking stack.  */
       if (mbox->stream == NULL)
        {
-         status = mu_tcp_stream_create (&mbox->stream, host, port, 
mbox->flags);
+         status = mu_tcp_stream_create (&mbox->stream, host, port,
+                                        mbox->flags);
          CHECK_ERROR (mpd, status);
+         /* FIXME: How to configure the buffer size? */
+         mu_stream_set_buffer (mbox->stream, mu_buffer_line, 1024);
 
 #ifdef WITH_TLS
          if (mpd->pops)
@@ -836,19 +839,18 @@ pop_open (mu_mailbox_t mbox, int flags)
              CHECK_EAGAIN (mpd, status);
              CHECK_ERROR_CLOSE (mbox, mpd, status);
 
-             status = mu_tls_stream_create_client_from_tcp (&newstr, 
mbox->stream, 0);
+             status = mu_tls_client_stream_create (&newstr, 
+                                                   mbox->stream, 
+                                                   mbox->stream, 0);
              if (status != 0)
                {
-                 mu_error ("pop_open: mu_tls_stream_create_client_from_tcp: 
%s",
+                 mu_error ("pop_open: mu_tls_client_stream_create: %s",
                            mu_strerror (status));
                  return status;
                }
              mbox->stream = newstr;
            }
 #endif /* WITH_TLS */
-
-         /* Using the awkward mu_stream_t buffering.  */
-         mu_stream_setbufsiz (mbox->stream, BUFSIZ);
        }
       else
        {
diff --git a/libproto/pop/pop3_stls.c b/libproto/pop/pop3_stls.c
index b9984f6..2c09222 100644
--- a/libproto/pop/pop3_stls.c
+++ b/libproto/pop/pop3_stls.c
@@ -66,7 +66,9 @@ mu_pop3_stls (mu_pop3_t pop3)
         MU_POP3_CHECK_EAGAIN (pop3, status);
         mu_pop3_debug_ack (pop3);
         MU_POP3_CHECK_OK (pop3);
-        status = mu_tls_stream_create_client_from_tcp (&tls_stream, 
pop3->carrier, 0);
+        status = mu_tls_client_stream_create (&tls_stream, 
+                                              pop3->carrier, 
+                                              pop3->carrier, 0);
         MU_POP3_CHECK_ERROR (pop3, status);
         pop3->carrier = tls_stream; 
         pop3->state = MU_POP3_STLS_CONNECT;
diff --git a/mailbox/amd.c b/mailbox/amd.c
index 6d1d855..2b88ffc 100644
--- a/mailbox/amd.c
+++ b/mailbox/amd.c
@@ -1648,7 +1648,6 @@ amd_body_stream_readdelim (mu_stream_t is, char *buffer, 
size_t buflen,
   mu_body_t body = amdstr->body;
   mu_message_t msg = mu_body_get_owner (body);
   struct _amd_message *mhm = mu_message_get_owner (msg);
-  size_t nread = 0;
   int status = 0;
 
   amd_pool_open (mhm);
@@ -1656,7 +1655,7 @@ amd_body_stream_readdelim (mu_stream_t is, char *buffer, 
size_t buflen,
   if (buffer == NULL || buflen == 0)
     {
       if (pnread)
-       *pnread = nread;
+       *pnread = 0;
       return 0;
     }
 
@@ -1669,27 +1668,22 @@ amd_body_stream_readdelim (mu_stream_t is, char 
*buffer, size_t buflen,
 
   status = mu_stream_seek (mhm->stream, mhm->body_start + amdstr->off,
                           MU_SEEK_SET, NULL);
-  if (status)
+  if (status == 0)
     {
-      buflen--;
-      while (buflen)
-       {
-         size_t ln, rdsize;
+      size_t nread = 0;
+      size_t ln;
          
-         ln = mhm->body_end - (mhm->body_start + amdstr->off);
-         if (ln > 0)
-           {
-             rdsize = ((size_t)ln < buflen) ? (size_t)ln : buflen;
-             status = mu_stream_readdelim (mhm->stream, buffer, rdsize,
-                                           delim, &rdsize);
-             amdstr->off += nread;
-             nread += rdsize;
-             if (status)
-               break;
-             buflen -= rdsize;
-             buffer += rdsize;
-           }
+      ln = mhm->body_end - (mhm->body_start + amdstr->off) + 1;
+      if (ln > 0)
+       {
+         size_t rdsize = ((size_t)ln < buflen) ? (size_t)ln : buflen;
+         status = mu_stream_readdelim (mhm->stream, buffer, rdsize,
+                                       delim, &nread);
+         amdstr->off += rdsize;
        }
+
+      if (pnread)
+       *pnread = nread;
     }
 
   mu_monitor_unlock (mhm->amd->mailbox->monitor);
@@ -1697,8 +1691,6 @@ amd_body_stream_readdelim (mu_stream_t is, char *buffer, 
size_t buflen,
   pthread_cleanup_pop (0);
 #endif
 
-  if (pnread)
-    *pnread = nread;
   return status;
 }
 
diff --git a/mailbox/message.c b/mailbox/message.c
index 1d95c71..8ac1258 100644
--- a/mailbox/message.c
+++ b/mailbox/message.c
@@ -182,7 +182,17 @@ _message_stream_seek (struct _mu_stream *str, mu_off_t 
off, mu_off_t *ppos)
        return rc;
       /* fall through */
     case _mss_body:
-      off -= hsize;
+      if (off > hsize)
+       off -= hsize;   
+      else
+       {
+         mu_stream_destroy (&sp->transport);
+         sp->state = _mss_init;
+         rc = _check_stream_state (sp);
+         if (rc)
+           return rc;
+       }
+
       break;
 
     default:
diff --git a/pop3d/capa.c b/pop3d/capa.c
index ca58512..38d5fed 100644
--- a/pop3d/capa.c
+++ b/pop3d/capa.c
@@ -32,9 +32,6 @@ pop3d_capa (char *arg)
   if (strlen (arg) != 0)
     return ERR_BAD_ARGS;
 
-  if (state != initial_state && state != TRANSACTION)
-    return ERR_WRONG_STATE;
-
   pop3d_outf ("+OK Capability list follows\n");
   pop3d_outf ("TOP\n");
   pop3d_outf ("USER\n");
diff --git a/pop3d/extra.c b/pop3d/extra.c
index ca5089e..2ab0f8a 100644
--- a/pop3d/extra.c
+++ b/pop3d/extra.c
@@ -126,6 +126,14 @@ pop3d_abquit (int reason)
   exit (code);
 }
 
+/* Keeps the *real* output stream.  Ostream is a RFC822 filter built over
+   real_ostream, or even over a TLS stream, which in turn is based on this
+   real_ostream.
+   FIXME: This is sorta kludge: we could use MU_IOCTL_GET_TRANSPORT call
+   to retrieve the bottom-level stream, if filter streams supported it.
+*/
+static mu_stream_t real_ostream;
+
 void
 pop3d_setio (FILE *in, FILE *out)
 {
@@ -136,14 +144,17 @@ pop3d_setio (FILE *in, FILE *out)
   if (!out)
     pop3d_abquit (ERR_NO_OFILE);
 
-  if (mu_stdio_stream_create (&istream, fileno (in), MU_STREAM_NO_CLOSE))
+  if (mu_stdio_stream_create (&istream, fileno (in),
+                             MU_STREAM_READ | MU_STREAM_NO_CLOSE))
     pop3d_abquit (ERR_NO_IFILE);
   mu_stream_set_buffer (istream, mu_buffer_line, 1024);
   
-  if (mu_stdio_stream_create (&str, fileno (out), MU_STREAM_NO_CLOSE))
+  if (mu_stdio_stream_create (&str, fileno (out),
+                             MU_STREAM_WRITE | MU_STREAM_NO_CLOSE))
     pop3d_abquit (ERR_NO_OFILE);
+  real_ostream = str;
   if (mu_filter_create (&ostream, str, "rfc822", MU_FILTER_ENCODE,
-                       MU_STREAM_WRITE|MU_STREAM_NO_CLOSE))
+                       MU_STREAM_WRITE | MU_STREAM_NO_CLOSE))
     pop3d_abquit (ERR_NO_IFILE);
   mu_stream_set_buffer (ostream, mu_buffer_line, 1024);
 }
@@ -154,8 +165,8 @@ pop3d_init_tls_server ()
 {
   mu_stream_t stream;
   int rc;
- 
-  rc = mu_tls_stream_create (&stream, istream, ostream, 0);
+
+  rc = mu_tls_server_stream_create (&stream, istream, real_ostream, 0);
   if (rc)
     return 0;
 
@@ -167,7 +178,12 @@ pop3d_init_tls_server ()
       return 0;
     }
   
-  istream = ostream = stream;
+  istream = stream;
+  mu_stream_destroy (&ostream);
+  if (mu_filter_create (&ostream, stream, "rfc822", MU_FILTER_ENCODE,
+                       MU_STREAM_WRITE | MU_STREAM_NO_CLOSE))
+    pop3d_abquit (ERR_NO_IFILE);
+  mu_stream_set_buffer (ostream, mu_buffer_line, 1024);
   return 1;
 }
 #endif
diff --git a/pop3d/top.c b/pop3d/top.c
index bab0583..73d6a27 100644
--- a/pop3d/top.c
+++ b/pop3d/top.c
@@ -71,13 +71,13 @@ pop3d_top (char *arg)
     {
       char *buf = NULL;
       size_t size = 0, n;
-      while (lines > 0 &&
+      for (; lines > 0 &&
             mu_stream_getline (stream, &buf, &size, &n) == 0 &&
-            n > 0)
+            n > 0; lines--)
        {
          if (buf[0] == '.')
            pop3d_outf (".");
-         pop3d_outf ("%s\n", buf);
+         pop3d_outf ("%s", buf);
        }
       mu_stream_destroy (&stream);
       free (buf);


hooks/post-receive
-- 
GNU Mailutils



reply via email to

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