73 lines
2.6 KiB
Diff
73 lines
2.6 KiB
Diff
# UNDF: UNDF-2026-000000101
|
||
--- a/include/haproxy/server-t.h
|
||
+++ b/include/haproxy/server-t.h
|
||
@@ -343,6 +343,7 @@ struct server {
|
||
int cklen; /* the len of the cookie, to speed up checks */
|
||
unsigned int flags; /* server permanent flags */
|
||
char *cookie; /* the id set in the cookie */
|
||
+ struct ebpt_node cookie_node; /* eb-tree node keyed by cookie string; used by proxy->cookies_tree */
|
||
|
||
--- a/include/haproxy/proxy-t.h
|
||
+++ b/include/haproxy/proxy-t.h
|
||
@@ -364,6 +364,7 @@ struct proxy {
|
||
struct server *srv, *defsrv; /* known servers; default server configuration */
|
||
+ struct eb_root cookies_tree; /* eb-tree of srv->cookie_node for O(1) cookie lookup; populated after config parse */
|
||
|
||
--- a/src/server.c
|
||
+++ b/src/server.c
|
||
@@ -XXX,0 +XXX,12 @@
|
||
+/*
|
||
+ * Build or rebuild the proxy's cookies_tree index.
|
||
+ * Called after srv_set_dyncookie() and after initial config parse.
|
||
+ * O(S log S) one-time cost; amortises the O(C×S) per-request cookie scan.
|
||
+ */
|
||
+void proxy_build_cookie_tree(struct proxy *px)
|
||
+{
|
||
+ struct server *srv;
|
||
+ px->cookies_tree = EB_ROOT_UNIQUE;
|
||
+ for (srv = px->srv; srv; srv = srv->next) {
|
||
+ if (srv->cookie) {
|
||
+ srv->cookie_node.key = srv->cookie;
|
||
+ ebis_insert(&px->cookies_tree, &srv->cookie_node);
|
||
+ }
|
||
+ }
|
||
+}
|
||
|
||
--- a/src/http_ana.c
|
||
+++ b/src/http_ana.c
|
||
@@ -3514,10 +3514,18 @@ static void http_manage_client_side_cookies(...)
|
||
if ((delim == val_beg) || (s->flags & (SF_IGNORE_PRST | SF_ASSIGNED)))
|
||
srv = NULL;
|
||
|
||
- while (srv) {
|
||
- if (srv->cookie && (srv->cklen == delim - val_beg) &&
|
||
- !memcmp(val_beg, srv->cookie, delim - val_beg)) {
|
||
- /* ... */
|
||
- }
|
||
- srv = srv->next;
|
||
- }
|
||
+ /* Replace O(S) linked-list walk with O(log S) eb-tree lookup.
|
||
+ * proxy_build_cookie_tree() indexes all srv->cookie strings at
|
||
+ * config-time; lookup is safe at runtime (cookies are immutable). */
|
||
+ if (srv) {
|
||
+ char cookie_key[delim - val_beg + 1];
|
||
+ memcpy(cookie_key, val_beg, delim - val_beg);
|
||
+ cookie_key[delim - val_beg] = '\0';
|
||
+
|
||
+ struct ebpt_node *node = ebis_lookup(&s->be->cookies_tree, cookie_key);
|
||
+ srv = node ? container_of(node, struct server, cookie_node) : NULL;
|
||
+ if (srv) {
|
||
+ if ((srv->cur_state != SRV_ST_STOPPED) ||
|
||
+ (s->be->options & PR_O_PERSIST) ||
|
||
+ (s->flags & SF_FORCE_PRST)) {
|
||
+ txn->flags &= ~TX_CK_MASK;
|
||
+ txn->flags |= (srv->cur_state != SRV_ST_STOPPED) ? TX_CK_VALID : TX_CK_DOWN;
|
||
+ s->flags |= SF_DIRECT | SF_ASSIGNED;
|
||
+ stream_set_srv_target(s, srv);
|
||
+ } else {
|
||
+ txn->flags &= ~TX_CK_MASK;
|
||
+ txn->flags |= TX_CK_DOWN;
|
||
+ srv = NULL;
|
||
+ }
|
||
+ }
|
||
+ }
|