dovecot-2.1: lib-storage: Added initial support for pop3c backend.

dovecot at dovecot.org dovecot at dovecot.org
Mon Jan 2 16:30:44 EET 2012


details:   http://hg.dovecot.org/dovecot-2.1/rev/d4c909d2306f
changeset: 13880:d4c909d2306f
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Jan 02 16:30:06 2012 +0200
description:
lib-storage: Added initial support for pop3c backend.

diffstat:

 configure.in                                 |   15 +-
 src/lib-storage/index/Makefile.am            |    2 +-
 src/lib-storage/index/pop3c/Makefile.am      |   28 +
 src/lib-storage/index/pop3c/pop3c-client.c   |  781 +++++++++++++++++++++++++++
 src/lib-storage/index/pop3c/pop3c-client.h   |   69 ++
 src/lib-storage/index/pop3c/pop3c-mail.c     |  184 ++++++
 src/lib-storage/index/pop3c/pop3c-settings.c |   87 +++
 src/lib-storage/index/pop3c/pop3c-settings.h |   21 +
 src/lib-storage/index/pop3c/pop3c-storage.c  |  282 +++++++++
 src/lib-storage/index/pop3c/pop3c-storage.h  |   35 +
 src/lib-storage/index/pop3c/pop3c-sync.c     |  298 ++++++++++
 src/lib-storage/index/pop3c/pop3c-sync.h     |   14 +
 12 files changed, 1812 insertions(+), 4 deletions(-)

diffs (truncated from 1900 to 300 lines):

diff -r 193c66096bb3 -r d4c909d2306f configure.in
--- a/configure.in	Fri Dec 30 17:44:23 2011 +0200
+++ b/configure.in	Mon Jan 02 16:30:06 2012 +0200
@@ -242,12 +242,12 @@
   want_gc=no)
 
 AC_ARG_WITH(storages,
-AS_HELP_STRING([--with-storages], [Build with specified mail storage formats (mdbox sdbox maildir mbox cydir imapc)]), [
+AS_HELP_STRING([--with-storages], [Build with specified mail storage formats (mdbox sdbox maildir mbox cydir imapc pop3c)]), [
 	if test "$withval" = "yes" || test "$withval" = "no"; then
 		AC_MSG_ERROR([--with-storages needs storage list as parameter])
 	fi
 	mail_storages="shared `echo "$withval"|sed 's/,/ /g'`" ],
-	mail_storages="shared mdbox sdbox maildir mbox cydir imapc")
+	mail_storages="shared mdbox sdbox maildir mbox cydir imapc pop3c")
 AC_SUBST(mail_storages)
 mail_storages="$mail_storages raw"
 # drop duplicates
@@ -2448,7 +2448,8 @@
 sdbox_libs='$(top_builddir)/src/lib-storage/index/dbox-single/libstorage_dbox_single.la'
 mdbox_libs='$(top_builddir)/src/lib-storage/index/dbox-multi/libstorage_dbox_multi.la'
 cydir_libs='$(top_builddir)/src/lib-storage/index/cydir/libstorage_cydir.la'
-imapc_libs='$(top_builddir)/src/lib-storage/index/imapc/libstorage_imapc.la $(top_builddir)/src/lib-imap-client/libimap_client.la $(top_builddir)/src/lib-ssl-iostream/libssl_iostream.la'
+imapc_libs='$(top_builddir)/src/lib-storage/index/imapc/libstorage_imapc.la $(top_builddir)/src/lib-imap-client/libimap_client.la'
+pop3c_libs='$(top_builddir)/src/lib-storage/index/pop3c/libstorage_pop3c.la'
 raw_libs='$(top_builddir)/src/lib-storage/index/raw/libstorage_raw.la'
 shared_libs='$(top_builddir)/src/lib-storage/index/shared/libstorage_shared.la'
 
@@ -2470,8 +2471,15 @@
   fi
   if test $storage = imapc; then
     mailbox_list_drivers="$mailbox_list_drivers imapc"
+    want_ssl_libs=yes
+  fi
+  if test $storage = pop3c; then
+    want_ssl_libs=yes
   fi
 done
+if test "$want_ssl_libs" = yes; then
+  LINKED_STORAGE_LIBS="$LINKED_STORAGE_LIBS \$(top_builddir)/src/lib-ssl-iostream/libssl_iostream.la"
+fi
 AC_SUBST(LINKED_STORAGE_LIBS)
 AC_SUBST(mailbox_list_drivers)
 AC_DEFINE_UNQUOTED(MAIL_STORAGES, "$mail_storages", List of compiled in mail storages)
@@ -2737,6 +2745,7 @@
 src/lib-storage/list/Makefile
 src/lib-storage/index/Makefile
 src/lib-storage/index/imapc/Makefile
+src/lib-storage/index/pop3c/Makefile
 src/lib-storage/index/maildir/Makefile
 src/lib-storage/index/mbox/Makefile
 src/lib-storage/index/dbox-common/Makefile
