1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3 /* Monkey HTTP Server
4 * ==================
5 * Copyright 2001-2017 Eduardo Silva <eduardo@monkey.io>
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 #ifndef MK_HTTP_PARSER_H
21 #define MK_HTTP_PARSER_H
22
23 #define _GNU_SOURCE
24 #include <ctype.h>
25
26 #include <monkey/mk_core.h>
27 #include <monkey/mk_http.h>
28 #include <monkey/mk_http_internal.h>
29
30 /* General status */
31 #define MK_HTTP_PARSER_PENDING -10 /* cannot complete until more data arrives */
32 #define MK_HTTP_PARSER_ERROR -1 /* found an error when parsing the string */
33 #define MK_HTTP_PARSER_OK 0 /* parser OK, ready to go */
34
extractPixmaps(const QIcon & icon)35 /* Connection header values */
36 #define MK_HTTP_PARSER_CONN_EMPTY 0
37 #define MK_HTTP_PARSER_CONN_UNKNOWN -1
38 #define MK_HTTP_PARSER_CONN_KA 1
39 #define MK_HTTP_PARSER_CONN_CLOSE 2
40 #define MK_HTTP_PARSER_CONN_UPGRADE 4
41 #define MK_HTTP_PARSER_CONN_HTTP2_SE 8
42
43 /* Upgrades supported */
44 #define MK_HTTP_PARSER_UPGRADE_NONE 0
45 #define MK_HTTP_PARSER_UPGRADE_H2 1
46 #define MK_HTTP_PARSER_UPGRADE_H2C 2
47
48 #define MK_HEADER_EXTRA_SIZE 8
49
50 /* Request levels
51 * ==============
52 *
53 * 1. FIRST_LINE : Method, URI (+ QS) + Protocol version + CRLF
54 * 2. HEADERS (optional) : KEY, SEP, VALUE + CRLF
55 * 3. BODY (option) : data based on Content-Length or Chunked transfer encoding
56 */
57
58 enum {
59 REQ_LEVEL_FIRST = 1,
60 REQ_LEVEL_CONTINUE ,
61 REQ_LEVEL_HEADERS ,
62 REQ_LEVEL_END ,
63 REQ_LEVEL_BODY
64 };
65
66 /* Statuses per levels */
67 enum {
68 /* REQ_LEVEL_FIRST */
icon(IconType type) const69 MK_ST_REQ_METHOD = 1,
70 MK_ST_REQ_URI ,
71 MK_ST_REQ_QUERY_STRING ,
72 MK_ST_REQ_PROT_VERSION ,
73 MK_ST_FIRST_CONTINUE ,
74 MK_ST_FIRST_FINALIZING , /* LEVEL_FIRST finalize the request */
75 MK_ST_FIRST_COMPLETE ,
76
77 /* REQ_HEADERS */
78 MK_ST_HEADER_KEY ,
79 MK_ST_HEADER_SEP ,
80 MK_ST_HEADER_VAL_STARTS ,
81 MK_ST_HEADER_VALUE ,
82 MK_ST_HEADER_END ,
83 MK_ST_BLOCK_END
84 };
85
86 /* Known HTTP Methods */
87 enum mk_request_methods {
88 MK_METHOD_GET = 0,
89 MK_METHOD_POST ,
90 MK_METHOD_HEAD ,
91 MK_METHOD_PUT ,
92 MK_METHOD_DELETE ,
93 MK_METHOD_OPTIONS ,
94 MK_METHOD_SIZEOF ,
95 MK_METHOD_UNKNOWN
96 };
97
98 /*
99 * Define a list of known headers, they are used to perform headers
100 * lookups in the parser and further Monkey core.
101 */
102 enum mk_request_headers {
103 MK_HEADER_ACCEPT = 0,
104 MK_HEADER_ACCEPT_CHARSET ,
105 MK_HEADER_ACCEPT_ENCODING ,
106 MK_HEADER_ACCEPT_LANGUAGE ,
107 MK_HEADER_AUTHORIZATION ,
108 MK_HEADER_CACHE_CONTROL ,
109 MK_HEADER_COOKIE ,
110 MK_HEADER_CONNECTION ,
111 MK_HEADER_CONTENT_LENGTH ,
112 MK_HEADER_CONTENT_RANGE ,
113 MK_HEADER_CONTENT_TYPE ,
114 MK_HEADER_HOST ,
115 MK_HEADER_HTTP2_SETTINGS ,
116 MK_HEADER_IF_MODIFIED_SINCE ,
117 MK_HEADER_LAST_MODIFIED ,
118 MK_HEADER_LAST_MODIFIED_SINCE ,
119 MK_HEADER_RANGE ,
120 MK_HEADER_REFERER ,
121 MK_HEADER_UPGRADE ,
122 MK_HEADER_USER_AGENT ,
123 MK_HEADER_SIZEOF ,
124
125 /* used by the core for custom headers */
126 MK_HEADER_OTHER
127 };
128
129 /*
130 * Expected Header values that are used to take logic
131 * decision.
132 */
133 #define MK_CONN_KEEP_ALIVE "keep-alive"
134 #define MK_CONN_CLOSE "close"
135 #define MK_CONN_UPGRADE "upgrade"
136
137 /* HTTP Upgrade options available */
138 #define MK_UPGRADE_H2 "h2"
139 #define MK_UPGRADE_H2C "h2c"
140
141 struct mk_http_header {
142 /* The header type/name, e.g: MK_HEADER_CONTENT_LENGTH */
143 int type;
144
145 /* Reference the header Key name, e.g: 'Content-Lentth' */
146 mk_ptr_t key;
147
148 /* Reference the header Value, e/g: '123456' */
149 mk_ptr_t val;
150
151 /*
152 * Link to head list, it's used to reference this node and
153 * iterate it as a linked list
154 */
155 struct mk_list _head;
156 };
157
158 /* This structure is the 'Parser Context' */
159 struct mk_http_parser {
160 int i;
161 int level; /* request level */
162 int status; /* level status */
163 int next; /* something next after status ? */
164 int length;
165 int method;
166
167 /* lookup fields */
168 int start;
169 int end;
170 int chars;
171
172 /* it stores the numeric value of Content-Length header */
173 int header_host_port;
174
175 long int body_received;
176 long int header_content_length;
177
178 /*
179 * connection header value discovered: it can be set with
180 * values:
181 *
182 * MK_HTTP_PARSER_CONN_EMPTY : header not set
183 * MK_HTTP_PARSER_CONN_UNKNOWN: unexpected value
184 * MK_HTTP_PARSER_CONN_KA : keep-alive
185 * MK_HTTP_PARSER_CONN_CLOSE : close
186 */
187 int header_connection;
188
189 /* upgrade request: we suppport the following values:
190 *
191 * MK_HTTP_PARSER_UPGRADE_H2 : HTTP/2.0 over TLS
192 * MK_HTTP_PARSER_UPGRADE_H2C : HTTP/2.0 (plain TCP)
193 */
194 int header_upgrade;
195
196 /* probable current header, fly parsing */
197 int header_key;
198 int header_sep;
199 int header_val;
200 int header_min;
201 int header_max;
202 int headers_extra_count;
203
204 /* Known headers */
205 struct mk_http_header headers[MK_HEADER_SIZEOF];
206
207 /* Head of linked list for all headers found in the request */
208 int header_count;
209 struct mk_list header_list;
210
211 /* Extra headers */
212 struct mk_http_header headers_extra[MK_HEADER_EXTRA_SIZE];
213 };
214
215
216 #ifdef HTTP_STANDALONE
217
218 /* ANSI Colors */
219
220 #define ANSI_RESET "\033[0m"
221 #define ANSI_BOLD "\033[1m"
222
223 #define ANSI_CYAN "\033[36m"
224 #define ANSI_BOLD_CYAN ANSI_BOLD ANSI_CYAN
225 #define ANSI_MAGENTA "\033[35m"
226 #define ANSI_BOLD_MAGENTA ANSI_BOLD ANSI_MAGENTA
227 #define ANSI_RED "\033[31m"
228 #define ANSI_BOLD_RED ANSI_BOLD ANSI_RED
229 #define ANSI_YELLOW "\033[33m"
230 #define ANSI_BOLD_YELLOW ANSI_BOLD ANSI_YELLOW
231 #define ANSI_BLUE "\033[34m"
232 #define ANSI_BOLD_BLUE ANSI_BOLD ANSI_BLUE
233 #define ANSI_GREEN "\033[32m"
234 #define ANSI_BOLD_GREEN ANSI_BOLD ANSI_GREEN
235 #define ANSI_WHITE "\033[37m"
236 #define ANSI_BOLD_WHITE ANSI_BOLD ANSI_WHITE
237
238 #define TEST_OK 0
239 #define TEST_FAIL 1
240
241
242 static inline void p_field(struct mk_http_parser *req, char *buffer)
243 {
244 int i;
245
246 printf("'");
247 for (i = req->start; i < req->end; i++) {
248 printf("%c", buffer[i]);
249 }
250 printf("'");
251
252 }
253
254 static inline int eval_field(struct mk_http_parser *req, char *buffer)
255 {
256 if (req->level == REQ_LEVEL_FIRST) {
257 printf("[ \033[35mfirst level\033[0m ] ");
258 }
259 else {
260 printf("[ \033[36mheaders\033[0m ] ");
261 }
262
263 printf(" ");
264 switch (req->status) {
265 case MK_ST_REQ_METHOD:
266 printf("MK_ST_REQ_METHOD : ");
267 break;
268 case MK_ST_REQ_URI:
269 printf("MK_ST_REQ_URI : ");
270 break;
271 case MK_ST_REQ_QUERY_STRING:
272 printf("MK_ST_REQ_QUERY_STRING : ");
273 break;
274 case MK_ST_REQ_PROT_VERSION:
275 printf("MK_ST_REQ_PROT_VERSION : ");
276 break;
277 case MK_ST_HEADER_KEY:
278 printf("MK_ST_HEADER_KEY : ");
279 break;
280 case MK_ST_HEADER_VAL_STARTS:
281 printf("MK_ST_HEADER_VAL_STARTS: ");
282 break;
283 case MK_ST_HEADER_VALUE:
284 printf("MK_ST_HEADER_VALUE : ");
285 break;
286 case MK_ST_HEADER_END:
287 printf("MK_ST_HEADER_END : ");
288 break;
289 default:
290 printf("\033[31mUNKNOWN STATUS (%i)\033[0m : ", req->status);
291 break;
292 };
293
294
295 p_field(req, buffer);
296 printf("\n");
297
298 return 0;
299 }
300 #endif /* HTTP_STANDALONE */
301
302 #define mk_http_set_minor_version(c) \
303 if (c == '1') { \
304 req->protocol = MK_HTTP_PROTOCOL_11; \
305 } \
306 else if (c == '0') { \
307 req->protocol = MK_HTTP_PROTOCOL_10; \
308 } \
309 else { \
310 req->protocol = MK_HTTP_PROTOCOL_UNKNOWN; \
311 }
312
313
314 static inline void mk_http_parser_init(struct mk_http_parser *p)
315 {
316 memset(p, '\0', sizeof(struct mk_http_parser));
317
318 p->level = REQ_LEVEL_FIRST;
319 p->status = MK_ST_REQ_METHOD;
320 p->chars = -1;
321 p->method = -1;
322
323 /* init headers */
324 p->header_key = -1;
325 p->header_sep = -1;
326 p->header_val = -1;
327 p->header_min = -1;
328 p->header_max = -1;
329 p->header_content_length = -1;
330
331 /* init list header */
332 p->header_count = 0;
333 mk_list_init(&p->header_list);
334 }
335
336 static inline int mk_http_parser_more(struct mk_http_parser *p, int len)
337 {
338 if (abs(len - p->i) - 1 > 0) {
339 return MK_TRUE;
340 }
341
342 return MK_FALSE;
343 }
344
345 int mk_http_parser(struct mk_http_request *req, struct mk_http_parser *p,
346 char *buffer, int buf_len, struct mk_server *server);
347
348 #endif /* MK_HTTP_H */
349