/* Finish initializing a session from a connection, or kills it if the * connection shows and error. Returns <0 if the connection was killed. */ static int conn_complete_session(struct connection *conn) { struct task *task = conn->owner; struct session *sess = task->context; struct stream *strm; if (conn->flags & CO_FL_ERROR) goto fail; /* we want the connection handler to notify the stream interface about updates. */ conn->flags |= CO_FL_WAKE_DATA; /* if logs require transport layer information, note it on the connection */ if (sess->fe->to_log & LW_XPRT) conn->flags |= CO_FL_XPRT_TRACKED; session_count_new(sess); task->process = sess->listener->handler; strm = stream_new(sess, task, &conn->obj_type); if (!strm) goto fail; strm->target = sess->listener->default_target; strm->req.analysers = sess->listener->analysers; conn->flags &= ~CO_FL_INIT_DATA; return 0; fail: session_kill_embryonic(sess); return -1; }
/* Manages the embryonic session timeout. It is only called when the timeout * strikes and performs the required cleanup. */ static struct task *session_expire_embryonic(struct task *t) { struct session *sess = t->context; if (!(t->state & TASK_WOKEN_TIMER)) return t; session_kill_embryonic(sess); return NULL; }
/* Update a session status. The connection is killed in case of * error, and <0 will be returned. Otherwise it does nothing. */ static int conn_update_session(struct connection *conn) { struct task *task = conn->owner; struct session *sess = task->context; if (conn->flags & CO_FL_ERROR) { session_kill_embryonic(sess); return -1; } return 0; }
/* Finish initializing a session from a connection, or kills it if the * connection shows and error. Returns <0 if the connection was killed. It may * be called either asynchronously as an xprt_done callback with an embryonic * session, or synchronously to finalize the session. The distinction is made * on sess->task which is only set in the embryonic session case. */ static int conn_complete_session(struct connection *conn) { struct session *sess = conn->owner; sess->t_handshake = tv_ms_elapsed(&sess->tv_accept, &now); conn_clear_xprt_done_cb(conn); /* Verify if the connection just established. */ if (unlikely(!(conn->flags & (CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN | CO_FL_CONNECTED)))) conn->flags |= CO_FL_CONNECTED; if (conn->flags & CO_FL_ERROR) goto fail; /* if logs require transport layer information, note it on the connection */ if (sess->fe->to_log & LW_XPRT) conn->flags |= CO_FL_XPRT_TRACKED; /* we may have some tcp-request-session rules */ if ((sess->listener->options & LI_O_TCP_L5_RULES) && !tcp_exec_l5_rules(sess)) goto fail; session_count_new(sess); if (conn_install_best_mux(conn, sess->fe->mode == PR_MODE_HTTP, NULL) < 0) goto fail; /* the embryonic session's task is not needed anymore */ if (sess->task) { task_delete(sess->task); task_free(sess->task); sess->task = NULL; } conn_set_owner(conn, sess, conn_session_free); return 0; fail: if (sess->task) session_kill_embryonic(sess); return -1; }