From: Willy Tarreau Date: Sun, 3 Dec 2006 14:21:35 +0000 (+0100) Subject: [MEDIUM] added the hdr_idx structure for future HTTP header indexing X-Git-Tag: v1.3.4~43 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e5f20dcea81529938ec4a6b1386b8ace36b0ce58;p=thirdparty%2Fhaproxy.git [MEDIUM] added the hdr_idx structure for future HTTP header indexing This structure will consume 4 bytes per header to keep track of headers within a request or a response without having to parse the whole request for each regex. As it's not possible to allocate only 4 bytes, we define a max number of HTTP headers. We set it to (BUFSIZE+79)/80 so that 8kB buffers can contain 100 headers (like Apache), resulting in 400 bytes dedicated to indexation, or about 400/(2*8kB) ~= 2.4% of the memory usage. --- diff --git a/Makefile b/Makefile index 1eef960aef..f690a14af3 100644 --- a/Makefile +++ b/Makefile @@ -158,7 +158,7 @@ OBJS = src/haproxy.o src/list.o src/chtbl.o src/hashpjw.o src/base64.o \ src/time.o src/fd.o src/regex.o src/cfgparse.o src/server.o \ src/checks.o src/queue.o src/capture.o src/client.o src/proxy.o \ src/proto_http.o src/stream_sock.o src/appsession.o src/backend.o \ - src/session.o + src/session.o src/hdr_idx.o haproxy: $(OBJS) $(LD) $(LDFLAGS) -o $@ $^ $(LIBS) diff --git a/Makefile.bsd b/Makefile.bsd index 4e274b029d..b288820b3b 100644 --- a/Makefile.bsd +++ b/Makefile.bsd @@ -87,7 +87,7 @@ OBJS = src/haproxy.o src/list.o src/chtbl.o src/hashpjw.o src/base64.o \ src/time.o src/fd.o src/regex.o src/cfgparse.o src/server.o \ src/checks.o src/queue.o src/capture.o src/client.o src/proxy.o \ src/proto_http.o src/stream_sock.o src/appsession.o src/backend.o \ - src/session.o + src/session.o src/hdr_idx.o all: haproxy diff --git a/include/common/defaults.h b/include/common/defaults.h index e44a64c2ec..84032ae562 100644 --- a/include/common/defaults.h +++ b/include/common/defaults.h @@ -52,6 +52,12 @@ // max # of matches per regexp #define MAX_MATCH 10 +// max # of headers in one HTTP request or response +// By default, about 100 headers per 8 kB. +#ifndef MAX_HTTP_HDR +#define MAX_HTTP_HDR ((BUFSIZE+79)/80) +#endif + // cookie delimitor in "prefix" mode. This character is inserted between the // persistence cookie and the original value. The '~' is allowed by RFC2965, // and should not be too common in server names. diff --git a/include/types/proxy.h b/include/types/proxy.h index 8523a694a4..28b05a05b6 100644 --- a/include/types/proxy.h +++ b/include/types/proxy.h @@ -118,6 +118,7 @@ struct proxy { struct cap_hdr *req_cap; /* chained list of request headers to be captured */ struct cap_hdr *rsp_cap; /* chained list of response headers to be captured */ void *req_cap_pool, *rsp_cap_pool; /* pools of pre-allocated char ** used to build the sessions */ + void *hdr_idx_pool; /* pools of pre-allocated int* used for headers indexing */ char *req_add[MAX_NEWHDR], *rsp_add[MAX_NEWHDR]; /* headers to be added */ int grace; /* grace time after stop request */ char *check_req; /* HTTP or SSL request to use for PR_O_HTTP_CHK|PR_O_SSL3_CHK */ diff --git a/include/types/session.h b/include/types/session.h index dd12d4f9eb..f5e9490543 100644 --- a/include/types/session.h +++ b/include/types/session.h @@ -36,6 +36,7 @@ #include #include #include +#include /* various session flags, bits values 0x01 to 0x20 (shift 0) */ @@ -120,6 +121,7 @@ struct session { struct pendconn *pend_pos; /* if not NULL, points to the position in the pending queue */ char **req_cap; /* array of captured request headers (may be NULL) */ char **rsp_cap; /* array of captured response headers (may be NULL) */ + struct hdr_idx hdr_idx; /* array of header indexes (max: MAX_HTTP_HDR) */ struct chunk req_line; /* points to first line */ struct chunk auth_hdr; /* points to 'Authorization:' header */ struct { diff --git a/src/client.c b/src/client.c index 26ef18698d..b867830674 100644 --- a/src/client.c +++ b/src/client.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -156,9 +157,6 @@ int event_accept(int fd) { t->context = s; s->task = t; -#ifdef BUILD_WITH_PROXY - s->proxy = p; -#endif s->be = s->fe = s->fi = p; s->cli_state = (p->mode == PR_MODE_HTTP) ? CL_STHEADERS : CL_STDATA; /* no HTTP headers for non-HTTP proxies */ @@ -227,6 +225,27 @@ int event_accept(int fd) { else s->rsp_cap = NULL; + if (p->mode == PR_MODE_HTTP) { + s->hdr_idx.size = MAX_HTTP_HDR; + if ((s->hdr_idx.v = + pool_alloc_from(p->hdr_idx_pool, s->hdr_idx.size*sizeof(*s->hdr_idx.v))) + == NULL) { /* no memory */ + if (s->rsp_cap != NULL) + pool_free_to(p->rsp_cap_pool, s->rsp_cap); + if (s->req_cap != NULL) + pool_free_to(p->req_cap_pool, s->req_cap); + close(cfd); /* nothing can be done for this fd without memory */ + pool_free(task, t); + pool_free(session, s); + return 0; + } + hdr_idx_init(&s->hdr_idx); + } + else { + s->hdr_idx.size = s->hdr_idx.used = 0; + s->hdr_idx.v = NULL; + } + if ((p->mode == PR_MODE_TCP || p->mode == PR_MODE_HTTP) && (p->logfac1 >= 0 || p->logfac2 >= 0)) { struct sockaddr_storage sockname; @@ -303,6 +322,8 @@ int event_accept(int fd) { } if ((s->req = pool_alloc(buffer)) == NULL) { /* no memory */ + if (s->hdr_idx.v != NULL) + pool_free_to(p->hdr_idx_pool, s->hdr_idx.v); if (s->rsp_cap != NULL) pool_free_to(p->rsp_cap_pool, s->rsp_cap); if (s->req_cap != NULL)