htx_truncate(htx, data_ofs);
return -1;
}
-
-/* Takes an H2 headers list <list> terminated by a name being <NULL,0> and emits
- * the equivalent HTX trailers blocks. The output contents are emitted in <htx>,
- * and a positive value is returned if some bytes were emitted. In case of
- * error, a negative error code is returned. The caller must have verified that
- * the message in the buffer is compatible with receipt of trailers.
- *
- * The headers list <list> must be composed of :
- * - n.name != NULL, n.len > 0 : literal header name
- * - n.name == NULL, n.len > 0 : indexed pseudo header name number <n.len>
- * among H2_PHDR_IDX_* (illegal here)
- * - n.name ignored, n.len == 0 : end of list
- * - in all cases except the end of list, v.name and v.len must designate a
- * valid value.
- */
-int h2_make_htx_trailers(struct http_hdr *list, struct htx *htx)
-{
- uint32_t data_ofs = htx->data; /* used to rollback on error */
- const char *ctl;
- struct ist v;
- uint32_t idx;
- int i;
-
- for (idx = 0; list[idx].n.len != 0; idx++) {
- if (!isttest(list[idx].n)) {
- /* This is an indexed pseudo-header (RFC7540#8.1.2.1) */
- goto fail;
- }
-
- /* RFC7540#8.1.2: upper case not allowed in header field names.
- * #10.3: header names must be valid (i.e. match a token). This
- * also catches pseudo-headers which are forbidden in trailers.
- */
- for (i = 0; i < list[idx].n.len; i++)
- if ((uint8_t)(list[idx].n.ptr[i] - 'A') <= 'Z' - 'A' || !HTTP_IS_TOKEN(list[idx].n.ptr[i]))
- goto fail;
-
- /* these ones are forbidden in trailers (RFC7540#8.1.2.2) */
- if (isteq(list[idx].n, ist("host")) ||
- isteq(list[idx].n, ist("content-length")) ||
- isteq(list[idx].n, ist("connection")) ||
- isteq(list[idx].n, ist("proxy-connection")) ||
- isteq(list[idx].n, ist("keep-alive")) ||
- isteq(list[idx].n, ist("upgrade")) ||
- isteq(list[idx].n, ist("te")) ||
- isteq(list[idx].n, ist("transfer-encoding")))
- goto fail;
-
- /* RFC7540#10.3: intermediaries forwarding to HTTP/1 must take care of
- * rejecting NUL, CR and LF characters.
- */
- ctl = ist_find_ctl(list[idx].v);
- if (unlikely(ctl) && http_header_has_forbidden_char(list[idx].v, ctl))
- goto fail;
-
- /* trim leading/trailing LWS as per RC9113#8.2.1 */
- for (v = list[idx].v; v.len; v.len--) {
- if (unlikely(HTTP_IS_LWS(*v.ptr)))
- v.ptr++;
- else if (!unlikely(HTTP_IS_LWS(v.ptr[v.len - 1])))
- break;
- }
-
- if (!htx_add_trailer(htx, list[idx].n, v))
- goto fail;
- }
-
- /* Check the number of trailers against "tune.http.maxhdr" value before adding EOT block */
- if (idx > global.tune.max_http_hdr)
- goto fail;
-
- if (!htx_add_endof(htx, HTX_BLK_EOT))
- goto fail;
-
- return 1;
-
- fail:
- /* Rollback the partial conversion. Note that a pointer on the tail
- * block cannot be used for this because it encodes a block position
- * and adding blocks may compact the block table, so rely on the
- * amount of data that was present on entry instead.
- */
- htx_truncate(htx, data_ofs);
- return -1;
-}