From: David CARLIER Date: Wed, 24 Apr 2019 19:41:53 +0000 (+0100) Subject: MEDIUM: da: HTX mode support. X-Git-Tag: v2.0-dev3~160 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4de0eba8488f7d7b471d60da76d815c69e44fecb;p=thirdparty%2Fhaproxy.git MEDIUM: da: HTX mode support. The DeviceAtlas module now can support both the legacy mode and the new HTX's with the known set of support headers for the latter. --- diff --git a/src/da.c b/src/da.c index 50862a167f..6c7ce814e0 100644 --- a/src/da.c +++ b/src/da.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -285,83 +286,164 @@ static int da_haproxy_conv(const struct arg *args, struct sample *smp, void *pri static int da_haproxy_fetch(const struct arg *args, struct sample *smp, const char *kw, void *private) { - struct hdr_idx *hidx; - struct hdr_ctx hctx; - const struct http_msg *hmsg; da_evidence_t ev[DA_MAX_HEADERS]; da_deviceinfo_t devinfo; da_status_t status; + struct channel *chn; char vbuf[DA_MAX_HEADERS][1024] = {{ 0 }}; int i, nbh = 0; if (global_deviceatlas.daset == 0) { - return 1; + return 0; } - CHECK_HTTP_MESSAGE_FIRST((smp->strm ? &smp->strm->req : NULL)); - smp->data.type = SMP_T_STR; - - /** - * Here we go through the whole list of headers from start - * they will be filtered via the DeviceAtlas API itself - */ - hctx.idx = 0; - hidx = &smp->strm->txn->hdr_idx; - hmsg = &smp->strm->txn->req; - - while (http_find_next_header(ci_head(hmsg->chn), hidx, &hctx) == 1 && - nbh < DA_MAX_HEADERS) { - char *pval; - size_t vlen; - da_evidence_id_t evid = -1; - char hbuf[24] = { 0 }; - - /* The HTTP headers used by the DeviceAtlas API are not longer */ - if (hctx.del >= sizeof(hbuf) || hctx.del <= 0 || hctx.vlen <= 0) { - continue; + chn = (smp->strm ? &smp->strm->req : NULL); + /* HTX Mode check */ + if (smp->px->options2 & PR_O2_USE_HTX) { + struct htx_blk *blk; + struct htx *htx = smp_prefetch_htx(smp, chn, 1); + if (!htx) { + return 0; } - vlen = hctx.vlen; - memcpy(hbuf, hctx.line, hctx.del); - hbuf[hctx.del] = 0; - pval = (hctx.line + hctx.val); - - if (strcmp(hbuf, "Accept-Language") == 0) { - evid = da_atlas_accept_language_evidence_id(&global_deviceatlas. - atlas); - } else if (strcmp(hbuf, "Cookie") == 0) { - char *p, *eval; - size_t pl; - - eval = pval + hctx.vlen; - /** - * The cookie value, if it exists, is located between the current header's - * value position and the next one - */ - if (http_extract_cookie_value(pval, eval, global_deviceatlas.cookiename, - global_deviceatlas.cookienamelen, 1, &p, &pl) == NULL) { + i = 0; + for (blk = htx_get_head_blk(htx); nbh < DA_MAX_HEADERS && blk; blk = htx_get_next_blk(htx, blk)) { + size_t vlen; + char *pval; + da_evidence_id_t evid; + enum htx_blk_type type; + struct ist n, v; + char hbuf[24] = { 0 }; + char tval[1024] = { 0 }; + + type = htx_get_blk_type(blk); + + if (type == HTX_BLK_HDR) { + n = htx_get_blk_name(htx, blk); + v = htx_get_blk_value(htx, blk); + } else if (type == HTX_BLK_EOH) { + break; + } else { continue; } - vlen = (size_t)pl; - pval = p; - evid = da_atlas_clientprop_evidence_id(&global_deviceatlas.atlas); - } else { - evid = da_atlas_header_evidence_id(&global_deviceatlas.atlas, - hbuf); - } + /* The HTTP headers used by the DeviceAtlas API are not longer */ + if (n.len >= sizeof(hbuf)) { + continue; + } - if (evid == -1) { - continue; + memcpy(hbuf, n.ptr, n.len); + hbuf[n.len] = 0; + pval = v.ptr; + vlen = v.len; + evid = -1; + i = v.len > sizeof(tval) - 1 ? sizeof(tval) - 1 : v.len; + memcpy(tval, v.ptr, i); + tval[i] = 0; + pval = tval; + + if (strcasecmp(hbuf, "Accept-Language") == 0) { + evid = da_atlas_accept_language_evidence_id(&global_deviceatlas.atlas); + } else if (strcasecmp(hbuf, "Cookie") == 0) { + char *p, *eval; + size_t pl; + + eval = pval + vlen; + /** + * The cookie value, if it exists, is located between the current header's + * value position and the next one + */ + if (http_extract_cookie_value(pval, eval, global_deviceatlas.cookiename, + global_deviceatlas.cookienamelen, 1, &p, &pl) == NULL) { + continue; + } + + vlen -= global_deviceatlas.cookienamelen - 1; + pval = p; + evid = da_atlas_clientprop_evidence_id(&global_deviceatlas.atlas); + } else { + evid = da_atlas_header_evidence_id(&global_deviceatlas.atlas, hbuf); + } + + if (evid == -1) { + continue; + } + + i = vlen > sizeof(vbuf[nbh]) - 1 ? sizeof(vbuf[nbh]) - 1 : vlen; + memcpy(vbuf[nbh], pval, i); + vbuf[nbh][i] = 0; + ev[nbh].key = evid; + ev[nbh].value = vbuf[nbh]; + ++ nbh; } + } else { + struct hdr_idx *hidx; + struct hdr_ctx hctx; + const struct http_msg *hmsg; + CHECK_HTTP_MESSAGE_FIRST(chn); + smp->data.type = SMP_T_STR; + + /** + * Here we go through the whole list of headers from start + * they will be filtered via the DeviceAtlas API itself + */ + hctx.idx = 0; + hidx = &smp->strm->txn->hdr_idx; + hmsg = &smp->strm->txn->req; + + while (http_find_next_header(ci_head(hmsg->chn), hidx, &hctx) == 1 && + nbh < DA_MAX_HEADERS) { + char *pval; + size_t vlen; + da_evidence_id_t evid = -1; + char hbuf[24] = { 0 }; + + /* The HTTP headers used by the DeviceAtlas API are not longer */ + if (hctx.del >= sizeof(hbuf) || hctx.del <= 0 || hctx.vlen <= 0) { + continue; + } + + vlen = hctx.vlen; + memcpy(hbuf, hctx.line, hctx.del); + hbuf[hctx.del] = 0; + pval = (hctx.line + hctx.val); + + if (strcmp(hbuf, "Accept-Language") == 0) { + evid = da_atlas_accept_language_evidence_id(&global_deviceatlas. + atlas); + } else if (strcmp(hbuf, "Cookie") == 0) { + char *p, *eval; + size_t pl; + + eval = pval + hctx.vlen; + /** + * The cookie value, if it exists, is located between the current header's + * value position and the next one + */ + if (http_extract_cookie_value(pval, eval, global_deviceatlas.cookiename, + global_deviceatlas.cookienamelen, 1, &p, &pl) == NULL) { + continue; + } - i = vlen > sizeof(vbuf[nbh]) ? sizeof(vbuf[nbh]) : vlen; - memcpy(vbuf[nbh], pval, i - 1); - vbuf[nbh][i - 1] = 0; - ev[nbh].key = evid; - ev[nbh].value = vbuf[nbh]; - ev[nbh].value[vlen] = 0; - ++ nbh; + vlen = (size_t)pl; + pval = p; + evid = da_atlas_clientprop_evidence_id(&global_deviceatlas.atlas); + } else { + evid = da_atlas_header_evidence_id(&global_deviceatlas.atlas, + hbuf); + } + + if (evid == -1) { + continue; + } + + i = vlen > sizeof(vbuf[nbh]) ? sizeof(vbuf[nbh]) : vlen; + memcpy(vbuf[nbh], pval, i - 1); + vbuf[nbh][i - 1] = 0; + ev[nbh].key = evid; + ev[nbh].value = vbuf[nbh]; + ++ nbh; + } } status = da_searchv(&global_deviceatlas.atlas, &devinfo, @@ -372,10 +454,10 @@ static int da_haproxy_fetch(const struct arg *args, struct sample *smp, const ch static struct cfg_kw_list dacfg_kws = {{ }, { { CFG_GLOBAL, "deviceatlas-json-file", da_json_file }, - { CFG_GLOBAL, "deviceatlas-log-level", da_log_level }, - { CFG_GLOBAL, "deviceatlas-property-separator", da_property_separator }, - { CFG_GLOBAL, "deviceatlas-properties-cookie", da_properties_cookie }, - { 0, NULL, NULL }, + { CFG_GLOBAL, "deviceatlas-log-level", da_log_level }, + { CFG_GLOBAL, "deviceatlas-property-separator", da_property_separator }, + { CFG_GLOBAL, "deviceatlas-properties-cookie", da_properties_cookie }, + { 0, NULL, NULL }, }}; INITCALL1(STG_REGISTER, cfg_register_keywords, &dacfg_kws); @@ -383,7 +465,7 @@ INITCALL1(STG_REGISTER, cfg_register_keywords, &dacfg_kws); /* Note: must not be declared as its list will be overwritten */ static struct sample_fetch_kw_list fetch_kws = {ILH, { { "da-csv-fetch", da_haproxy_fetch, ARG12(1,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR), NULL, SMP_T_STR, SMP_USE_HRQHV }, - { NULL, NULL, 0, 0, 0 }, + { NULL, NULL, 0, 0, 0 }, }}; INITCALL1(STG_REGISTER, sample_register_fetches, &fetch_kws); @@ -391,7 +473,7 @@ INITCALL1(STG_REGISTER, sample_register_fetches, &fetch_kws); /* Note: must not be declared as its list will be overwritten */ static struct sample_conv_kw_list conv_kws = {ILH, { { "da-csv-conv", da_haproxy_conv, ARG12(1,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR), NULL, SMP_T_STR, SMP_T_STR }, - { NULL, NULL, 0, 0, 0 }, + { NULL, NULL, 0, 0, 0 }, }}; static void da_haproxy_register_build_options()