static int parse_message_header(http_parser_t *parser) { int field_num; http_header_field_t *field; field_num = add_field(parser); field = &parser->req.fields[field_num]; field->valid = 0; parse_crlf(parser); field->name = parse_token(parser); if (!field) return 1; if (parse_char(parser, ':')) { free(field->name); return 1; } // optional while (parse_char(parser, ' ') == 0) ; field->value = parse_field_content(parser); if (!field->value) return 1; while (parse_char(parser, ' ') == 0) ; field->valid = 1; return 0; }
static char *parse_field_content(http_parser_t *parser) { char *start, *str, ch; start = parser->parse_ptr; do { if (parser->parse_ptr - parser->data >= parser->len) break; ch = *parser->parse_ptr; if (is_ctl(ch)) break; if (!parse_crlf(parser)) break; parser->parse_ptr++; } while (1); if (parser->parse_ptr - start == 0) return NULL; str = malloc(parser->parse_ptr - start + 1); ASSERT(str != NULL); strncpy(str, start, parser->parse_ptr - start); str[parser->parse_ptr - start] = '\0'; return str; }
// generic-message = start-line // *(message-header CRLF) // CRLF // [ message-body ] const char* parse_generic_message(unsigned char** p) { if (parse_start_line(p)) return ERR; while (0 != (char)**p) { if (parse_message_header(p)) break; if (parse_crlf(p)) return ERR; } if (parse_crlf(p)) return ERR; return parse_message_body(p); }
// Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF const char* parse_status_line(unsigned char** p) { if (parse_http_version(p)) return ERR; if (parse_space(p)) return ERR; if (parse_status_code(p)) return ERR; if (parse_space(p)) return ERR; if (parse_reason_phrase(p)) return ERR; return parse_crlf(p); }
// Request-Line = Method SP Request-URI SP HTTP-Version CRLF const char* parse_request_line(unsigned char** p) { if (parse_method(p)) return ERR; if (parse_space(p)) return ERR; if (parse_request_uri(p)) return ERR; if (parse_space(p)) return ERR; if (parse_http_version(p)) return ERR; return parse_crlf(p); }
http_request_t *parse_http_request(http_parser_t *parser, const char *data, size_t len) { if (!parser || !data || !len) return NULL; parser->data = data; parser->len = len; parser->parse_ptr = (char*)data; parse_method(parser); parse_char(parser, ' '); parse_absolute_path(parser); parse_params(parser); parse_char(parser, ' '); parse_http_version(parser); parse_crlf(parser); while (parse_message_header(parser) == 0) ; return &parser->req; }
// LWS = [*WSP CRLF] 1*WSP // LWS = [CRLF] 1*WSP const char* parse_lws(unsigned char **p) { unsigned char *ptmp = *p; int arr[3][4] = { {1, 1, 3, 3}, {2, 2, -1, -1}, {-1, 4, -1, 4} }; int line = 0, state = 0; do { if (!parse_wsp(p)) line = 0; else if (!parse_crlf(p)) line = 1; else line = 2; state = arr[line][state]; if (-1 == state) { *p = ptmp; return ERR; } } while (state != 4); return NULL; }