diff -r 193c66096bb3 -r d4c909d2306f src/lib-storage/index/Makefile.am
--- a/src/lib-storage/index/Makefile.am	Fri Dec 30 17:44:23 2011 +0200
+++ b/src/lib-storage/index/Makefile.am	Mon Jan 02 16:30:06 2012 +0200
@@ -1,4 +1,4 @@
-SUBDIRS = maildir mbox dbox-common dbox-multi dbox-single cydir imapc raw shared
+SUBDIRS = maildir mbox dbox-common dbox-multi dbox-single cydir imapc pop3c raw shared
 
 noinst_LTLIBRARIES = libstorage_index.la
 
diff -r 193c66096bb3 -r d4c909d2306f src/lib-storage/index/pop3c/Makefile.am
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-storage/index/pop3c/Makefile.am	Mon Jan 02 16:30:06 2012 +0200
@@ -0,0 +1,28 @@
+noinst_LTLIBRARIES = libstorage_pop3c.la
+
+AM_CPPFLAGS = \
+	-I$(top_srcdir)/src/lib \
+	-I$(top_srcdir)/src/lib-settings \
+	-I$(top_srcdir)/src/lib-dns \
+	-I$(top_srcdir)/src/lib-ssl-iostream \
+	-I$(top_srcdir)/src/lib-mail \
+	-I$(top_srcdir)/src/lib-imap \
+	-I$(top_srcdir)/src/lib-index \
+	-I$(top_srcdir)/src/lib-storage \
+	-I$(top_srcdir)/src/lib-storage/index
+
+libstorage_pop3c_la_SOURCES = \
+	pop3c-client.c \
+	pop3c-mail.c \
+	pop3c-settings.c \
+	pop3c-storage.c \
+	pop3c-sync.c
+
+headers = \
+	pop3c-client.h \
+	pop3c-settings.h \
+	pop3c-storage.h \
+	pop3c-sync.h
+
+pkginc_libdir=$(pkgincludedir)
+pkginc_lib_HEADERS = $(headers)
diff -r 193c66096bb3 -r d4c909d2306f src/lib-storage/index/pop3c/pop3c-client.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-storage/index/pop3c/pop3c-client.c	Mon Jan 02 16:30:06 2012 +0200
@@ -0,0 +1,781 @@
+/* Copyright (c) 2011 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "ioloop.h"
+#include "network.h"
+#include "istream.h"
+#include "istream-dot.h"
+#include "istream-seekable.h"
+#include "ostream.h"
+#include "iostream-rawlog.h"
+#include "iostream-ssl.h"
+#include "close-keep-errno.h"
+#include "safe-mkstemp.h"
+#include "base64.h"
+#include "str.h"
+#include "dns-lookup.h"
+#include "pop3c-client.h"
+
+#include <unistd.h>
+
+#define POP3C_MAX_INBUF_SIZE (1024*32)
+#define POP3C_DNS_LOOKUP_TIMEOUT_MSECS (1000*30)
+#define POP3C_CONNECT_TIMEOUT_MSECS (1000*30)
+#define POP3C_COMMAND_TIMEOUT_MSECS (1000*30)
+
+enum pop3c_client_state {
+	/* No connection */
+	POP3C_CLIENT_STATE_DISCONNECTED = 0,
+	/* Trying to connect */
+	POP3C_CLIENT_STATE_CONNECTING,
+	/* Connected, trying to authenticate */
+	POP3C_CLIENT_STATE_USER,
+	POP3C_CLIENT_STATE_AUTH,
+	POP3C_CLIENT_STATE_PASS,
+	/* Post-authentication, asking for capabilities */
+	POP3C_CLIENT_STATE_CAPA,
+	/* Authenticated, ready to accept commands */
+	POP3C_CLIENT_STATE_DONE
+};
+
+struct pop3c_client {
+	pool_t pool;
+	struct pop3c_client_settings set;
+	struct ssl_iostream_context *ssl_ctx;
+	struct ip_addr ip;
+
+	int fd;
+	struct io *io;
+	struct istream *input, *raw_input;
+	struct ostream *output, *raw_output;
+	struct ssl_iostream *ssl_iostream;
+	struct timeout *to;
+
+	enum pop3c_client_state state;
+	enum pop3c_capability capabilities;
+
+	pop3c_login_callback_t *login_callback;
+	void *login_context;
+
+	unsigned int async_commands;
+	const char *input_line;
+	struct istream *dot_input;
+
+	unsigned int handshake_failed:1;
+	unsigned int running:1;
+};
+
+static void
+pop3c_dns_callback(const struct dns_lookup_result *result, void *context);
+
+struct pop3c_client *
+pop3c_client_init(const struct pop3c_client_settings *set)
+{
+	struct pop3c_client *client;
+	struct ssl_iostream_settings ssl_set;
+	const char *source;
+	pool_t pool;
+
+	pool = pool_alloconly_create("pop3c client", 1024);
+	client = p_new(pool, struct pop3c_client, 1);
+	client->pool = pool;
+	client->fd = -1;
+
+	client->set.debug = set->debug;
+	client->set.host = p_strdup(pool, set->host);
+	client->set.port = set->port;
+	client->set.master_user = p_strdup(pool, set->master_user);
+	client->set.username = p_strdup(pool, set->username);
+	client->set.password = p_strdup(pool, set->password);
+	client->set.dns_client_socket_path =
+		p_strdup(pool, set->dns_client_socket_path);
+	client->set.temp_path_prefix = p_strdup(pool, set->temp_path_prefix);
+	client->set.rawlog_dir = p_strdup(pool, set->rawlog_dir);
+
+	if (set->ssl_mode != POP3C_CLIENT_SSL_MODE_NONE) {
+		client->set.ssl_mode = set->ssl_mode;
+		client->set.ssl_ca_dir = p_strdup(pool, set->ssl_ca_dir);
+		client->set.ssl_verify = set->ssl_verify;
+
+		memset(&ssl_set, 0, sizeof(ssl_set));
+		ssl_set.ca_dir = set->ssl_ca_dir;
+		ssl_set.verify_remote_cert = set->ssl_verify;
+		ssl_set.crypto_device = set->ssl_crypto_device;
+
+		source = t_strdup_printf("%s:%u", set->host, set->port);
+		if (ssl_iostream_context_init_client(source, &ssl_set,
+						     &client->ssl_ctx) < 0) {
+			i_error("pop3c(%s): Couldn't initialize SSL context",
+				source);
+		}
+	}
+	return client;
+}
+
+static void
+client_login_callback(struct pop3c_client *client,
+		      enum pop3c_command_state state, const char *reason)
+{
+	pop3c_login_callback_t *callback = client->login_callback;
+	void *context = client->login_context;
+
+	if (client->login_callback != NULL) {
+		client->login_callback = NULL;
+		client->login_context = NULL;
+		callback(state, reason, context);
+	}
+}
+
+static void pop3c_client_disconnect(struct pop3c_client *client)
+{
+	client->state = POP3C_CLIENT_STATE_DISCONNECTED;
+	client->async_commands = 0;
+
+	if (client->running)
+		io_loop_stop(current_ioloop);
+
+	if (client->to != NULL)
+		timeout_remove(&client->to);
+	if (client->io != NULL)
+		io_remove(&client->io);
+	if (client->input != NULL)
+		i_stream_destroy(&client->input);
+	if (client->output != NULL)
+		o_stream_destroy(&client->output);
+	if (client->ssl_iostream != NULL)
+		ssl_iostream_unref(&client->ssl_iostream);
+	if (client->fd != -1) {
+		if (close(client->fd) < 0)
+			i_error("close(pop3c) failed: %m");
+		client->fd = -1;
+	}
+	client_login_callback(client, POP3C_COMMAND_STATE_DISCONNECTED,
+			      "Disconnected");
+}
+
+void pop3c_client_deinit(struct pop3c_client **_client)
+{
+	struct pop3c_client *client = *_client;
+
+	pop3c_client_disconnect(client);
+	if (client->ssl_ctx != NULL)
+		ssl_iostream_context_deinit(&client->ssl_ctx);
+	pool_unref(&client->pool);
+}
+
+static void pop3c_client_ioloop_changed(struct pop3c_client *client)
+{
+	if (client->to != NULL)
+		io_loop_move_timeout(&client->to);
+	if (client->io != NULL)
+		client->io = io_loop_move_io(&client->io);
+	if (client->output != NULL)
+		o_stream_switch_ioloop(client->output);
+}
+
+static void pop3c_client_timeout(struct pop3c_client *client)
+{
+	switch (client->state) {
+	case POP3C_CLIENT_STATE_CONNECTING:
+		i_error("pop3c(%s): connect(%s, %u) timed out after %u seconds",
+			client->set.host, net_ip2addr(&client->ip),
+			client->set.port, POP3C_CONNECT_TIMEOUT_MSECS/1000);
+		break;
+	case POP3C_CLIENT_STATE_DONE:
+		i_error("pop3c(%s): Command timed out after %u seconds",
+			client->set.host, POP3C_COMMAND_TIMEOUT_MSECS/1000);
+		break;
+	default:
+		i_error("pop3c(%s): Authentication timed out after %u seconds",
+			client->set.host, POP3C_CONNECT_TIMEOUT_MSECS/1000);
+		break;
+	}
+	pop3c_client_disconnect(client);
+}
+
+void pop3c_client_run(struct pop3c_client *client)
+{
+	struct ioloop *ioloop, *prev_ioloop = current_ioloop;
+	bool timeout_added = FALSE;
+
+	i_assert(client->fd != -1 ||
+		 client->state == POP3C_CLIENT_STATE_CONNECTING);
+


More information about the dovecot-cvs mailing list