From: Stephan Bosch Date: Sun, 31 Jul 2022 22:08:40 +0000 (+0200) Subject: lib-imap-urlauth: imap-urlauth-connection - Use the connection.h API. X-Git-Tag: 2.4.0~2881 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4d61c235a49285bba4133df635f9ca8a50170964;p=thirdparty%2Fdovecot%2Fcore.git lib-imap-urlauth: imap-urlauth-connection - Use the connection.h API. --- diff --git a/src/lib-imap-urlauth/imap-urlauth-connection.c b/src/lib-imap-urlauth/imap-urlauth-connection.c index acf1bef2b2..89bcc7b5ce 100644 --- a/src/lib-imap-urlauth/imap-urlauth-connection.c +++ b/src/lib-imap-urlauth/imap-urlauth-connection.c @@ -14,6 +14,7 @@ #include "write-full.h" #include "array.h" #include "aqueue.h" +#include "connection.h" #include "mail-user.h" #include "imap-urlauth-fetch.h" @@ -21,6 +22,7 @@ enum imap_urlauth_state { IMAP_URLAUTH_STATE_DISCONNECTED = 0, + IMAP_URLAUTH_STATE_CONNECTING, IMAP_URLAUTH_STATE_AUTHENTICATING, IMAP_URLAUTH_STATE_AUTHENTICATED, IMAP_URLAUTH_STATE_SELECTING_TARGET, @@ -54,17 +56,12 @@ struct imap_urlauth_target { }; struct imap_urlauth_connection { - int refcount; + struct connection conn; struct event *event; char *path, *service, *session_id; struct mail_user *user; - int fd; - struct istream *input; - struct ostream *output; - struct io *io; - struct timeout *to_reconnect, *to_idle, *to_response; time_t last_reconnect; unsigned int reconnect_attempts; @@ -88,10 +85,15 @@ struct imap_urlauth_connection { #define IMAP_URLAUTH_RESPONSE_TIMEOUT_MSECS 2*60*1000 -#define IMAP_URLAUTH_HANDSHAKE "VERSION\timap-urlauth\t2\t0\n" - #define IMAP_URLAUTH_MAX_INLINE_LITERAL_SIZE (1024*32) +static struct connection_list *imap_urlauth_connections = NULL; + +static void imap_urlauth_connection_connected(struct connection *_conn, + bool success); +static void imap_urlauth_connection_input(struct connection *_conn); +static void imap_urlauth_connection_destroy(struct connection *_conn); + static void imap_urlauth_connection_disconnect(struct imap_urlauth_connection *conn, const char *reason); @@ -107,6 +109,22 @@ imap_urlauth_connection_timeout_abort(struct imap_urlauth_connection *conn); static void imap_urlauth_connection_fail(struct imap_urlauth_connection *conn); +static const struct connection_vfuncs imap_urlauth_connection_vfuncs = { + .destroy = imap_urlauth_connection_destroy, + .input = imap_urlauth_connection_input, + .client_connected = imap_urlauth_connection_connected, +}; + +static const struct connection_settings imap_urlauth_connection_set = { + .service_name_in = "imap-urlauth", + .service_name_out = "imap-urlauth", + .major_version = IMAP_URLAUTH_PROTOCOL_MAJOR_VERSION, + .minor_version = IMAP_URLAUTH_PROTOCOL_MINOR_VERSION, + .input_max_size = SIZE_MAX, + .output_max_size = SIZE_MAX, + .client = TRUE, +}; + struct imap_urlauth_connection * imap_urlauth_connection_init(const char *path, const char *service, struct mail_user *user, const char *session_id, @@ -114,18 +132,27 @@ imap_urlauth_connection_init(const char *path, const char *service, { struct imap_urlauth_connection *conn; + if (imap_urlauth_connections == NULL) { + imap_urlauth_connections = + connection_list_init(&imap_urlauth_connection_set, + &imap_urlauth_connection_vfuncs); + } + conn = i_new(struct imap_urlauth_connection, 1); - conn->refcount = 1; conn->service = i_strdup(service); conn->path = i_strdup(path); if (session_id != NULL) conn->session_id = i_strdup(session_id); conn->user = user; - conn->fd = -1; conn->literal_fd = -1; conn->idle_timeout_msecs = idle_timeout_msecs; + conn->event = event_create(user->event); event_set_append_log_prefix(conn->event, "imap-urlauth: "); + + conn->conn.event_parent = conn->event; + connection_init_client_unix(imap_urlauth_connections, + &conn->conn, conn->path); return conn; } @@ -146,8 +173,12 @@ void imap_urlauth_connection_deinit(struct imap_urlauth_connection **_conn) i_assert(conn->to_reconnect == NULL); i_assert(conn->to_response == NULL); + connection_deinit(&conn->conn); event_unref(&conn->event); i_free(conn); + + if (imap_urlauth_connections->connections == NULL) + connection_list_deinit(&imap_urlauth_connections); } static void @@ -204,7 +235,7 @@ imap_urlauth_connection_select_target(struct imap_urlauth_connection *conn) conn->state = IMAP_URLAUTH_STATE_SELECTING_TARGET; cmd = t_strdup_printf("USER\t%s\n", str_tabescape(target->userid)); - if (o_stream_send_str(conn->output, cmd) < 0) { + if (o_stream_send_str(conn->conn.output, cmd) < 0) { e_warning(conn->event, "Error sending USER request to imap-urlauth server: %m"); imap_urlauth_connection_fail(conn); @@ -249,7 +280,7 @@ imap_urlauth_connection_send_request(struct imap_urlauth_connection *conn) conn->state = IMAP_URLAUTH_STATE_UNSELECTING_TARGET; imap_urlauth_target_free(conn, conn->targets_head); - if (o_stream_send_str(conn->output, "END\n") < 0) { + if (o_stream_send_str(conn->conn.output, "END\n") < 0) { e_warning(conn->event, "Error sending END request to imap-urlauth server: %m"); imap_urlauth_connection_fail(conn); @@ -272,7 +303,7 @@ imap_urlauth_connection_send_request(struct imap_urlauth_connection *conn) str_append_c(cmd, '\n'); conn->state = IMAP_URLAUTH_STATE_REQUEST_PENDING; - if (o_stream_send(conn->output, str_data(cmd), str_len(cmd)) < 0) { + if (o_stream_send(conn->conn.output, str_data(cmd), str_len(cmd)) < 0) { e_warning(conn->event, "Error sending URL request to imap-urlauth server: %m"); imap_urlauth_connection_fail(conn); @@ -560,7 +591,7 @@ imap_urlauth_connection_read_literal_data(struct imap_urlauth_connection *conn) size_t size; /* Read data */ - data = i_stream_get_data(conn->input, &size); + data = i_stream_get_data(conn->conn.input, &size); if (size > conn->literal_bytes_left) size = conn->literal_bytes_left; @@ -576,7 +607,7 @@ imap_urlauth_connection_read_literal_data(struct imap_urlauth_connection *conn) i_assert(conn->literal_buf != NULL); buffer_append(conn->literal_buf, data, size); } - i_stream_skip(conn->input, size); + i_stream_skip(conn->conn.input, size); conn->literal_bytes_left -= size; } @@ -585,7 +616,7 @@ imap_urlauth_connection_read_literal_data(struct imap_urlauth_connection *conn) return 0; /* Read LF guard */ - data = i_stream_get_data(conn->input, &size); + data = i_stream_get_data(conn->conn.input, &size); if (size < 1) return 0; @@ -595,7 +626,7 @@ imap_urlauth_connection_read_literal_data(struct imap_urlauth_connection *conn) data[0]); return -1; } - i_stream_skip(conn->input, 1); + i_stream_skip(conn->conn.input, 1); return 1; } @@ -698,6 +729,24 @@ imap_urlauth_connection_read_literal(struct imap_urlauth_connection *conn) return 1; } +static void imap_urlauth_connection_destroy(struct connection *_conn) +{ + struct imap_urlauth_connection *conn = + container_of(_conn, struct imap_urlauth_connection, conn); + + switch (_conn->disconnect_reason) { + case CONNECTION_DISCONNECT_HANDSHAKE_FAILED: + imap_urlauth_connection_disconnect( + conn, "Handshake with imap-urlauth service failed"); + break; + case CONNECTION_DISCONNECT_BUFFER_FULL: + i_unreached(); + default: + /* Disconnected */ + imap_urlauth_connection_reconnect(conn); + } +} + static int imap_urlauth_input_pending(struct imap_urlauth_connection *conn) { struct imap_urlauth_request *urlreq; @@ -715,7 +764,7 @@ static int imap_urlauth_input_pending(struct imap_urlauth_connection *conn) /* "OK"[]"\t""\n" or "NO"["\terror="]"\n" */ - if ((response = i_stream_next_line(conn->input)) == NULL) + if ((response = i_stream_next_line(conn->conn.input)) == NULL) return 0; imap_urlauth_stop_response_timeout(conn); @@ -777,9 +826,10 @@ static int imap_urlauth_authenticate(struct imap_urlauth_connection *conn) { string_t *str; + conn->state = IMAP_URLAUTH_STATE_AUTHENTICATING; + str = t_str_new(128); - str_printfa(str, IMAP_URLAUTH_HANDSHAKE"AUTH\t%s\t%s\t", - conn->service, my_pid); + str_printfa(str, "AUTH\t%s\t%s\t", conn->service, my_pid); str_append_tabescaped(str, conn->user->username); str_append_c(str, '\t'); if (conn->session_id != NULL) @@ -787,12 +837,13 @@ static int imap_urlauth_authenticate(struct imap_urlauth_connection *conn) str_append_c(str, '\t'); str_append_tabescaped(str, conn->user->auth_token); str_append_c(str, '\n'); - if (o_stream_send(conn->output, str_data(str), str_len(str)) < 0) { + if (o_stream_send(conn->conn.output, str_data(str), str_len(str)) < 0) { e_warning(conn->event, "Error sending handshake to imap-urlauth server: %m"); imap_urlauth_connection_abort(conn, NULL); return -1; } + return 0; } @@ -802,9 +853,11 @@ static int imap_urlauth_input_next(struct imap_urlauth_connection *conn) int ret; switch (conn->state) { + case IMAP_URLAUTH_STATE_CONNECTING: + break; case IMAP_URLAUTH_STATE_AUTHENTICATING: case IMAP_URLAUTH_STATE_UNSELECTING_TARGET: - if ((response = i_stream_next_line(conn->input)) == NULL) + if ((response = i_stream_next_line(conn->conn.input)) == NULL) return 0; imap_urlauth_stop_response_timeout(conn); @@ -836,7 +889,7 @@ static int imap_urlauth_input_next(struct imap_urlauth_connection *conn) imap_urlauth_connection_select_target(conn); return 0; case IMAP_URLAUTH_STATE_SELECTING_TARGET: - if ((response = i_stream_next_line(conn->input)) == NULL) + if ((response = i_stream_next_line(conn->conn.input)) == NULL) return 0; imap_urlauth_stop_response_timeout(conn); @@ -870,7 +923,7 @@ static int imap_urlauth_input_next(struct imap_urlauth_connection *conn) case IMAP_URLAUTH_STATE_AUTHENTICATED: case IMAP_URLAUTH_STATE_READY: case IMAP_URLAUTH_STATE_REQUEST_WAIT: - if ((response = i_stream_next_line(conn->input)) == NULL) + if ((response = i_stream_next_line(conn->conn.input)) == NULL) return 0; e_error(conn->event, @@ -888,18 +941,21 @@ static int imap_urlauth_input_next(struct imap_urlauth_connection *conn) i_unreached(); } -static void imap_urlauth_input(struct imap_urlauth_connection *conn) +static void imap_urlauth_connection_input(struct connection *_conn) { + struct imap_urlauth_connection *conn = + container_of(_conn, struct imap_urlauth_connection, conn); + i_assert(conn->state != IMAP_URLAUTH_STATE_DISCONNECTED); - if (conn->input->closed) { + if (conn->conn.input->closed) { /* Disconnected */ e_error(conn->event, "Service disconnected unexpectedly"); imap_urlauth_connection_fail(conn); return; } - switch (i_stream_read(conn->input)) { + switch (i_stream_read(conn->conn.input)) { case -1: /* Disconnected */ e_error(conn->event, "Service disconnected unexpectedly"); @@ -912,21 +968,36 @@ static void imap_urlauth_input(struct imap_urlauth_connection *conn) return; } - while (!conn->input->closed) { + while (!conn->conn.input->closed) { if (imap_urlauth_input_next(conn) <= 0) break; } } +static void +imap_urlauth_connection_connected(struct connection *_conn, bool success) +{ + struct imap_urlauth_connection *conn = + container_of(_conn, struct imap_urlauth_connection, conn); + + /* Cannot get here unless UNIX socket connect() was successful */ + i_assert(success); + + if (imap_urlauth_authenticate(conn) < 0) + return; + + imap_urlauth_start_response_timeout(conn); +} + static int imap_urlauth_connection_do_connect(struct imap_urlauth_connection *conn) { - int fd; - - if (conn->state != IMAP_URLAUTH_STATE_DISCONNECTED) { + if (conn->state >= IMAP_URLAUTH_STATE_AUTHENTICATED) { imap_urlauth_connection_send_request(conn); return 1; } + if (conn->state >= IMAP_URLAUTH_STATE_CONNECTING) + return 1; if (conn->user->auth_token == NULL) { e_error(conn->event, @@ -938,27 +1009,17 @@ imap_urlauth_connection_do_connect(struct imap_urlauth_connection *conn) e_debug(conn->event, "Connecting to service at %s", conn->path); - i_assert(conn->fd == -1); - fd = net_connect_unix(conn->path); - if (fd == -1) { + timeout_remove(&conn->to_reconnect); + + conn->state = IMAP_URLAUTH_STATE_CONNECTING; + imap_urlauth_start_response_timeout(conn); + + if (connection_client_connect(&conn->conn) < 0) { e_error(conn->event, "net_connect_unix(%s) failed: %m", conn->path); imap_urlauth_connection_abort(conn, NULL); return -1; } - - timeout_remove(&conn->to_reconnect); - - conn->fd = fd; - conn->input = i_stream_create_fd(fd, SIZE_MAX); - conn->output = o_stream_create_fd(fd, SIZE_MAX); - conn->io = io_add(fd, IO_READ, imap_urlauth_input, conn); - conn->state = IMAP_URLAUTH_STATE_AUTHENTICATING; - - if (imap_urlauth_authenticate(conn) < 0) - return -1; - - imap_urlauth_start_response_timeout(conn); return 0; } @@ -971,22 +1032,19 @@ int imap_urlauth_connection_connect(struct imap_urlauth_connection *conn) return 0; } -static void imap_urlauth_connection_disconnect -(struct imap_urlauth_connection *conn, const char *reason) +static void +imap_urlauth_connection_disconnect(struct imap_urlauth_connection *conn, + const char *reason) { conn->state = IMAP_URLAUTH_STATE_DISCONNECTED; - if (conn->fd != -1) { + if (!conn->conn.disconnected) { if (reason == NULL) e_debug(conn->event, "Disconnecting from service"); else e_debug(conn->event, "Disconnected: %s", reason); - io_remove(&conn->io); - i_stream_destroy(&conn->input); - o_stream_destroy(&conn->output); - net_disconnect(conn->fd); - conn->fd = -1; + connection_disconnect(&conn->conn); } conn->reading_literal = FALSE; @@ -1054,6 +1112,6 @@ imap_urlauth_connection_timeout_abort(struct imap_urlauth_connection *conn) bool imap_urlauth_connection_is_connected(struct imap_urlauth_connection *conn) { - return (conn->fd != -1 && + return (conn->conn.disconnected && conn->state != IMAP_URLAUTH_STATE_DISCONNECTED); } diff --git a/src/lib-imap-urlauth/imap-urlauth-connection.h b/src/lib-imap-urlauth/imap-urlauth-connection.h index b60186a2c7..f74156490f 100644 --- a/src/lib-imap-urlauth/imap-urlauth-connection.h +++ b/src/lib-imap-urlauth/imap-urlauth-connection.h @@ -1,6 +1,9 @@ #ifndef IMAP_URLAUTH_CONNECTION_H #define IMAP_URLAUTH_CONNECTION_H +#define IMAP_URLAUTH_PROTOCOL_MAJOR_VERSION 2 +#define IMAP_URLAUTH_PROTOCOL_MINOR_VERSION 0 + struct imap_urlauth_request; struct imap_urlauth_fetch_reply;