service_flags |= MASTER_SERVICE_FLAG_STANDALONE |
MASTER_SERVICE_FLAG_STD_CLIENT;
} else {
+ service_flags |= MASTER_SERVICE_FLAG_KEEP_CONFIG_OPEN;
storage_service_flags |=
MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT;
}
main_stdio_run();
} T_END;
} else {
- master_login = master_login_init("auth-master",
+ master_login = master_login_init(master_service, "auth-master",
login_client_connected);
io_loop_set_running(current_ioloop);
}
#include "fdpass.h"
#include "fd-close-on-exec.h"
#include "llist.h"
+#include "master-service-private.h"
#include "master-login.h"
#include "master-login-auth.h"
};
struct master_login {
+ struct master_service *service;
master_login_callback_t *callback;
struct master_login_connection *conns;
struct master_login_auth *auth;
static void master_login_conn_deinit(struct master_login_connection **_conn);
struct master_login *
-master_login_init(const char *auth_socket_path,
+master_login_init(struct master_service *service, const char *auth_socket_path,
master_login_callback_t *callback)
{
struct master_login *login;
login = i_new(struct master_login, 1);
+ login->service = service;
login->callback = callback;
login->auth = master_login_auth_init(auth_socket_path);
+ service->login_connections = TRUE;
return login;
}
{
struct master_login_client *client = context;
struct master_auth_reply reply;
+ struct master_service *service = client->conn->login->service;
+ bool close_config;
memset(&reply, 0, sizeof(reply));
reply.tag = client->auth_req.tag;
return;
}
+ service->master_status.available_count--;
+ master_status_update(service);
+ close_config = service->master_status.available_count == 0 &&
+ service->service_count_left == 1;
+
client->conn->login->callback(client, auth_args[0], auth_args+1);
i_free(client);
+
+ if (close_config) {
+ /* we're dying as soon as this connection closes. */
+ master_service_close_config_fd(service);
+ }
}
static void master_login_conn_input(struct master_login_connection *conn)
const char *username, const char *const *extra_fields);
struct master_login *
-master_login_init(const char *auth_socket_path,
+master_login_init(struct master_service *service, const char *auth_socket_path,
master_login_callback_t *callback);
void master_login_deinit(struct master_login **login);
unsigned int die_with_master:1;
unsigned int call_avail_overflow:1;
unsigned int delay_status_updates:1;
+ /* incoming connections are going to master-login and they're not
+ counted as real connections */
+ unsigned int login_connections:1;
};
void master_service_io_listeners_add(struct master_service *service);
+void master_status_update(struct master_service *service);
+void master_service_close_config_fd(struct master_service *service);
#endif
static void master_service_refresh_login_state(struct master_service *service);
static void io_listeners_remove(struct master_service *service);
-static void master_status_update(struct master_service *service);
const char *master_service_getopt_string(void)
{
master_service_set_login_state(service, ret);
}
-static void master_service_close_config_fd(struct master_service *service)
+void master_service_close_config_fd(struct master_service *service)
{
if (service->config_fd != -1) {
if (close(service->config_fd) < 0)
{
struct master_service *service = l->service;
struct master_service_connection conn;
+ bool close_config;
if (service->master_status.available_count == 0) {
/* we are full. stop listening for now, unless overflow
conn.ssl = l->ssl;
net_set_nonblock(conn.fd, TRUE);
- service->master_status.available_count--;
- master_status_update(service);
+ if (service->login_connections)
+ close_config = FALSE;
+ else {
+ service->master_status.available_count--;
+ master_status_update(service);
+ close_config = service->master_status.available_count == 0 &&
+ service->service_count_left == 1;
+ }
service->callback(&conn);
- if (service->master_status.available_count == 0 &&
- service->service_count_left == 1) {
+ if (close_config) {
/* we're dying as soon as this connection closes. */
master_service_close_config_fd(service);
}
return FALSE;
}
-static void master_status_update(struct master_service *service)
+void master_status_update(struct master_service *service)
{
ssize_t ret;
service_flags |= MASTER_SERVICE_FLAG_STANDALONE |
MASTER_SERVICE_FLAG_STD_CLIENT;
} else {
+ service_flags |= MASTER_SERVICE_FLAG_KEEP_CONFIG_OPEN;
storage_service_flags |=
MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT;
}
main_stdio_run();
} T_END;
} else {
- master_login = master_login_init("auth-master",
+ master_login = master_login_init(master_service, "auth-master",
login_client_connected);
io_loop_set_running(current_ioloop);
}