diff options
Diffstat (limited to '')
-rw-r--r-- | src/nxt_http_parse.c | 595 |
1 files changed, 0 insertions, 595 deletions
diff --git a/src/nxt_http_parse.c b/src/nxt_http_parse.c deleted file mode 100644 index fbc2f73f..00000000 --- a/src/nxt_http_parse.c +++ /dev/null @@ -1,595 +0,0 @@ - -/* - * Copyright (C) Igor Sysoev - * Copyright (C) NGINX, Inc. - */ - -#include <nxt_main.h> - - -static nxt_int_t nxt_http_split_header_part(nxt_http_split_header_parse_t *shp, - u_char *start, u_char *end); -static nxt_int_t nxt_http_split_header_join(nxt_http_split_header_parse_t *shp); - - -nxt_int_t -nxt_http_status_parse(nxt_http_status_parse_t *sp, nxt_buf_mem_t *b) -{ - u_char ch, *p; - enum { - sw_start = 0, - sw_H, - sw_HT, - sw_HTT, - sw_HTTP, - sw_major_digit, - sw_dot, - sw_minor_digit, - sw_space_after_version, - sw_status_start, - sw_status_code, - sw_status_text, - sw_end, - } state; - - state = sp->state; - - for (p = b->pos; p < b->free; p++) { - - ch = *p; - - switch (state) { - - /* "HTTP/" */ - case sw_start: - if (nxt_fast_path(ch == 'H')) { - state = sw_H; - continue; - } - - return NXT_ERROR; - - case sw_H: - if (nxt_fast_path(ch == 'T')) { - state = sw_HT; - continue; - } - - return NXT_ERROR; - - case sw_HT: - if (nxt_fast_path(ch == 'T')) { - state = sw_HTT; - continue; - } - - return NXT_ERROR; - - case sw_HTT: - if (nxt_fast_path(ch == 'P')) { - state = sw_HTTP; - continue; - } - - return NXT_ERROR; - - case sw_HTTP: - if (nxt_fast_path(ch == '/')) { - state = sw_major_digit; - continue; - } - - return NXT_ERROR; - - /* - * Only HTTP/x.x format is tested because it - * is unlikely that other formats will appear. - */ - case sw_major_digit: - if (nxt_fast_path(ch >= '1' && ch <= '9')) { - sp->http_version = 10 * (ch - '0'); - state = sw_dot; - continue; - } - - return NXT_ERROR; - - case sw_dot: - if (nxt_fast_path(ch == '.')) { - state = sw_minor_digit; - continue; - } - - return NXT_ERROR; - - case sw_minor_digit: - if (nxt_fast_path(ch >= '0' && ch <= '9')) { - sp->http_version += ch - '0'; - state = sw_space_after_version; - continue; - } - - return NXT_ERROR; - - case sw_space_after_version: - if (nxt_fast_path(ch == ' ')) { - state = sw_status_start; - continue; - } - - return NXT_ERROR; - - case sw_status_start: - if (nxt_slow_path(ch == ' ')) { - continue; - } - - sp->start = p; - state = sw_status_code; - - /* Fall through. */ - - /* HTTP status code. */ - case sw_status_code: - if (nxt_fast_path(ch >= '0' && ch <= '9')) { - sp->code = sp->code * 10 + (ch - '0'); - continue; - } - - switch (ch) { - case ' ': - state = sw_status_text; - continue; - case '.': /* IIS may send 403.1, 403.2, etc. */ - state = sw_status_text; - continue; - case NXT_CR: - sp->end = p; - state = sw_end; - continue; - case NXT_LF: - sp->end = p; - goto done; - default: - return NXT_ERROR; - } - - /* Any text until end of line. */ - case sw_status_text: - switch (ch) { - case NXT_CR: - sp->end = p; - state = sw_end; - continue; - case NXT_LF: - sp->end = p; - goto done; - } - continue; - - /* End of status line. */ - case sw_end: - if (nxt_fast_path(ch == NXT_LF)) { - goto done; - } - - return NXT_ERROR; - } - } - - b->pos = p; - sp->state = state; - - return NXT_AGAIN; - -done: - - b->pos = p + 1; - - return NXT_OK; -} - - -nxt_int_t -nxt_http_header_parse(nxt_http_header_parse_t *hp, nxt_buf_mem_t *b) -{ - u_char c, ch, *p; - uint32_t hash; - enum { - sw_start = 0, - sw_name, - sw_space_before_value, - sw_value, - sw_space_after_value, - sw_ignore_line, - sw_almost_done, - sw_header_almost_done, - } state; - - static const u_char normal[256] nxt_aligned(64) = - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0-\0\0" "0123456789\0\0\0\0\0\0" - - /* These 64 bytes should reside in one cache line */ - "\0abcdefghijklmnopqrstuvwxyz\0\0\0\0\0" - "\0abcdefghijklmnopqrstuvwxyz\0\0\0\0\0" - - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; - - nxt_prefetch(&normal[0]); - nxt_prefetch(&normal[64]); - - state = hp->state; - hash = hp->header_hash; - - for (p = b->pos; p < b->free; p++) { - ch = *p; - - switch (state) { - - /* first char */ - case sw_start: - hp->header_name_start = p; - hp->invalid_header = 0; - - switch (ch) { - case NXT_CR: - hp->header_end = p; - state = sw_header_almost_done; - break; - case NXT_LF: - hp->header_end = p; - goto header_done; - default: - state = sw_name; - - c = normal[ch]; - - if (c) { - hash = nxt_djb_hash_add(NXT_DJB_HASH_INIT, c); - break; - } - - if (ch == '_') { - hash = nxt_djb_hash_add(NXT_DJB_HASH_INIT, ch); - hp->underscore = 1; - break; - } - - hp->invalid_header = 1; - break; - } - break; - - /* header name */ - case sw_name: - c = normal[ch]; - - if (c) { - hash = nxt_djb_hash_add(hash, c); - break; - } - - if (ch == ':') { - hp->header_name_end = p; - state = sw_space_before_value; - break; - } - - if (ch == NXT_CR) { - hp->header_name_end = p; - hp->header_start = p; - hp->header_end = p; - state = sw_almost_done; - break; - } - - if (ch == NXT_LF) { - hp->header_name_end = p; - hp->header_start = p; - hp->header_end = p; - goto done; - } - - if (ch == '_') { - hash = nxt_djb_hash_add(hash, ch); - hp->underscore = 1; - break; - } - - /* IIS may send the duplicate "HTTP/1.1 ..." lines */ - if (ch == '/' - && hp->upstream - && p - hp->header_name_start == 4 - && nxt_memcmp(hp->header_name_start, "HTTP", 4) == 0) - { - state = sw_ignore_line; - break; - } - - hp->invalid_header = 1; - break; - - /* space* before header value */ - case sw_space_before_value: - switch (ch) { - case ' ': - break; - case NXT_CR: - hp->header_start = p; - hp->header_end = p; - state = sw_almost_done; - break; - case NXT_LF: - hp->header_start = p; - hp->header_end = p; - goto done; - case '\0': - hp->invalid_header = 1; - /* Fall through. */ - default: - hp->header_start = p; - state = sw_value; - break; - } - break; - - /* header value */ - case sw_value: - switch (ch) { - case ' ': - hp->header_end = p; - state = sw_space_after_value; - break; - case NXT_CR: - hp->header_end = p; - state = sw_almost_done; - break; - case NXT_LF: - hp->header_end = p; - goto done; - case '\0': - hp->invalid_header = 1; - break; - } - break; - - /* space* before end of header line */ - case sw_space_after_value: - switch (ch) { - case ' ': - break; - case NXT_CR: - state = sw_almost_done; - break; - case NXT_LF: - goto done; - case '\0': - hp->invalid_header = 1; - /* Fall through. */ - default: - state = sw_value; - break; - } - break; - - /* ignore header line */ - case sw_ignore_line: - switch (ch) { - case NXT_LF: - state = sw_start; - break; - default: - break; - } - break; - - /* end of header line */ - case sw_almost_done: - switch (ch) { - case NXT_LF: - goto done; - case NXT_CR: - break; - default: - return NXT_DECLINED; - } - break; - - /* end of header */ - case sw_header_almost_done: - switch (ch) { - case NXT_LF: - goto header_done; - default: - return NXT_DECLINED; - } - } - } - - b->pos = p; - hp->state = state; - hp->header_hash = hash; - - return NXT_AGAIN; - -done: - - b->pos = p + 1; - hp->state = sw_start; - hp->header_hash = hash; - - return NXT_OK; - -header_done: - - b->pos = p + 1; - hp->state = sw_start; - - return NXT_DONE; -} - - -nxt_int_t -nxt_http_split_header_parse(nxt_http_split_header_parse_t *shp, - nxt_buf_mem_t *b) -{ - u_char *end; - nxt_int_t ret; - - if (shp->parts == NULL || nxt_array_is_empty(shp->parts)) { - - ret = nxt_http_header_parse(&shp->parse, b); - - if (nxt_fast_path(ret == NXT_OK)) { - return ret; - } - - if (nxt_fast_path(ret == NXT_AGAIN)) { - /* A buffer is over. */ - - if (shp->parse.state == 0) { - /* - * A previous parsed header line is - * over right on the end of the buffer. - */ - return ret; - } - /* - * Add the first header line part and return NXT_AGAIN on success. - */ - return nxt_http_split_header_part(shp, shp->parse.header_name_start, - b->pos); - } - - return ret; - } - - /* A header line is split in buffers. */ - - end = nxt_memchr(b->pos, NXT_LF, b->free - b->pos); - - if (end != NULL) { - - /* The last header line part found. */ - end++; - - ret = nxt_http_split_header_part(shp, b->pos, end); - - if (nxt_fast_path(ret != NXT_ERROR)) { - /* ret == NXT_AGAIN: success, mark the part if it were parsed. */ - b->pos = end; - - return nxt_http_split_header_join(shp); - } - - return ret; - } - - /* Add another header line part and return NXT_AGAIN on success. */ - - return nxt_http_split_header_part(shp, b->pos, b->free); -} - - -static nxt_int_t -nxt_http_split_header_part(nxt_http_split_header_parse_t *shp, u_char *start, - u_char *end) -{ - nxt_http_header_part_t *part; - - nxt_thread_log_debug("http source header part: \"%*s\"", - end - start, start); - - if (shp->parts == NULL) { - shp->parts = nxt_array_create(shp->mem_pool, 2, - sizeof(nxt_http_header_part_t)); - if (nxt_slow_path(shp->parts == NULL)) { - return NXT_ERROR; - } - } - - if (!nxt_array_is_empty(shp->parts)) { - - part = nxt_array_last(shp->parts); - - if (part->end == end) { - part->end = end; - return NXT_AGAIN; - } - } - - part = nxt_array_add(shp->parts); - - if (nxt_fast_path(part != NULL)) { - part->start = start; - part->end = end; - return NXT_AGAIN; - } - - return NXT_ERROR; -} - - -static nxt_int_t -nxt_http_split_header_join(nxt_http_split_header_parse_t *shp) -{ - u_char *p; - size_t size; - nxt_uint_t n; - nxt_buf_mem_t b; - nxt_http_header_part_t *part; - - part = shp->parts->elts; - n = shp->parts->nelts; - - if (n == 1) { - /* - * A header line was read by parts, but resides continuously in a - * stream source buffer, so use disposition in the original buffer. - */ - b.pos = part->start; - b.free = part->end; - - } else { - /* Join header line parts to store the header line and ot parse it. */ - - size = 0; - - do { - size += part->end - part->start; - part++; - n--; - } while (n != 0); - - p = nxt_mem_alloc(shp->mem_pool, size); - if (nxt_slow_path(p == NULL)) { - return NXT_ERROR; - } - - b.pos = p; - - part = shp->parts->elts; - n = shp->parts->nelts; - - do { - p = nxt_cpymem(p, part->start, part->end - part->start); - part++; - n--; - } while (n != 0); - - b.free = p; - } - - /* b.start and b.end are not required for parsing. */ - - nxt_array_reset(shp->parts); - - /* Reset a header parse state to the sw_start. */ - shp->parse.state = 0; - - return nxt_http_header_parse(&shp->parse, &b); -} |