From 664beb8610e4cc1dfc389789e0310b0c4fc88f72 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Thu, 10 Mar 2011 11:38:29 +0100 Subject: [PATCH] [MINOR] session: add a pointer to the new target into the session When dealing with HTTP keep-alive, we'll have to know if we can reuse an existing connection. For that, we'll have to check if the current connection was made on the exact same target (referenced in the stream interface). Thus, we need to first assign the next target to the session, then copy it to the stream interface upon connect(). Later we'll check for equivalence between those two operations. --- include/types/session.h | 1 + src/backend.c | 41 ++++++++++++++++++++++++++--------------- src/checks.c | 2 ++ src/peers.c | 2 ++ src/proto_http.c | 9 +++++++++ src/queue.c | 2 ++ src/session.c | 4 ++++ 7 files changed, 46 insertions(+), 15 deletions(-) diff --git a/include/types/session.h b/include/types/session.h index 0a001be06c..d141d8c024 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 857496c5ce..bd9ee14d74 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->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 if (!(s->be->options2 & PR_O2_DISPATCH) && !(s->be->options & PR_O_TRANSP)) { + 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 ee0b97bd73..628f3e5728 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 78855a1ebb..f4ace64894 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 c91c014f6d..27e29c050a 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 38b15429d7..c66aa6bc6d 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 eb0a2521d9..9ecb6edcc4 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; } } } -- 2.39.5