si->appctx.applet = NULL;
}
+/* Assign the stream interface's pre-allocated connection to the end point,
+ * and initialize the connection's context. This is used for outgoing
+ * connections.
+ */
static inline void si_prepare_conn(struct stream_interface *si, const struct protocol *ctrl, const struct xprt_ops *xprt)
{
+ struct connection *conn = si->conn;
+
si->ops = &si_conn_ops;
- si->end = &si->conn->obj_type;
- conn_prepare(si->conn, &si_conn_cb, ctrl, xprt, si);
+ si->end = &conn->obj_type;
+ conn_prepare(conn, &si_conn_cb, ctrl, xprt, si);
}
+/* Assign the stream interface's pre-allocated connection to the end point,
+ * and leave the connection's context untouched. This is used for incoming
+ * connections.
+ */
static inline void si_takeover_conn(struct stream_interface *si, const struct protocol *ctrl, const struct xprt_ops *xprt)
{
+ struct connection *conn = si->conn;
+
si->ops = &si_conn_ops;
- si->end = &si->conn->obj_type;
- conn_assign(si->conn, &si_conn_cb, ctrl, xprt, si);
+ si->end = &conn->obj_type;
+ conn_assign(conn, &si_conn_cb, ctrl, xprt, si);
}
static inline void si_prepare_applet(struct stream_interface *si, struct si_applet *applet)
/* Calls chk_snd on the connection using the ctrl layer */
static inline int si_connect(struct stream_interface *si)
{
+ struct connection *conn = objt_conn(si->end);
int ret;
- if (unlikely(!si->conn->ctrl || !si->conn->ctrl->connect))
+ if (unlikely(!conn || !conn->ctrl || !conn->ctrl->connect))
return SN_ERR_INTERNAL;
- ret = si->conn->ctrl->connect(si->conn, !channel_is_empty(si->ob), !!si->send_proxy_ofs);
+ ret = conn->ctrl->connect(conn, !channel_is_empty(si->ob), !!si->send_proxy_ofs);
if (ret != SN_ERR_NONE)
return ret;
/* needs src ip/port for logging */
if (si->flags & SI_FL_SRC_ADDR)
- conn_get_from_addr(si->conn);
+ conn_get_from_addr(conn);
/* Prepare to send a few handshakes related to the on-wire protocol. */
if (si->send_proxy_ofs)
- si->conn->flags |= CO_FL_SI_SEND_PROXY;
+ conn->flags |= CO_FL_SI_SEND_PROXY;
/* we need to be notified about connection establishment */
- si->conn->flags |= CO_FL_WAKE_DATA;
+ conn->flags |= CO_FL_WAKE_DATA;
/* we're in the process of establishing a connection */
si->state = SI_ST_CON;
unsigned int err_type; /* first error detected, one of SI_ET_* */
enum obj_type *end; /* points to the end point (connection or appctx) */
- struct connection *conn; /* descriptor for a connection */
+ struct connection *conn; /* pre-allocated connection */
struct si_ops *ops; /* general operations at the stream interface layer */
/* struct members below are the "remote" part, as seen from the buffer side */
int assign_server(struct session *s)
{
-
+ struct connection *conn;
struct server *conn_slot;
struct server *srv, *prev_srv;
int err;
switch (s->be->lbprm.algo & BE_LB_PARM) {
case BE_LB_HASH_SRC:
- if (s->req->prod->conn->addr.from.ss_family == AF_INET) {
+ conn = objt_conn(s->req->prod->end);
+ if (conn && conn->addr.from.ss_family == AF_INET) {
srv = get_server_sh(s->be,
- (void *)&((struct sockaddr_in *)&s->req->prod->conn->addr.from)->sin_addr,
+ (void *)&((struct sockaddr_in *)&conn->addr.from)->sin_addr,
4);
}
- else if (s->req->prod->conn->addr.from.ss_family == AF_INET6) {
+ else if (conn && conn->addr.from.ss_family == AF_INET6) {
srv = get_server_sh(s->be,
- (void *)&((struct sockaddr_in6 *)&s->req->prod->conn->addr.from)->sin6_addr,
+ (void *)&((struct sockaddr_in6 *)&conn->addr.from)->sin6_addr,
16);
}
else {
s->target = &s->be->obj_type;
}
else if ((s->be->options & PR_O_HTTP_PROXY) &&
- is_addr(&s->req->cons->conn->addr.to)) {
+ (conn = objt_conn(s->req->cons->end)) &&
+ is_addr(&conn->addr.to)) {
/* in proxy mode, we need a valid destination address */
s->target = &s->be->obj_type;
}
* Upon successful return, the session flag SN_ADDR_SET is set. This flag is
* not cleared, so it's to the caller to clear it if required.
*
+ * The address is set on si->conn only. This connection is expected to be
+ * already allocated and initialized.
+ *
*/
int assign_server_address(struct session *s)
{
+ struct connection *cli_conn = objt_conn(s->req->prod->end);
+ struct connection *srv_conn = s->req->cons->conn;
+
#ifdef DEBUG_FULL
fprintf(stderr,"assign_server_address : s=%p\n",s);
#endif
if (!(s->flags & SN_ASSIGNED))
return SRV_STATUS_INTERNAL;
- s->req->cons->conn->addr.to = objt_server(s->target)->addr;
+ srv_conn->addr.to = objt_server(s->target)->addr;
- if (!is_addr(&s->req->cons->conn->addr.to)) {
+ if (!is_addr(&srv_conn->addr.to) && cli_conn) {
/* if the server has no address, we use the same address
* the client asked, which is handy for remapping ports
* locally on multiple addresses at once.
*/
- conn_get_to_addr(s->req->prod->conn);
+ conn_get_to_addr(cli_conn);
- if (s->req->prod->conn->addr.to.ss_family == AF_INET) {
- ((struct sockaddr_in *)&s->req->cons->conn->addr.to)->sin_addr = ((struct sockaddr_in *)&s->req->prod->conn->addr.to)->sin_addr;
- } else if (s->req->prod->conn->addr.to.ss_family == AF_INET6) {
- ((struct sockaddr_in6 *)&s->req->cons->conn->addr.to)->sin6_addr = ((struct sockaddr_in6 *)&s->req->prod->conn->addr.to)->sin6_addr;
+ if (cli_conn->addr.to.ss_family == AF_INET) {
+ ((struct sockaddr_in *)&srv_conn->addr.to)->sin_addr = ((struct sockaddr_in *)&cli_conn->addr.to)->sin_addr;
+ } else if (cli_conn->addr.to.ss_family == AF_INET6) {
+ ((struct sockaddr_in6 *)&srv_conn->addr.to)->sin6_addr = ((struct sockaddr_in6 *)&cli_conn->addr.to)->sin6_addr;
}
}
/* if this server remaps proxied ports, we'll use
* the port the client connected to with an offset. */
- if (objt_server(s->target)->state & SRV_MAPPORTS) {
+ if ((objt_server(s->target)->state & SRV_MAPPORTS) && cli_conn) {
int base_port;
- conn_get_to_addr(s->req->prod->conn);
+ conn_get_to_addr(cli_conn);
/* First, retrieve the port from the incoming connection */
- base_port = get_host_port(&s->req->prod->conn->addr.to);
+ base_port = get_host_port(&cli_conn->addr.to);
/* Second, assign the outgoing connection's port */
- base_port += get_host_port(&s->req->cons->conn->addr.to);
- set_host_port(&s->req->cons->conn->addr.to, base_port);
+ base_port += get_host_port(&srv_conn->addr.to);
+ set_host_port(&srv_conn->addr.to, base_port);
}
}
else if (s->be->options & PR_O_DISPATCH) {
/* connect to the defined dispatch addr */
- s->req->cons->conn->addr.to = s->be->dispatch_addr;
+ srv_conn->addr.to = s->be->dispatch_addr;
}
- else if (s->be->options & PR_O_TRANSP) {
+ else if ((s->be->options & PR_O_TRANSP) && cli_conn) {
/* in transparent mode, use the original dest addr if no dispatch specified */
- conn_get_to_addr(s->req->prod->conn);
+ conn_get_to_addr(cli_conn);
- if (s->req->prod->conn->addr.to.ss_family == AF_INET || s->req->prod->conn->addr.to.ss_family == AF_INET6) {
- memcpy(&s->req->cons->conn->addr.to, &s->req->prod->conn->addr.to, MIN(sizeof(s->req->cons->conn->addr.to), sizeof(s->req->prod->conn->addr.to)));
- }
- /* when we support IPv6 on the backend, we may add other tests */
- //qfprintf(stderr, "Cannot get original server address.\n");
- //return SRV_STATUS_INTERNAL;
+ if (cli_conn->addr.to.ss_family == AF_INET || cli_conn->addr.to.ss_family == AF_INET6)
+ srv_conn->addr.to = cli_conn->addr.to;
}
else if (s->be->options & PR_O_HTTP_PROXY) {
/* If HTTP PROXY option is set, then server is already assigned
/* If an explicit source binding is specified on the server and/or backend, and
* this source makes use of the transparent proxy, then it is extracted now and
- * assigned to the session's req->cons->addr.from entry.
+ * assigned to the session's pending connection. This function assumes that an
+ * outgoing connection has already been allocated into s->req->cons->conn.
*/
static void assign_tproxy_address(struct session *s)
{
#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
struct server *srv = objt_server(s->target);
struct conn_src *src;
+ struct connection *cli_conn;
+ struct connection *srv_conn = s->req->cons->conn;
if (srv && srv->conn_src.opts & CO_SRC_BIND)
src = &srv->conn_src;
switch (src->opts & CO_SRC_TPROXY_MASK) {
case CO_SRC_TPROXY_ADDR:
- s->req->cons->conn->addr.from = src->tproxy_addr;
+ srv_conn->addr.from = src->tproxy_addr;
break;
case CO_SRC_TPROXY_CLI:
case CO_SRC_TPROXY_CIP:
/* FIXME: what can we do if the client connects in IPv6 or unix socket ? */
- s->req->cons->conn->addr.from = s->req->prod->conn->addr.from;
+ cli_conn = objt_conn(s->req->prod->end);
+ if (cli_conn)
+ srv_conn->addr.from = cli_conn->addr.from;
+ else
+ memset(&srv_conn->addr.from, 0, sizeof(srv_conn->addr.from));
break;
case CO_SRC_TPROXY_DYN:
if (src->bind_hdr_occ) {
int rewind;
/* bind to the IP in a header */
- ((struct sockaddr_in *)&s->req->cons->conn->addr.from)->sin_family = AF_INET;
- ((struct sockaddr_in *)&s->req->cons->conn->addr.from)->sin_port = 0;
- ((struct sockaddr_in *)&s->req->cons->conn->addr.from)->sin_addr.s_addr = 0;
+ ((struct sockaddr_in *)&srv_conn->addr.from)->sin_family = AF_INET;
+ ((struct sockaddr_in *)&srv_conn->addr.from)->sin_port = 0;
+ ((struct sockaddr_in *)&srv_conn->addr.from)->sin_addr.s_addr = 0;
b_rew(s->req->buf, rewind = s->req->buf->o);
if (http_get_hdr(&s->txn.req, src->bind_hdr_name, src->bind_hdr_len,
&s->txn.hdr_idx, src->bind_hdr_occ, NULL, &vptr, &vlen)) {
- ((struct sockaddr_in *)&s->req->cons->conn->addr.from)->sin_addr.s_addr =
+ ((struct sockaddr_in *)&srv_conn->addr.from)->sin_addr.s_addr =
htonl(inetaddr_host_lim(vptr, vptr + vlen));
}
b_adv(s->req->buf, rewind);
}
break;
default:
- memset(&s->req->cons->conn->addr.from, 0, sizeof(s->req->cons->conn->addr.from));
+ memset(&srv_conn->addr.from, 0, sizeof(srv_conn->addr.from));
}
#endif
}
* - SN_ERR_RESOURCE if a system resource is lacking (eg: fd limits, ports, ...)
* - SN_ERR_INTERNAL for any other purely internal errors
* Additionnally, in the case of SN_ERR_RESOURCE, an emergency log will be emitted.
+ * The server-facing stream interface is expected to hold a pre-allocated connection
+ * in s->req->cons->conn.
*/
int connect_server(struct session *s)
{
+ struct connection *cli_conn;
+ struct connection *srv_conn = s->req->cons->conn;
struct server *srv;
int err;
}
/* the target was only on the session, assign it to the SI now */
- s->req->cons->conn->target = s->target;
+ srv_conn->target = s->target;
/* set the correct protocol on the output stream interface */
if (objt_server(s->target)) {
}
else if (obj_type(s->target) == OBJ_TYPE_PROXY) {
/* proxies exclusively run on raw_sock right now */
- si_prepare_conn(s->req->cons, protocol_by_family(s->req->cons->conn->addr.to.ss_family), &raw_sock);
- if (!s->req->cons->conn->ctrl)
+ si_prepare_conn(s->req->cons, protocol_by_family(srv_conn->addr.to.ss_family), &raw_sock);
+ if (!objt_conn(s->req->cons->end) || !objt_conn(s->req->cons->end)->ctrl)
return SN_ERR_INTERNAL;
}
else
s->req->cons->send_proxy_ofs = 0;
if (objt_server(s->target) && (objt_server(s->target)->state & SRV_SEND_PROXY)) {
s->req->cons->send_proxy_ofs = 1; /* must compute size */
- conn_get_to_addr(s->req->prod->conn);
+ cli_conn = objt_conn(s->req->prod->end);
+ if (cli_conn)
+ conn_get_to_addr(cli_conn);
}
assign_tproxy_address(s);
extern const char *stat_status_codes[];
/* This function is called from the session-level accept() in order to instanciate
- * a new stats socket. It returns a positive value upon success, 0 if the connection
+ * a new stats socket. It returns a positive value upon success, 0 if the session
* needs to be closed and ignored, or a negative value upon critical failure.
*/
static int stats_accept(struct session *s)
struct tm tm;
extern const char *monthname[12];
char pn[INET6_ADDRSTRLEN];
+ struct connection *conn;
chunk_reset(&trash);
sess->uniq_id,
sess->listener && sess->listener->proto->name ? sess->listener->proto->name : "?");
- switch ((obj_type(sess->si[0].end) == OBJ_TYPE_CONN) ?
- addr_to_str(&sess->si[0].conn->addr.from, pn, sizeof(pn)) : AF_UNSPEC) {
+ conn = objt_conn(sess->si[0].end);
+ switch (conn ? addr_to_str(&conn->addr.from, pn, sizeof(pn)) : AF_UNSPEC) {
case AF_INET:
case AF_INET6:
chunk_appendf(&trash, " source=%s:%d\n",
- pn, get_host_port(&sess->si[0].conn->addr.from));
+ pn, get_host_port(&conn->addr.from));
break;
case AF_UNIX:
chunk_appendf(&trash, " source=unix:%d\n", sess->listener->luid);
sess->listener ? sess->listener->name ? sess->listener->name : "?" : "?",
sess->listener ? sess->listener->luid : 0);
- if (obj_type(sess->si[0].end) == OBJ_TYPE_CONN)
- conn_get_to_addr(sess->si[0].conn);
+ if (conn)
+ conn_get_to_addr(conn);
- switch ((obj_type(sess->si[0].end) == OBJ_TYPE_CONN) ?
- addr_to_str(&sess->si[0].conn->addr.to, pn, sizeof(pn)) : AF_UNSPEC) {
+ switch (conn ? addr_to_str(&conn->addr.to, pn, sizeof(pn)) : AF_UNSPEC) {
case AF_INET:
case AF_INET6:
chunk_appendf(&trash, " addr=%s:%d\n",
- pn, get_host_port(&sess->si[0].conn->addr.to));
+ pn, get_host_port(&conn->addr.to));
break;
case AF_UNIX:
chunk_appendf(&trash, " addr=unix:%d\n", sess->listener->luid);
else
chunk_appendf(&trash, " backend=<NONE> (id=-1 mode=-)");
- if (obj_type(sess->si[1].end) == OBJ_TYPE_CONN)
- conn_get_from_addr(sess->si[1].conn);
+ conn = objt_conn(sess->si[1].end);
+ if (conn)
+ conn_get_from_addr(conn);
- switch ((obj_type(sess->si[1].end) == OBJ_TYPE_CONN) ?
- addr_to_str(&sess->si[1].conn->addr.from, pn, sizeof(pn)) : AF_UNSPEC) {
+ switch (conn ? addr_to_str(&conn->addr.from, pn, sizeof(pn)) : AF_UNSPEC) {
case AF_INET:
case AF_INET6:
chunk_appendf(&trash, " addr=%s:%d\n",
- pn, get_host_port(&sess->si[1].conn->addr.from));
+ pn, get_host_port(&conn->addr.from));
break;
case AF_UNIX:
chunk_appendf(&trash, " addr=unix\n");
else
chunk_appendf(&trash, " server=<NONE> (id=-1)");
- if (obj_type(sess->si[1].end) == OBJ_TYPE_CONN)
- conn_get_to_addr(sess->si[1].conn);
+ if (conn)
+ conn_get_to_addr(conn);
- switch ((obj_type(sess->si[1].end) == OBJ_TYPE_CONN) ?
- addr_to_str(&sess->si[1].conn->addr.to, pn, sizeof(pn)) : AF_UNSPEC) {
+ switch (conn ? addr_to_str(&conn->addr.to, pn, sizeof(pn)) : AF_UNSPEC) {
case AF_INET:
case AF_INET6:
chunk_appendf(&trash, " addr=%s:%d\n",
- pn, get_host_port(&sess->si[1].conn->addr.to));
+ pn, get_host_port(&conn->addr.to));
break;
case AF_UNIX:
chunk_appendf(&trash, " addr=unix\n");
TICKS_TO_MS(1000)) : "<NEVER>",
sess->si[1].err_type);
- if (obj_type(sess->si[0].end) == OBJ_TYPE_CONN) {
+ conn = objt_conn(sess->si[0].end);
+ if (conn) {
chunk_appendf(&trash,
" co0=%p ctrl=%s xprt=%s data=%s target=%s:%p\n",
- sess->si[0].conn,
- get_conn_ctrl_name(sess->si[0].conn),
- get_conn_xprt_name(sess->si[0].conn),
- get_conn_data_name(sess->si[0].conn),
- obj_type_name(sess->si[0].conn->target),
- obj_base_ptr(sess->si[0].conn->target));
+ conn,
+ get_conn_ctrl_name(conn),
+ get_conn_xprt_name(conn),
+ get_conn_data_name(conn),
+ obj_type_name(conn->target),
+ obj_base_ptr(conn->target));
chunk_appendf(&trash,
" flags=0x%08x fd=%d fd_spec_e=%02x fd_spec_p=%d updt=%d\n",
- sess->si[0].conn->flags,
- sess->si[0].conn->t.sock.fd,
- sess->si[0].conn->t.sock.fd >= 0 ? fdtab[sess->si[0].conn->t.sock.fd].spec_e : 0,
- sess->si[0].conn->t.sock.fd >= 0 ? fdtab[sess->si[0].conn->t.sock.fd].spec_p : 0,
- sess->si[0].conn->t.sock.fd >= 0 ? fdtab[sess->si[0].conn->t.sock.fd].updated : 0);
+ conn->flags,
+ conn->t.sock.fd,
+ conn->t.sock.fd >= 0 ? fdtab[conn->t.sock.fd].spec_e : 0,
+ conn->t.sock.fd >= 0 ? fdtab[conn->t.sock.fd].spec_p : 0,
+ conn->t.sock.fd >= 0 ? fdtab[conn->t.sock.fd].updated : 0);
}
- if (obj_type(sess->si[1].end) == OBJ_TYPE_CONN) {
+ conn = objt_conn(sess->si[1].end);
+ if (conn) {
chunk_appendf(&trash,
" co1=%p ctrl=%s xprt=%s data=%s target=%s:%p\n",
- sess->si[1].conn,
- get_conn_ctrl_name(sess->si[1].conn),
- get_conn_xprt_name(sess->si[1].conn),
- get_conn_data_name(sess->si[1].conn),
- obj_type_name(sess->si[1].conn->target),
- obj_base_ptr(sess->si[1].conn->target));
+ conn,
+ get_conn_ctrl_name(conn),
+ get_conn_xprt_name(conn),
+ get_conn_data_name(conn),
+ obj_type_name(conn->target),
+ obj_base_ptr(conn->target));
chunk_appendf(&trash,
" flags=0x%08x fd=%d fd_spec_e=%02x fd_spec_p=%d updt=%d\n",
- sess->si[1].conn->flags,
- sess->si[1].conn->t.sock.fd,
- sess->si[1].conn->t.sock.fd >= 0 ? fdtab[sess->si[1].conn->t.sock.fd].spec_e : 0,
- sess->si[1].conn->t.sock.fd >= 0 ? fdtab[sess->si[1].conn->t.sock.fd].spec_p : 0,
- sess->si[1].conn->t.sock.fd >= 0 ? fdtab[sess->si[1].conn->t.sock.fd].updated : 0);
+ conn->flags,
+ conn->t.sock.fd,
+ conn->t.sock.fd >= 0 ? fdtab[conn->t.sock.fd].spec_e : 0,
+ conn->t.sock.fd >= 0 ? fdtab[conn->t.sock.fd].spec_p : 0,
+ conn->t.sock.fd >= 0 ? fdtab[conn->t.sock.fd].updated : 0);
}
chunk_appendf(&trash,
*/
static int stats_dump_sess_to_buffer(struct stream_interface *si)
{
+ struct connection *conn;
+
if (unlikely(si->ib->flags & (CF_WRITE_ERROR|CF_SHUTW))) {
/* If we're forced to shut down, we might have to remove our
* reference to the last session being dumped.
curr_sess->listener->proto->name);
- switch ((obj_type(curr_sess->si[0].end) == OBJ_TYPE_CONN) ?
- addr_to_str(&curr_sess->si[0].conn->addr.from, pn, sizeof(pn)) : AF_UNSPEC) {
+ conn = objt_conn(curr_sess->si[0].end);
+ switch (conn ? addr_to_str(&conn->addr.from, pn, sizeof(pn)) : AF_UNSPEC) {
case AF_INET:
case AF_INET6:
chunk_appendf(&trash,
" src=%s:%d fe=%s be=%s srv=%s",
pn,
- get_host_port(&curr_sess->si[0].conn->addr.from),
+ get_host_port(&conn->addr.from),
curr_sess->fe->id,
(curr_sess->be->cap & PR_CAP_BE) ? curr_sess->be->id : "<NONE>",
objt_server(curr_sess->target) ? objt_server(curr_sess->target)->id : "<none>"
human_time(TICKS_TO_MS(curr_sess->rep->analyse_exp - now_ms),
TICKS_TO_MS(1000)) : "");
+ conn = objt_conn(curr_sess->si[0].end);
chunk_appendf(&trash,
" s0=[%d,%1xh,fd=%d,ex=%s]",
curr_sess->si[0].state,
curr_sess->si[0].flags,
- (obj_type(curr_sess->si[0].end) == OBJ_TYPE_CONN) ?
- curr_sess->si[0].conn->t.sock.fd : -1,
+ conn ? conn->t.sock.fd : -1,
curr_sess->si[0].exp ?
human_time(TICKS_TO_MS(curr_sess->si[0].exp - now_ms),
TICKS_TO_MS(1000)) : "");
+ conn = objt_conn(curr_sess->si[1].end);
chunk_appendf(&trash,
" s1=[%d,%1xh,fd=%d,ex=%s]",
curr_sess->si[1].state,
curr_sess->si[1].flags,
- (obj_type(curr_sess->si[1].end) == OBJ_TYPE_CONN) ?
- curr_sess->si[1].conn->t.sock.fd : -1,
+ conn ? conn->t.sock.fd : -1,
curr_sess->si[1].exp ?
human_time(TICKS_TO_MS(curr_sess->si[1].exp - now_ms),
TICKS_TO_MS(1000)) : "");
/* Finish a session accept() for a proxy (TCP or HTTP). It returns a negative
* value in case of a critical failure which must cause the listener to be
* disabled, a positive value in case of success, or zero if it is a success
- * but the session must be closed ASAP (eg: monitoring).
+ * but the session must be closed ASAP (eg: monitoring). It only supports
+ * sessions with a connection in si[0].
*/
int frontend_accept(struct session *s)
{
- int cfd = s->si[0].conn->t.sock.fd;
+ struct connection *conn = __objt_conn(s->si[0].end);
+ int cfd = conn->t.sock.fd;
tv_zero(&s->logs.tv_request);
s->logs.t_queue = -1;
else {
char pn[INET6_ADDRSTRLEN], sn[INET6_ADDRSTRLEN];
- conn_get_from_addr(s->req->prod->conn);
- conn_get_to_addr(s->req->prod->conn);
+ conn_get_from_addr(conn);
+ conn_get_to_addr(conn);
- switch (addr_to_str(&s->req->prod->conn->addr.from, pn, sizeof(pn))) {
+ switch (addr_to_str(&conn->addr.from, pn, sizeof(pn))) {
case AF_INET:
case AF_INET6:
- addr_to_str(&s->req->prod->conn->addr.to, sn, sizeof(sn));
+ addr_to_str(&conn->addr.to, sn, sizeof(sn));
send_log(s->fe, LOG_INFO, "Connect from %s:%d to %s:%d (%s/%s)\n",
- pn, get_host_port(&s->req->prod->conn->addr.from),
- sn, get_host_port(&s->req->prod->conn->addr.to),
+ pn, get_host_port(&conn->addr.from),
+ sn, get_host_port(&conn->addr.to),
s->fe->id, (s->fe->mode == PR_MODE_HTTP) ? "HTTP" : "TCP");
break;
case AF_UNIX:
if (unlikely((global.mode & MODE_DEBUG) && (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)))) {
char pn[INET6_ADDRSTRLEN];
- conn_get_from_addr(s->req->prod->conn);
+ conn_get_from_addr(conn);
- switch (addr_to_str(&s->req->prod->conn->addr.from, pn, sizeof(pn))) {
+ switch (addr_to_str(&conn->addr.from, pn, sizeof(pn))) {
case AF_INET:
case AF_INET6:
chunk_printf(&trash, "%08x:%s.accept(%04x)=%04x from [%s:%d]\n",
s->uniq_id, s->fe->id, (unsigned short)s->listener->fd, (unsigned short)cfd,
- pn, get_host_port(&s->req->prod->conn->addr.from));
+ pn, get_host_port(&conn->addr.from));
break;
case AF_UNIX:
/* UNIX socket, only the destination is known */
return 0;
list_for_each_entry(tmp, list_format, list) {
+ struct connection *conn;
const char *src = NULL;
struct sample *key;
break;
case LOG_FMT_CLIENTIP: // %ci
- ret = lf_ip(tmplog, (struct sockaddr *)&s->req->prod->conn->addr.from,
- dst + maxsize - tmplog, tmp);
+ conn = objt_conn(s->req->prod->end);
+ if (conn)
+ ret = lf_ip(tmplog, (struct sockaddr *)&conn->addr.from, dst + maxsize - tmplog, tmp);
+ else
+ ret = lf_text_len(tmplog, NULL, 0, dst + maxsize - tmplog, tmp);
if (ret == NULL)
goto out;
tmplog = ret;
break;
case LOG_FMT_CLIENTPORT: // %cp
- if (s->req->prod->conn->addr.from.ss_family == AF_UNIX) {
- ret = ltoa_o(s->listener->luid, tmplog, dst + maxsize - tmplog);
- } else {
- ret = lf_port(tmplog, (struct sockaddr *)&s->req->prod->conn->addr.from,
- dst + maxsize - tmplog, tmp);
+ conn = objt_conn(s->req->prod->end);
+ if (conn) {
+ if (conn->addr.from.ss_family == AF_UNIX) {
+ ret = ltoa_o(s->listener->luid, tmplog, dst + maxsize - tmplog);
+ } else {
+ ret = lf_port(tmplog, (struct sockaddr *)&conn->addr.from,
+ dst + maxsize - tmplog, tmp);
+ }
}
+ else
+ ret = lf_text_len(tmplog, NULL, 0, dst + maxsize - tmplog, tmp);
+
if (ret == NULL)
goto out;
tmplog = ret;
break;
case LOG_FMT_FRONTENDIP: // %fi
- conn_get_to_addr(s->req->prod->conn);
- ret = lf_ip(tmplog, (struct sockaddr *)&s->req->prod->conn->addr.to,
- dst + maxsize - tmplog, tmp);
+ conn = objt_conn(s->req->prod->end);
+ if (conn) {
+ conn_get_to_addr(conn);
+ ret = lf_ip(tmplog, (struct sockaddr *)&conn->addr.to, dst + maxsize - tmplog, tmp);
+ }
+ else
+ ret = lf_text_len(tmplog, NULL, 0, dst + maxsize - tmplog, tmp);
+
if (ret == NULL)
goto out;
tmplog = ret;
break;
case LOG_FMT_FRONTENDPORT: // %fp
- conn_get_to_addr(s->req->prod->conn);
- if (s->req->prod->conn->addr.to.ss_family == AF_UNIX) {
- ret = ltoa_o(s->listener->luid,
- tmplog, dst + maxsize - tmplog);
- } else {
- ret = lf_port(tmplog, (struct sockaddr *)&s->req->prod->conn->addr.to,
- dst + maxsize - tmplog, tmp);
+ conn = objt_conn(s->req->prod->end);
+ if (conn) {
+ conn_get_to_addr(conn);
+ if (conn->addr.to.ss_family == AF_UNIX)
+ ret = ltoa_o(s->listener->luid, tmplog, dst + maxsize - tmplog);
+ else
+ ret = lf_port(tmplog, (struct sockaddr *)&conn->addr.to, dst + maxsize - tmplog, tmp);
}
+ else
+ ret = lf_text_len(tmplog, NULL, 0, dst + maxsize - tmplog, tmp);
+
if (ret == NULL)
goto out;
tmplog = ret;
break;
case LOG_FMT_BACKENDIP: // %bi
- ret = lf_ip(tmplog, (struct sockaddr *)&s->req->cons->conn->addr.from,
- dst + maxsize - tmplog, tmp);
+ conn = objt_conn(s->req->cons->end);
+ if (conn)
+ ret = lf_ip(tmplog, (struct sockaddr *)&conn->addr.from, dst + maxsize - tmplog, tmp);
+ else
+ ret = lf_text_len(tmplog, NULL, 0, dst + maxsize - tmplog, tmp);
+
if (ret == NULL)
goto out;
tmplog = ret;
break;
case LOG_FMT_BACKENDPORT: // %bp
- ret = lf_port(tmplog, (struct sockaddr *)&s->req->cons->conn->addr.from,
- dst + maxsize - tmplog, tmp);
+ conn = objt_conn(s->req->cons->end);
+ if (conn)
+ ret = lf_port(tmplog, (struct sockaddr *)&conn->addr.from, dst + maxsize - tmplog, tmp);
+ else
+ ret = lf_text_len(tmplog, NULL, 0, dst + maxsize - tmplog, tmp);
+
if (ret == NULL)
goto out;
tmplog = ret;
break;
case LOG_FMT_SERVERIP: // %si
- ret = lf_ip(tmplog, (struct sockaddr *)&s->req->cons->conn->addr.to,
- dst + maxsize - tmplog, tmp);
+ conn = objt_conn(s->req->cons->end);
+ if (conn)
+ ret = lf_ip(tmplog, (struct sockaddr *)&conn->addr.to, dst + maxsize - tmplog, tmp);
+ else
+ ret = lf_text_len(tmplog, NULL, 0, dst + maxsize - tmplog, tmp);
+
if (ret == NULL)
goto out;
tmplog = ret;
break;
case LOG_FMT_SERVERPORT: // %sp
- ret = lf_port(tmplog, (struct sockaddr *)&s->req->cons->conn->addr.to,
- dst + maxsize - tmplog, tmp);
+ conn = objt_conn(s->req->cons->end);
+ if (conn)
+ ret = lf_port(tmplog, (struct sockaddr *)&conn->addr.to, dst + maxsize - tmplog, tmp);
+ else
+ ret = lf_text_len(tmplog, NULL, 0, dst + maxsize - tmplog, tmp);
+
if (ret == NULL)
goto out;
tmplog = ret;
#ifdef USE_OPENSSL
case LOG_FMT_SSL_CIPHER: // %sslc
src = NULL;
- if (s->listener->xprt == &ssl_sock)
- src = ssl_sock_get_cipher_name(s->si[0].conn);
+ conn = objt_conn(s->si[0].end);
+ if (conn) {
+ if (s->listener->xprt == &ssl_sock)
+ src = ssl_sock_get_cipher_name(conn);
+ }
ret = lf_text(tmplog, src, dst + maxsize - tmplog, tmp);
if (ret == NULL)
goto out;
case LOG_FMT_SSL_VERSION: // %sslv
src = NULL;
- if (s->listener->xprt == &ssl_sock)
- src = ssl_sock_get_proto_version(s->si[0].conn);
+ conn = objt_conn(s->si[0].end);
+ if (conn) {
+ if (s->listener->xprt == &ssl_sock)
+ src = ssl_sock_get_proto_version(conn);
+ }
ret = lf_text(tmplog, src, dst + maxsize - tmplog, tmp);
if (ret == NULL)
goto out;
task_wakeup(session->task, TASK_WOKEN_MSG);
}
-/*
- * this function is called on a read event from a listen socket, corresponding
- * to an accept. It tries to accept as many connections as possible.
- * It returns a positive value upon success, 0 if the connection needs to be
- * closed and ignored, or a negative value upon critical failure.
+/* Finish a session accept() for a peer. It returns a negative value in case of
+ * a critical failure which must cause the listener to be disabled, a positive
+ * value in case of success, or zero if it is a success but the session must be
+ * closed ASAP and ignored.
*/
int peer_accept(struct session *s)
{
s->req = s->rep = NULL; /* will be allocated later */
+ /* si[0] is the applet, we should not need s->si[0].conn anymore soon */
s->si[0].conn->obj_type = OBJ_TYPE_CONN;
s->si[0].conn->t.sock.fd = -1;
s->si[0].conn->flags = CO_FL_NONE;
s->si[0].conn->err_code = CO_ER_NONE;
+ s->si[0].conn->target = &l->obj_type;
+
s->si[0].owner = t;
s->si[0].state = s->si[0].prev_state = SI_ST_EST;
s->si[0].err_type = SI_ET_NONE;
s->si[0].send_proxy_ofs = 0;
- s->si[0].conn->target = &l->obj_type;
s->si[0].exp = TICK_ETERNITY;
s->si[0].flags = SI_FL_NONE;
if (s->fe->options2 & PR_O2_INDEPSTR)
s->si[1].conn->t.sock.fd = -1; /* just to help with debugging */
s->si[1].conn->flags = CO_FL_NONE;
s->si[1].conn->err_code = CO_ER_NONE;
+ s->si[1].conn->target = &s->be->obj_type;
+
s->si[1].owner = t;
s->si[1].state = s->si[1].prev_state = SI_ST_ASS;
s->si[1].conn_retries = p->conn_retries;
s->si[1].err_type = SI_ET_NONE;
s->si[1].send_proxy_ofs = 0;
- s->si[1].conn->target = &s->be->obj_type;
- si_prepare_conn(&s->si[1], peer->proto, peer->xprt);
s->si[1].exp = TICK_ETERNITY;
s->si[1].flags = SI_FL_NONE;
if (s->be->options2 & PR_O2_INDEPSTR)
s->si[1].flags |= SI_FL_INDEP_STR;
+ /* will automatically prepare the stream interface to connect to the
+ * pre-initialized connection in si->conn.
+ */
+ si_prepare_conn(&s->si[1], peer->proto, peer->xprt);
+
session_init_srv_conn(s);
s->target = &s->be->obj_type;
s->pend_pos = NULL;
req->flags |= CF_READ_DONTWAIT; /* try to get back here ASAP */
s->rep->flags &= ~CF_EXPECT_MORE; /* speed up sending a previous response */
#ifdef TCP_QUICKACK
- if (s->listener->options & LI_O_NOQUICKACK && req->buf->i) {
+ if (s->listener->options & LI_O_NOQUICKACK && req->buf->i && objt_conn(s->req->prod->end)) {
/* We need more data, we have to re-enable quick-ack in case we
* previously disabled it, otherwise we might cause the client
* to delay next data.
*/
- setsockopt(s->si[0].conn->t.sock.fd, IPPROTO_TCP, TCP_QUICKACK, &one, sizeof(one));
+ setsockopt(__objt_conn(s->req->prod->end)->t.sock.fd, IPPROTO_TCP, TCP_QUICKACK, &one, sizeof(one));
}
#endif
static struct http_req_rule *
http_req_get_intercept_rule(struct proxy *px, struct list *rules, struct session *s, struct http_txn *txn)
{
+ struct connection *cli_conn;
struct http_req_rule *rule;
struct hdr_ctx ctx;
break;
case HTTP_REQ_ACT_SET_TOS:
- inet_set_tos(s->req->prod->conn->t.sock.fd, s->req->prod->conn->addr.from, rule->arg.tos);
+ if ((cli_conn = objt_conn(s->req->prod->end)))
+ inet_set_tos(cli_conn->t.sock.fd, cli_conn->addr.from, rule->arg.tos);
break;
case HTTP_REQ_ACT_SET_MARK:
#ifdef SO_MARK
- setsockopt(s->req->prod->conn->t.sock.fd, SOL_SOCKET, SO_MARK, &rule->arg.mark, sizeof(rule->arg.mark));
+ if ((cli_conn = objt_conn(s->req->prod->end)))
+ setsockopt(cli_conn->t.sock.fd, SOL_SOCKET, SO_MARK, &rule->arg.mark, sizeof(rule->arg.mark));
#endif
break;
static struct http_res_rule *
http_res_get_intercept_rule(struct proxy *px, struct list *rules, struct session *s, struct http_txn *txn)
{
+ struct connection *cli_conn;
struct http_res_rule *rule;
struct hdr_ctx ctx;
break;
case HTTP_RES_ACT_SET_TOS:
- inet_set_tos(s->req->prod->conn->t.sock.fd, s->req->prod->conn->addr.from, rule->arg.tos);
+ if ((cli_conn = objt_conn(s->req->prod->end)))
+ inet_set_tos(cli_conn->t.sock.fd, cli_conn->addr.from, rule->arg.tos);
break;
case HTTP_RES_ACT_SET_MARK:
#ifdef SO_MARK
- setsockopt(s->req->prod->conn->t.sock.fd, SOL_SOCKET, SO_MARK, &rule->arg.mark, sizeof(rule->arg.mark));
+ if ((cli_conn = objt_conn(s->req->prod->end)))
+ setsockopt(cli_conn->t.sock.fd, SOL_SOCKET, SO_MARK, &rule->arg.mark, sizeof(rule->arg.mark));
#endif
break;
{
struct http_txn *txn = &s->txn;
struct http_msg *msg = &txn->req;
+ struct connection *cli_conn = objt_conn(req->prod->end);
if (unlikely(msg->msg_state < HTTP_MSG_BODY)) {
/* we need more data */
*/
/*
- * If HTTP PROXY is set we simply get remote server address
- * parsing incoming request.
+ * If HTTP PROXY is set we simply get remote server address parsing
+ * incoming request. Note that this requires that a connection is
+ * allocated on the server side.
*/
if ((s->be->options & PR_O_HTTP_PROXY) && !(s->flags & SN_ADDR_SET)) {
url2sa(req->buf->p + msg->sl.rq.u, msg->sl.rq.u_l, &s->req->cons->conn->addr.to);
* and we found it, so don't do anything.
*/
}
- else if (s->req->prod->conn->addr.from.ss_family == AF_INET) {
+ else if (cli_conn && cli_conn->addr.from.ss_family == AF_INET) {
/* Add an X-Forwarded-For header unless the source IP is
* in the 'except' network range.
*/
if ((!s->fe->except_mask.s_addr ||
- (((struct sockaddr_in *)&s->req->prod->conn->addr.from)->sin_addr.s_addr & s->fe->except_mask.s_addr)
+ (((struct sockaddr_in *)&cli_conn->addr.from)->sin_addr.s_addr & s->fe->except_mask.s_addr)
!= s->fe->except_net.s_addr) &&
(!s->be->except_mask.s_addr ||
- (((struct sockaddr_in *)&s->req->prod->conn->addr.from)->sin_addr.s_addr & s->be->except_mask.s_addr)
+ (((struct sockaddr_in *)&cli_conn->addr.from)->sin_addr.s_addr & s->be->except_mask.s_addr)
!= s->be->except_net.s_addr)) {
int len;
unsigned char *pn;
- pn = (unsigned char *)&((struct sockaddr_in *)&s->req->prod->conn->addr.from)->sin_addr;
+ pn = (unsigned char *)&((struct sockaddr_in *)&cli_conn->addr.from)->sin_addr;
/* Note: we rely on the backend to get the header name to be used for
* x-forwarded-for, because the header is really meant for the backends.
goto return_bad_req;
}
}
- else if (s->req->prod->conn->addr.from.ss_family == AF_INET6) {
+ else if (cli_conn && cli_conn->addr.from.ss_family == AF_INET6) {
/* FIXME: for the sake of completeness, we should also support
* 'except' here, although it is mostly useless in this case.
*/
int len;
char pn[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6,
- (const void *)&((struct sockaddr_in6 *)(&s->req->prod->conn->addr.from))->sin6_addr,
+ (const void *)&((struct sockaddr_in6 *)(&cli_conn->addr.from))->sin6_addr,
pn, sizeof(pn));
/* Note: we rely on the backend to get the header name to be used for
if ((s->fe->options | s->be->options) & PR_O_ORGTO) {
/* FIXME: don't know if IPv6 can handle that case too. */
- if (s->req->prod->conn->addr.from.ss_family == AF_INET) {
+ if (cli_conn && cli_conn->addr.from.ss_family == AF_INET) {
/* Add an X-Original-To header unless the destination IP is
* in the 'except' network range.
*/
- conn_get_to_addr(s->req->prod->conn);
+ conn_get_to_addr(cli_conn);
- if (s->req->prod->conn->addr.to.ss_family == AF_INET &&
+ if (cli_conn->addr.to.ss_family == AF_INET &&
((!s->fe->except_mask_to.s_addr ||
- (((struct sockaddr_in *)&s->req->prod->conn->addr.to)->sin_addr.s_addr & s->fe->except_mask_to.s_addr)
+ (((struct sockaddr_in *)&cli_conn->addr.to)->sin_addr.s_addr & s->fe->except_mask_to.s_addr)
!= s->fe->except_to.s_addr) &&
(!s->be->except_mask_to.s_addr ||
- (((struct sockaddr_in *)&s->req->prod->conn->addr.to)->sin_addr.s_addr & s->be->except_mask_to.s_addr)
+ (((struct sockaddr_in *)&cli_conn->addr.to)->sin_addr.s_addr & s->be->except_mask_to.s_addr)
!= s->be->except_to.s_addr))) {
int len;
unsigned char *pn;
- pn = (unsigned char *)&((struct sockaddr_in *)&s->req->prod->conn->addr.to)->sin_addr;
+ pn = (unsigned char *)&((struct sockaddr_in *)&cli_conn->addr.to)->sin_addr;
/* Note: we rely on the backend to get the header name to be used for
* x-original-to, because the header is really meant for the backends.
* the client to delay further data.
*/
if ((s->listener->options & LI_O_NOQUICKACK) &&
+ cli_conn &&
((msg->flags & HTTP_MSGF_TE_CHNK) ||
(msg->body_len > req->buf->i - txn->req.eoh - 2)))
- setsockopt(s->si[0].conn->t.sock.fd, IPPROTO_TCP, TCP_QUICKACK, &one, sizeof(one));
+ setsockopt(cli_conn->t.sock.fd, IPPROTO_TCP, TCP_QUICKACK, &one, sizeof(one));
#endif
}
s->target = NULL;
+ /* reinitialize the connection to the server */
s->req->cons->state = s->req->cons->prev_state = SI_ST_INI;
+ s->req->cons->end = NULL;
s->req->cons->conn->obj_type = OBJ_TYPE_CONN;
s->req->cons->conn->t.sock.fd = -1; /* just to help with debugging */
s->req->cons->conn->flags = CO_FL_NONE;
es->sid = s->uniq_id;
es->srv = objt_server(s->target);
es->oe = other_end;
- es->src = s->req->prod->conn->addr.from;
+ if (objt_conn(s->req->prod->end))
+ es->src = __objt_conn(s->req->prod->end)->addr.from;
+ else
+ memset(&es->src, 0, sizeof(es->src));
+
es->state = state;
es->ev_id = error_snapshot_id++;
es->b_flags = chn->flags;
{
int max;
chunk_printf(&trash, "%08x:%s.%s[%04x:%04x]: ", t->uniq_id, t->be->id,
- dir, (unsigned short)t->req->prod->conn->t.sock.fd,
- (unsigned short)t->req->cons->conn->t.sock.fd);
+ dir,
+ objt_conn(t->req->prod->end) ? (unsigned short)objt_conn(t->req->prod->end)->t.sock.fd : -1,
+ objt_conn(t->req->cons->end) ? (unsigned short)objt_conn(t->req->cons->end)->t.sock.fd : -1);
for (max = 0; start + max < end; max++)
if (start[max] == '\r' || start[max] == '\n')
const struct arg *args, struct sample *smp, const char *kw)
{
struct chunk *temp;
+ struct connection *cli_conn = objt_conn(l4->si[0].end);
+
+ if (!cli_conn)
+ return 0;
if (!smp_fetch_base32(px, l4, l7, opt, args, smp, kw))
return 0;
memcpy(temp->str + temp->len, &smp->data.uint, sizeof(smp->data.uint));
temp->len += sizeof(smp->data.uint);
- switch (l4->si[0].conn->addr.from.ss_family) {
+ switch (cli_conn->addr.from.ss_family) {
case AF_INET:
- memcpy(temp->str + temp->len, &((struct sockaddr_in *)&l4->si[0].conn->addr.from)->sin_addr, 4);
+ memcpy(temp->str + temp->len, &((struct sockaddr_in *)&cli_conn->addr.from)->sin_addr, 4);
temp->len += 4;
break;
case AF_INET6:
- memcpy(temp->str + temp->len, &((struct sockaddr_in6 *)(&l4->si[0].conn->addr.from))->sin6_addr, 16);
+ memcpy(temp->str + temp->len, &((struct sockaddr_in6 *)&cli_conn->addr.from)->sin6_addr, 16);
temp->len += 16;
break;
default:
const struct arg *args, struct sample *smp, const char *kw)
{
struct chunk *temp;
+ struct connection *cli_conn = objt_conn(l4->si[0].end);
if (!smp_fetch_url32(px, l4, l7, opt, args, smp, kw))
return 0;
memcpy(temp->str + temp->len, &smp->data.uint, sizeof(smp->data.uint));
temp->len += sizeof(smp->data.uint);
- switch (l4->si[0].conn->addr.from.ss_family) {
+ switch (cli_conn->addr.from.ss_family) {
case AF_INET:
- memcpy(temp->str + temp->len, &((struct sockaddr_in *)&l4->si[0].conn->addr.from)->sin_addr, 4);
+ memcpy(temp->str + temp->len, &((struct sockaddr_in *)&cli_conn->addr.from)->sin_addr, 4);
temp->len += 4;
break;
case AF_INET6:
- memcpy(temp->str + temp->len, &((struct sockaddr_in6 *)(&l4->si[0].conn->addr.from))->sin6_addr, 16);
+ memcpy(temp->str + temp->len, &((struct sockaddr_in6 *)&cli_conn->addr.from)->sin6_addr, 16);
temp->len += 16;
break;
default:
/* This function performs the TCP layer4 analysis on the current request. It
* returns 0 if a reject rule matches, otherwise 1 if either an accept rule
* matches or if no more rule matches. It can only use rules which don't need
- * any data.
+ * any data. This only works on connection-based client-facing stream interfaces.
*/
int tcp_exec_req_rules(struct session *s)
{
struct tcp_rule *rule;
struct stksess *ts;
struct stktable *t = NULL;
+ struct connection *conn = objt_conn(s->si[0].end);
int result = 1;
enum acl_test_res ret;
+ if (!conn)
+ return result;
+
list_for_each_entry(rule, &s->fe->tcp_req.l4_rules, list) {
ret = ACL_TEST_PASS;
session_track_stkctr(&s->stkctr[tcp_trk_idx(rule->action)], t, ts);
}
else if (rule->action == TCP_ACT_EXPECT_PX) {
- s->si[0].conn->flags |= CO_FL_ACCEPT_PROXY;
- conn_sock_want_recv(s->si[0].conn);
+ conn->flags |= CO_FL_ACCEPT_PROXY;
+ conn_sock_want_recv(conn);
}
else {
/* otherwise it's an accept */
smp_fetch_src(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
- switch (l4->si[0].conn->addr.from.ss_family) {
+ struct connection *cli_conn = objt_conn(l4->si[0].end);
+
+ if (!cli_conn)
+ return 0;
+
+ switch (cli_conn->addr.from.ss_family) {
case AF_INET:
- smp->data.ipv4 = ((struct sockaddr_in *)&l4->si[0].conn->addr.from)->sin_addr;
+ smp->data.ipv4 = ((struct sockaddr_in *)&cli_conn->addr.from)->sin_addr;
smp->type = SMP_T_IPV4;
break;
case AF_INET6:
- smp->data.ipv6 = ((struct sockaddr_in6 *)(&l4->si[0].conn->addr.from))->sin6_addr;
+ smp->data.ipv6 = ((struct sockaddr_in6 *)&cli_conn->addr.from)->sin6_addr;
smp->type = SMP_T_IPV6;
break;
default:
smp_fetch_sport(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
+ struct connection *cli_conn = objt_conn(l4->si[0].end);
+
+ if (!cli_conn)
+ return 0;
+
smp->type = SMP_T_UINT;
- if (!(smp->data.uint = get_host_port(&l4->si[0].conn->addr.from)))
+ if (!(smp->data.uint = get_host_port(&cli_conn->addr.from)))
return 0;
smp->flags = 0;
smp_fetch_dst(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
- conn_get_to_addr(l4->si[0].conn);
+ struct connection *cli_conn = objt_conn(l4->si[0].end);
- switch (l4->si[0].conn->addr.to.ss_family) {
+ if (!cli_conn)
+ return 0;
+
+ conn_get_to_addr(cli_conn);
+
+ switch (cli_conn->addr.to.ss_family) {
case AF_INET:
- smp->data.ipv4 = ((struct sockaddr_in *)&l4->si[0].conn->addr.to)->sin_addr;
+ smp->data.ipv4 = ((struct sockaddr_in *)&cli_conn->addr.to)->sin_addr;
smp->type = SMP_T_IPV4;
break;
case AF_INET6:
- smp->data.ipv6 = ((struct sockaddr_in6 *)(&l4->si[0].conn->addr.to))->sin6_addr;
+ smp->data.ipv6 = ((struct sockaddr_in6 *)&cli_conn->addr.to)->sin6_addr;
smp->type = SMP_T_IPV6;
break;
default:
smp_fetch_dport(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
- conn_get_to_addr(l4->si[0].conn);
+ struct connection *cli_conn = objt_conn(l4->si[0].end);
+
+ if (!cli_conn)
+ return 0;
+
+ conn_get_to_addr(cli_conn);
smp->type = SMP_T_UINT;
- if (!(smp->data.uint = get_host_port(&l4->si[0].conn->addr.to)))
+ if (!(smp->data.uint = get_host_port(&cli_conn->addr.to)))
return 0;
smp->flags = 0;
*/
int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr)
{
+ struct connection *cli_conn;
struct proxy *p = l->frontend;
struct session *s;
struct task *t;
if (unlikely((s = pool_alloc2(pool2_session)) == NULL))
goto out_close;
- if (unlikely((s->si[0].conn = pool_alloc2(pool2_connection)) == NULL))
+ if (unlikely((cli_conn = s->si[0].conn = pool_alloc2(pool2_connection)) == NULL))
goto out_fail_conn0;
if (unlikely((s->si[1].conn = pool_alloc2(pool2_connection)) == NULL))
s->listener = l;
s->fe = p;
- /* OK, we're keeping the session, so let's properly initialize the session */
- s->si[0].conn->obj_type = OBJ_TYPE_CONN;
- s->si[0].conn->t.sock.fd = cfd;
- s->si[0].conn->ctrl = l->proto;
- s->si[0].conn->flags = CO_FL_NONE | CO_FL_ADDR_FROM_SET;
- s->si[0].conn->err_code = CO_ER_NONE;
- s->si[0].conn->addr.from = *addr;
- s->si[0].conn->target = &l->obj_type;
-
- /* FIXME: this should be replaced with OBJ_TYPE_NONE once all users check the
- * object type before dereferencing the connection pointer.
+ /* OK, we're keeping the session, so let's properly initialize the session.
+ * We first have to initialize the client-side connection.
*/
- s->si[1].conn->obj_type = OBJ_TYPE_CONN;
+ cli_conn->obj_type = OBJ_TYPE_CONN;
+ cli_conn->t.sock.fd = cfd;
+ cli_conn->ctrl = l->proto;
+ cli_conn->flags = CO_FL_NONE | CO_FL_ADDR_FROM_SET;
+ cli_conn->err_code = CO_ER_NONE;
+ cli_conn->addr.from = *addr;
+ cli_conn->target = &l->obj_type;
+
+ /* The server side is not used yet, but just initialize it to avoid
+ * confusing some debugging or "show sess" for example.
+ */
+ s->si[1].conn->obj_type = OBJ_TYPE_NONE;
s->logs.accept_date = date; /* user-visible date for logging */
s->logs.tv_accept = now; /* corrected date for internal use */
/* wait for a PROXY protocol header */
if (l->options & LI_O_ACC_PROXY) {
- s->si[0].conn->flags |= CO_FL_ACCEPT_PROXY;
- conn_sock_want_recv(s->si[0].conn);
+ cli_conn->flags |= CO_FL_ACCEPT_PROXY;
+ conn_sock_want_recv(cli_conn);
}
if (unlikely((t = task_new()) == NULL))
* but not initialized. Also note we need to be careful as the stream
* int is not initialized yet.
*/
- conn_prepare(s->si[0].conn, &sess_conn_cb, l->proto, l->xprt, s);
+ conn_prepare(cli_conn, &sess_conn_cb, l->proto, l->xprt, s);
/* finish initialization of the accepted file descriptor */
fd_insert(cfd);
- fdtab[cfd].owner = s->si[0].conn;
+ fdtab[cfd].owner = cli_conn;
fdtab[cfd].iocb = conn_fd_handler;
- conn_data_want_recv(s->si[0].conn);
- if (conn_xprt_init(s->si[0].conn) < 0)
+ conn_data_want_recv(cli_conn);
+ if (conn_xprt_init(cli_conn) < 0)
goto out_free_task;
/* OK, now either we have a pending handshake to execute with and
* set the I/O timeout to the frontend's client timeout.
*/
- if (s->si[0].conn->flags & CO_FL_HANDSHAKE) {
+ if (cli_conn->flags & CO_FL_HANDSHAKE) {
t->process = expire_mini_session;
t->expire = tick_add_ifset(now_ms, p->timeout.client);
task_queue(t);
- s->si[0].conn->flags |= CO_FL_INIT_DATA | CO_FL_WAKE_DATA;
+ cli_conn->flags |= CO_FL_INIT_DATA | CO_FL_WAKE_DATA;
return 1;
}
/* OK let's complete session initialization since there is no handshake */
- s->si[0].conn->flags |= CO_FL_CONNECTED;
+ cli_conn->flags |= CO_FL_CONNECTED;
ret = session_complete(s);
if (ret > 0)
return ret;
}
-/* prepare the trash with a log prefix for session <s> */
+/* prepare the trash with a log prefix for session <s>. It only works with
+ * embryonic sessions based on a real connection.
+ */
static void prepare_mini_sess_log_prefix(struct session *s)
{
struct tm tm;
char pn[INET6_ADDRSTRLEN];
int ret;
char *end;
+ struct connection *cli_conn = s->si[0].conn;
- ret = addr_to_str(&s->si[0].conn->addr.from, pn, sizeof(pn));
+ ret = addr_to_str(&cli_conn->addr.from, pn, sizeof(pn));
if (ret <= 0)
chunk_printf(&trash, "unknown [");
else if (ret == AF_UNIX)
chunk_printf(&trash, "%s:%d [", pn, s->listener->luid);
else
- chunk_printf(&trash, "%s:%d [", pn, get_host_port(&s->si[0].conn->addr.from));
+ chunk_printf(&trash, "%s:%d [", pn, get_host_port(&cli_conn->addr.from));
get_localtime(s->logs.accept_date.tv_sec, &tm);
end = date2str_log(trash.str + trash.len, &tm, &(s->logs.accept_date), trash.size - trash.len);
}
/* kill the connection now */
- conn_full_close(s->si[0].conn);
+ conn_full_close(conn);
s->fe->feconn--;
session_store_counters(s);
* be called with an embryonic session. It returns a positive value upon
* success, 0 if the connection can be ignored, or a negative value upon
* critical failure. The accepted file descriptor is closed if we return <= 0.
+ * The client-side end point is assumed to be a connection.
*/
int session_complete(struct session *s)
{
s->si[1].conn->t.sock.fd = -1; /* just to help with debugging */
s->si[1].conn->flags = CO_FL_NONE;
s->si[1].conn->err_code = CO_ER_NONE;
+ s->si[1].conn->target = NULL;
s->si[1].owner = t;
s->si[1].state = s->si[1].prev_state = SI_ST_INI;
s->si[1].err_type = SI_ET_NONE;
s->si[1].conn_retries = 0; /* used for logging too */
s->si[1].send_proxy_ofs = 0;
- si_prepare_none(&s->si[1]);
s->si[1].exp = TICK_ETERNITY;
s->si[1].flags = SI_FL_NONE;
+ si_prepare_none(&s->si[1]);
+
if (likely(s->fe->options2 & PR_O2_INDEPSTR))
s->si[1].flags |= SI_FL_INDEP_STR;
txn->rsp.chn = s->rep;
/* finish initialization of the accepted file descriptor */
- conn_data_want_recv(s->si[0].conn);
+ conn_data_want_recv(__objt_conn(s->si[0].end));
if (p->accept && (ret = p->accept(s)) <= 0) {
/* Either we had an unrecoverable error (<0) or work is
/* if logs require transport layer information, note it on the connection */
if (s->logs.logwait & LW_XPRT)
- s->si[0].conn->flags |= CO_FL_XPRT_TRACKED;
+ __objt_conn(s->si[0].end)->flags |= CO_FL_XPRT_TRACKED;
/* we want the connection handler to notify the stream interface about updates. */
- s->si[0].conn->flags |= CO_FL_WAKE_DATA;
+ __objt_conn(s->si[0].end)->flags |= CO_FL_WAKE_DATA;
/* it is important not to call the wakeup function directly but to
* pass through task_wakeup(), because this one knows how to apply
struct http_txn *txn = &s->txn;
struct proxy *fe = s->fe;
struct bref *bref, *back;
+ struct connection *cli_conn = objt_conn(s->si[0].end);
int i;
if (s->pend_pos)
http_end_txn(s);
/* ensure the client-side transport layer is destroyed */
- s->si[0].conn->flags &= ~CO_FL_XPRT_TRACKED;
- conn_full_close(s->si[0].conn);
+ if (cli_conn) {
+ cli_conn->flags &= ~CO_FL_XPRT_TRACKED;
+ conn_full_close(cli_conn);
+ }
for (i = 0; i < s->store_count; i++) {
if (!s->store[i].ts)
* We must check for establishment, error and abort. Possible output states
* are SI_ST_EST (established), SI_ST_CER (error), SI_ST_DIS (abort), and
* SI_ST_CON (no change). The function returns 0 if it switches to SI_ST_CER,
- * otherwise 1.
+ * otherwise 1. This only works with connection-based sessions.
*/
static int sess_update_st_con_tcp(struct session *s, struct stream_interface *si)
{
struct channel *req = si->ob;
struct channel *rep = si->ib;
+ struct connection *srv_conn = __objt_conn(si->end);
/* If we got an error, or if nothing happened and the connection timed
* out, we must give up. The CER state handler will take care of retry
si->exp = TICK_ETERNITY;
si->state = SI_ST_CER;
- si->conn->flags &= ~CO_FL_XPRT_TRACKED;
- conn_full_close(si->conn);
+ srv_conn->flags &= ~CO_FL_XPRT_TRACKED;
+ conn_full_close(srv_conn);
if (si->err_type)
return 0;
rep->analysers |= s->fe->fe_rsp_ana | s->be->be_rsp_ana;
rep->flags |= CF_READ_ATTACHED; /* producer is now attached */
- if (si->conn->ctrl) {
+ if (objt_conn(si->end)) {
/* real connections have timeouts */
req->wto = s->be->timeout.server;
rep->rto = s->be->timeout.server;
if (!(s->req->flags & (CF_KERN_SPLICING|CF_SHUTR)) &&
s->req->to_forward &&
(global.tune.options & GTUNE_USE_SPLICE) &&
- (s->si[0].conn->xprt && s->si[0].conn->xprt->rcv_pipe && s->si[0].conn->xprt->snd_pipe) &&
- (s->si[1].conn->xprt && s->si[1].conn->xprt->rcv_pipe && s->si[1].conn->xprt->snd_pipe) &&
+ (objt_conn(s->si[0].end) && __objt_conn(s->si[0].end)->xprt && __objt_conn(s->si[0].end)->xprt->rcv_pipe) &&
+ (objt_conn(s->si[1].end) && __objt_conn(s->si[1].end)->xprt && __objt_conn(s->si[1].end)->xprt->snd_pipe) &&
(pipes_used < global.maxpipes) &&
(((s->fe->options2|s->be->options2) & PR_O2_SPLIC_REQ) ||
(((s->fe->options2|s->be->options2) & PR_O2_SPLIC_AUT) &&
if (!(s->rep->flags & (CF_KERN_SPLICING|CF_SHUTR)) &&
s->rep->to_forward &&
(global.tune.options & GTUNE_USE_SPLICE) &&
- (s->si[0].conn->xprt && s->si[0].conn->xprt->rcv_pipe && s->si[0].conn->xprt->snd_pipe) &&
- (s->si[1].conn->xprt && s->si[1].conn->xprt->rcv_pipe && s->si[1].conn->xprt->snd_pipe) &&
+ (objt_conn(s->si[0].end) && __objt_conn(s->si[0].end)->xprt && __objt_conn(s->si[0].end)->xprt->snd_pipe) &&
+ (objt_conn(s->si[1].end) && __objt_conn(s->si[1].end)->xprt && __objt_conn(s->si[1].end)->xprt->rcv_pipe) &&
(pipes_used < global.maxpipes) &&
(((s->fe->options2|s->be->options2) & PR_O2_SPLIC_RTR) ||
(((s->fe->options2|s->be->options2) & PR_O2_SPLIC_AUT) &&
s->si[1].prev_state == SI_ST_EST) {
chunk_printf(&trash, "%08x:%s.srvcls[%04x:%04x]\n",
s->uniq_id, s->be->id,
- (unsigned short)s->si[0].conn->t.sock.fd,
- (unsigned short)s->si[1].conn->t.sock.fd);
+ objt_conn(s->si[0].end) ? (unsigned short)objt_conn(s->si[0].end)->t.sock.fd : -1,
+ objt_conn(s->si[1].end) ? (unsigned short)objt_conn(s->si[1].end)->t.sock.fd : -1);
if (write(1, trash.str, trash.len) < 0) /* shut gcc warning */;
}
s->si[0].prev_state == SI_ST_EST) {
chunk_printf(&trash, "%08x:%s.clicls[%04x:%04x]\n",
s->uniq_id, s->be->id,
- (unsigned short)s->si[0].conn->t.sock.fd,
- (unsigned short)s->si[1].conn->t.sock.fd);
+ objt_conn(s->si[0].end) ? (unsigned short)objt_conn(s->si[0].end)->t.sock.fd : -1,
+ objt_conn(s->si[1].end) ? (unsigned short)objt_conn(s->si[1].end)->t.sock.fd : -1);
if (write(1, trash.str, trash.len) < 0) /* shut gcc warning */;
}
}
(!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)))) {
chunk_printf(&trash, "%08x:%s.closed[%04x:%04x]\n",
s->uniq_id, s->be->id,
- (unsigned short)s->req->prod->conn->t.sock.fd,
- (unsigned short)s->req->cons->conn->t.sock.fd);
+ objt_conn(s->si[0].end) ? (unsigned short)objt_conn(s->si[0].end)->t.sock.fd : -1,
+ objt_conn(s->si[1].end) ? (unsigned short)objt_conn(s->si[1].end)->t.sock.fd : -1);
if (write(1, trash.str, trash.len) < 0) /* shut gcc warning */;
}
return NULL;
}
else if (num > 9) { /* src_* variant, args[0] = table */
- struct stktable_key *key = addr_to_stktable_key(&l4->si[0].conn->addr.from);
+ struct stktable_key *key;
+ struct connection *conn = objt_conn(l4->si[0].end);
+
+ if (!conn)
+ return NULL;
+ key = addr_to_stktable_key(&conn->addr.from);
if (!key)
return NULL;
+
stkctr.table = &args->data.prx->table;
stkctr.entry = stktable_lookup_key(stkctr.table, key);
return &stkctr;
smp_fetch_src_updt_conn_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
+ struct connection *conn = objt_conn(l4->si[0].end);
struct stksess *ts;
struct stktable_key *key;
void *ptr;
- key = addr_to_stktable_key(&l4->si[0].conn->addr.from);
+ if (!conn)
+ return 0;
+
+ key = addr_to_stktable_key(&conn->addr.from);
if (!key)
return 0;
smp_fetch_ssl_fc_has_crt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
- if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+ struct connection *conn;
+
+ if (!l4)
+ return 0;
+
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || conn->xprt != &ssl_sock)
return 0;
- if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+ if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
smp->flags = 0;
smp->type = SMP_T_BOOL;
- smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & l4->si[0].conn->xprt_st ? 1 : 0;
+ smp->data.uint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
return 1;
}
X509 *crt = NULL;
int ret = 0;
struct chunk *smp_trash;
+ struct connection *conn;
+
+ if (!l4)
+ return 0;
- if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || conn->xprt != &ssl_sock)
return 0;
- if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+ if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
/* SSL_get_peer_certificate, it increase X509 * ref count */
- crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
+ crt = SSL_get_peer_certificate(conn->xprt_ctx);
if (!crt)
goto out;
const EVP_MD *digest;
int ret = 0;
struct chunk *smp_trash;
+ struct connection *conn;
+
+ if (!l4)
+ return 0;
- if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || conn->xprt != &ssl_sock)
return 0;
- if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+ if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
/* SSL_get_peer_certificate, it increase X509 * ref count */
- crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
+ crt = SSL_get_peer_certificate(conn->xprt_ctx);
if (!crt)
goto out;
X509 *crt = NULL;
int ret = 0;
struct chunk *smp_trash;
+ struct connection *conn;
- if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+ if (!l4)
return 0;
- if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || conn->xprt != &ssl_sock)
+ return 0;
+
+ if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
/* SSL_get_peer_certificate, it increase X509 * ref count */
- crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
+ crt = SSL_get_peer_certificate(conn->xprt_ctx);
if (!crt)
goto out;
X509_NAME *name;
int ret = 0;
struct chunk *smp_trash;
+ struct connection *conn;
- if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+ if (!l4)
return 0;
- if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || conn->xprt != &ssl_sock)
+ return 0;
+
+ if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
/* SSL_get_peer_certificate, it increase X509 * ref count */
- crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
+ crt = SSL_get_peer_certificate(conn->xprt_ctx);
if (!crt)
goto out;
X509 *crt = NULL;
int ret = 0;
struct chunk *smp_trash;
+ struct connection *conn;
- if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+ if (!l4)
return 0;
- if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || conn->xprt != &ssl_sock)
+ return 0;
+
+ if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
/* SSL_get_peer_certificate, it increase X509 * ref count */
- crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
+ crt = SSL_get_peer_certificate(conn->xprt_ctx);
if (!crt)
goto out;
X509_NAME *name;
int ret = 0;
struct chunk *smp_trash;
+ struct connection *conn;
- if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+ if (!l4)
return 0;
- if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || conn->xprt != &ssl_sock)
+ return 0;
+
+ if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
/* SSL_get_peer_certificate, it increase X509 * ref count */
- crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
+ crt = SSL_get_peer_certificate(conn->xprt_ctx);
if (!crt)
goto out;
const struct arg *args, struct sample *smp, const char *kw)
{
X509 *crt;
+ struct connection *conn;
+
+ if (!l4)
+ return 0;
- if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || conn->xprt != &ssl_sock)
return 0;
- if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+ if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
/* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
- crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
+ crt = SSL_get_peer_certificate(conn->xprt_ctx);
if (crt) {
X509_free(crt);
}
const struct arg *args, struct sample *smp, const char *kw)
{
X509 *crt;
+ struct connection *conn;
+
+ if (!l4)
+ return 0;
- if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || conn->xprt != &ssl_sock)
return 0;
- if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+ if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
/* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
- crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
+ crt = SSL_get_peer_certificate(conn->xprt_ctx);
if (!crt)
return 0;
{
X509 *crt;
int nid;
+ struct connection *conn;
+
+ if (!l4)
+ return 0;
- if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || conn->xprt != &ssl_sock)
return 0;
- if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+ if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
/* SSL_get_peer_certificate increase X509 * ref count */
- crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
+ crt = SSL_get_peer_certificate(conn->xprt_ctx);
if (!crt)
return 0;
{
X509 *crt;
int nid;
+ struct connection *conn;
+
+ if (!l4)
+ return 0;
- if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || conn->xprt != &ssl_sock)
return 0;
- if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+ if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
/* SSL_get_peer_certificate increase X509 * ref count */
- crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
+ crt = SSL_get_peer_certificate(conn->xprt_ctx);
if (!crt)
return 0;
smp_fetch_ssl_fc(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
+ struct connection *conn = objt_conn(l4->si[0].end);
+
smp->type = SMP_T_BOOL;
- smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock);
+ smp->data.uint = (conn && conn->xprt == &ssl_sock);
return 1;
}
const struct arg *args, struct sample *smp, const char *kw)
{
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+ struct connection *conn = objt_conn(l4->si[0].end);
+
smp->type = SMP_T_BOOL;
- smp->data.uint = (l4->si[0].conn->xprt == &ssl_sock) &&
- l4->si[0].conn->xprt_ctx &&
- SSL_get_servername(l4->si[0].conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
+ smp->data.uint = (conn && conn->xprt == &ssl_sock) &&
+ conn->xprt_ctx &&
+ SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
return 1;
#else
return 0;
X509 *crt = NULL;
int ret = 0;
struct chunk *smp_trash;
+ struct connection *conn;
- if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+ if (!l4)
return 0;
- if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || conn->xprt != &ssl_sock)
+ return 0;
+
+ if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
- crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
+ crt = SSL_get_certificate(conn->xprt_ctx);
if (!crt)
goto out;
X509 *crt = NULL;
int ret = 0;
struct chunk *smp_trash;
+ struct connection *conn;
- if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+ if (!l4)
return 0;
- if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || conn->xprt != &ssl_sock)
+ return 0;
+
+ if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
- crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
+ crt = SSL_get_certificate(conn->xprt_ctx);
if (!crt)
goto out;
X509 *crt = NULL;
int ret = 0;
struct chunk *smp_trash;
+ struct connection *conn;
+
+ if (!l4)
+ return 0;
- if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || conn->xprt != &ssl_sock)
return 0;
- if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+ if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
- crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
+ crt = SSL_get_certificate(conn->xprt_ctx);
if (!crt)
goto out;
const struct arg *args, struct sample *smp, const char *kw)
{
X509 *crt;
+ struct connection *conn;
+
+ if (!l4)
+ return 0;
- if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || conn->xprt != &ssl_sock)
return 0;
- if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+ if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
/* SSL_get_certificate returns a ptr on an SSL * internal sub struct */
- crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
+ crt = SSL_get_certificate(conn->xprt_ctx);
if (!crt)
return 0;
{
X509 *crt;
int nid;
+ struct connection *conn;
+
+ if (!l4)
+ return 0;
- if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || conn->xprt != &ssl_sock)
return 0;
- if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+ if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
- crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
+ crt = SSL_get_certificate(conn->xprt_ctx);
if (!crt)
return 0;
{
X509 *crt;
int nid;
+ struct connection *conn;
+
+ if (!l4)
+ return 0;
- if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || conn->xprt != &ssl_sock)
return 0;
- if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+ if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
- crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
+ crt = SSL_get_certificate(conn->xprt_ctx);
if (!crt)
return 0;
X509_NAME *name;
int ret = 0;
struct chunk *smp_trash;
+ struct connection *conn;
+
+ if (!l4)
+ return 0;
- if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || conn->xprt != &ssl_sock)
return 0;
- if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+ if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
- crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
+ crt = SSL_get_certificate(conn->xprt_ctx);
if (!crt)
goto out;
X509_NAME *name;
int ret = 0;
struct chunk *smp_trash;
+ struct connection *conn;
- if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+ if (!l4)
return 0;
- if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
+ return 0;
+
+ if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
- crt = SSL_get_certificate(l4->si[0].conn->xprt_ctx);
+ crt = SSL_get_certificate(conn->xprt_ctx);
if (!crt)
goto out;
smp_fetch_ssl_fc_cipher(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
+ struct connection *conn;
+
smp->flags = 0;
- if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
+ if (!l4)
+ return 0;
+
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
return 0;
- smp->data.str.str = (char *)SSL_get_cipher_name(l4->si[0].conn->xprt_ctx);
+ smp->data.str.str = (char *)SSL_get_cipher_name(conn->xprt_ctx);
if (!smp->data.str.str)
return 0;
smp_fetch_ssl_fc_alg_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
+ struct connection *conn;
+
smp->flags = 0;
- if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
+ if (!l4)
+ return 0;
+
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
return 0;
- if (!SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, (int *)&smp->data.uint))
+ if (!SSL_get_cipher_bits(conn->xprt_ctx, (int *)&smp->data.uint))
return 0;
smp->type = SMP_T_UINT;
smp_fetch_ssl_fc_use_keysize(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
+ struct connection *conn;
+
smp->flags = 0;
- if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
+ if (!l4)
+ return 0;
+
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
return 0;
- smp->data.uint = (unsigned int)SSL_get_cipher_bits(l4->si[0].conn->xprt_ctx, NULL);
+ smp->data.uint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
if (!smp->data.uint)
return 0;
smp_fetch_ssl_fc_npn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
+ struct connection *conn;
+
smp->flags = 0;
smp->type = SMP_T_CSTR;
- if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
+ if (!l4)
+ return 0;
+
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
return 0;
smp->data.str.str = NULL;
- SSL_get0_next_proto_negotiated(l4->si[0].conn->xprt_ctx,
+ SSL_get0_next_proto_negotiated(conn->xprt_ctx,
(const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
if (!smp->data.str.str)
smp_fetch_ssl_fc_alpn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
+ struct connection *conn;
+
smp->flags = 0;
smp->type = SMP_T_CSTR;
- if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
+ if (!l4)
+ return 0;
+
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
return 0;
smp->data.str.str = NULL;
- SSL_get0_alpn_negotiated(l4->si[0].conn->xprt_ctx,
+ SSL_get0_alpn_negotiated(conn->xprt_ctx,
(const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
if (!smp->data.str.str)
smp_fetch_ssl_fc_protocol(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
+ struct connection *conn;
+
smp->flags = 0;
- if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
+ if (!l4)
+ return 0;
+
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
return 0;
- smp->data.str.str = (char *)SSL_get_version(l4->si[0].conn->xprt_ctx);
+ smp->data.str.str = (char *)SSL_get_version(conn->xprt_ctx);
if (!smp->data.str.str)
return 0;
{
#if OPENSSL_VERSION_NUMBER > 0x0090800fL
SSL_SESSION *sess;
+ struct connection *conn;
smp->flags = 0;
smp->type = SMP_T_CBIN;
- if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
+ if (!l4)
return 0;
- sess = SSL_get_session(l4->si[0].conn->xprt_ctx);
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
+ return 0;
+
+ sess = SSL_get_session(conn->xprt_ctx);
if (!sess)
return 0;
const struct arg *args, struct sample *smp, const char *kw)
{
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+ struct connection *conn;
+
smp->flags = 0;
smp->type = SMP_T_CSTR;
- if (!l4 || !l4->si[0].conn->xprt_ctx || l4->si[0].conn->xprt != &ssl_sock)
+ if (!l4)
+ return 0;
+
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
return 0;
- smp->data.str.str = (char *)SSL_get_servername(l4->si[0].conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
+ smp->data.str.str = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
if (!smp->data.str.str)
return 0;
smp_fetch_ssl_c_ca_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
- if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+ struct connection *conn;
+
+ if (!l4)
+ return 0;
+
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || conn->xprt != &ssl_sock)
return 0;
- if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+ if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags = SMP_F_MAY_CHANGE;
return 0;
}
smp->type = SMP_T_UINT;
- smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(l4->si[0].conn->xprt_st);
+ smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
smp->flags = 0;
return 1;
smp_fetch_ssl_c_ca_err_depth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
- if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+ struct connection *conn;
+
+ if (!l4)
+ return 0;
+
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || conn->xprt != &ssl_sock)
return 0;
- if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+ if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags = SMP_F_MAY_CHANGE;
return 0;
}
smp->type = SMP_T_UINT;
- smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(l4->si[0].conn->xprt_st);
+ smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
smp->flags = 0;
return 1;
smp_fetch_ssl_c_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
- if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+ struct connection *conn;
+
+ if (!l4)
return 0;
- if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || conn->xprt != &ssl_sock)
+ return 0;
+
+ if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags = SMP_F_MAY_CHANGE;
return 0;
}
smp->type = SMP_T_UINT;
- smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(l4->si[0].conn->xprt_st);
+ smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
smp->flags = 0;
return 1;
smp_fetch_ssl_c_verify(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
- if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
+ struct connection *conn;
+
+ if (!l4)
return 0;
- if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
+ conn = objt_conn(l4->si[0].end);
+ if (!conn || conn->xprt != &ssl_sock)
+ return 0;
+
+ if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags = SMP_F_MAY_CHANGE;
return 0;
}
- if (!l4->si[0].conn->xprt_ctx)
+ if (!conn->xprt_ctx)
return 0;
smp->type = SMP_T_UINT;
- smp->data.uint = (unsigned int)SSL_get_verify_result(l4->si[0].conn->xprt_ctx);
+ smp->data.uint = (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
smp->flags = 0;
return 1;
* (which is recomputed every time since it's constant). If
* it is positive, it means we have to send from the start.
*/
- ret = make_proxy_line(trash.str, trash.size, &si->ob->prod->conn->addr.from, &si->ob->prod->conn->addr.to);
+ struct connection *remote = objt_conn(si->ob->prod->end);
+ if (remote)
+ ret = make_proxy_line(trash.str, trash.size, &remote->addr.from, &remote->addr.to);
+ else
+ ret = make_proxy_line(trash.str, trash.size, NULL, NULL);
+
if (!ret)
goto out_error;
{
struct channel *ib = si->ib;
struct channel *ob = si->ob;
+ struct connection *conn = __objt_conn(si->end);
/* Check if we need to close the read side */
if (!(ib->flags & CF_SHUTR)) {
if (!(si->flags & SI_FL_WAIT_ROOM)) {
if (!(ib->flags & CF_DONT_READ)) /* full */
si->flags |= SI_FL_WAIT_ROOM;
- conn_data_stop_recv(si->conn);
+ conn_data_stop_recv(conn);
ib->rex = TICK_ETERNITY;
}
}
* have updated it if there has been a completed I/O.
*/
si->flags &= ~SI_FL_WAIT_ROOM;
- conn_data_want_recv(si->conn);
+ conn_data_want_recv(conn);
if (!(ib->flags & (CF_READ_NOEXP|CF_DONT_READ)) && !tick_isset(ib->rex))
ib->rex = tick_add_ifset(now_ms, ib->rto);
}
if (!(si->flags & SI_FL_WAIT_DATA)) {
if ((ob->flags & CF_SHUTW_NOW) == 0)
si->flags |= SI_FL_WAIT_DATA;
- conn_data_stop_send(si->conn);
+ conn_data_stop_send(conn);
ob->wex = TICK_ETERNITY;
}
}
* have updated it if there has been a completed I/O.
*/
si->flags &= ~SI_FL_WAIT_DATA;
- conn_data_want_send(si->conn);
+ conn_data_want_send(conn);
if (!tick_isset(ob->wex)) {
ob->wex = tick_add_ifset(now_ms, ob->wto);
if (tick_isset(ib->rex) && !(si->flags & SI_FL_INDEP_STR)) {
*/
static void stream_int_shutr_conn(struct stream_interface *si)
{
- struct connection *conn = si->conn;
+ struct connection *conn = __objt_conn(si->end);
si->ib->flags &= ~CF_SHUTR_NOW;
if (si->ib->flags & CF_SHUTR)
*/
static void stream_int_shutw_conn(struct stream_interface *si)
{
- struct connection *conn = si->conn;
+ struct connection *conn = __objt_conn(si->end);
si->ob->flags &= ~CF_SHUTW_NOW;
if (si->ob->flags & CF_SHUTW)
static void stream_int_chk_rcv_conn(struct stream_interface *si)
{
struct channel *ib = si->ib;
+ struct connection *conn = __objt_conn(si->end);
if (unlikely(si->state > SI_ST_EST || (ib->flags & CF_SHUTR)))
return;
- conn_refresh_polling_flags(si->conn);
+ conn_refresh_polling_flags(conn);
if ((ib->flags & CF_DONT_READ) || channel_full(ib)) {
/* stop reading */
if (!(ib->flags & CF_DONT_READ)) /* full */
si->flags |= SI_FL_WAIT_ROOM;
- __conn_data_stop_recv(si->conn);
+ __conn_data_stop_recv(conn);
}
else {
/* (re)start reading */
si->flags &= ~SI_FL_WAIT_ROOM;
- __conn_data_want_recv(si->conn);
+ __conn_data_want_recv(conn);
}
- conn_cond_update_data_polling(si->conn);
+ conn_cond_update_data_polling(conn);
}
static void stream_int_chk_snd_conn(struct stream_interface *si)
{
struct channel *ob = si->ob;
+ struct connection *conn = __objt_conn(si->end);
if (unlikely(si->state > SI_ST_EST || (ob->flags & CF_SHUTW)))
return;
!(si->flags & SI_FL_WAIT_DATA)) /* not waiting for data */
return;
- if (si->conn->flags & (CO_FL_DATA_WR_ENA|CO_FL_CURR_WR_ENA)) {
+ if (conn->flags & (CO_FL_DATA_WR_ENA|CO_FL_CURR_WR_ENA)) {
/* already subscribed to write notifications, will be called
* anyway, so let's avoid calling it especially if the reader
* is not ready.
return;
}
- if (!(si->conn->flags & (CO_FL_HANDSHAKE|CO_FL_WAIT_L4_CONN|CO_FL_WAIT_L6_CONN))) {
+ if (!(conn->flags & (CO_FL_HANDSHAKE|CO_FL_WAIT_L4_CONN|CO_FL_WAIT_L6_CONN))) {
/* Before calling the data-level operations, we have to prepare
* the polling flags to ensure we properly detect changes.
*/
- if (si->conn->ctrl)
- fd_want_send(si->conn->t.sock.fd);
+ if (conn->ctrl)
+ fd_want_send(conn->t.sock.fd);
- conn_refresh_polling_flags(si->conn);
+ conn_refresh_polling_flags(conn);
- si_conn_send(si->conn);
- if (si->conn->flags & CO_FL_ERROR) {
+ si_conn_send(conn);
+ if (conn->flags & CO_FL_ERROR) {
/* Write error on the file descriptor */
- fd_stop_both(si->conn->t.sock.fd);
- __conn_data_stop_both(si->conn);
+ fd_stop_both(conn->t.sock.fd);
+ __conn_data_stop_both(conn);
si->flags |= SI_FL_ERR;
goto out_wakeup;
}
* ->o limit was reached. Maybe we just wrote the last
* chunk and need to close.
*/
- __conn_data_stop_send(si->conn);
+ __conn_data_stop_send(conn);
if (((ob->flags & (CF_SHUTW|CF_AUTO_CLOSE|CF_SHUTW_NOW)) ==
(CF_AUTO_CLOSE|CF_SHUTW_NOW)) &&
(si->state == SI_ST_EST)) {
/* Otherwise there are remaining data to be sent in the buffer,
* which means we have to poll before doing so.
*/
- __conn_data_want_send(si->conn);
+ __conn_data_want_send(conn);
si->flags &= ~SI_FL_WAIT_DATA;
if (!tick_isset(ob->wex))
ob->wex = tick_add_ifset(now_ms, ob->wto);
}
/* commit possible polling changes */
- conn_cond_update_polling(si->conn);
+ conn_cond_update_polling(conn);
}
/*
if (conn->flags & CO_FL_ERROR)
return;
- if (si->conn->flags & CO_FL_HANDSHAKE)
+ if (conn->flags & CO_FL_HANDSHAKE)
/* a handshake was requested */
return;
*/
void stream_sock_read0(struct stream_interface *si)
{
+ struct connection *conn = __objt_conn(si->end);
+
si->ib->flags &= ~CF_SHUTR_NOW;
if (si->ib->flags & CF_SHUTR)
return;
/* we want to immediately forward this close to the write side */
if (si->flags & SI_FL_NOLINGER) {
si->flags &= ~SI_FL_NOLINGER;
- setsockopt(si->conn->t.sock.fd, SOL_SOCKET, SO_LINGER,
+ setsockopt(conn->t.sock.fd, SOL_SOCKET, SO_LINGER,
(struct linger *) &nolinger, sizeof(struct linger));
}
/* force flag on ssl to keep session in cache */
- if (si->conn->xprt->shutw)
- si->conn->xprt->shutw(si->conn, 0);
+ if (conn->xprt->shutw)
+ conn->xprt->shutw(conn, 0);
goto do_close;
}
/* otherwise that's just a normal read shutdown */
- __conn_data_stop_recv(si->conn);
+ __conn_data_stop_recv(conn);
return;
do_close:
/* OK we completely close the socket here just as if we went through si_shut[rw]() */
- conn_full_close(si->conn);
+ conn_full_close(conn);
si->ib->flags &= ~CF_SHUTR_NOW;
si->ib->flags |= CF_SHUTR;