static void login_proxy_free_final(struct login_proxy *proxy) { if (proxy->delayed_disconnect) { DLLIST_REMOVE(&login_proxies_disconnecting, proxy); i_assert(proxy->state_rec->num_delayed_client_disconnects > 0); if (--proxy->state_rec->num_delayed_client_disconnects == 0) proxy->state_rec->num_disconnects_since_ts = 0; timeout_remove(&proxy->to); } if (proxy->client_io != NULL) io_remove(&proxy->client_io); if (proxy->client_input != NULL) i_stream_destroy(&proxy->client_input); if (proxy->client_output != NULL) o_stream_destroy(&proxy->client_output); if (proxy->client_fd != -1) net_disconnect(proxy->client_fd); if (proxy->ssl_server_proxy != NULL) { ssl_proxy_destroy(proxy->ssl_server_proxy); ssl_proxy_free(&proxy->ssl_server_proxy); } i_free(proxy->host); i_free(proxy); }
bool client_unref(struct client **_client) { struct client *client = *_client; i_assert(client->refcount > 0); if (--client->refcount > 0) return TRUE; *_client = NULL; i_assert(client->destroyed); i_assert(client->login_proxy == NULL); if (client->ssl_proxy != NULL) ssl_proxy_free(&client->ssl_proxy); if (client->input != NULL) i_stream_unref(&client->input); if (client->output != NULL) o_stream_unref(&client->output); i_free(client->proxy_user); i_free(client->proxy_master_user); i_free(client->virtual_user); i_free(client->virtual_user_orig); i_free(client->virtual_auth_user); i_free(client->auth_mech_name); i_free(client->master_data_prefix); pool_unref(&client->pool); i_assert(clients_count > 0); clients_count--; master_service_client_connection_destroyed(master_service); login_refresh_proctitle(); return FALSE; }
login_proxy_free_reason(struct login_proxy **_proxy, const char *reason) { struct login_proxy *proxy = *_proxy; struct client *client = proxy->client; const char *ipstr; *_proxy = NULL; if (proxy->destroying) return; proxy->destroying = TRUE; if (proxy->to != NULL) timeout_remove(&proxy->to); if (proxy->to_notify != NULL) timeout_remove(&proxy->to_notify); if (proxy->state_rec != NULL) proxy->state_rec->num_waiting_connections--; if (proxy->to != NULL) timeout_remove(&proxy->to); if (proxy->server_io != NULL) io_remove(&proxy->server_io); if (proxy->server_input != NULL) i_stream_destroy(&proxy->server_input); if (proxy->server_output != NULL) o_stream_destroy(&proxy->server_output); if (proxy->client_fd != -1) { /* detached proxy */ DLLIST_REMOVE(&login_proxies, proxy); ipstr = net_ip2addr(&proxy->client->ip); client_log(proxy->client, t_strdup_printf( "proxy(%s): disconnecting %s%s", proxy->client->virtual_user, ipstr != NULL ? ipstr : "", reason == NULL ? "" : t_strdup_printf(" (%s)", reason))); if (proxy->client_io != NULL) io_remove(&proxy->client_io); if (proxy->client_output != NULL) o_stream_destroy(&proxy->client_output); net_disconnect(proxy->client_fd); } else { i_assert(proxy->client_io == NULL); i_assert(proxy->client_output == NULL); DLLIST_REMOVE(&login_proxies_pending, proxy); if (proxy->callback != NULL) proxy->callback(proxy->client); } if (proxy->server_fd != -1) net_disconnect(proxy->server_fd); if (proxy->ssl_server_proxy != NULL) ssl_proxy_free(&proxy->ssl_server_proxy); i_free(proxy->host); i_free(proxy); client->login_proxy = NULL; client_unref(&client); }
void client_destroy(struct client *client, const char *reason) { if (client->destroyed) return; client->destroyed = TRUE; if (!client->login_success && reason != NULL) { reason = t_strconcat(reason, " ", client_get_extra_disconnect_reason(client), NULL); } if (reason != NULL) client_log(client, reason); if (last_client == client) last_client = client->prev; DLLIST_REMOVE(&clients, client); if (client->input != NULL) i_stream_close(client->input); if (client->output != NULL) o_stream_close(client->output); if (client->master_tag != 0) { i_assert(client->auth_request == NULL); i_assert(client->authenticating); i_assert(client->refcount > 1); client->authenticating = FALSE; master_auth_request_abort(master_auth, client->master_tag); client->refcount--; } else if (client->auth_request != NULL) { i_assert(client->authenticating); sasl_server_auth_abort(client); } else { i_assert(!client->authenticating); } if (client->io != NULL) io_remove(&client->io); if (client->to_disconnect != NULL) timeout_remove(&client->to_disconnect); if (client->to_auth_waiting != NULL) timeout_remove(&client->to_auth_waiting); if (client->auth_response != NULL) str_free(&client->auth_response); if (client->fd != -1) { net_disconnect(client->fd); client->fd = -1; } if (client->proxy_password != NULL) { safe_memset(client->proxy_password, 0, strlen(client->proxy_password)); i_free_and_null(client->proxy_password); } if (client->login_proxy != NULL) login_proxy_free(&client->login_proxy); if (client->ssl_proxy != NULL) ssl_proxy_free(&client->ssl_proxy); client->v.destroy(client); if (client_unref(&client) && master_service_get_service_count(master_service) == 1) { /* as soon as this connection is done with proxying (or whatever), the process will die. there's no need for authentication anymore, so close the connection. */ auth_client_disconnect(auth_client); } login_client_destroyed(); login_refresh_proctitle(); }