static int login_proxy_connect(struct login_proxy *proxy) { struct login_proxy_record *rec; rec = login_proxy_state_get(proxy_state, &proxy->ip, proxy->port); if (timeval_cmp(&rec->last_failure, &rec->last_success) > 0 && rec->last_failure.tv_sec - rec->last_success.tv_sec > PROXY_IMMEDIATE_FAILURE_SECS && rec->num_waiting_connections != 0) { /* the server is down. fail immediately */ i_error("proxy(%s): Host %s:%u is down", proxy->client->virtual_user, proxy->host, proxy->port); login_proxy_free(&proxy); return -1; } proxy->server_fd = net_connect_ip(&proxy->ip, proxy->port, NULL); if (proxy->server_fd == -1) { proxy_log_connect_error(proxy); login_proxy_free(&proxy); return -1; } proxy->server_io = io_add(proxy->server_fd, IO_WRITE, proxy_wait_connect, proxy); if (proxy->connect_timeout_msecs != 0) { proxy->to = timeout_add(proxy->connect_timeout_msecs, proxy_connect_timeout, proxy); } proxy->state_rec = rec; proxy->state_rec->num_waiting_connections++; return 0; }
static void proxy_wait_connect(struct login_proxy *proxy) { errno = net_geterror(proxy->server_fd); if (errno != 0) { proxy_fail_connect(proxy); if (!proxy_try_reconnect(proxy)) { proxy_log_connect_error(proxy); login_proxy_free(&proxy); } return; } proxy->connected = TRUE; proxy->num_waiting_connections_updated = TRUE; proxy->state_rec->last_success = ioloop_timeval; i_assert(proxy->state_rec->num_waiting_connections > 0); proxy->state_rec->num_waiting_connections--; proxy->state_rec->num_proxying_connections++; proxy->state_rec->num_disconnects_since_ts = 0; if ((proxy->ssl_flags & PROXY_SSL_FLAG_YES) != 0 && (proxy->ssl_flags & PROXY_SSL_FLAG_STARTTLS) == 0) { if (login_proxy_starttls(proxy) < 0) { login_proxy_free(&proxy); return; } } else { io_remove(&proxy->server_io); proxy_plain_connected(proxy); } }
static void proxy_connect_timeout(struct login_proxy *proxy) { errno = ETIMEDOUT; proxy_log_connect_error(proxy); if (!proxy->connected) proxy_fail_connect(proxy); login_proxy_free(&proxy); }
static int login_proxy_connect(struct login_proxy *proxy) { struct login_proxy_record *rec = proxy->state_rec; /* this needs to be done early, since login_proxy_free() shrinks num_waiting_connections. */ proxy->num_waiting_connections_updated = FALSE; rec->num_waiting_connections++; if (proxy->ip.family == 0 && net_addr2ip(proxy->host, &proxy->ip) < 0) { client_log_err(proxy->client, t_strdup_printf( "proxy(%s): BUG: host %s is not an IP " "(auth should have changed it)", proxy->client->virtual_user, proxy->host)); return -1; } if (rec->last_success.tv_sec == 0) { /* first connect to this IP. don't start immediately failing the check below. */ rec->last_success.tv_sec = ioloop_timeval.tv_sec - 1; } if (timeval_cmp(&rec->last_failure, &rec->last_success) > 0 && rec->last_failure.tv_sec - rec->last_success.tv_sec > PROXY_IMMEDIATE_FAILURE_SECS && rec->num_waiting_connections > 1) { /* the server is down. fail immediately */ client_log_err(proxy->client, t_strdup_printf( "proxy(%s): Host %s:%u is down", proxy->client->virtual_user, proxy->host, proxy->port)); return -1; } proxy->server_fd = net_connect_ip(&proxy->ip, proxy->port, proxy->source_ip.family == 0 ? NULL : &proxy->source_ip); if (proxy->server_fd == -1) { proxy_log_connect_error(proxy); return -1; } proxy->server_io = io_add(proxy->server_fd, IO_WRITE, proxy_wait_connect, proxy); if (proxy->connect_timeout_msecs != 0) { proxy->to = timeout_add(proxy->connect_timeout_msecs, proxy_connect_timeout, proxy); } return 0; }
static int login_proxy_connect(struct login_proxy *proxy) { struct login_proxy_record *rec = proxy->state_rec; if (rec->last_success.tv_sec == 0) { /* first connect to this IP. don't start immediately failing the check below. */ rec->last_success.tv_sec = ioloop_timeval.tv_sec - 1; } if (timeval_cmp(&rec->last_failure, &rec->last_success) > 0 && rec->last_failure.tv_sec - rec->last_success.tv_sec > PROXY_IMMEDIATE_FAILURE_SECS && rec->num_waiting_connections != 0) { /* the server is down. fail immediately */ i_error("proxy(%s): Host %s:%u is down", proxy->client->virtual_user, proxy->host, proxy->port); login_proxy_free(&proxy); return -1; } proxy->server_fd = net_connect_ip(&proxy->ip, proxy->port, proxy->source_ip.family == 0 ? NULL : &proxy->source_ip); if (proxy->server_fd == -1) { proxy_log_connect_error(proxy); login_proxy_free(&proxy); return -1; } proxy->server_io = io_add(proxy->server_fd, IO_WRITE, proxy_wait_connect, proxy); if (proxy->connect_timeout_msecs != 0) { proxy->to = timeout_add(proxy->connect_timeout_msecs, proxy_connect_timeout, proxy); } proxy->num_waiting_connections_updated = FALSE; proxy->state_rec = rec; proxy->state_rec->num_waiting_connections++; return 0; }