[dovecot-cvs] dovecot/src/login-common common.h, 1.10, 1.11 login-proxy.c, 1.10, 1.11 login-proxy.h, 1.2, 1.3 main.c, 1.33, 1.34 master.c, 1.18, 1.19 master.h, 1.5, 1.6 ssl-proxy-openssl.c, 1.42, 1.43 ssl-proxy.c, 1.7, 1.8 ssl-proxy.h, 1.6, 1.7
cras at dovecot.org
cras at dovecot.org
Sun Aug 6 23:05:43 EEST 2006
Update of /var/lib/cvs/dovecot/src/login-common
In directory talvi:/tmp/cvs-serv16539/src/login-common
Modified Files:
common.h login-proxy.c login-proxy.h main.c master.c master.h
ssl-proxy-openssl.c ssl-proxy.c ssl-proxy.h
Log Message:
Fixes to login process handling, especially with
login_process_per_connection=no. Removed login_max_logging_users setting
since it was somewhat weird in how it worked. Added login_max_connections to
replace it with login_process_per_connection=no, and with =yes its
functionality is now within login_max_processes_count.
Index: common.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/login-common/common.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- common.h 14 Apr 2006 18:20:57 -0000 1.10
+++ common.h 6 Aug 2006 20:05:35 -0000 1.11
@@ -16,13 +16,15 @@
extern const char *greeting, *log_format;
extern const char *const *log_format_elements;
extern const char *capability_string;
-extern unsigned int max_logging_users;
+extern unsigned int max_connections;
extern unsigned int login_process_uid;
extern struct auth_client *auth_client;
+extern bool closing_down;
void main_ref(void);
void main_unref(void);
-void main_close_listen(void);
+void main_listen_start(void);
+void main_listen_stop(void);
#endif
Index: login-proxy.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/login-common/login-proxy.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- login-proxy.c 2 Apr 2006 10:46:42 -0000 1.10
+++ login-proxy.c 6 Aug 2006 20:05:35 -0000 1.11
@@ -220,6 +220,13 @@
i_free(proxy->host);
i_free(proxy->user);
i_free(proxy);
+
+ main_listen_start();
+}
+
+unsigned int login_proxy_get_count(void)
+{
+ return login_proxies == NULL ? 0 : hash_size(login_proxies);
}
void login_proxy_detach(struct login_proxy *proxy, struct istream *client_input,
Index: login-proxy.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/login-common/login-proxy.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- login-proxy.h 18 Oct 2004 23:07:01 -0000 1.2
+++ login-proxy.h 6 Aug 2006 20:05:35 -0000 1.3
@@ -20,6 +20,9 @@
void login_proxy_detach(struct login_proxy *proxy, struct istream *client_input,
struct ostream *client_output);
+/* Return number of active detached login proxies */
+unsigned int login_proxy_get_count(void);
+
void login_proxy_deinit(void);
#endif
Index: main.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/login-common/main.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- main.c 3 May 2006 22:58:54 -0000 1.33
+++ main.c 6 Aug 2006 20:05:35 -0000 1.34
@@ -22,15 +22,16 @@
bool verbose_proctitle, verbose_ssl, verbose_auth;
const char *greeting, *log_format;
const char *const *log_format_elements;
-unsigned int max_logging_users;
+unsigned int max_connections;
unsigned int login_process_uid;
struct auth_client *auth_client;
+bool closing_down;
static const char *process_name;
static struct ioloop *ioloop;
static struct io *io_listen, *io_ssl_listen;
static int main_refcount;
-static bool is_inetd, closing_down;
+static bool is_inetd, listening;
void main_ref(void)
{
@@ -49,27 +50,6 @@
}
}
-void main_close_listen(void)
-{
- if (closing_down)
- return;
-
- if (io_listen != NULL) {
- io_remove(&io_listen);
- if (close(LOGIN_LISTEN_FD) < 0)
- i_fatal("close(listen) failed: %m");
- }
-
- if (io_ssl_listen != NULL) {
- io_remove(&io_ssl_listen);
- if (close(LOGIN_SSL_LISTEN_FD) < 0)
- i_fatal("close(ssl_listen) failed: %m");
- }
-
- closing_down = TRUE;
- master_notify_finished();
-}
-
static void sig_die(int signo, void *context __attr_unused__)
{
/* warn about being killed because of some signal, except SIGINT (^C)
@@ -91,13 +71,15 @@
return;
}
- if (process_per_connection)
- main_close_listen();
-
if (net_getsockname(fd, &local_ip, NULL) < 0)
memset(&local_ip, 0, sizeof(local_ip));
(void)client_create(fd, FALSE, &local_ip, &ip);
+
+ if (process_per_connection) {
+ closing_down = TRUE;
+ main_listen_stop();
+ }
}
static void login_accept_ssl(void *context __attr_unused__)
@@ -114,8 +96,6 @@
return;
}
- if (process_per_connection)
- main_close_listen();
if (net_getsockname(fd, &local_ip, NULL) < 0)
memset(&local_ip, 0, sizeof(local_ip));
@@ -126,6 +106,82 @@
client = client_create(fd_ssl, TRUE, &local_ip, &ip);
client->proxy = proxy;
}
+
+ if (process_per_connection) {
+ closing_down = TRUE;
+ main_listen_stop();
+ }
+}
+
+void main_listen_start(void)
+{
+ unsigned int current_count;
+
+ if (listening)
+ return;
+ if (closing_down) {
+ /* typically happens only with
+ login_process_per_connection=yes after client logs in */
+ master_notify_state_change(LOGIN_STATE_FULL_LOGINS);
+ return;
+ }
+
+ current_count = ssl_proxy_get_count() + login_proxy_get_count();
+ if (current_count >= max_connections) {
+ /* can't accept any more connections until existing proxies
+ get destroyed */
+ return;
+ }
+
+ if (net_getsockname(LOGIN_LISTEN_FD, NULL, NULL) == 0) {
+ io_listen = io_add(LOGIN_LISTEN_FD, IO_READ,
+ login_accept, NULL);
+ }
+
+ if (net_getsockname(LOGIN_SSL_LISTEN_FD, NULL, NULL) == 0) {
+ if (!ssl_initialized) {
+ /* this shouldn't happen, master should have
+ disabled the ssl socket.. */
+ i_fatal("BUG: SSL initialization parameters not given "
+ "while they should have been");
+ }
+
+ io_ssl_listen = io_add(LOGIN_SSL_LISTEN_FD, IO_READ,
+ login_accept_ssl, NULL);
+ }
+ listening = TRUE;
+
+ /* the initial notification tells master that we're ok. if we die
+ before sending it, the master should shutdown itself. */
+ master_notify_state_change(LOGIN_STATE_LISTENING);
+}
+
+void main_listen_stop(void)
+{
+ if (!listening)
+ return;
+
+ listening = FALSE;
+ if (io_listen != NULL) {
+ io_remove(&io_listen);
+ if (closing_down) {
+ if (close(LOGIN_LISTEN_FD) < 0)
+ i_fatal("close(listen) failed: %m");
+ }
+ }
+
+ if (io_ssl_listen != NULL) {
+ io_remove(&io_ssl_listen);
+ if (closing_down) {
+ if (close(LOGIN_SSL_LISTEN_FD) < 0)
+ i_fatal("close(ssl_listen) failed: %m");
+ }
+ }
+
+ listening = FALSE;
+ master_notify_state_change(clients_get_count() == 0 ?
+ LOGIN_STATE_FULL_LOGINS :
+ LOGIN_STATE_FULL_PRELOGINS);
}
static void auth_connect_notify(struct auth_client *client __attr_unused__,
@@ -183,8 +239,8 @@
verbose_ssl = getenv("VERBOSE_SSL") != NULL;
verbose_auth = getenv("VERBOSE_AUTH") != NULL;
- value = getenv("MAX_LOGGING_USERS");
- max_logging_users = value == NULL ? 0 : strtoul(value, NULL, 10);
+ value = getenv("MAX_CONNECTIONS");
+ max_connections = value == NULL ? 0 : strtoul(value, NULL, 10);
greeting = getenv("GREETING");
if (greeting == NULL)
@@ -222,27 +278,8 @@
io_listen = io_ssl_listen = NULL;
if (!is_inetd) {
- if (net_getsockname(LOGIN_LISTEN_FD, NULL, NULL) == 0) {
- io_listen = io_add(LOGIN_LISTEN_FD, IO_READ,
- login_accept, NULL);
- }
-
- if (net_getsockname(LOGIN_SSL_LISTEN_FD, NULL, NULL) == 0) {
- if (!ssl_initialized) {
- /* this shouldn't happen, master should have
- disabled the ssl socket.. */
- i_fatal("BUG: SSL initialization parameters "
- "not given while they should have "
- "been");
- }
-
- io_ssl_listen = io_add(LOGIN_SSL_LISTEN_FD, IO_READ,
- login_accept_ssl, NULL);
- }
-
- /* initialize master last - it sends the "we're ok"
- notification */
- master_init(LOGIN_MASTER_SOCKET_FD, TRUE);
+ master_init(LOGIN_MASTER_SOCKET_FD);
+ main_listen_start();
}
}
@@ -332,7 +369,7 @@
return 1;
}
- master_init(master_fd, FALSE);
+ master_init(master_fd);
closing_down = TRUE;
if (fd != -1) {
Index: master.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/login-common/master.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- master.c 26 Feb 2006 10:05:23 -0000 1.18
+++ master.c 6 Aug 2006 20:05:35 -0000 1.19
@@ -26,6 +26,13 @@
struct client *client;
master_callback_t *master_callback;
+ if (reply->tag == 0 && !process_per_connection) {
+ /* this means we have to start listening again.
+ we've reached maximum number of login processes. */
+ main_listen_start();
+ return;
+ }
+
client = hash_lookup(master_requests, POINTER_CAST(reply->tag));
if (client == NULL)
i_fatal("Master sent reply with unknown tag %u", reply->tag);
@@ -73,7 +80,7 @@
client->master_callback = NULL;
}
-void master_notify_finished(void)
+void master_notify_state_change(enum master_login_state state)
{
struct master_login_request req;
@@ -82,6 +89,7 @@
memset(&req, 0, sizeof(req));
req.version = MASTER_LOGIN_PROTOCOL_VERSION;
+ req.tag = state;
/* sending -1 as fd does the notification */
if (fd_send(master_fd, -1, &req, sizeof(req)) != sizeof(req))
@@ -98,7 +106,8 @@
i_fatal("close(master) failed: %m");
master_fd = -1;
- main_close_listen();
+ closing_down = TRUE;
+ main_listen_stop();
main_unref();
/* may call this function again through main_unref() */
@@ -223,7 +232,7 @@
master_pos = 0;
}
-void master_init(int fd, bool notify)
+void master_init(int fd)
{
main_ref();
@@ -233,12 +242,6 @@
master_pos = 0;
io_master = io_add(master_fd, IO_READ, master_input, NULL);
-
- if (notify) {
- /* just a note to master that we're ok. if we die before,
- master should shutdown itself. */
- master_notify_finished();
- }
}
void master_deinit(void)
Index: master.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/login-common/master.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- master.h 13 Jan 2006 20:26:39 -0000 1.5
+++ master.h 6 Aug 2006 20:05:35 -0000 1.6
@@ -11,8 +11,8 @@
unsigned int auth_pid, unsigned int auth_id);
void master_request_abort(struct client *client);
-/* Notify master that we're not listening for new connections anymore. */
-void master_notify_finished(void);
+/* Notify master of a change in our state */
+void master_notify_state_change(enum master_login_state state);
/* Close connection to master process */
void master_close(void);
@@ -20,7 +20,7 @@
/* inetd: Connect to existing master process, or create new one. */
int master_connect(const char *group_name);
-void master_init(int fd, bool notify);
+void master_init(int fd);
void master_deinit(void);
#endif
Index: ssl-proxy-openssl.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/login-common/ssl-proxy-openssl.c,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -d -r1.42 -r1.43
--- ssl-proxy-openssl.c 23 Jul 2006 23:32:11 -0000 1.42
+++ ssl-proxy-openssl.c 6 Aug 2006 20:05:35 -0000 1.43
@@ -26,11 +26,11 @@
/* Check every 30 minutes if parameters file has been updated */
#define SSL_PARAMFILE_CHECK_INTERVAL (60*30)
-#define PLAIN_OUTPUT_OPTIMAL_SIZE 2048
-
-enum ssl_want {
- WANT_INPUT,
- WANT_OUTPUT
+enum ssl_io_action {
+ SSL_ADD_INPUT,
+ SSL_REMOVE_INPUT,
+ SSL_ADD_OUTPUT,
+ SSL_REMOVE_OUTPUT
};
struct ssl_proxy {
@@ -40,13 +40,10 @@
struct ip_addr ip;
int fd_ssl, fd_plain;
- struct io *io_ssl, *io_plain_input;
-
- enum ssl_want want;
- void (*step)(struct ssl_proxy *);
- unsigned int ssl_want_size;
+ struct io *io_ssl_read, *io_ssl_write, *io_plain_read, *io_plain_write;
- struct ostream *plain_output;
+ unsigned char plainout_buf[1024];
+ unsigned int plainout_size;
unsigned char sslout_buf[1024];
unsigned int sslout_size;
@@ -70,8 +67,10 @@
static struct hash_table *ssl_proxies;
static struct ssl_parameters ssl_params;
-static void ssl_input(struct ssl_proxy *proxy);
-static void ssl_output(struct ssl_proxy *proxy);
+static void plain_read(void *context);
+static void plain_write(void *context);
+static void ssl_read(struct ssl_proxy *proxy);
+static void ssl_write(struct ssl_proxy *proxy);
static void ssl_step(void *context);
static void ssl_proxy_destroy(struct ssl_proxy *proxy);
static void ssl_proxy_unref(struct ssl_proxy *proxy);
@@ -188,6 +187,120 @@
}
}
+static void ssl_set_io(struct ssl_proxy *proxy, enum ssl_io_action action)
+{
+ switch (action) {
+ case SSL_ADD_INPUT:
+ if (proxy->io_ssl_read != NULL)
+ break;
+ proxy->io_ssl_read = io_add(proxy->fd_ssl, IO_READ,
+ ssl_step, proxy);
+ break;
+ case SSL_REMOVE_INPUT:
+ if (proxy->io_ssl_read != NULL)
+ io_remove(&proxy->io_ssl_read);
+ break;
+ case SSL_ADD_OUTPUT:
+ if (proxy->io_ssl_write != NULL)
+ break;
+ proxy->io_ssl_write = io_add(proxy->fd_ssl, IO_WRITE,
+ ssl_step, proxy);
+ break;
+ case SSL_REMOVE_OUTPUT:
+ if (proxy->io_ssl_write != NULL)
+ io_remove(&proxy->io_ssl_write);
+ break;
+ }
+}
+
+static void plain_block_input(struct ssl_proxy *proxy, bool block)
+{
+ if (block) {
+ if (proxy->io_plain_read != NULL)
+ io_remove(&proxy->io_plain_read);
+ } else {
+ if (proxy->io_plain_read == NULL) {
+ proxy->io_plain_read = io_add(proxy->fd_plain, IO_READ,
+ plain_read, proxy);
+ }
+ }
+}
+
+static void plain_read(void *context)
+{
+ struct ssl_proxy *proxy = context;
+ ssize_t ret;
+ bool corked = FALSE;
+
+ if (proxy->sslout_size == sizeof(proxy->sslout_buf)) {
+ /* buffer full, block input until it's written */
+ plain_block_input(proxy, TRUE);
+ return;
+ }
+
+ proxy->refcount++;
+
+ while (proxy->sslout_size < sizeof(proxy->sslout_buf) &&
+ !proxy->destroyed) {
+ ret = net_receive(proxy->fd_plain,
+ proxy->sslout_buf + proxy->sslout_size,
+ sizeof(proxy->sslout_buf) -
+ proxy->sslout_size);
+ if (ret <= 0) {
+ if (ret < 0)
+ ssl_proxy_destroy(proxy);
+ break;
+ } else {
+ proxy->sslout_size += ret;
+ if (!corked) {
+ net_set_cork(proxy->fd_ssl, TRUE);
+ corked = TRUE;
+ }
+ ssl_write(proxy);
+ }
+ }
+
+ if (corked)
+ net_set_cork(proxy->fd_ssl, FALSE);
+
+ ssl_proxy_unref(proxy);
+}
+
+static void plain_write(void *context)
+{
+ struct ssl_proxy *proxy = context;
+ ssize_t ret;
+
+ proxy->refcount++;
+
+ ret = net_transmit(proxy->fd_plain, proxy->plainout_buf,
+ proxy->plainout_size);
+ if (ret < 0)
+ ssl_proxy_destroy(proxy);
+ else {
+ proxy->plainout_size -= ret;
+ memmove(proxy->plainout_buf, proxy->plainout_buf + ret,
+ proxy->plainout_size);
+
+ if (proxy->plainout_size > 0) {
+ if (proxy->io_plain_write == NULL) {
+ proxy->io_plain_write =
+ io_add(proxy->fd_plain, IO_WRITE,
+ plain_write, proxy);
+ }
+ } else {
+ if (proxy->io_plain_write != NULL)
+ io_remove(&proxy->io_plain_write);
+ }
+
+ ssl_set_io(proxy, SSL_ADD_INPUT);
+ if (SSL_pending(proxy->ssl) > 0)
+ ssl_read(proxy);
+ }
+
+ ssl_proxy_unref(proxy);
+}
+
static const char *ssl_last_error(void)
{
unsigned long err;
@@ -204,30 +317,8 @@
return buf;
}
-static void ssl_set_io(struct ssl_proxy *proxy, enum ssl_want want)
-{
- if (proxy->io_ssl != NULL) {
- if (want == proxy->want)
- return;
- io_remove(&proxy->io_ssl);
- }
-
- proxy->want = want;
- switch (want) {
- case WANT_INPUT:
- proxy->io_ssl =
- io_add(proxy->fd_ssl, IO_READ, ssl_step, proxy);
- break;
- case WANT_OUTPUT:
- proxy->io_ssl =
- io_add(proxy->fd_ssl, IO_WRITE, ssl_step, proxy);
- break;
- }
-}
-
-static void
-ssl_handle_error(struct ssl_proxy *proxy, int ret, const char *func_name,
- void (*func)(struct ssl_proxy *), unsigned int want_size)
+static void ssl_handle_error(struct ssl_proxy *proxy, int ret,
+ const char *func_name)
{
const char *errstr;
int err;
@@ -236,14 +327,10 @@
switch (err) {
case SSL_ERROR_WANT_READ:
- proxy->step = func;
- proxy->ssl_want_size = want_size;
- ssl_set_io(proxy, WANT_INPUT);
+ ssl_set_io(proxy, SSL_ADD_INPUT);
break;
case SSL_ERROR_WANT_WRITE:
- proxy->step = func;
- proxy->ssl_want_size = want_size;
- ssl_set_io(proxy, WANT_OUTPUT);
+ ssl_set_io(proxy, SSL_ADD_OUTPUT);
break;
case SSL_ERROR_SYSCALL:
/* eat up the error queue */
@@ -282,150 +369,56 @@
}
}
-static void plain_input(void *context)
-{
- struct ssl_proxy *proxy = context;
- ssize_t ret;
-
- if (proxy->sslout_size == sizeof(proxy->sslout_buf)) {
- /* buffer full, block input until it's written */
- io_remove(&proxy->io_plain_input);
- return;
- }
-
- ret = net_receive(proxy->fd_plain,
- proxy->sslout_buf + proxy->sslout_size,
- sizeof(proxy->sslout_buf) - proxy->sslout_size);
- if (ret <= 0) {
- if (ret < 0)
- ssl_proxy_destroy(proxy);
- } else {
- proxy->sslout_size += ret;
- if (SSL_want(proxy->ssl) == SSL_NOTHING) {
- i_assert(proxy->ssl_want_size == 0);
- ssl_output(proxy);
- }
- }
-}
-
-static int plain_output(void *context)
-{
- struct ssl_proxy *proxy = context;
- int ret;
-
- if (proxy->ssl_want_size != 0)
- return 0;
-
- if ((ret = o_stream_flush(proxy->plain_output)) < 0) {
- ssl_proxy_destroy(proxy);
- return 1;
- }
-
- if (o_stream_get_buffer_used_size(proxy->plain_output) <
- PLAIN_OUTPUT_OPTIMAL_SIZE &&
- proxy->want == WANT_INPUT && proxy->io_ssl == NULL)
- ssl_set_io(proxy, WANT_INPUT);
-
- return ret;
-}
-
static void ssl_handshake(struct ssl_proxy *proxy)
{
- int ret, old_errno;
+ int ret;
- net_set_cork(proxy->fd_ssl, TRUE);
ret = SSL_accept(proxy->ssl);
-
- old_errno = errno;
- net_set_cork(proxy->fd_ssl, FALSE);
- errno = old_errno;
-
if (ret != 1)
- ssl_handle_error(proxy, ret, "SSL_accept()", ssl_handshake, 0);
+ ssl_handle_error(proxy, ret, "SSL_accept()");
else {
proxy->handshaked = TRUE;
- proxy->step = ssl_input;
- ssl_set_io(proxy, WANT_INPUT);
- proxy->io_plain_input = io_add(proxy->fd_plain, IO_READ,
- plain_input, proxy);
+ ssl_set_io(proxy, SSL_ADD_INPUT);
+ plain_block_input(proxy, FALSE);
}
}
-static void ssl_input(struct ssl_proxy *proxy)
+static void ssl_read(struct ssl_proxy *proxy)
{
- unsigned char buf[PLAIN_OUTPUT_OPTIMAL_SIZE];
- size_t size, used;
- ssize_t ret, ret2;
-
- used = o_stream_get_buffer_used_size(proxy->plain_output);
- if (used >= PLAIN_OUTPUT_OPTIMAL_SIZE) {
- io_remove(&proxy->io_ssl);
- return;
- }
-
- size = sizeof(buf) - used;
- if (proxy->ssl_want_size != 0) {
- i_assert(proxy->ssl_want_size <= size);
- size = proxy->ssl_want_size;
- proxy->ssl_want_size = 0;
- }
+ int ret;
- do {
- ret = SSL_read(proxy->ssl, buf, size);
+ while (proxy->plainout_size < sizeof(proxy->plainout_buf) &&
+ !proxy->destroyed) {
+ ret = SSL_read(proxy->ssl,
+ proxy->plainout_buf + proxy->plainout_size,
+ sizeof(proxy->plainout_buf) -
+ proxy->plainout_size);
if (ret <= 0) {
- ssl_handle_error(proxy, ret, "SSL_read()",
- ssl_input, size);
- return;
+ ssl_handle_error(proxy, ret, "SSL_read()");
+ break;
+ } else {
+ proxy->plainout_size += ret;
+ plain_write(proxy);
}
- o_stream_cork(proxy->plain_output);
- ret2 = o_stream_send(proxy->plain_output, buf, ret);
- i_assert(ret2 < 0 || ret2 == ret);
- o_stream_uncork(proxy->plain_output);
-
- if (proxy->sslout_size > 0)
- ssl_output(proxy);
- } while (SSL_pending(proxy->ssl) > 0);
+ }
}
-static void ssl_output(struct ssl_proxy *proxy)
+static void ssl_write(struct ssl_proxy *proxy)
{
- unsigned int size;
- int ret, old_errno;
+ int ret;
- if (proxy->ssl_want_size == 0)
- size = proxy->sslout_size;
+ ret = SSL_write(proxy->ssl, proxy->sslout_buf, proxy->sslout_size);
+ if (ret <= 0)
+ ssl_handle_error(proxy, ret, "SSL_write()");
else {
- i_assert(proxy->ssl_want_size <= proxy->sslout_size);
- size = proxy->ssl_want_size;
- proxy->ssl_want_size = 0;
- }
-
- net_set_cork(proxy->fd_ssl, TRUE);
- ret = SSL_write(proxy->ssl, proxy->sslout_buf, size);
-
- old_errno = errno;
- net_set_cork(proxy->fd_ssl, FALSE);
- errno = old_errno;
-
- if (ret <= 0) {
- ssl_handle_error(proxy, ret, "SSL_write()", ssl_output, size);
- return;
- }
-
- proxy->sslout_size -= ret;
- memmove(proxy->sslout_buf, proxy->sslout_buf + ret, proxy->sslout_size);
+ proxy->sslout_size -= ret;
+ memmove(proxy->sslout_buf, proxy->sslout_buf + ret,
+ proxy->sslout_size);
- if (proxy->sslout_size > 0) {
- ssl_set_io(proxy, WANT_OUTPUT);
- proxy->step = ssl_output;
- } else {
- ssl_set_io(proxy, WANT_INPUT);
- proxy->step = ssl_input;
- }
- if (proxy->io_plain_input == NULL) {
- proxy->io_plain_input = io_add(proxy->fd_plain, IO_READ,
- plain_input, proxy);
+ ssl_set_io(proxy, proxy->sslout_size > 0 ?
+ SSL_ADD_OUTPUT : SSL_REMOVE_OUTPUT);
+ plain_block_input(proxy, FALSE);
}
}
@@ -433,7 +426,27 @@
{
struct ssl_proxy *proxy = context;
- proxy->step(proxy);
+ proxy->refcount++;
+
+ if (!proxy->handshaked)
+ ssl_handshake(proxy);
+
+ if (proxy->handshaked) {
+ if (proxy->plainout_size == sizeof(proxy->plainout_buf))
+ ssl_set_io(proxy, SSL_REMOVE_INPUT);
+ else
+ ssl_read(proxy);
+
+ if (proxy->sslout_size == 0)
+ ssl_set_io(proxy, SSL_REMOVE_OUTPUT);
+ else {
+ net_set_cork(proxy->fd_ssl, TRUE);
+ ssl_write(proxy);
+ net_set_cork(proxy->fd_ssl, FALSE);
+ }
+ }
+
+ ssl_proxy_unref(proxy);
}
int ssl_proxy_new(int fd, struct ip_addr *ip, struct ssl_proxy **proxy_r)
@@ -479,16 +492,10 @@
proxy->fd_ssl = fd;
proxy->fd_plain = sfd[0];
proxy->ip = *ip;
- proxy->plain_output =
- o_stream_create_file(proxy->fd_plain, default_pool,
- (size_t)-1, FALSE);
- o_stream_set_flush_callback(proxy->plain_output, plain_output, proxy);
-
SSL_set_ex_data(ssl, extdata_index, proxy);
hash_insert(ssl_proxies, proxy, proxy);
- proxy->step = ssl_handshake;
ssl_handshake(proxy);
main_ref();
@@ -549,16 +556,21 @@
hash_remove(ssl_proxies, proxy);
- if (proxy->io_ssl != NULL)
- io_remove(&proxy->io_ssl);
- if (proxy->io_plain_input != NULL)
- io_remove(&proxy->io_plain_input);
+ if (proxy->io_ssl_read != NULL)
+ io_remove(&proxy->io_ssl_read);
+ if (proxy->io_ssl_write != NULL)
+ io_remove(&proxy->io_ssl_write);
+ if (proxy->io_plain_read != NULL)
+ io_remove(&proxy->io_plain_read);
+ if (proxy->io_plain_write != NULL)
+ io_remove(&proxy->io_plain_write);
- o_stream_unref(&proxy->plain_output);
(void)net_disconnect(proxy->fd_ssl);
(void)net_disconnect(proxy->fd_plain);
ssl_proxy_unref(proxy);
+
+ main_listen_start();
}
static RSA *ssl_gen_rsa_key(SSL *ssl __attr_unused__,
@@ -641,6 +653,11 @@
return strlen(buf);
}
+unsigned int ssl_proxy_get_count(void)
+{
+ return hash_size(ssl_proxies);
+}
+
void ssl_proxy_init(void)
{
const char *cafile, *certfile, *keyfile, *cipher_list;
Index: ssl-proxy.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/login-common/ssl-proxy.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- ssl-proxy.c 13 Jan 2006 20:26:39 -0000 1.7
+++ ssl-proxy.c 6 Aug 2006 20:05:36 -0000 1.8
@@ -28,6 +28,11 @@
void ssl_proxy_free(struct ssl_proxy *proxy __attr_unused__) {}
+unsigned int ssl_proxy_get_count(void)
+{
+ return 0;
+}
+
void ssl_proxy_init(void) {}
void ssl_proxy_deinit(void) {}
Index: ssl-proxy.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/login-common/ssl-proxy.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- ssl-proxy.h 13 Jan 2006 20:26:39 -0000 1.6
+++ ssl-proxy.h 6 Aug 2006 20:05:36 -0000 1.7
@@ -14,6 +14,9 @@
const char *ssl_proxy_get_peer_name(struct ssl_proxy *proxy);
void ssl_proxy_free(struct ssl_proxy *proxy);
+/* Return number of active SSL proxies */
+unsigned int ssl_proxy_get_count(void);
+
void ssl_proxy_init(void);
void ssl_proxy_deinit(void);
More information about the dovecot-cvs
mailing list