]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MINOR] session: add a pointer to the new target into the session
authorWilly Tarreau <w@1wt.eu>
Thu, 10 Mar 2011 10:38:29 +0000 (11:38 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 10 Mar 2011 22:32:16 +0000 (23:32 +0100)
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
src/backend.c
src/checks.c
src/peers.c
src/proto_http.c
src/queue.c
src/session.c

index 0a001be06c9a660c4ad993051e3ee4b27a2c28cc..d141d8c024e4d240272a0aa8ea065eb426d607e8 100644 (file)
@@ -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. */
 
index 857496c5ce618371d4d721ba33b6d308f834221f..bd9ee14d749225f4de4b59693ddff9a9b6555493 100644 (file)
@@ -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;
                        }
                }
index ee0b97bd73bc60928217f55ac83ef1692a8b378d..628f3e5728fbd713226353ac0356b8204f6e3d76 100644 (file)
@@ -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);
index 78855a1ebb0d96818d3d3f6504f31d0d5656fc2f..f4ace64894a5d846a5771e41153f0819f0dc111d 100644 (file)
@@ -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 */
index c91c014f6d7485d34bc9c626f2ba319719f02cbe..27e29c050a9f22d1d43bf061108eecb9bb1ead18 100644 (file)
@@ -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;
 
index 38b15429d7d96f62f8b177c8a56675660bb9444f..c66aa6bc6d9a119d46e612abe3f85638d06ed711 100644 (file)
@@ -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++;
index eb0a2521d970ee5edd380d3d64e5304958a80db6..9ecb6edcc4923da4b9b391a6e4d204e9dc083c19 100644 (file)
@@ -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;
                                                        }
                                                }
                                        }