Le mercredi 14 octobre 2009 22:39:39, Willy Tarreau a écrit : > > > Do it for either 1.3 or 1.4, I'll do the back/forward port. If you > > > prefer to proceed on both, of course feel free to do so :-) > > > > I can do both, this will let you work on something else ;) > > Nice, I appreciate it.
OK, here comes the 2 patch files for haproxy-1.3.21 and haproxy-1.4-dev4. Please note 3 minor changes in those versions (proto_http.c / proto_http.h) : 1. void manage_client_side_appsession(struct session *t, char *buf); becomes void manage_client_side_appsession(struct session *t, const char *buf); 2. An unused variable in get_srv_from_appsession(...) has been removed. 3. After some more tests, I've applied a fix on request_count (used for debug) to have nearly the same behaviour in normal mode and "request-learn" mode. -- Cyril Bonté
diff -Naur haproxy-1.4-dev4/include/proto/proto_http.h haproxy-1.4-dev4-appsession-final/include/proto/proto_http.h --- haproxy-1.4-dev4/include/proto/proto_http.h 2009-10-12 06:40:53.000000000 +0200 +++ haproxy-1.4-dev4-appsession-final/include/proto/proto_http.h 2009-10-14 22:55:55.000000000 +0200 @@ -74,6 +74,7 @@ int apply_filter_to_req_line(struct session *t, struct buffer *req, struct hdr_exp *exp); int apply_filters_to_request(struct session *t, struct buffer *req, struct hdr_exp *exp); int apply_filters_to_response(struct session *t, struct buffer *rtr, struct hdr_exp *exp); +void manage_client_side_appsession(struct session *t, const char *buf); void manage_client_side_cookies(struct session *t, struct buffer *req); void manage_server_side_cookies(struct session *t, struct buffer *rtr); void check_response_for_cacheability(struct session *t, struct buffer *rtr); diff -Naur haproxy-1.4-dev4/include/types/proxy.h haproxy-1.4-dev4-appsession-final/include/types/proxy.h --- haproxy-1.4-dev4/include/types/proxy.h 2009-10-12 06:40:53.000000000 +0200 +++ haproxy-1.4-dev4-appsession-final/include/types/proxy.h 2009-10-12 21:24:42.000000000 +0200 @@ -124,6 +124,9 @@ #define PR_O2_INDEPSTR 0x00001000 /* independant streams, don't update rex on write */ #define PR_O2_SOCKSTAT 0x00002000 /* collect & provide separate statistics for sockets */ +/* bits for proxy->appsession_options */ +#define PR_O_AS_REQL 0x00000001 /* learn the session id from the request */ + struct error_snapshot { struct timeval when; /* date of this event, (tv_sec == 0) means "never" */ unsigned int len; /* original length of the last invalid request/response */ @@ -177,6 +180,7 @@ char *appsession_name; /* name of the cookie to look for */ int appsession_name_len; /* strlen(appsession_name), computed only once */ int appsession_len; /* length of the appsession cookie value to be used */ + int appsession_options; /* options for appsession */ struct appsession_hash htbl_proxy; /* Per Proxy hashtable */ char *capture_name; /* beginning of the name of the cookie to capture */ int capture_namelen; /* length of the cookie name to match */ diff -Naur haproxy-1.4-dev4/include/types/session.h haproxy-1.4-dev4-appsession-final/include/types/session.h --- haproxy-1.4-dev4/include/types/session.h 2009-10-12 06:40:53.000000000 +0200 +++ haproxy-1.4-dev4-appsession-final/include/types/session.h 2009-10-12 21:25:15.000000000 +0200 @@ -162,6 +162,7 @@ int conn_retries; /* number of connect retries left */ int flags; /* some flags describing the session */ unsigned term_trace; /* term trace: 4*8 bits indicating which part of the code closed */ + char *sessid; /* the session id, if found in the request or in the response */ struct buffer *req; /* request buffer */ struct buffer *rep; /* response buffer */ struct stream_interface si[2]; /* client and server stream interfaces */ diff -Naur haproxy-1.4-dev4/src/cfgparse.c haproxy-1.4-dev4-appsession-final/src/cfgparse.c --- haproxy-1.4-dev4/src/cfgparse.c 2009-10-12 06:40:53.000000000 +0200 +++ haproxy-1.4-dev4-appsession-final/src/cfgparse.c 2009-10-12 21:26:10.000000000 +0200 @@ -1517,6 +1517,7 @@ } } else if (!strcmp(args[0], "appsession")) { /* cookie name */ + int cur_arg; if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) err_code |= ERR_WARN; @@ -1546,6 +1547,14 @@ err_code |= ERR_ALERT | ERR_ABORT; goto out; } + + cur_arg = 6; + while (*(args[cur_arg])) { + if (!strcmp(args[cur_arg], "request-learn")) { + curproxy->appsession_options |= PR_O_AS_REQL; + } + cur_arg++; + } } /* Url App Session */ else if (!strcmp(args[0], "capture")) { if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL)) diff -Naur haproxy-1.4-dev4/src/client.c haproxy-1.4-dev4-appsession-final/src/client.c --- haproxy-1.4-dev4/src/client.c 2009-10-12 06:40:53.000000000 +0200 +++ haproxy-1.4-dev4-appsession-final/src/client.c 2009-10-12 21:26:38.000000000 +0200 @@ -184,7 +184,7 @@ */ s->be = s->fe = p; - s->req = s->rep = NULL; /* will be allocated later */ + s->sessid = s->req = s->rep = NULL; /* will be allocated later */ s->si[0].state = s->si[0].prev_state = SI_ST_EST; s->si[0].err_type = SI_ET_NONE; diff -Naur haproxy-1.4-dev4/src/proto_http.c haproxy-1.4-dev4-appsession-final/src/proto_http.c --- haproxy-1.4-dev4/src/proto_http.c 2009-10-12 06:40:53.000000000 +0200 +++ haproxy-1.4-dev4-appsession-final/src/proto_http.c 2009-10-14 23:38:28.000000000 +0200 @@ -3557,6 +3557,73 @@ /* + * Try to retrieve the server associated to the appsession. + * If the server is found, it's assigned to the session. + */ +void manage_client_side_appsession(struct session *t, const char *buf) { + struct http_txn *txn = &t->txn; + appsess *asession = NULL; + char *sessid_temp = NULL; + + if (t->be->appsession_options & PR_O_AS_REQL) { + /* request-learn option is enabled : store the sessid in the session for future use */ + if (t->sessid != NULL) { + /* free previously allocated memory as we don't need the session id found in the URL anymore */ + pool_free2(apools.sessid, t->sessid); + } + + if ((t->sessid = pool_alloc2(apools.sessid)) == NULL) { + Alert("Not enough memory process_cli():asession->sessid:malloc().\n"); + send_log(t->be, LOG_ALERT, "Not enough memory process_cli():asession->sessid:malloc().\n"); + return; + } + + memcpy(t->sessid, buf, t->be->appsession_len); + t->sessid[t->be->appsession_len] = 0; + } + + if ((sessid_temp = pool_alloc2(apools.sessid)) == NULL) { + Alert("Not enough memory process_cli():asession->sessid:malloc().\n"); + send_log(t->be, LOG_ALERT, "Not enough memory process_cli():asession->sessid:malloc().\n"); + return; + } + + memcpy(sessid_temp, buf, t->be->appsession_len); + sessid_temp[t->be->appsession_len] = 0; + + asession = appsession_hash_lookup(&(t->be->htbl_proxy), sessid_temp); + /* free previously allocated memory */ + pool_free2(apools.sessid, sessid_temp); + + if (asession != NULL) { + asession->expire = tick_add_ifset(now_ms, t->be->timeout.appsession); + if (!(t->be->appsession_options & PR_O_AS_REQL)) { + asession->request_count++; + } + + if (asession->serverid != NULL) { + struct server *srv = t->be->srv; + while (srv) { + if (strcmp(srv->id, asession->serverid) == 0) { + if (srv->state & SRV_RUNNING || t->be->options & PR_O_PERSIST) { + /* we found the server and it's usable */ + txn->flags &= ~TX_CK_MASK; + txn->flags |= TX_CK_VALID; + t->flags |= SN_DIRECT | SN_ASSIGNED; + t->srv = srv; + break; + } else { + txn->flags &= ~TX_CK_MASK; + txn->flags |= TX_CK_DOWN; + } + } + srv = srv->next; + } + } + } +} + +/* * Manage client-side cookie. It can impact performance by about 2% so it is * desirable to call it only when needed. */ @@ -3567,9 +3634,6 @@ char *del_colon, *del_cookie, *colon; int app_cookies; - appsess *asession_temp = NULL; - appsess local_asession; - char *cur_ptr, *cur_end, *cur_next; int cur_idx, old_idx; @@ -3799,63 +3863,7 @@ /* first, let's see if the cookie is our appcookie*/ /* Cool... it's the right one */ - - asession_temp = &local_asession; - - if ((asession_temp->sessid = pool_alloc2(apools.sessid)) == NULL) { - Alert("Not enough memory process_cli():asession->sessid:malloc().\n"); - send_log(t->be, LOG_ALERT, "Not enough memory process_cli():asession->sessid:malloc().\n"); - return; - } - - memcpy(asession_temp->sessid, p3, t->be->appsession_len); - asession_temp->sessid[t->be->appsession_len] = 0; - asession_temp->serverid = NULL; - - /* only do insert, if lookup fails */ - asession_temp = appsession_hash_lookup(&(t->be->htbl_proxy), asession_temp->sessid); - if (asession_temp == NULL) { - if ((asession_temp = pool_alloc2(pool2_appsess)) == NULL) { - /* free previously allocated memory */ - pool_free2(apools.sessid, local_asession.sessid); - Alert("Not enough memory process_cli():asession:calloc().\n"); - send_log(t->be, LOG_ALERT, "Not enough memory process_cli():asession:calloc().\n"); - return; - } - - asession_temp->sessid = local_asession.sessid; - asession_temp->serverid = local_asession.serverid; - asession_temp->request_count = 0; - appsession_hash_insert(&(t->be->htbl_proxy), asession_temp); - } else { - /* free previously allocated memory */ - pool_free2(apools.sessid, local_asession.sessid); - } - if (asession_temp->serverid == NULL) { - /* TODO redispatch request */ - Alert("Found Application Session without matching server.\n"); - } else { - struct server *srv = t->be->srv; - while (srv) { - if (strcmp(srv->id, asession_temp->serverid) == 0) { - if (srv->state & SRV_RUNNING || t->be->options & PR_O_PERSIST) { - /* we found the server and it's usable */ - txn->flags &= ~TX_CK_MASK; - txn->flags |= TX_CK_VALID; - t->flags |= SN_DIRECT | SN_ASSIGNED; - t->srv = srv; - break; - } else { - txn->flags &= ~TX_CK_MASK; - txn->flags |= TX_CK_DOWN; - } - } - srv = srv->next; - }/* end while(srv) */ - }/* end else if server == NULL */ - - asession_temp->expire = tick_add_ifset(now_ms, t->be->timeout.appsession); - asession_temp->request_count++; + manage_client_side_appsession(t, p3); #if defined(DEBUG_HASH) Alert("manage_client_side_cookies\n"); appsession_hash_dump(&(t->be->htbl_proxy)); @@ -4133,9 +4141,6 @@ struct http_txn *txn = &t->txn; char *p1, *p2, *p3, *p4; - appsess *asession_temp = NULL; - appsess local_asession; - char *cur_ptr, *cur_end, *cur_next; int cur_idx, old_idx, delta; @@ -4276,60 +4281,64 @@ /* Cool... it's the right one */ - size_t server_id_len = strlen(t->srv->id) + 1; - asession_temp = &local_asession; - - if ((asession_temp->sessid = pool_alloc2(apools.sessid)) == NULL) { + if (t->sessid != NULL) { + /* free previously allocated memory as we don't need it anymore */ + pool_free2(apools.sessid, t->sessid); + } + /* Store the sessid in the session for future use */ + if ((t->sessid = pool_alloc2(apools.sessid)) == NULL) { Alert("Not enough Memory process_srv():asession->sessid:malloc().\n"); send_log(t->be, LOG_ALERT, "Not enough Memory process_srv():asession->sessid:malloc().\n"); return; } - memcpy(asession_temp->sessid, p3, t->be->appsession_len); - asession_temp->sessid[t->be->appsession_len] = 0; - asession_temp->serverid = NULL; - - /* only do insert, if lookup fails */ - asession_temp = appsession_hash_lookup(&(t->be->htbl_proxy), asession_temp->sessid); - if (asession_temp == NULL) { - if ((asession_temp = pool_alloc2(pool2_appsess)) == NULL) { - Alert("Not enough Memory process_srv():asession:calloc().\n"); - send_log(t->be, LOG_ALERT, "Not enough Memory process_srv():asession:calloc().\n"); - return; - } - asession_temp->sessid = local_asession.sessid; - asession_temp->serverid = local_asession.serverid; - asession_temp->request_count = 0; - appsession_hash_insert(&(t->be->htbl_proxy), asession_temp); - } else { - /* free wasted memory */ - pool_free2(apools.sessid, local_asession.sessid); - } - - if (asession_temp->serverid == NULL) { - if ((asession_temp->serverid = pool_alloc2(apools.serverid)) == NULL) { - Alert("Not enough Memory process_srv():asession->sessid:malloc().\n"); - send_log(t->be, LOG_ALERT, "Not enough Memory process_srv():asession->sessid:malloc().\n"); - return; - } - asession_temp->serverid[0] = '\0'; - } - - if (asession_temp->serverid[0] == '\0') - memcpy(asession_temp->serverid, t->srv->id, server_id_len); - - asession_temp->expire = tick_add_ifset(now_ms, t->be->timeout.appsession); - asession_temp->request_count++; -#if defined(DEBUG_HASH) - Alert("manage_server_side_cookies\n"); - appsession_hash_dump(&(t->be->htbl_proxy)); -#endif + memcpy(t->sessid, p3, t->be->appsession_len); + t->sessid[t->be->appsession_len] = 0; }/* end if ((t->proxy->appsession_name != NULL) ... */ break; /* we don't want to loop again since there cannot be another cookie on the same line */ } /* we're now at the end of the cookie value */ - /* keep the link from this header to next one */ old_idx = cur_idx; } /* end of cookie processing on this header */ + + if (t->sessid != NULL) { + appsess *asession = NULL; + /* only do insert, if lookup fails */ + asession = appsession_hash_lookup(&(t->be->htbl_proxy), t->sessid); + if (asession == NULL) { + if ((asession = pool_alloc2(pool2_appsess)) == NULL) { + Alert("Not enough Memory process_srv():asession:calloc().\n"); + send_log(t->be, LOG_ALERT, "Not enough Memory process_srv():asession:calloc().\n"); + return; + } + if ((asession->sessid = pool_alloc2(apools.sessid)) == NULL) { + Alert("Not enough Memory process_srv():asession->sessid:malloc().\n"); + send_log(t->be, LOG_ALERT, "Not enough Memory process_srv():asession->sessid:malloc().\n"); + return; + } + memcpy(asession->sessid, t->sessid, t->be->appsession_len); + asession->sessid[t->be->appsession_len] = 0; + + size_t server_id_len = strlen(t->srv->id) + 1; + if ((asession->serverid = pool_alloc2(apools.serverid)) == NULL) { + Alert("Not enough Memory process_srv():asession->sessid:malloc().\n"); + send_log(t->be, LOG_ALERT, "Not enough Memory process_srv():asession->sessid:malloc().\n"); + return; + } + asession->serverid[0] = '\0'; + memcpy(asession->serverid, t->srv->id, server_id_len); + + asession->request_count = 0; + appsession_hash_insert(&(t->be->htbl_proxy), asession); + } + + asession->expire = tick_add_ifset(now_ms, t->be->timeout.appsession); + asession->request_count++; + } + +#if defined(DEBUG_HASH) + Alert("manage_server_side_cookies\n"); + appsession_hash_dump(&(t->be->htbl_proxy)); +#endif } @@ -4427,9 +4436,6 @@ */ void get_srv_from_appsession(struct session *t, const char *begin, int len) { - struct http_txn *txn = &t->txn; - appsess *asession_temp = NULL; - appsess local_asession; char *request_line; if (t->be->appsession_name == NULL || @@ -4448,69 +4454,11 @@ /* skip jsessionid= */ request_line += t->be->appsession_name_len + 1; - /* First try if we already have an appsession */ - asession_temp = &local_asession; - - if ((asession_temp->sessid = pool_alloc2(apools.sessid)) == NULL) { - Alert("Not enough memory process_cli():asession_temp->sessid:calloc().\n"); - send_log(t->be, LOG_ALERT, "Not enough Memory process_cli():asession_temp->sessid:calloc().\n"); - return; - } - - /* Copy the sessionid */ - memcpy(asession_temp->sessid, request_line, t->be->appsession_len); - asession_temp->sessid[t->be->appsession_len] = 0; - asession_temp->serverid = NULL; - - /* only do insert, if lookup fails */ - asession_temp = appsession_hash_lookup(&(t->be->htbl_proxy), asession_temp->sessid); - if (asession_temp == NULL) { - if ((asession_temp = pool_alloc2(pool2_appsess)) == NULL) { - /* free previously allocated memory */ - pool_free2(apools.sessid, local_asession.sessid); - Alert("Not enough memory process_cli():asession:calloc().\n"); - send_log(t->be, LOG_ALERT, "Not enough memory process_cli():asession:calloc().\n"); - return; - } - asession_temp->sessid = local_asession.sessid; - asession_temp->serverid = local_asession.serverid; - asession_temp->request_count=0; - appsession_hash_insert(&(t->be->htbl_proxy), asession_temp); - } - else { - /* free previously allocated memory */ - pool_free2(apools.sessid, local_asession.sessid); - } - - asession_temp->expire = tick_add_ifset(now_ms, t->be->timeout.appsession); - asession_temp->request_count++; - + manage_client_side_appsession(t, request_line); #if defined(DEBUG_HASH) Alert("get_srv_from_appsession\n"); appsession_hash_dump(&(t->be->htbl_proxy)); #endif - if (asession_temp->serverid == NULL) { - /* TODO redispatch request */ - Alert("Found Application Session without matching server.\n"); - } else { - struct server *srv = t->be->srv; - while (srv) { - if (strcmp(srv->id, asession_temp->serverid) == 0) { - if (srv->state & SRV_RUNNING || t->be->options & PR_O_PERSIST) { - /* we found the server and it's usable */ - txn->flags &= ~TX_CK_MASK; - txn->flags |= TX_CK_VALID; - t->flags |= SN_DIRECT | SN_ASSIGNED; - t->srv = srv; - break; - } else { - txn->flags &= ~TX_CK_MASK; - txn->flags |= TX_CK_DOWN; - } - } - srv = srv->next; - } - } } diff -Naur haproxy-1.4-dev4/src/session.c haproxy-1.4-dev4-appsession-final/src/session.c --- haproxy-1.4-dev4/src/session.c 2009-10-12 06:40:53.000000000 +0200 +++ haproxy-1.4-dev4-appsession-final/src/session.c 2009-10-12 21:41:23.000000000 +0200 @@ -77,6 +77,9 @@ pool_free2(pool2_buffer, s->req); pool_free2(pool2_buffer, s->rep); + if (s->sessid) + pool_free2(apools.sessid, s->sessid); + if (fe) { pool_free2(fe->hdr_idx_pool, txn->hdr_idx.v);
diff -Naur haproxy-1.3.21/include/proto/proto_http.h haproxy-1.3.21-appsession-final/include/proto/proto_http.h --- haproxy-1.3.21/include/proto/proto_http.h 2009-10-12 06:20:09.000000000 +0200 +++ haproxy-1.3.21-appsession-final/include/proto/proto_http.h 2009-10-14 23:12:55.000000000 +0200 @@ -75,6 +75,7 @@ int apply_filter_to_req_line(struct session *t, struct buffer *req, struct hdr_exp *exp); int apply_filters_to_request(struct session *t, struct buffer *req, struct hdr_exp *exp); int apply_filters_to_response(struct session *t, struct buffer *rtr, struct hdr_exp *exp); +void manage_client_side_appsession(struct session *t, const char *buf); void manage_client_side_cookies(struct session *t, struct buffer *req); void manage_server_side_cookies(struct session *t, struct buffer *rtr); void check_response_for_cacheability(struct session *t, struct buffer *rtr); diff -Naur haproxy-1.3.21/include/types/proxy.h haproxy-1.3.21-appsession-final/include/types/proxy.h --- haproxy-1.3.21/include/types/proxy.h 2009-10-12 06:20:09.000000000 +0200 +++ haproxy-1.3.21-appsession-final/include/types/proxy.h 2009-10-14 22:58:41.000000000 +0200 @@ -120,6 +120,9 @@ /* 0x80..0x800 already used in 1.4 */ #define PR_O2_INDEPSTR 0x00001000 /* independant streams, don't update rex on write */ +/* bits for proxy->appsession_options */ +#define PR_O_AS_REQL 0x00000001 /* learn the session id from the request */ + /* This structure is used to apply fast weighted round robin on a server group */ struct fwrr_group { struct eb_root curr; /* tree for servers in "current" time range */ @@ -207,6 +210,7 @@ char *appsession_name; /* name of the cookie to look for */ int appsession_name_len; /* strlen(appsession_name), computed only once */ int appsession_len; /* length of the appsession cookie value to be used */ + int appsession_options; /* options for appsession */ struct appsession_hash htbl_proxy; /* Per Proxy hashtable */ char *capture_name; /* beginning of the name of the cookie to capture */ int capture_namelen; /* length of the cookie name to match */ diff -Naur haproxy-1.3.21/include/types/session.h haproxy-1.3.21-appsession-final/include/types/session.h --- haproxy-1.3.21/include/types/session.h 2009-10-12 06:20:09.000000000 +0200 +++ haproxy-1.3.21-appsession-final/include/types/session.h 2009-10-14 22:59:06.000000000 +0200 @@ -162,6 +162,7 @@ int conn_retries; /* number of connect retries left */ int flags; /* some flags describing the session */ unsigned term_trace; /* term trace: 4*8 bits indicating which part of the code closed */ + char *sessid; /* the session id, if found in the request or in the response */ struct buffer *req; /* request buffer */ struct buffer *rep; /* response buffer */ struct stream_interface si[2]; /* client and server stream interfaces */ diff -Naur haproxy-1.3.21/src/cfgparse.c haproxy-1.3.21-appsession-final/src/cfgparse.c --- haproxy-1.3.21/src/cfgparse.c 2009-10-12 06:20:09.000000000 +0200 +++ haproxy-1.3.21-appsession-final/src/cfgparse.c 2009-10-14 23:00:08.000000000 +0200 @@ -1326,6 +1326,7 @@ } }/* end else if (!strcmp(args[0], "cookie")) */ else if (!strcmp(args[0], "appsession")) { /* cookie name */ + int cur_arg; if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) err_code |= ERR_WARN; @@ -1355,6 +1356,14 @@ err_code |= ERR_ALERT | ERR_ABORT; goto out; } + + cur_arg = 6; + while (*(args[cur_arg])) { + if (!strcmp(args[cur_arg], "request-learn")) { + curproxy->appsession_options |= PR_O_AS_REQL; + } + cur_arg++; + } } /* Url App Session */ else if (!strcmp(args[0], "capture")) { if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL)) diff -Naur haproxy-1.3.21/src/client.c haproxy-1.3.21-appsession-final/src/client.c --- haproxy-1.3.21/src/client.c 2009-10-12 06:20:09.000000000 +0200 +++ haproxy-1.3.21-appsession-final/src/client.c 2009-10-14 23:00:49.000000000 +0200 @@ -179,7 +179,7 @@ } s->ana_state = 0; /* analysers may change it but must reset it upon exit */ - s->req = s->rep = NULL; /* will be allocated later */ + s->sessid = s->req = s->rep = NULL; /* will be allocated later */ s->si[0].state = s->si[0].prev_state = SI_ST_EST; s->si[0].err_type = SI_ET_NONE; diff -Naur haproxy-1.3.21/src/proto_http.c haproxy-1.3.21-appsession-final/src/proto_http.c --- haproxy-1.3.21/src/proto_http.c 2009-10-12 06:20:09.000000000 +0200 +++ haproxy-1.3.21-appsession-final/src/proto_http.c 2009-10-14 23:46:44.000000000 +0200 @@ -3368,6 +3368,73 @@ /* + * Try to retrieve the server associated to the appsession. + * If the server is found, it's assigned to the session. + */ +void manage_client_side_appsession(struct session *t, const char *buf) { + struct http_txn *txn = &t->txn; + appsess *asession = NULL; + char *sessid_temp = NULL; + + if (t->be->appsession_options & PR_O_AS_REQL) { + /* request-learn option is enabled : store the sessid in the session for future use */ + if (t->sessid != NULL) { + /* free previously allocated memory as we don't need the session id found in the URL anymore */ + pool_free2(apools.sessid, t->sessid); + } + + if ((t->sessid = pool_alloc2(apools.sessid)) == NULL) { + Alert("Not enough memory process_cli():asession->sessid:malloc().\n"); + send_log(t->be, LOG_ALERT, "Not enough memory process_cli():asession->sessid:malloc().\n"); + return; + } + + memcpy(t->sessid, buf, t->be->appsession_len); + t->sessid[t->be->appsession_len] = 0; + } + + if ((sessid_temp = pool_alloc2(apools.sessid)) == NULL) { + Alert("Not enough memory process_cli():asession->sessid:malloc().\n"); + send_log(t->be, LOG_ALERT, "Not enough memory process_cli():asession->sessid:malloc().\n"); + return; + } + + memcpy(sessid_temp, buf, t->be->appsession_len); + sessid_temp[t->be->appsession_len] = 0; + + asession = appsession_hash_lookup(&(t->be->htbl_proxy), sessid_temp); + /* free previously allocated memory */ + pool_free2(apools.sessid, sessid_temp); + + if (asession != NULL) { + asession->expire = tick_add_ifset(now_ms, t->be->timeout.appsession); + if (!(t->be->appsession_options & PR_O_AS_REQL)) { + asession->request_count++; + } + + if (asession->serverid != NULL) { + struct server *srv = t->be->srv; + while (srv) { + if (strcmp(srv->id, asession->serverid) == 0) { + if (srv->state & SRV_RUNNING || t->be->options & PR_O_PERSIST) { + /* we found the server and it's usable */ + txn->flags &= ~TX_CK_MASK; + txn->flags |= TX_CK_VALID; + t->flags |= SN_DIRECT | SN_ASSIGNED; + t->srv = srv; + break; + } else { + txn->flags &= ~TX_CK_MASK; + txn->flags |= TX_CK_DOWN; + } + } + srv = srv->next; + } + } + } +} + +/* * Manage client-side cookie. It can impact performance by about 2% so it is * desirable to call it only when needed. */ @@ -3378,9 +3445,6 @@ char *del_colon, *del_cookie, *colon; int app_cookies; - appsess *asession_temp = NULL; - appsess local_asession; - char *cur_ptr, *cur_end, *cur_next; int cur_idx, old_idx; @@ -3610,63 +3674,7 @@ /* first, let's see if the cookie is our appcookie*/ /* Cool... it's the right one */ - - asession_temp = &local_asession; - - if ((asession_temp->sessid = pool_alloc2(apools.sessid)) == NULL) { - Alert("Not enough memory process_cli():asession->sessid:malloc().\n"); - send_log(t->be, LOG_ALERT, "Not enough memory process_cli():asession->sessid:malloc().\n"); - return; - } - - memcpy(asession_temp->sessid, p3, t->be->appsession_len); - asession_temp->sessid[t->be->appsession_len] = 0; - asession_temp->serverid = NULL; - - /* only do insert, if lookup fails */ - asession_temp = appsession_hash_lookup(&(t->be->htbl_proxy), asession_temp->sessid); - if (asession_temp == NULL) { - if ((asession_temp = pool_alloc2(pool2_appsess)) == NULL) { - /* free previously allocated memory */ - pool_free2(apools.sessid, local_asession.sessid); - Alert("Not enough memory process_cli():asession:calloc().\n"); - send_log(t->be, LOG_ALERT, "Not enough memory process_cli():asession:calloc().\n"); - return; - } - - asession_temp->sessid = local_asession.sessid; - asession_temp->serverid = local_asession.serverid; - asession_temp->request_count = 0; - appsession_hash_insert(&(t->be->htbl_proxy), asession_temp); - } else { - /* free previously allocated memory */ - pool_free2(apools.sessid, local_asession.sessid); - } - if (asession_temp->serverid == NULL) { - /* TODO redispatch request */ - Alert("Found Application Session without matching server.\n"); - } else { - struct server *srv = t->be->srv; - while (srv) { - if (strcmp(srv->id, asession_temp->serverid) == 0) { - if (srv->state & SRV_RUNNING || t->be->options & PR_O_PERSIST) { - /* we found the server and it's usable */ - txn->flags &= ~TX_CK_MASK; - txn->flags |= TX_CK_VALID; - t->flags |= SN_DIRECT | SN_ASSIGNED; - t->srv = srv; - break; - } else { - txn->flags &= ~TX_CK_MASK; - txn->flags |= TX_CK_DOWN; - } - } - srv = srv->next; - }/* end while(srv) */ - }/* end else if server == NULL */ - - asession_temp->expire = tick_add_ifset(now_ms, t->be->timeout.appsession); - asession_temp->request_count++; + manage_client_side_appsession(t, p3); #if defined(DEBUG_HASH) Alert("manage_client_side_cookies\n"); appsession_hash_dump(&(t->be->htbl_proxy)); @@ -3944,9 +3952,6 @@ struct http_txn *txn = &t->txn; char *p1, *p2, *p3, *p4; - appsess *asession_temp = NULL; - appsess local_asession; - char *cur_ptr, *cur_end, *cur_next; int cur_idx, old_idx, delta; @@ -4087,60 +4092,64 @@ /* Cool... it's the right one */ - size_t server_id_len = strlen(t->srv->id) + 1; - asession_temp = &local_asession; - - if ((asession_temp->sessid = pool_alloc2(apools.sessid)) == NULL) { + if (t->sessid != NULL) { + /* free previously allocated memory as we don't need it anymore */ + pool_free2(apools.sessid, t->sessid); + } + /* Store the sessid in the session for future use */ + if ((t->sessid = pool_alloc2(apools.sessid)) == NULL) { Alert("Not enough Memory process_srv():asession->sessid:malloc().\n"); send_log(t->be, LOG_ALERT, "Not enough Memory process_srv():asession->sessid:malloc().\n"); return; } - memcpy(asession_temp->sessid, p3, t->be->appsession_len); - asession_temp->sessid[t->be->appsession_len] = 0; - asession_temp->serverid = NULL; - - /* only do insert, if lookup fails */ - asession_temp = appsession_hash_lookup(&(t->be->htbl_proxy), asession_temp->sessid); - if (asession_temp == NULL) { - if ((asession_temp = pool_alloc2(pool2_appsess)) == NULL) { - Alert("Not enough Memory process_srv():asession:calloc().\n"); - send_log(t->be, LOG_ALERT, "Not enough Memory process_srv():asession:calloc().\n"); - return; - } - asession_temp->sessid = local_asession.sessid; - asession_temp->serverid = local_asession.serverid; - asession_temp->request_count = 0; - appsession_hash_insert(&(t->be->htbl_proxy), asession_temp); - } else { - /* free wasted memory */ - pool_free2(apools.sessid, local_asession.sessid); - } - - if (asession_temp->serverid == NULL) { - if ((asession_temp->serverid = pool_alloc2(apools.serverid)) == NULL) { - Alert("Not enough Memory process_srv():asession->sessid:malloc().\n"); - send_log(t->be, LOG_ALERT, "Not enough Memory process_srv():asession->sessid:malloc().\n"); - return; - } - asession_temp->serverid[0] = '\0'; - } - - if (asession_temp->serverid[0] == '\0') - memcpy(asession_temp->serverid, t->srv->id, server_id_len); - - asession_temp->expire = tick_add_ifset(now_ms, t->be->timeout.appsession); - asession_temp->request_count++; -#if defined(DEBUG_HASH) - Alert("manage_server_side_cookies\n"); - appsession_hash_dump(&(t->be->htbl_proxy)); -#endif + memcpy(t->sessid, p3, t->be->appsession_len); + t->sessid[t->be->appsession_len] = 0; }/* end if ((t->proxy->appsession_name != NULL) ... */ break; /* we don't want to loop again since there cannot be another cookie on the same line */ } /* we're now at the end of the cookie value */ - /* keep the link from this header to next one */ old_idx = cur_idx; } /* end of cookie processing on this header */ + + if (t->sessid != NULL) { + appsess *asession = NULL; + /* only do insert, if lookup fails */ + asession = appsession_hash_lookup(&(t->be->htbl_proxy), t->sessid); + if (asession == NULL) { + if ((asession = pool_alloc2(pool2_appsess)) == NULL) { + Alert("Not enough Memory process_srv():asession:calloc().\n"); + send_log(t->be, LOG_ALERT, "Not enough Memory process_srv():asession:calloc().\n"); + return; + } + if ((asession->sessid = pool_alloc2(apools.sessid)) == NULL) { + Alert("Not enough Memory process_srv():asession->sessid:malloc().\n"); + send_log(t->be, LOG_ALERT, "Not enough Memory process_srv():asession->sessid:malloc().\n"); + return; + } + memcpy(asession->sessid, t->sessid, t->be->appsession_len); + asession->sessid[t->be->appsession_len] = 0; + + size_t server_id_len = strlen(t->srv->id) + 1; + if ((asession->serverid = pool_alloc2(apools.serverid)) == NULL) { + Alert("Not enough Memory process_srv():asession->sessid:malloc().\n"); + send_log(t->be, LOG_ALERT, "Not enough Memory process_srv():asession->sessid:malloc().\n"); + return; + } + asession->serverid[0] = '\0'; + memcpy(asession->serverid, t->srv->id, server_id_len); + + asession->request_count = 0; + appsession_hash_insert(&(t->be->htbl_proxy), asession); + } + + asession->expire = tick_add_ifset(now_ms, t->be->timeout.appsession); + asession->request_count++; + } + +#if defined(DEBUG_HASH) + Alert("manage_server_side_cookies\n"); + appsession_hash_dump(&(t->be->htbl_proxy)); +#endif } @@ -4238,9 +4247,6 @@ */ void get_srv_from_appsession(struct session *t, const char *begin, int len) { - struct http_txn *txn = &t->txn; - appsess *asession_temp = NULL; - appsess local_asession; char *request_line; if (t->be->appsession_name == NULL || @@ -4259,69 +4265,11 @@ /* skip jsessionid= */ request_line += t->be->appsession_name_len + 1; - /* First try if we already have an appsession */ - asession_temp = &local_asession; - - if ((asession_temp->sessid = pool_alloc2(apools.sessid)) == NULL) { - Alert("Not enough memory process_cli():asession_temp->sessid:calloc().\n"); - send_log(t->be, LOG_ALERT, "Not enough Memory process_cli():asession_temp->sessid:calloc().\n"); - return; - } - - /* Copy the sessionid */ - memcpy(asession_temp->sessid, request_line, t->be->appsession_len); - asession_temp->sessid[t->be->appsession_len] = 0; - asession_temp->serverid = NULL; - - /* only do insert, if lookup fails */ - asession_temp = appsession_hash_lookup(&(t->be->htbl_proxy), asession_temp->sessid); - if (asession_temp == NULL) { - if ((asession_temp = pool_alloc2(pool2_appsess)) == NULL) { - /* free previously allocated memory */ - pool_free2(apools.sessid, local_asession.sessid); - Alert("Not enough memory process_cli():asession:calloc().\n"); - send_log(t->be, LOG_ALERT, "Not enough memory process_cli():asession:calloc().\n"); - return; - } - asession_temp->sessid = local_asession.sessid; - asession_temp->serverid = local_asession.serverid; - asession_temp->request_count=0; - appsession_hash_insert(&(t->be->htbl_proxy), asession_temp); - } - else { - /* free previously allocated memory */ - pool_free2(apools.sessid, local_asession.sessid); - } - - asession_temp->expire = tick_add_ifset(now_ms, t->be->timeout.appsession); - asession_temp->request_count++; - + manage_client_side_appsession(t, request_line); #if defined(DEBUG_HASH) Alert("get_srv_from_appsession\n"); appsession_hash_dump(&(t->be->htbl_proxy)); #endif - if (asession_temp->serverid == NULL) { - /* TODO redispatch request */ - Alert("Found Application Session without matching server.\n"); - } else { - struct server *srv = t->be->srv; - while (srv) { - if (strcmp(srv->id, asession_temp->serverid) == 0) { - if (srv->state & SRV_RUNNING || t->be->options & PR_O_PERSIST) { - /* we found the server and it's usable */ - txn->flags &= ~TX_CK_MASK; - txn->flags |= TX_CK_VALID; - t->flags |= SN_DIRECT | SN_ASSIGNED; - t->srv = srv; - break; - } else { - txn->flags &= ~TX_CK_MASK; - txn->flags |= TX_CK_DOWN; - } - } - srv = srv->next; - } - } } diff -Naur haproxy-1.3.21/src/session.c haproxy-1.3.21-appsession-final/src/session.c --- haproxy-1.3.21/src/session.c 2009-10-12 06:20:09.000000000 +0200 +++ haproxy-1.3.21-appsession-final/src/session.c 2009-10-14 23:09:30.000000000 +0200 @@ -78,6 +78,9 @@ pool_free2(pool2_buffer, s->req); pool_free2(pool2_buffer, s->rep); + if (s->sessid) + pool_free2(apools.sessid, s->sessid); + if (fe) { pool_free2(fe->hdr_idx_pool, txn->hdr_idx.v);