specific headers such as 'Host'. For instance, in the Host
value "haproxy.1wt.eu", only "1wt" will be considered.
+ rdp-cookie
+ rdp-cookie(name)
+ The RDP cookie <name> (or "mstshash" if omitted) will be
+ looked up and hashed for each incoming TCP request. Just as
+ with the equivalent ACL 'req_rdp_cookie()' function, the name
+ is not case-sensitive. This mechanism is useful as a degraded
+ persistence mode, as it makes it possible to always send the
+ same user (or the same session ID) to the same server. If the
+ cookie is not found, the normal round-robind algorithm is
+ used instead.
+
+ Note that for this to work, the frontend must ensure that an
+ RDP cookie is already present in the request buffer. For this
+ you must use 'tcp-request content accept' rule combined with
+ a 'req_rdp_cookie_cnt' ACL.
+
<arguments> is an optional list of arguments which may be needed by some
algorithms. Right now, only "url_param" and "uri" support an
optional argument.
return px->lbprm.map.srv[hash % px->lbprm.tot_weight];
}
+struct server *get_server_rch(struct session *s)
+{
+ unsigned long hash = 0;
+ struct proxy *px = s->be;
+ unsigned long len;
+ const char *p;
+ int ret;
+ struct acl_expr expr;
+ struct acl_test test;
+
+ /* tot_weight appears to mean srv_count */
+ if (px->lbprm.tot_weight == 0)
+ return NULL;
+
+ if (px->lbprm.map.state & PR_MAP_RECALC)
+ recalc_server_map(px);
+
+ memset(&expr, 0, sizeof(expr));
+ memset(&test, 0, sizeof(test));
+
+ expr.arg.str = px->hh_name;
+ expr.arg_len = px->hh_len;
+
+ ret = acl_fetch_rdp_cookie(px, s, NULL, ACL_DIR_REQ, &expr, &test);
+ if (ret == 0 || (test.flags & ACL_TEST_F_MAY_CHANGE) || test.len == 0)
+ return NULL;
+
+ /* Found a the hh_name in the headers.
+ * we will compute the hash based on this value ctx.val.
+ */
+ len = test.len;
+ p = (char *)test.ptr;
+ while (len) {
+ hash = *p + (hash << 6) + (hash << 16) - hash;
+ len--;
+ p++;
+ }
+
+ return px->lbprm.map.srv[hash % px->lbprm.tot_weight];
+}
/*
* This function applies the load-balancing algorithm to the session, as
/* Header Parameter hashing */
s->srv = get_server_hh(s);
+ if (!s->srv) {
+ /* parameter not found, fall back to round robin on the map */
+ s->srv = get_server_rr_with_conns(s->be, s->prev_srv);
+ if (!s->srv) {
+ err = SRV_STATUS_FULL;
+ goto out;
+ }
+ }
+ break;
+ case BE_LB_ALGO_RCH:
+ /* RDP Cookie hashing */
+ s->srv = get_server_rch(s);
+
if (!s->srv) {
/* parameter not found, fall back to round robin on the map */
s->srv = get_server_rr_with_conns(s->be, s->prev_srv);
}
}
+ else if (!strncmp(args[0], "rdp-cookie", 10)) {
+ curproxy->lbprm.algo &= ~BE_LB_ALGO;
+ curproxy->lbprm.algo |= BE_LB_ALGO_RCH;
+
+ if ( *(args[0] + 10 ) == '(' ) { /* cookie name */
+ const char *beg, *end;
+
+ beg = args[0] + 11;
+ end = strchr(beg, ')');
+
+ if (!end || end == beg) {
+ snprintf(err, errlen, "'balance rdp-cookie(name)' requires an rdp cookie name.");
+ return -1;
+ }
+
+ free(curproxy->hh_name);
+ curproxy->hh_name = my_strndup(beg, end - beg);
+ curproxy->hh_len = end - beg;
+ }
+ else if ( *(args[0] + 10 ) == '\0' ) { /* default cookie name 'mstshash' */
+ free(curproxy->hh_name);
+ curproxy->hh_name = strdup("mstshash");
+ curproxy->hh_len = strlen(curproxy->hh_name);
+ }
+ else { /* syntax */
+ snprintf(err, errlen, "'balance rdp-cookie(name)' requires an rdp cookie name.");
+ return -1;
+ }
+ }
else {
- snprintf(err, errlen, "'balance' only supports 'roundrobin', 'leastconn', 'source', 'uri', 'url_param' and 'hdr(name)' options.");
+ snprintf(err, errlen, "'balance' only supports 'roundrobin', 'leastconn', 'source', 'uri', 'url_param', 'hdr(name)' and 'rdp-cookie(name)' options.");
return -1;
}
return 0;