diff options
Diffstat (limited to '')
-rw-r--r-- | src/session.c | 92 |
1 files changed, 53 insertions, 39 deletions
diff --git a/src/session.c b/src/session.c index ce9ccbf..f8953df 100644 --- a/src/session.c +++ b/src/session.c @@ -27,8 +27,8 @@ DECLARE_POOL(pool_head_session, "session", sizeof(struct session)); -DECLARE_POOL(pool_head_sess_srv_list, "session server list", - sizeof(struct sess_srv_list)); +DECLARE_POOL(pool_head_sess_priv_conns, "session priv conns list", + sizeof(struct sess_priv_conns)); int conn_complete_session(struct connection *conn); @@ -61,7 +61,7 @@ struct session *session_new(struct proxy *fe, struct listener *li, enum obj_type sess->t_idle = -1; _HA_ATOMIC_INC(&totalconn); _HA_ATOMIC_INC(&jobs); - LIST_INIT(&sess->srv_list); + LIST_INIT(&sess->priv_conns); sess->idle_conns = 0; sess->flags = SESS_FL_NONE; sess->src = NULL; @@ -76,33 +76,29 @@ struct session *session_new(struct proxy *fe, struct listener *li, enum obj_type void session_free(struct session *sess) { struct connection *conn, *conn_back; - struct sess_srv_list *srv_list, *srv_list_back; + struct sess_priv_conns *pconns, *pconns_back; - if (sess->listener) + if (sess->flags & SESS_FL_RELEASE_LI) { + /* listener must be set for session used to account FE conns. */ + BUG_ON(!sess->listener); listener_release(sess->listener); + } + session_store_counters(sess); pool_free(pool_head_stk_ctr, sess->stkctr); vars_prune_per_sess(&sess->vars); conn = objt_conn(sess->origin); if (conn != NULL && conn->mux) conn->mux->destroy(conn->ctx); - list_for_each_entry_safe(srv_list, srv_list_back, &sess->srv_list, srv_list) { - list_for_each_entry_safe(conn, conn_back, &srv_list->conn_list, session_list) { - LIST_DEL_INIT(&conn->session_list); - if (conn->mux) { - conn->owner = NULL; - conn->flags &= ~CO_FL_SESS_IDLE; - conn->mux->destroy(conn->ctx); - } else { - /* We have a connection, but not yet an associated mux. - * So destroy it now. - */ - conn_stop_tracking(conn); - conn_full_close(conn); - conn_free(conn); - } + list_for_each_entry_safe(pconns, pconns_back, &sess->priv_conns, sess_el) { + list_for_each_entry_safe(conn, conn_back, &pconns->conn_list, sess_el) { + LIST_DEL_INIT(&conn->sess_el); + conn->owner = NULL; + conn->flags &= ~CO_FL_SESS_IDLE; + conn_release(conn); } - pool_free(pool_head_sess_srv_list, srv_list); + MT_LIST_DELETE(&pconns->srv_el); + pool_free(pool_head_sess_priv_conns, pconns); } sockaddr_free(&sess->src); sockaddr_free(&sess->dst); @@ -190,11 +186,17 @@ int session_accept_fd(struct connection *cli_conn) } } - sess = session_new(p, l, &cli_conn->obj_type); - if (!sess) - goto out_free_conn; + /* Reversed conns already have an assigned session, do not recreate it. */ + if (!(cli_conn->flags & CO_FL_REVERSED)) { + sess = session_new(p, l, &cli_conn->obj_type); + if (!sess) + goto out_free_conn; - conn_set_owner(cli_conn, sess, NULL); + conn_set_owner(cli_conn, sess, NULL); + } + else { + sess = cli_conn->owner; + } /* now evaluate the tcp-request layer4 rules. We only need a session * and no stream for these rules. @@ -293,12 +295,19 @@ int session_accept_fd(struct connection *cli_conn) sess->task->process = session_expire_embryonic; sess->task->expire = tick_add_ifset(now_ms, timeout); task_queue(sess->task); + + /* Session is responsible to decrement listener conns counters. */ + sess->flags |= SESS_FL_RELEASE_LI; + return 1; } /* OK let's complete stream initialization since there is no handshake */ - if (conn_complete_session(cli_conn) >= 0) + if (conn_complete_session(cli_conn) >= 0) { + /* Session is responsible to decrement listener conns counters. */ + sess->flags |= SESS_FL_RELEASE_LI; return 1; + } /* if we reach here we have deliberately decided not to keep this * session (e.g. tcp-request rule), so that's not an error we should @@ -308,9 +317,9 @@ int session_accept_fd(struct connection *cli_conn) /* error unrolling */ out_free_sess: - /* prevent call to listener_release during session_free. It will be - * done below, for all errors. */ - sess->listener = NULL; + /* SESS_FL_RELEASE_LI must not be set here as listener_release() is + * called manually for all errors. + */ session_free(sess); out_free_conn: @@ -322,15 +331,8 @@ int session_accept_fd(struct connection *cli_conn) MSG_DONTWAIT|MSG_NOSIGNAL); } - if (cli_conn->mux) { - /* Mux is already initialized for active reversed connection. */ - cli_conn->mux->destroy(cli_conn->ctx); - } - else { - conn_stop_tracking(cli_conn); - conn_full_close(cli_conn); - conn_free(cli_conn); - } + /* Mux is already initialized for active reversed connection. */ + conn_release(cli_conn); listener_release(l); return ret; } @@ -443,7 +445,7 @@ static void session_kill_embryonic(struct session *sess, unsigned int state) conn->err_code = CO_ER_SSL_TIMEOUT; } - if(!LIST_ISEMPTY(&sess->fe->logformat_error)) { + if(!lf_expr_isempty(&sess->fe->logformat_error)) { /* Display a log line following the configured error-log-format. */ sess_log(sess); } @@ -520,6 +522,18 @@ int conn_complete_session(struct connection *conn) return -1; } +/* Add <inc> to the number of cumulated glitches in the tracked counters for + * session <sess> which is known for being tracked, and implicitly update the + * rate if also tracked. + */ +void __session_add_glitch_ctr(struct session *sess, uint inc) +{ + int i; + + for (i = 0; i < global.tune.nb_stk_ctr; i++) + stkctr_add_glitch_ctr(&sess->stkctr[i], inc); +} + /* * Local variables: * c-indent-level: 8 |