Line data Source code
1 : /*
2 : START OF LICENSE STUB
3 : DeDOS: Declarative Dispersion-Oriented Software
4 : Copyright (C) 2017 University of Pennsylvania, Georgetown University
5 :
6 : This program is free software: you can redistribute it and/or modify
7 : it under the terms of the GNU General Public License as published by
8 : the Free Software Foundation, either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : GNU General Public License for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>.
18 : END OF LICENSE STUB
19 : */
20 : #include "webserver/connection-handler.h"
21 : #include "logging.h"
22 :
23 : #ifdef __GNUC__
24 : #define UNUSED __attribute__ ((unused))
25 : #else
26 : #define UNUSED
27 : #endif
28 :
29 144 : static int url_callback(http_parser *parser, const char *at, size_t length) {
30 144 : struct parser_state *state = parser->data;
31 144 : strncpy(&state->url[state->url_len], at, length);
32 144 : state->url[state->url_len + length] = '\0';
33 144 : state->url_len += length;
34 144 : log(LOG_HTTP_PARSING, "Got URL: %s", state->url);
35 144 : return 0;
36 : }
37 :
38 140 : static int headers_complete_callback(http_parser *parser) {
39 140 : struct parser_state *state = parser->data;
40 140 : state->headers_complete = 1;
41 140 : log(LOG_HTTP_PARSING, "Got end of headers");
42 140 : return 0;
43 : }
44 :
45 858 : static int header_field_or_value_callback(http_parser UNUSED *parser,
46 : const char UNUSED *at,
47 : size_t UNUSED length) {
48 : #if LOG_HTTP_PARSING
49 : char cpy[length+1];
50 : strncpy(cpy, at, length);
51 : cpy[length] = '\0'
52 : log(LOG_HTTP_PARSING, "Got header field %s", cpy);
53 : #endif
54 858 : return 0;
55 : }
56 :
57 :
58 144 : void init_parser_state(struct parser_state *state) {
59 144 : memset(state, 0, sizeof(*state));
60 144 : state->settings.on_url = url_callback;
61 144 : state->settings.on_header_field = header_field_or_value_callback;
62 144 : state->settings.on_header_value = header_field_or_value_callback;
63 144 : state->settings.on_headers_complete = headers_complete_callback;
64 144 : http_parser_init(&state->parser, HTTP_REQUEST);
65 144 : state->parser.data = (void*)state;
66 144 : }
67 :
68 144 : int parse_http(struct parser_state *state, char *buf, ssize_t bytes) {
69 144 : if (state == NULL) {
70 0 : log_error("Cannot handle connection with NULL state");
71 0 : return WS_ERROR;
72 : }
73 :
74 144 : if (state->headers_complete) {
75 0 : log_warn("Parsing even though header is already complete");
76 : }
77 :
78 144 : size_t nparsed = http_parser_execute(&state->parser, &state->settings,
79 : buf, bytes);
80 :
81 144 : if (nparsed != bytes) {
82 1 : buf[bytes] = '\0';
83 1 : log_error("Error parsing HTTP request %s (rcvd: %d, parsed: %d)",
84 : buf, (int)bytes, (int)nparsed);
85 1 : return WS_ERROR;
86 : }
87 :
88 143 : return state->headers_complete && state->url_len ? WS_COMPLETE : WS_INCOMPLETE_READ;
89 : }
90 :
|