diff --git a/include/types/session.h b/include/types/session.h index 0a001be06..d141d8c02 100644 --- a/include/types/session.h +++ b/include/types/session.h @@ -171,6 +171,7 @@ struct session { struct server *srv; /* the server the session will be running or has been running on */ struct server *srv_conn; /* session already has a slot on a server and is not in queue */ struct server *prev_srv; /* the server the was running on, after a redispatch, otherwise NULL */ + struct target target; /* target to use for this session */ struct pendconn *pend_pos; /* if not NULL, points to the position in the pending queue */ struct http_txn txn; /* current HTTP transaction being processed. Should become a list. */ diff --git a/src/backend.c b/src/backend.c index 857496c5c..bd9ee14d7 100644 --- a/src/backend.c +++ b/src/backend.c @@ -452,7 +452,7 @@ struct server *get_server_rch(struct session *s) * It is illegal to call this function with a session in a queue. * * It may return : - * SRV_STATUS_OK if everything is OK. Session assigned to ->srv + * SRV_STATUS_OK if everything is OK. ->srv and ->target are assigned. * SRV_STATUS_NOSRV if no server is available. Session is not ASSIGNED * SRV_STATUS_FULL if all servers are saturated. Session is not ASSIGNED * SRV_STATUS_INTERNAL for other unrecoverable errors. @@ -492,6 +492,9 @@ int assign_server(struct session *s) */ s->srv = NULL; + s->target.type = TARG_TYPE_NONE; + s->target.ptr.v = NULL; + if (s->be->lbprm.algo & BE_LB_KIND) { int len; /* we must check if we have at least one server available */ @@ -612,14 +615,20 @@ int assign_server(struct session *s) s->be->counters.cum_lbconn++; s->srv->counters.cum_lbconn++; } + + s->target.type = TARG_TYPE_SERVER; + s->target.ptr.s = s->srv; } - else if (s->be->options & PR_O_HTTP_PROXY) { - if (!s->req->cons->addr.s.to.sin_addr.s_addr) { - err = SRV_STATUS_NOSRV; - goto out; - } + else if ((s->be->options2 & PR_O2_DISPATCH) || (s->be->options & PR_O_TRANSP)) { + s->target.type = TARG_TYPE_PROXY; + s->target.ptr.p = s->be; } - else if (!(s->be->options2 & PR_O2_DISPATCH) && !(s->be->options & PR_O_TRANSP)) { + else if ((s->be->options & PR_O_HTTP_PROXY) && s->req->cons->addr.s.to.sin_addr.s_addr) { + /* in proxy mode, we need a valid destination address */ + s->target.type = TARG_TYPE_PROXY; + s->target.ptr.p = s->be; + } + else { err = SRV_STATUS_NOSRV; goto out; } @@ -910,7 +919,8 @@ static void assign_tproxy_address(struct session *s) /* * This function initiates a connection to the server assigned to this session - * (s->srv, s->req->cons->addr.s.to). It will assign a server if none is assigned yet. + * (s->srv, s->target, s->req->cons->addr.s.to). It will assign a server if none + * is assigned yet. * It can return one of : * - SN_ERR_NONE if everything's OK * - SN_ERR_SRVTO if there are no more servers @@ -932,16 +942,13 @@ int connect_server(struct session *s) /* Prepare the stream interface for a TCP connection. Later * we may assign a protocol-specific connect() function. + * NOTE: when we later support HTTP keep-alive, we'll have to + * decide here if we can reuse the connection by comparing the + * session's freshly assigned target with the stream interface's. */ stream_sock_prepare_interface(s->req->cons); s->req->cons->connect = tcpv4_connect_server; - if (s->srv) { - s->req->cons->target.type = TARG_TYPE_SERVER; - s->req->cons->target.ptr.s = s->srv; - } else { - s->req->cons->target.type = TARG_TYPE_PROXY; - s->req->cons->target.ptr.p = s->be; - } + s->req->cons->target = s->target; assign_tproxy_address(s); @@ -1098,12 +1105,16 @@ int tcp_persist_rdp_cookie(struct session *s, struct buffer *req, int an_bit) if (*p != '.') goto no_cookie; + s->target.type = TARG_TYPE_NONE; + s->target.ptr.v = NULL; while (srv) { if (memcmp(&addr, &(srv->addr), sizeof(addr)) == 0) { if ((srv->state & SRV_RUNNING) || (px->options & PR_O_PERSIST)) { /* we found the server and it is usable */ s->flags |= SN_DIRECT | SN_ASSIGNED; s->srv = srv; + s->target.type = TARG_TYPE_SERVER; + s->target.ptr.s = s->srv; break; } } diff --git a/src/checks.c b/src/checks.c index ee0b97bd7..628f3e572 100644 --- a/src/checks.c +++ b/src/checks.c @@ -349,6 +349,8 @@ static int check_for_pending(struct server *s) if (!p) break; p->sess->srv = s; + p->sess->target.ptr.s = s; + p->sess->target.type = TARG_TYPE_SERVER; sess = p->sess; pendconn_free(p); task_wakeup(sess->task, TASK_WOKEN_RES); diff --git a/src/peers.c b/src/peers.c index 78855a1eb..f4ace6489 100644 --- a/src/peers.c +++ b/src/peers.c @@ -1187,6 +1187,8 @@ struct session *peer_session_create(struct peer *peer, struct peer_session *ps) s->si[1].release = NULL; s->srv = s->prev_srv = s->srv_conn = NULL; + s->target.type = TARG_TYPE_NONE; + s->target.ptr.v = NULL; s->pend_pos = NULL; /* init store persistence */ diff --git a/src/proto_http.c b/src/proto_http.c index c91c014f6..27e29c050 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -3949,6 +3949,8 @@ void http_end_txn_clean_session(struct session *s) if (unlikely(s->srv_conn)) sess_change_server(s, NULL); s->srv = NULL; + s->target.type = TARG_TYPE_NONE; + s->target.ptr.v = NULL; s->req->cons->state = s->req->cons->prev_state = SI_ST_INI; s->req->cons->fd = -1; /* just to help with debugging */ @@ -5962,6 +5964,9 @@ void manage_client_side_appsession(struct session *t, const char *buf, int len) txn->flags |= (srv->state & SRV_RUNNING) ? TX_CK_VALID : TX_CK_DOWN; t->flags |= SN_DIRECT | SN_ASSIGNED; t->srv = srv; + t->target.type = TARG_TYPE_SERVER; + t->target.ptr.s = srv; + break; } else { txn->flags &= ~TX_CK_MASK; @@ -6371,6 +6376,8 @@ void manage_client_side_cookies(struct session *t, struct buffer *req) txn->flags |= (srv->state & SRV_RUNNING) ? TX_CK_VALID : TX_CK_DOWN; t->flags |= SN_DIRECT | SN_ASSIGNED; t->srv = srv; + t->target.type = TARG_TYPE_SERVER; + t->target.ptr.s = srv; break; } else { /* we found a server, but it's down, @@ -7535,6 +7542,8 @@ void http_reset_txn(struct session *s) s->be = s->fe; s->logs.logwait = s->fe->to_log; s->srv = s->prev_srv = s->srv_conn = NULL; + s->target.type = TARG_TYPE_NONE; + s->target.ptr.v = NULL; /* re-init store persistence */ s->store_count = 0; diff --git a/src/queue.c b/src/queue.c index 38b15429d..c66aa6bc6 100644 --- a/src/queue.c +++ b/src/queue.c @@ -122,6 +122,8 @@ struct session *pendconn_get_next_sess(struct server *srv, struct proxy *px) /* we want to note that the session has now been assigned a server */ sess->flags |= SN_ASSIGNED; + sess->target.type = TARG_TYPE_SERVER; + sess->target.ptr.s = srv; sess->srv = srv; sess->srv_conn = srv; srv->served++; diff --git a/src/session.c b/src/session.c index eb0a2521d..9ecb6edcc 100644 --- a/src/session.c +++ b/src/session.c @@ -203,6 +203,8 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr) s->si[1].flags |= SI_FL_INDEP_STR; s->srv = s->prev_srv = s->srv_conn = NULL; + s->target.type = TARG_TYPE_NONE; + s->target.ptr.v = NULL; s->pend_pos = NULL; /* init store persistence */ @@ -1066,6 +1068,8 @@ int process_sticking_rules(struct session *s, struct buffer *req, int an_bit) (s->flags & SN_FORCE_PRST)) { s->flags |= SN_DIRECT | SN_ASSIGNED; s->srv = srv; + s->target.type = TARG_TYPE_SERVER; + s->target.ptr.s = srv; } } }