i_set_failure_prefix("imap-hibernate: ");
}
-static const char *imap_client_get_anvil_userip_ident(struct imap_client_state *state)
-{
- if (state->remote_ip.family == 0)
- return NULL;
- return t_strconcat(net_ip2addr(&state->remote_ip), "/",
- str_tabescape(state->username), NULL);
-}
-
struct imap_client *
imap_client_create(int fd, const struct imap_client_state *state)
{
struct imap_client *client;
pool_t pool = pool_alloconly_create("imap client", 256);
void *statebuf;
- const char *ident, *error;
+ const char *error;
i_assert(state->username != NULL);
i_assert(state->mail_log_prefix != NULL);
client->log_prefix = p_strdup(pool, str_c(str));
} T_END;
- ident = imap_client_get_anvil_userip_ident(&client->state);
- if (ident != NULL) {
- if (master_service_anvil_send(master_service, t_strconcat(
- "CONNECT\t", my_pid, "\timap/", ident, "\n", NULL)))
- client->state.anvil_sent = TRUE;
- }
+ struct master_service_anvil_session anvil_session = {
+ .username = client->state.username,
+ .service_name = "imap",
+ .ip = client->state.remote_ip,
+ };
+ if (master_service_anvil_connect(master_service, &anvil_session))
+ client->state.anvil_sent = TRUE;
p_array_init(&client->notifys, pool, 2);
DLLIST_PREPEND(&imap_clients, client);
}
if (client->state.anvil_sent) {
- master_service_anvil_send(master_service, t_strconcat(
- "DISCONNECT\t", my_pid, "\timap/",
- imap_client_get_anvil_userip_ident(&client->state),
- "\n", NULL));
+ struct master_service_anvil_session anvil_session = {
+ .username = client->state.username,
+ .service_name = "imap",
+ .ip = client->state.remote_ip,
+ };
+ master_service_anvil_disconnect(master_service, &anvil_session);
}
if (client->master_conn != NULL)
{
const struct mail_storage_settings *mail_set;
struct client *client;
- const char *ident;
pool_t pool;
/* always use nonblocking I/O */
client_add_capability(client, "SPECIAL-USE");
}
- ident = mail_user_get_anvil_userip_ident(client->user);
- if (ident != NULL) {
- if (master_service_anvil_send(master_service, t_strconcat(
- "CONNECT\t", my_pid, "\timap/", ident, "\n", NULL)))
- client->anvil_sent = TRUE;
- }
+ struct master_service_anvil_session anvil_session;
+ mail_user_get_anvil_session(client->user, &anvil_session);
+ if (master_service_anvil_connect(master_service, &anvil_session))
+ client->anvil_sent = TRUE;
imap_client_count++;
DLLIST_PREPEND(&imap_clients, client);
if (client->mailbox != NULL)
imap_client_close_mailbox(client);
if (client->anvil_sent) {
- master_service_anvil_send(master_service, t_strconcat(
- "DISCONNECT\t", my_pid, "\timap/",
- mail_user_get_anvil_userip_ident(client->user),
- "\n", NULL));
+ struct master_service_anvil_session anvil_session;
+ mail_user_get_anvil_session(client->user, &anvil_session);
+ master_service_anvil_disconnect(master_service, &anvil_session);
}
if (client->free_parser != NULL)
#include "hostpid.h"
#include "path-util.h"
#include "array.h"
+#include "str.h"
#include "strescape.h"
#include "env-util.h"
#include "home-expand.h"
(service->flags & MASTER_SERVICE_FLAG_STANDALONE) == 0;
}
-bool master_service_anvil_send(struct master_service *service, const char *cmd)
+static bool
+master_service_anvil_send(struct master_service *service, const char *cmd)
{
ssize_t ret;
}
}
+static void
+master_service_anvil_session_to_cmd(string_t *cmd,
+ const struct master_service_anvil_session *session)
+{
+ str_printfa(cmd, "%s\t", my_pid);
+ str_append_tabescaped(cmd, session->service_name);
+ if (session->ip.family != 0) {
+ str_append_c(cmd, '/');
+ str_append(cmd, net_ip2addr(&session->ip));
+ }
+ str_append_c(cmd, '/');
+ str_append_tabescaped(cmd, session->username);
+}
+
+bool master_service_anvil_connect(struct master_service *service,
+ const struct master_service_anvil_session *session)
+{
+ string_t *cmd = t_str_new(128);
+ str_append(cmd, "CONNECT\t");
+ master_service_anvil_session_to_cmd(cmd, session);
+ str_append_c(cmd, '\n');
+ return master_service_anvil_send(service, str_c(cmd));
+}
+
+void master_service_anvil_disconnect(struct master_service *service,
+ const struct master_service_anvil_session *session)
+{
+ string_t *cmd = t_str_new(128);
+ str_append(cmd, "DISCONNECT\t");
+ master_service_anvil_session_to_cmd(cmd, session);
+ str_append_c(cmd, '\n');
+ (void)master_service_anvil_send(service, str_c(cmd));
+}
+
void master_service_client_connection_created(struct master_service *service)
{
i_assert(service->master_status.available_count > 0);
bool accepted:1;
};
+struct master_service_anvil_session {
+ const char *username;
+ const char *service_name;
+ struct ip_addr ip;
+};
+
typedef void
master_service_connection_callback_t(struct master_service_connection *conn);
standalone. */
bool master_service_is_master_stopped(struct master_service *service);
-/* Send command to anvil process, if we have fd to it. Returns TRUE if it was
- successfully sent. */
-bool master_service_anvil_send(struct master_service *service, const char *cmd);
+/* Send CONNECT command to anvil process, if it's still connected.
+ Returns TRUE if it was successfully sent. */
+bool master_service_anvil_connect(struct master_service *service,
+ const struct master_service_anvil_session *session);
+/* Send DISCONNECT command to anvil process, if it's still connected. */
+void master_service_anvil_disconnect(struct master_service *service,
+ const struct master_service_anvil_session *session);
/* Call to accept the client connection. Otherwise the connection is closed. */
void master_service_client_connection_accept(struct master_service_connection *conn);
/* Used to create "extra client connections" outside the common accept()
return mail_storage_lock_create(path, &lock_set, mail_set, lock_r, error_r);
}
-const char *mail_user_get_anvil_userip_ident(struct mail_user *user)
+void mail_user_get_anvil_session(struct mail_user *user,
+ struct master_service_anvil_session *session_r)
{
- if (user->conn.remote_ip == NULL)
- return NULL;
- return t_strconcat(net_ip2addr(user->conn.remote_ip), "/",
- str_tabescape(user->username), NULL);
+ i_zero(session_r);
+ session_r->username = user->username;
+ session_r->service_name = master_service_get_name(master_service);
+ if (user->conn.remote_ip != NULL)
+ session_r->ip = *user->conn.remote_ip;
}
static void
struct stats;
struct fs_settings;
struct ssl_iostream_settings;
+struct master_service_anvil_session;
struct mail_user;
struct dict_op_settings;
const char *mail_user_home_expand(struct mail_user *user, const char *path);
/* Returns 0 if ok, -1 if home directory isn't set. */
int mail_user_try_home_expand(struct mail_user *user, const char **path);
-/* Returns unique user+ip identifier for anvil. */
-const char *mail_user_get_anvil_userip_ident(struct mail_user *user);
+/* Fill out anvil session struct for the user session. */
+void mail_user_get_anvil_session(struct mail_user *user,
+ struct master_service_anvil_session *session_r);
/* Basically the same as mail_storage_find_class(), except automatically load
storage plugins when needed. */
llrcpt->anvil_connect_sent = FALSE;
input = mail_storage_service_user_get_input(llrcpt->service_user);
- master_service_anvil_send(master_service, t_strconcat(
- "DISCONNECT\t", my_pid, "\t", master_service_get_name(master_service),
- "/", input->username, "\n", NULL));
+ struct master_service_anvil_session anvil_session = {
+ .username = input->username,
+ .service_name = master_service_get_name(master_service),
+ };
+ master_service_anvil_disconnect(master_service, &anvil_session);
}
static void
"Too many concurrent deliveries for user");
} else if (lmtp_local_rcpt_anvil_finish(llrcpt)) {
input = mail_storage_service_user_get_input(llrcpt->service_user);
- if (master_service_anvil_send(master_service, t_strconcat(
- "CONNECT\t", my_pid, "\t", master_service_get_name(master_service),
- "/", input->username, "\n", NULL)))
+ struct master_service_anvil_session anvil_session = {
+ .username = input->username,
+ .service_name = master_service_get_name(master_service),
+ };
+ if (master_service_anvil_connect(master_service, &anvil_session))
llrcpt->anvil_connect_sent = TRUE;
}
}
int client_init_mailbox(struct client *client, const char **error_r)
{
enum mailbox_flags flags;
- const char *ident, *errmsg;
+ const char *errmsg;
/* refresh proctitle before a potentially long-running init_mailbox() */
pop3_refresh_proctitle();
if (!client->set->pop3_no_flag_updates && client->messages_count > 0)
client->seen_bitmask = i_malloc(MSGS_BITMASK_SIZE(client));
- ident = mail_user_get_anvil_userip_ident(client->user);
- if (ident != NULL) {
- if (master_service_anvil_send(master_service, t_strconcat(
- "CONNECT\t", my_pid, "\tpop3/", ident, "\n", NULL)))
- client->anvil_sent = TRUE;
- }
+ struct master_service_anvil_session anvil_session;
+ mail_user_get_anvil_session(client->user, &anvil_session);
+ if (master_service_anvil_connect(master_service, &anvil_session))
+ client->anvil_sent = TRUE;
return 0;
}
if (client->mailbox != NULL)
mailbox_free(&client->mailbox);
if (client->anvil_sent) {
- master_service_anvil_send(master_service, t_strconcat(
- "DISCONNECT\t", my_pid, "\tpop3/",
- mail_user_get_anvil_userip_ident(client->user),
- "\n", NULL));
+ struct master_service_anvil_session anvil_session;
+ mail_user_get_anvil_session(client->user, &anvil_session);
+ master_service_anvil_disconnect(master_service, &anvil_session);
}
if (client->session_dotlock != NULL)
set->parsed_workarounds;
const struct mail_storage_settings *mail_set;
struct smtp_server_settings smtp_set;
- const char *ident;
struct client *client;
pool_t pool;
submission_client_count++;
DLLIST_PREPEND(&submission_clients, client);
- ident = mail_user_get_anvil_userip_ident(client->user);
- if (ident != NULL) {
- if (master_service_anvil_send(
- master_service, t_strconcat(
- "CONNECT\t", my_pid, "\tsubmission/", ident,
- "\n", NULL)))
- client->anvil_sent = TRUE;
- }
+ struct master_service_anvil_session anvil_session;
+ mail_user_get_anvil_session(client->user, &anvil_session);
+ if (master_service_anvil_connect(master_service, &anvil_session))
+ client->anvil_sent = TRUE;
if (hook_client_created != NULL)
hook_client_created(&client);
DLLIST_REMOVE(&submission_clients, client);
if (client->anvil_sent) {
- master_service_anvil_send(
- master_service, t_strconcat(
- "DISCONNECT\t", my_pid, "\tsubmission/",
- mail_user_get_anvil_userip_ident(client->user),
- "\n", NULL));
+ struct master_service_anvil_session anvil_session;
+ mail_user_get_anvil_session(client->user, &anvil_session);
+ master_service_anvil_disconnect(master_service, &anvil_session);
}
if (client->urlauth_ctx != NULL)