Skip to content

Commit

Permalink
HTTP/2: add header name tracking into the headers' compare procedure (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
aleksostapenko committed Mar 1, 2020
1 parent 2d7bb75 commit b5e71ac
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 125 deletions.
3 changes: 1 addition & 2 deletions tempesta_fw/hpack.c
Original file line number Diff line number Diff line change
Expand Up @@ -1822,8 +1822,7 @@ do { \
for (; i < h_mods->sz; ++i) {
TfwHdrModsDesc *d = &h_mods->hdrs[i];

if (!__hdr_name_cmp(&dc_iter->hdr_data,
TFW_STR_CHUNK(d->hdr, 0)))
if (!__hdr_name_cmp(&dc_iter->hdr_data, d->hdr))
{
dc_iter->desc = d;
break;
Expand Down
20 changes: 2 additions & 18 deletions tempesta_fw/http.c
Original file line number Diff line number Diff line change
Expand Up @@ -3104,7 +3104,7 @@ __h2_req_hdrs(TfwHttpReq *req, const TfwStr *hdr, unsigned int hid, bool append)
}
}
else {
hid = __h2_hdr_lookup(hm, TFW_STR_CHUNK(hdr, 0));
hid = __h2_hdr_lookup(hm, hdr);
if (hid == ht->off && !s_val)
/*
* The raw header not found, and there is nothing
Expand Down Expand Up @@ -4035,8 +4035,7 @@ tfw_h2_resp_next_hdr(TfwHttpResp *resp, const TfwHdrMods *h_mods)

if ((hid < TFW_HTTP_HDR_RAW && hid == desc->hid)
|| (hid >= TFW_HTTP_HDR_RAW
&& !__hdr_name_cmp(tgt,
TFW_STR_CHUNK(desc->hdr, 0))))
&& !__hdr_name_cmp(tgt, desc->hdr)))
{
f_desc = desc;
break;
Expand Down Expand Up @@ -5870,21 +5869,6 @@ tfw_http_req_key_calc(TfwHttpReq *req)
}
EXPORT_SYMBOL(tfw_http_req_key_calc);

TfwHdrModsDesc *
tfw_http_find_desc(const TfwStr *hdr, const TfwHdrMods *h_mods)
{
int i;

for (i = 0; i < h_mods->sz; ++i) {
TfwHdrModsDesc *desc = &h_mods->hdrs[i];

if (!__hdr_name_cmp(hdr, TFW_STR_CHUNK(desc->hdr, 0)))
return desc;
}

return NULL;
}

static TfwConnHooks http_conn_hooks = {
.conn_init = tfw_http_conn_init,
.conn_repair = tfw_http_conn_repair,
Expand Down
1 change: 0 additions & 1 deletion tempesta_fw/http.h
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,5 @@ unsigned long tfw_http_hdr_split(TfwStr *hdr, TfwStr *name_out, TfwStr *val_out,
bool inplace);
unsigned long tfw_h2_hdr_size(unsigned long n_len, unsigned long v_len,
unsigned short st_index);
TfwHdrModsDesc *tfw_http_find_desc(const TfwStr *hdr, const TfwHdrMods *h_mods);

#endif /* __TFW_HTTP_H__ */
120 changes: 47 additions & 73 deletions tempesta_fw/http_msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,35 +260,6 @@ __http_msg_hdr_val(TfwStr *hdr, unsigned id, TfwStr *val, bool client)
}
EXPORT_SYMBOL(__http_msg_hdr_val);

void
__h2_msg_hdr_name(TfwStr *hdr, TfwStr *out_name)
{
const TfwStr *c, *end;

if (unlikely(TFW_STR_EMPTY(hdr))) {
TFW_STR_INIT(out_name);
return;
}

BUG_ON(TFW_STR_DUP(hdr));
BUG_ON(TFW_STR_EMPTY(hdr));

*out_name = *hdr;

if (unlikely(TFW_STR_PLAIN(hdr))) {
WARN_ON_ONCE(hdr->flags & TFW_STR_HDR_VALUE);
return;
}

TFW_STR_FOR_EACH_CHUNK(c, hdr, end) {
if (c->flags & TFW_STR_HDR_VALUE) {
out_name->len -= c->len;
out_name->nchunks--;
}
}
}
EXPORT_SYMBOL(__h2_msg_hdr_name);

void
__h2_msg_hdr_val(TfwStr *hdr, TfwStr *out_val)
{
Expand Down Expand Up @@ -380,33 +351,36 @@ __hdr_lookup(TfwHttpMsg *hm, const TfwStr *hdr)
}

/**
* Special procedure comparing specified name against the header in HTTP/2
* or HTTP/1.1 format.
* Special procedure comparing the name or HPACK static index of @cmp_hdr (can
* be in HTTP/2 or HTTP/1.1 format) against the header @hdr which also can be
* in HTTP/2 or HTTP/1.1 format.
*/
int
__hdr_name_cmp(const TfwStr *hdr, const TfwStr *name)
bool
__hdr_name_cmp(const TfwStr *hdr, const TfwStr *cmp_hdr)
{
long n;
int i1, i2, off1, off2;
const TfwStr *c1, *c2;

BUG_ON(hdr->flags & TFW_STR_DUPLICATE);
BUG_ON(!name->len);
BUG_ON(!cmp_hdr->len);

if (cmp_hdr->hpack_idx && cmp_hdr->hpack_idx == hdr->hpack_idx)
return 0;

if (unlikely(!hdr->len))
return -name->len;
return 1;

i1 = i2 = 0;
off1 = off2 = 0;
n = min(hdr->len, name->len);
n = min(hdr->len, cmp_hdr->len);
c1 = TFW_STR_CHUNK(hdr, 0);
c2 = TFW_STR_CHUNK(name, 0);
c2 = TFW_STR_CHUNK(cmp_hdr, 0);
while (n) {
int cn = min(c1->len - off1, c2->len - off2);
int r = tfw_cstricmp(c1->data + off1,
c2->data + off2, cn);
if (r)
return r;

if (tfw_cstricmp(c1->data + off1, c2->data + off2, cn))
return 1;

n -= cn;
if (cn == c1->len - off1) {
Expand All @@ -419,36 +393,44 @@ __hdr_name_cmp(const TfwStr *hdr, const TfwStr *name)
if (cn == c2->len - off2) {
off2 = 0;
++i2;
c2 = TFW_STR_CHUNK(name, i2);
c2 = TFW_STR_CHUNK(cmp_hdr, i2);
} else {
off2 += cn;
}
BUG_ON(n && (!c1 || !c2));
}

/* Only name is contained in the header. */
if (hdr->len == name->len)
return 0;
BUG_ON(n && (!c1 || !c2));

if (hdr->len > name->len) {
/*
* If the header is of HTTP/2 format, the end of name must match
* the end of the chunk, and the following value must have
* appropriate flag.
* Regardless of the header format (HTTP/2 or HTTP/1.1), the end
* of the name must match the end of the chunk, and the following
* chunk must contain value with appropriate flag (or it must
* contain just a single colon in case of HTTP/1.1-header).
*/
if (!off1
&& (c1->flags & TFW_STR_HDR_VALUE)
&& !(TFW_STR_CHUNK(hdr, i1 - 1)->flags & TFW_STR_HDR_VALUE))
return 0;
/*
* If this is the HTTP/1.1-format header, the value must begin
* after the colon.
*/
if (*(c1->data + off1) == ':')
return 0;
if (!off2) {
const TfwStr *prev_c1;
/*
* If @c2 or @c1 is NULL, then only name is contained in
* the @cmp_hdr or @hdr respectively.
*/
if (c2
&& !(c2->flags & TFW_STR_HDR_VALUE)
&& *c2->data != ':')
continue;

prev_c1 = TFW_STR_CHUNK(hdr, i1 - 1);

if (!off1
&& !(prev_c1->flags & TFW_STR_HDR_VALUE)
&& (!c1
|| c1->flags & TFW_STR_HDR_VALUE
|| *c1->data == ':'))
return 0;

return 1;
}
}

return (long)hdr->len - (long)name->len;
return 1;
}

/**
Expand All @@ -457,7 +439,7 @@ __hdr_name_cmp(const TfwStr *hdr, const TfwStr *name)
* headers in HTTP/2 or HTTP/1.1 format.
*/
int
__h2_hdr_lookup(TfwHttpMsg *hm, const TfwStr *h_name)
__h2_hdr_lookup(TfwHttpMsg *hm, const TfwStr *hdr)
{
unsigned int id;
TfwHttpHdrTbl *ht = hm->h_tbl;
Expand All @@ -470,7 +452,7 @@ __h2_hdr_lookup(TfwHttpMsg *hm, const TfwStr *h_name)
*/
if (h->flags & TFW_STR_DUPLICATE)
h = TFW_STR_CHUNK(h, 0);
if (!__hdr_name_cmp(h, h_name))
if (!__hdr_name_cmp(h, hdr))
break;
}

Expand Down Expand Up @@ -548,15 +530,7 @@ tfw_http_msg_hdr_close(TfwHttpMsg *hm)
* Both the headers, the new one and existing one, can already be
* compound.
*/
if (TFW_MSG_H2(hm)) {
TfwStr h_name;

__h2_msg_hdr_name(&parser->hdr, &h_name);
id = __h2_hdr_lookup(hm, &h_name);
}
else {
id = __hdr_lookup(hm, &parser->hdr);
}
id = __h2_hdr_lookup(hm, &parser->hdr);

/* Allocate some more room if not enough to store the header. */
if (unlikely(id == ht->size)) {
Expand Down
5 changes: 2 additions & 3 deletions tempesta_fw/http_msg.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ __tfw_http_msg_set_str_data(TfwStr *str, void *data, struct sk_buff *skb)
__tfw_http_msg_set_str_data(str, data, \
ss_skb_peek_tail(&hm->msg.skb_head))

void __h2_msg_hdr_name(TfwStr *hdr, TfwStr *out_name);
void __h2_msg_hdr_val(TfwStr *hdr, TfwStr *out_val);
void __http_msg_hdr_val(TfwStr *hdr, unsigned id, TfwStr *val, bool client);

Expand Down Expand Up @@ -180,8 +179,8 @@ int tfw_http_msg_grow_hdr_tbl(TfwHttpMsg *hm);
void tfw_http_msg_free(TfwHttpMsg *m);
int tfw_http_msg_expand_data(TfwMsgIter *it, struct sk_buff **skb_head,
const TfwStr *src, unsigned int *start_off);
int __hdr_name_cmp(const TfwStr *hdr, const TfwStr *name);
int __h2_hdr_lookup(TfwHttpMsg *hm, const TfwStr *h_name);
int __hdr_name_cmp(const TfwStr *hdr, const TfwStr *cmp_hdr);
int __h2_hdr_lookup(TfwHttpMsg *hm, const TfwStr *hdr);
int tfw_h2_msg_rewrite_data(TfwHttpTransIter *mit, const TfwStr *str,
const char *stop);

Expand Down
Loading

0 comments on commit b5e71ac

Please sign in to comment.