/* This function kills an existing embryonic session. It stops the connection's * transport layer, releases assigned resources, resumes the listener if it was * disabled and finally kills the file descriptor. This function requires that * sess->origin points to the incoming connection. */ static void session_kill_embryonic(struct session *sess) { int level = LOG_INFO; struct connection *conn = __objt_conn(sess->origin); struct task *task = sess->task; unsigned int log = sess->fe->to_log; const char *err_msg; if (sess->fe->options2 & PR_O2_LOGERRORS) level = LOG_ERR; if (log && (sess->fe->options & PR_O_NULLNOLOG)) { /* with "option dontlognull", we don't log connections with no transfer */ if (!conn->err_code || conn->err_code == CO_ER_PRX_EMPTY || conn->err_code == CO_ER_PRX_ABORT || conn->err_code == CO_ER_CIP_EMPTY || conn->err_code == CO_ER_CIP_ABORT || conn->err_code == CO_ER_SSL_EMPTY || conn->err_code == CO_ER_SSL_ABORT) log = 0; } if (log) { if (!conn->err_code && (task->state & TASK_WOKEN_TIMER)) { if (conn->flags & CO_FL_ACCEPT_PROXY) conn->err_code = CO_ER_PRX_TIMEOUT; else if (conn->flags & CO_FL_ACCEPT_CIP) conn->err_code = CO_ER_CIP_TIMEOUT; else if (conn->flags & CO_FL_SSL_WAIT_HS) conn->err_code = CO_ER_SSL_TIMEOUT; } session_prepare_log_prefix(sess); err_msg = conn_err_code_str(conn); if (err_msg) send_log(sess->fe, level, "%s: %s\n", trash.str, err_msg); else send_log(sess->fe, level, "%s: unknown connection error (code=%d flags=%08x)\n", trash.str, conn->err_code, conn->flags); } /* kill the connection now */ conn_stop_tracking(conn); conn_full_close(conn); conn_free(conn); task_delete(task); task_free(task); session_free(sess); }
/* This function kills an existing embryonic session. It stops the connection's * transport layer, releases assigned resources, resumes the listener if it was * disabled and finally kills the file descriptor. This function requires that * sess->origin points to the incoming connection. */ static void session_kill_embryonic(struct session *sess) { int level = LOG_INFO; struct connection *conn = __objt_conn(sess->origin); struct task *task = conn->owner; unsigned int log = sess->fe->to_log; const char *err_msg; if (sess->fe->options2 & PR_O2_LOGERRORS) level = LOG_ERR; if (log && (sess->fe->options & PR_O_NULLNOLOG)) { /* with "option dontlognull", we don't log connections with no transfer */ if (!conn->err_code || conn->err_code == CO_ER_PRX_EMPTY || conn->err_code == CO_ER_PRX_ABORT || conn->err_code == CO_ER_SSL_EMPTY || conn->err_code == CO_ER_SSL_ABORT) log = 0; } if (log) { if (!conn->err_code && (task->state & TASK_WOKEN_TIMER)) { if (conn->flags & CO_FL_ACCEPT_PROXY) conn->err_code = CO_ER_PRX_TIMEOUT; else if (conn->flags & CO_FL_SSL_WAIT_HS) conn->err_code = CO_ER_SSL_TIMEOUT; } session_prepare_log_prefix(sess); err_msg = conn_err_code_str(conn); if (err_msg) send_log(sess->fe, level, "%s: %s\n", trash.str, err_msg); else send_log(sess->fe, level, "%s: unknown connection error (code=%d flags=%08x)\n", trash.str, conn->err_code, conn->flags); } /* kill the connection now */ conn_force_close(conn); conn_free(conn); sess->fe->feconn--; if (!(sess->listener->options & LI_O_UNLIMITED)) actconn--; jobs--; sess->listener->nbconn--; if (sess->listener->state == LI_FULL) resume_listener(sess->listener); /* Dequeues all of the listeners waiting for a resource */ if (!LIST_ISEMPTY(&global_listener_queue)) dequeue_all_listeners(&global_listener_queue); if (!LIST_ISEMPTY(&sess->fe->listener_queue) && (!sess->fe->fe_sps_lim || freq_ctr_remain(&sess->fe->fe_sess_per_sec, sess->fe->fe_sps_lim, 0) > 0)) dequeue_all_listeners(&sess->fe->listener_queue); task_delete(task); task_free(task); session_free(sess); }