* Returns < 0 on error.
*/
static inline int conn_install_mux(struct connection *conn, const struct mux_ops *mux,
- void *ctx, struct proxy *prx)
+ void *ctx, struct proxy *prx, struct session *sess)
{
conn->mux = mux;
conn->mux_ctx = ctx;
- return mux->init ? mux->init(conn, prx) : 0;
+ return mux->init ? mux->init(conn, prx, sess) : 0;
}
/* returns a human-readable error code for conn->err_code, or NULL if the code
if (!mux_ops)
return -1;
}
- return conn_install_mux(conn, mux_ops, ctx, bind_conf->frontend);
+ return conn_install_mux(conn, mux_ops, ctx, bind_conf->frontend, conn->owner);
}
/* installs the best mux for outgoing connection <conn> using the upper context
* <ctx>. If the mux protocol is forced, we use it to find the best mux. Returns
* < 0 on error.
*/
-static inline int conn_install_mux_be(struct connection *conn, void *ctx)
+static inline int conn_install_mux_be(struct connection *conn, void *ctx, struct session *sess)
{
struct server *srv = objt_server(conn->target);
struct proxy *prx = objt_proxy(conn->target);
if (!mux_ops)
return -1;
}
- return conn_install_mux(conn, mux_ops, ctx, prx);
+ return conn_install_mux(conn, mux_ops, ctx, prx, sess);
}
#endif /* _PROTO_CONNECTION_H */
struct buffer;
struct proxy;
struct server;
+struct session;
struct pipe;
enum sub_event_type {
* layer is not ready yet.
*/
struct mux_ops {
- int (*init)(struct connection *conn, struct proxy *prx); /* early initialization */
+ int (*init)(struct connection *conn, struct proxy *prx, struct session *sess); /* early initialization */
int (*wake)(struct connection *conn); /* mux-layer callback to report activity, mandatory */
size_t (*rcv_buf)(struct conn_stream *cs, struct buffer *buf, size_t count, int flags); /* Called from the upper layer to get data */
size_t (*snd_buf)(struct conn_stream *cs, struct buffer *buf, size_t count, int flags); /* Called from the upper layer to send data */
void (*shutr)(struct conn_stream *cs, enum cs_shr_mode); /* shutr function */
void (*shutw)(struct conn_stream *cs, enum cs_shw_mode); /* shutw function */
- struct conn_stream *(*attach)(struct connection *); /* Create and attach a conn_stream to an outgoing connection */
+ struct conn_stream *(*attach)(struct connection *, struct session *sess); /* Create and attach a conn_stream to an outgoing connection */
const struct conn_stream *(*get_first_cs)(const struct connection *); /* retrieves any valid conn_stream from this connection */
void (*detach)(struct conn_stream *); /* Detach a conn_stream from an outgoing connection, when the request is done */
void (*show_fd)(struct buffer *, struct connection *); /* append some data about connection into chunk for "show fd" */
cs = si_alloc_cs(&s->si[1], conn);
if (!cs)
goto fail;
- if (conn_install_mux_be(conn, cs) < 0)
+ if (conn_install_mux_be(conn, cs, s->sess) < 0)
goto fail;
srv = objt_server(s->target);
if (srv && ((s->be->options & PR_O_REUSE_MASK) == PR_O_REUSE_ALWS) &&
LIST_DEL(&srv_conn->list);
LIST_INIT(&srv_conn->list);
}
- srv_cs = srv_conn->mux->attach(srv_conn);
+ srv_cs = srv_conn->mux->attach(srv_conn, s->sess);
if (srv_cs)
si_attach_cs(&s->si[1], srv_cs);
}
conn_free(srv_conn);
return SF_ERR_RESOURCE;
}
- if (conn_install_mux_be(srv_conn, srv_cs) < 0)
+ if (conn_install_mux_be(srv_conn, srv_cs, s->sess) < 0)
return SF_ERR_INTERNAL;
/* If we're doing http-reuse always, and the connection
* is an http2 connection, add it to the available list,
clear_addr(&conn->addr.from);
conn_prepare(conn, proto, check->xprt);
- conn_install_mux(conn, &mux_pt_ops, cs, s->proxy);
+ conn_install_mux(conn, &mux_pt_ops, cs, s->proxy, NULL);
cs_attach(cs, check, &check_conn_cb);
/* only plain tcp-check supports quick ACK */
}
conn_prepare(conn, proto, xprt);
- conn_install_mux(conn, &mux_pt_ops, cs, s->proxy);
+ conn_install_mux(conn, &mux_pt_ops, cs, s->proxy, NULL);
cs_attach(cs, check, &check_conn_cb);
ret = SF_ERR_INTERNAL;
struct wait_event *recv_wait; /* Address of the wait_event the conn_stream associated is waiting on */
struct wait_event *send_wait; /* Address of the wait_event the conn_stream associated is waiting on */
+ struct session *sess; /* Associated session */
struct h1m req;
struct h1m res;
return NULL;
}
-static struct h1s *h1s_create(struct h1c *h1c, struct conn_stream *cs)
+static struct h1s *h1s_create(struct h1c *h1c, struct conn_stream *cs, struct session *sess)
{
struct h1s *h1s;
h1s->h1c = h1c;
h1c->h1s = h1s;
+ h1s->sess = sess;
+
h1s->cs = NULL;
h1s->flags = H1S_F_NONE;
h1s->cs = cs;
}
else {
- struct session *sess = h1c->conn->owner;
+ /* For frontend connections we should always have a session */
+ sess = h1c->conn->owner;
h1s->csinfo.create_date = sess->accept_date;
h1s->csinfo.tv_create = sess->tv_accept;
* points to the existing conn_stream (for outgoing connections) or NULL (for
* incoming ones). Returns < 0 on error.
*/
-static int h1_init(struct connection *conn, struct proxy *proxy)
+static int h1_init(struct connection *conn, struct proxy *proxy, struct session *sess)
{
struct h1c *h1c;
h1c->flags |= H1C_F_CS_WAIT_CONN;
/* Always Create a new H1S */
- if (!h1s_create(h1c, conn->mux_ctx))
+ if (!h1s_create(h1c, conn->mux_ctx, sess))
goto fail;
conn->mux_ctx = h1c;
static void h1_set_srv_conn_mode(struct h1s *h1s, struct h1m *h1m)
{
struct h1c *h1c = h1s->h1c;
- struct session *sess = h1c->conn->owner;
- struct proxy *fe = sess->fe;
+ struct session *sess = h1s->sess;
struct proxy *be = h1c->px;
int flag = H1S_F_WANT_KAL;
+ int fe_flags = sess ? sess->fe->options : 0;
/* Tunnel mode can only by set on the frontend */
- if ((fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
+ if ((fe_flags & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
flag = H1S_F_WANT_TUN;
/* For the server connection: server-close == httpclose */
- if ((fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL ||
+ if ((fe_flags & PR_O_HTTP_MODE) == PR_O_HTTP_SCL ||
(be->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL ||
- (fe->options & PR_O_HTTP_MODE) == PR_O_HTTP_CLO ||
+ (fe_flags & PR_O_HTTP_MODE) == PR_O_HTTP_CLO ||
(be->options & PR_O_HTTP_MODE) == PR_O_HTTP_CLO)
flag = H1S_F_WANT_CLO;
conn_xprt_read0_pending(conn))
goto release;
if (!conn_is_back(conn) && !(h1c->flags & (H1C_F_CS_SHUTW_NOW|H1C_F_CS_SHUTW))) {
- if (!h1s_create(h1c, NULL))
+ if (!h1s_create(h1c, NULL, NULL))
goto release;
}
else
* Attach a new stream to a connection
* (Used for outgoing connections)
*/
-static struct conn_stream *h1_attach(struct connection *conn)
+static struct conn_stream *h1_attach(struct connection *conn, struct session *sess)
{
struct h1c *h1c = conn->mux_ctx;
struct conn_stream *cs = NULL;
if (!cs)
goto end;
- h1s = h1s_create(h1c, cs);
+ h1s = h1s_create(h1c, cs, sess);
if (h1s == NULL)
goto end;
{
struct h1s *h1s = cs->ctx;
struct h1c *h1c;
+ struct session *sess;
int has_keepalive;
int is_not_first;
if (!h1s)
return;
+ sess = h1s->sess;
h1c = h1s->h1c;
h1s->cs = NULL;
if (conn_is_back(h1c->conn) && has_keepalive &&
!(h1c->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_SOCK_WR_SH))) {
- struct stream_interface *si = cs->data;
- struct stream *s = si_strm(si);
-
/* Never ever allow to reuse a connection from a non-reuse backend */
if ((h1c->px->options & PR_O_REUSE_MASK) == PR_O_REUSE_NEVR)
h1c->conn->flags |= CO_FL_PRIVATE;
if (!(h1c->conn->owner)) {
- h1c->conn->owner = s->sess;
- session_add_conn(s->sess, h1c->conn, s->target);
+ h1c->conn->owner = sess;
+ session_add_conn(sess, h1c->conn, h1c->conn->target);
}
/* we're in keep-alive with an idle connection, monitor it if not already done */
if (LIST_ISEMPTY(&h1c->conn->list)) {
*/
struct h2s {
struct conn_stream *cs;
+ struct session *sess;
struct h2c *h2c;
struct h1m h1m; /* request or response parser state for H1 */
struct eb32_node by_id; /* place in h2c's streams_by_id */
static int h2s_decode_headers(struct h2s *h2s);
static int h2_frt_transfer_data(struct h2s *h2s);
static struct task *h2_deferred_shut(struct task *t, void *ctx, unsigned short state);
-static struct h2s *h2c_bck_stream_new(struct h2c *h2c, struct conn_stream *cs);
+static struct h2s *h2c_bck_stream_new(struct h2c *h2c, struct conn_stream *cs, struct session *sess);
/*****************************************************/
/* functions below are for dynamic buffer management */
* connections from the fact that the context is still NULL. Returns < 0 on
* error.
*/
-static int h2_init(struct connection *conn, struct proxy *prx)
+static int h2_init(struct connection *conn, struct proxy *prx, struct session *sess)
{
struct h2c *h2c;
struct task *t = NULL;
*/
struct h2s *h2s;
- h2s = h2c_bck_stream_new(h2c, conn->mux_ctx);
+ h2s = h2c_bck_stream_new(h2c, conn->mux_ctx, sess);
if (!h2s)
goto fail_stream;
}
* and returns it, or NULL in case of memory allocation error or if the highest
* possible stream ID was reached.
*/
-static struct h2s *h2c_bck_stream_new(struct h2c *h2c, struct conn_stream *cs)
+static struct h2s *h2c_bck_stream_new(struct h2c *h2c, struct conn_stream *cs, struct session *sess)
{
struct h2s *h2s = NULL;
goto out;
h2s->cs = cs;
+ h2s->sess = sess;
cs->ctx = h2s;
h2c->nb_cs++;
* Attach a new stream to a connection
* (Used for outgoing connections)
*/
-static struct conn_stream *h2_attach(struct connection *conn)
+static struct conn_stream *h2_attach(struct connection *conn, struct session *sess)
{
struct conn_stream *cs;
struct h2s *h2s;
cs = cs_new(conn);
if (!cs)
return NULL;
- h2s = h2c_bck_stream_new(h2c, cs);
+ h2s = h2c_bck_stream_new(h2c, cs, sess);
if (!h2s) {
cs_free(cs);
return NULL;
{
struct h2s *h2s = cs->ctx;
struct h2c *h2c;
+ struct session *sess;
cs->ctx = NULL;
if (!h2s)
return;
+ sess = h2s->sess;
h2c = h2s->h2c;
h2s->cs = NULL;
h2c->nb_cs--;
if (h2c->flags & H2_CF_IS_BACK &&
(h2c->proxy->options2 & PR_O2_USE_HTX)) {
- struct stream_interface *si;
- struct stream *s;
-
- si = cs->data;
- s = si_strm(si);
if (!(h2c->conn->flags &
(CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_SOCK_WR_SH))) {
if (!h2c->conn->owner) {
- h2c->conn->owner = s->sess;
- session_add_conn(s->sess, h2c->conn, s->target);
+ h2c->conn->owner = sess;
+ session_add_conn(sess, h2c->conn, h2c->conn->target);
}
/* Never ever allow to reuse a connection from a non-reuse backend */
if ((h2c->proxy->options & PR_O_REUSE_MASK) == PR_O_REUSE_NEVR)
* incoming ones, in which case one will be allocated and a new stream will be
* instanciated). Returns < 0 on error.
*/
-static int mux_pt_init(struct connection *conn, struct proxy *prx)
+static int mux_pt_init(struct connection *conn, struct proxy *prx, struct session *sess)
{
struct conn_stream *cs = conn->mux_ctx;
struct mux_pt_ctx *ctx = pool_alloc(pool_head_pt_ctx);
* Attach a new stream to a connection
* (Used for outgoing connections)
*/
-static struct conn_stream *mux_pt_attach(struct connection *conn)
+static struct conn_stream *mux_pt_attach(struct connection *conn, struct session *sess)
{
struct conn_stream *cs;
struct mux_pt_ctx *ctx = conn->mux_ctx;
memcpy(&conn->addr.to, &peer->addr, sizeof(conn->addr.to));
conn_prepare(conn, peer->proto, peer->xprt);
- conn_install_mux(conn, &mux_pt_ops, cs, s->be);
+ conn_install_mux(conn, &mux_pt_ops, cs, s->be, NULL);
si_attach_cs(&s->si[1], cs);
s->do_log = NULL;