dovecot-2.2: director: Added a new DIRECTOR-LOOKUP command that ...
dovecot at dovecot.org
dovecot at dovecot.org
Wed May 13 02:27:36 UTC 2015
details: http://hg.dovecot.org/dovecot-2.2/rev/e178413a905d
changeset: 18666:e178413a905d
user: Timo Sirainen <tss at iki.fi>
date: Wed May 13 05:25:31 2015 +0300
description:
director: Added a new DIRECTOR-LOOKUP command that auth connections can use.
The parameters are the same as what auth lookup would receive from auth
process. So the idea is that a proxy could do an auth lookup, then forward
the reply to director, which would return back the updated reply with the
host field added.
diffstat:
src/director/auth-connection.c | 8 +---
src/director/auth-connection.h | 5 +-
src/director/login-connection.c | 68 ++++++++++++++++++++++++++++++++++------
3 files changed, 63 insertions(+), 18 deletions(-)
diffs (161 lines):
diff -r b7aed6290e7e -r e178413a905d src/director/auth-connection.c
--- a/src/director/auth-connection.c Wed May 13 05:22:22 2015 +0300
+++ b/src/director/auth-connection.c Wed May 13 05:25:31 2015 +0300
@@ -121,12 +121,10 @@
conn->callback(NULL, conn->context);
}
-void auth_connection_send(struct auth_connection *conn,
- const void *data, size_t size)
+struct ostream *auth_connection_send(struct auth_connection *conn)
{
- i_assert(conn->fd != -1);
-
- o_stream_nsend(conn->output, data, size);
+ i_assert(conn->output != NULL);
+ return conn->output;
}
void auth_connections_deinit(void)
diff -r b7aed6290e7e -r e178413a905d src/director/auth-connection.h
--- a/src/director/auth-connection.h Wed May 13 05:22:22 2015 +0300
+++ b/src/director/auth-connection.h Wed May 13 05:25:31 2015 +0300
@@ -13,9 +13,8 @@
/* Start connecting. Returns 0 if ok, -1 if connect failed. */
int auth_connection_connect(struct auth_connection *conn);
-/* Send data to auth connection. */
-void auth_connection_send(struct auth_connection *conn,
- const void *data, size_t size);
+/* Get auth connection's output stream. */
+struct ostream *auth_connection_send(struct auth_connection *conn);
void auth_connections_deinit(void);
diff -r b7aed6290e7e -r e178413a905d src/director/login-connection.c
--- a/src/director/login-connection.c Wed May 13 05:22:22 2015 +0300
+++ b/src/director/login-connection.c Wed May 13 05:25:31 2015 +0300
@@ -3,8 +3,10 @@
#include "lib.h"
#include "ioloop.h"
#include "net.h"
+#include "istream.h"
#include "ostream.h"
#include "llist.h"
+#include "str.h"
#include "master-service.h"
#include "director.h"
#include "director-request.h"
@@ -20,12 +22,14 @@
int fd;
struct io *io;
+ struct istream *input;
struct ostream *output;
struct auth_connection *auth;
struct director *dir;
unsigned int destroyed:1;
unsigned int userdb:1;
+ unsigned int input_newline:1;
};
struct login_host_request {
@@ -40,25 +44,66 @@
static struct login_connection *login_connections;
+static void auth_input_line(const char *line, void *context);
static void login_connection_unref(struct login_connection **_conn);
+static void
+login_connection_director_lookup(struct login_connection *conn,
+ const unsigned char *data, size_t size)
+{
+ T_BEGIN {
+ string_t *line = t_str_new(128);
+ str_append(line, "OK\t");
+ str_append_n(line, data, size);
+ auth_input_line(str_c(line), conn);
+ } T_END;
+}
+
static void login_connection_input(struct login_connection *conn)
{
- unsigned char buf[4096];
- ssize_t ret;
+ const unsigned char *data, *p;
+ size_t size;
+ struct ostream *auth_output;
- ret = read(conn->fd, buf, sizeof(buf));
- if (ret <= 0) {
- if (ret < 0) {
- if (errno == EAGAIN)
- return;
- if (errno != ECONNRESET)
- i_error("read(login connection) failed: %m");
+ auth_output = auth_connection_send(conn->auth);
+ switch (i_stream_read(conn->input)) {
+ case -2:
+ data = i_stream_get_data(conn->input, &size);
+ o_stream_nsend(auth_output, data, size);
+ i_stream_skip(conn->input, size);
+ conn->input_newline = FALSE;
+ return;
+ case -1:
+ if (conn->input->stream_errno != 0 &&
+ conn->input->stream_errno != ECONNRESET) {
+ i_error("read(login connection) failed: %s",
+ i_stream_get_error(conn->input));
}
login_connection_deinit(&conn);
return;
+ case 0:
+ return;
+ default:
+ break;
}
- auth_connection_send(conn->auth, buf, ret);
+
+ o_stream_cork(auth_output);
+ data = i_stream_get_data(conn->input, &size);
+ while ((p = memchr(data, '\n', size)) != NULL) {
+ size_t linelen = p-data;
+
+ if (!conn->input_newline || linelen <= 16 ||
+ memcmp(data, "DIRECTOR-LOOKUP\t", 16) != 0) {
+ /* forward data to auth process */
+ o_stream_nsend(auth_output, data, linelen+1);
+ conn->input_newline = TRUE;
+ } else {
+ login_connection_director_lookup(conn, data+16, linelen-16);
+ }
+ i_stream_skip(conn->input, linelen+1);
+ data = i_stream_get_data(conn->input, &size);
+ }
+ o_stream_uncork(auth_output);
}
static void
@@ -215,10 +260,12 @@
conn->fd = fd;
conn->auth = auth;
conn->dir = dir;
+ conn->input = i_stream_create_fd(conn->fd, IO_BLOCK_SIZE, FALSE);
conn->output = o_stream_create_fd(conn->fd, (size_t)-1, FALSE);
o_stream_set_no_error_handling(conn->output, TRUE);
conn->io = io_add(conn->fd, IO_READ, login_connection_input, conn);
conn->userdb = userdb;
+ conn->input_newline = TRUE;
auth_connection_set_callback(conn->auth, auth_input_line, conn);
DLLIST_PREPEND(&login_connections, conn);
@@ -237,6 +284,7 @@
DLLIST_REMOVE(&login_connections, conn);
io_remove(&conn->io);
+ i_stream_destroy(&conn->input);
o_stream_destroy(&conn->output);
if (close(conn->fd) < 0)
i_error("close(login connection) failed: %m");
More information about the dovecot-cvs
mailing list