struct master_login_connection *prev, *next;
struct master_login *login;
+ int refcount;
int fd;
struct io *io;
struct ostream *output;
};
static void master_login_conn_deinit(struct master_login_connection **_conn);
+static void master_login_conn_unref(struct master_login_connection **_conn);
struct master_login *
master_login_init(struct master_service *service, const char *auth_socket_path,
return 1;
}
+static void master_login_client_free(struct master_login_client **_client)
+{
+ struct master_login_client *client = *_client;
+
+ *_client = NULL;
+ if (client->fd != -1) {
+ if (close(client->fd) < 0)
+ i_error("close(fd_read client) failed: %m");
+ }
+
+ master_login_conn_unref(&client->conn);
+ i_free(client);
+}
+
static void master_login_auth_finish(struct master_login_client *client,
const char *const *auth_args)
{
service->service_count_left == 1;
login->callback(client, auth_args[0], auth_args+1);
- i_free(client);
+
+ client->fd = -1;
+ master_login_client_free(&client);
if (close_sockets) {
/* we're dying as soon as this connection closes. */
}
}
-static void master_login_client_free(struct master_login_client *client)
-{
- if (close(client->fd) < 0)
- i_error("close(fd_read client) failed: %m");
- i_free(client);
-}
-
static void master_login_postlogin_free(struct master_login_postlogin *pl)
{
timeout_remove(&pl->to);
i_error("fd_read(%s) failed: disconnected",
login->postlogin_socket_path);
}
- master_login_client_free(pl->client);
+ master_login_client_free(&pl->client);
master_login_postlogin_free(pl);
master_service_client_connection_destroyed(login->service);
return;
i_error("%s: Timeout waiting for post-login script to finish, aborting",
login->postlogin_socket_path);
- master_login_client_free(pl->client);
+ master_login_client_free(&pl->client);
master_login_postlogin_free(pl);
master_service_client_connection_destroyed(login->service);
}
if (auth_args == NULL || auth_args[0] == NULL) {
if (auth_args != NULL)
i_error("login client: Username missing from auth reply");
- master_login_client_free(client);
+ master_login_client_free(&client);
return;
}
else {
/* execute post-login scripts before finishing auth */
if (master_login_postlogin(client, auth_args) < 0) {
- master_login_client_free(client);
+ master_login_client_free(&client);
master_service_client_connection_destroyed(service);
}
}
client->fd = client_fd;
client->auth_req = req;
memcpy(client->data, data, req.data_size);
+ conn->refcount++;
master_login_auth_request(login->auth, &req,
master_login_auth_callback, client);
struct master_login_connection *conn;
conn = i_new(struct master_login_connection, 1);
+ conn->refcount = 1;
conn->login = login;
conn->fd = fd;
conn->io = io_add(conn->fd, IO_READ, master_login_conn_input, conn);
if (close(conn->fd) < 0)
i_error("close(master login) failed: %m");
master_service_io_listeners_add(conn->login->service);
- i_free(conn);
+ master_login_conn_unref(&conn);
+}
+
+static void master_login_conn_unref(struct master_login_connection **_conn)
+{
+ struct master_login_connection *conn = *_conn;
+
+ i_assert(conn->refcount > 0);
+
+ if (--conn->refcount == 0) {
+ *_conn = NULL;
+ i_free(conn);
+ }
}
void master_login_stop(struct master_login *login)