static int header_initial_cmp (Slrn_Header_Type **unsorted, Slrn_Header_Type **sorted) /*{{{*/ { return header_cmp(Sort_Functions, unsorted, sorted); }
static int header_thread_cmp (Slrn_Header_Type **unsorted, Slrn_Header_Type **sorted) /*{{{*/ { return header_cmp(Sort_Thread_Functions, unsorted, sorted); }
static inline int header_lookup(struct mk_http_parser *p, char *buffer) { int i; int len; int pos; long val; char *endptr; char *tmp; struct mk_http_header *header; struct mk_http_header *header_extra; struct row_entry *h; len = (p->header_sep - p->header_key); for (i = p->header_min; i <= p->header_max; i++) { h = &mk_headers_table[i]; /* Check string length first */ if (h->len != len) { continue; } if (header_cmp(h->name + 1, buffer + p->header_key + 1, len - 1) == 0) { /* We got a header match, register the header index */ header = &p->headers[i]; header->type = i; header->key.data = buffer + p->header_key; header->key.len = len; header->val.data = buffer + p->header_val; header->val.len = p->end - p->header_val; p->header_count++; mk_list_add(&header->_head, &p->header_list); if (i == MK_HEADER_HOST) { /* Handle a possible port number in the Host header */ int sep = str_searchr(header->val.data, ':', header->val.len); if (sep > 0) { int plen; short int port_size = 6; char port[port_size]; plen = header->val.len - sep - 1; if (plen <= 0 || plen >= port_size) { return -MK_CLIENT_BAD_REQUEST; } memcpy(&port, header->val.data + sep + 1, plen); port[plen] = '\0'; errno = 0; val = strtol(port, &endptr, 10); if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || (errno != 0 && val == 0)) { return -MK_CLIENT_BAD_REQUEST; } if (endptr == port || *endptr != '\0') { return -MK_CLIENT_BAD_REQUEST; } p->header_host_port = val; /* Re-set the Host header value without port */ header->val.len = sep; } } else if (i == MK_HEADER_CONTENT_LENGTH) { errno = 0; val = strtol(header->val.data, &endptr, 10); if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || (errno != 0 && val == 0)) { return -MK_CLIENT_REQUEST_ENTITY_TOO_LARGE; } if (endptr == header->val.data) { return -1; } if (val < 0) { return -1; } p->header_content_length = val; } else if (i == MK_HEADER_CONNECTION) { /* Check Connection: Keep-Alive */ if (header->val.len == sizeof(MK_CONN_KEEP_ALIVE) - 1) { if (header_cmp(MK_CONN_KEEP_ALIVE, header->val.data, header->val.len ) == 0) { p->header_connection = MK_HTTP_PARSER_CONN_KA; } } /* Check Connection: Close */ else if (header->val.len == sizeof(MK_CONN_CLOSE) -1) { if (header_cmp(MK_CONN_CLOSE, header->val.data, header->val.len) == 0) { p->header_connection = MK_HTTP_PARSER_CONN_CLOSE; } } else { p->header_connection = MK_HTTP_PARSER_CONN_UNKNOWN; /* Try to find some known values */ /* Connection: upgrade */ pos = mk_string_search_n(header->val.data, "Upgrade", MK_STR_INSENSITIVE, header->val.len); if (pos >= 0) { p->header_connection = MK_HTTP_PARSER_CONN_UPGRADE; } /* Connection: HTTP2-Settings */ pos = mk_string_search_n(header->val.data, "HTTP2-Settings", MK_STR_INSENSITIVE, header->val.len); if (pos >= 0) { p->header_connection |= MK_HTTP_PARSER_CONN_HTTP2_SE; } } } else if (i == MK_HEADER_UPGRADE) { if (header_cmp(MK_UPGRADE_H2C, header->val.data, header->val.len) == 0) { p->header_upgrade = MK_HTTP_PARSER_UPGRADE_H2C; } } return 0; } } /* * The header_lookup did not match any known header, so we register this * entry into the headers_extra array. */ if (p->headers_extra_count < MK_HEADER_EXTRA_SIZE) { header_extra = &p->headers_extra[p->headers_extra_count]; header_extra->key.data = tmp = (buffer + p->header_key); header_extra->key.len = len; /* Transform the header key string to lowercase */ for (i = 0; i < len; i++) { tmp[i] = tolower(tmp[i]); } header_extra->val.data = buffer + p->header_val; header_extra->val.len = p->end - p->header_val; p->headers_extra_count++; p->header_count++; mk_list_add(&header_extra->_head, &p->header_list); return 0; } /* * Header is unknown and we cannot store it on our extra headers * list as it's already full. Request is too large. */ return -MK_CLIENT_REQUEST_ENTITY_TOO_LARGE; }