ry / libebb
- Source
- Commits
- Network (5)
- Issues (0)
- Downloads (0)
- Wiki (1)
- Graphs
-
Tree:
7f734d3
libebb / ebb_request_parser.rl
| 117aecd9 » | ry | 2008-07-21 | 1 | /* HTTP/1.1 Parser | |
| 2 | * Copyright 2008 ryah dahl, ry at tiny clouds punkt org | ||||
| 3 | * | ||||
| 4 | * Based on Zed Shaw's parser for Mongrel. | ||||
| 5 | * Copyright (c) 2005 Zed A. Shaw | ||||
| 6 | * | ||||
| 7 | * This software may be distributed under the "MIT" license included in the | ||||
| 8 | * README | ||||
| 9 | */ | ||||
| 4a32be1d » | ry | 2008-07-21 | 10 | #include "ebb_request_parser.h" | |
| a2556cd6 » | ry | 2008-07-15 | 11 | ||
| db036d99 » | ry | 2008-07-13 | 12 | #include <stdio.h> | |
| 13 | #include <assert.h> | ||||
| 8b611115 » | ry | 2008-07-17 | 14 | ||
| 15 | #define TRUE 1 | ||||
| 16 | #define FALSE 0 | ||||
| 17 | #define MIN(a,b) (a < b ? a : b) | ||||
| db036d99 » | ry | 2008-07-13 | 18 | ||
| 19 | #define REMAINING (pe - p) | ||||
| c3aab561 » | ry | 2008-07-15 | 20 | #define CURRENT (parser->current_request) | |
| 21 | #define CONTENT_LENGTH (parser->current_request->content_length) | ||||
| 22 | |||||
| 3177fb5d » | ry | 2008-07-18 | 23 | #define LEN(FROM) (p - parser->FROM##_mark) | |
| e33da647 » | ry | 2008-07-31 | 24 | #define CALLBACK(FOR) \ | |
| 25 | if(parser->FOR##_mark && CURRENT->on_##FOR) { \ | ||||
| 26 | CURRENT->on_##FOR( CURRENT \ | ||||
| 27 | , parser->FOR##_mark \ | ||||
| 28 | , p - parser->FOR##_mark \ | ||||
| 29 | ); \ | ||||
| 3177fb5d » | ry | 2008-07-18 | 30 | } | |
| e33da647 » | ry | 2008-07-31 | 31 | #define HEADER_CALLBACK(FOR) \ | |
| 32 | if(parser->FOR##_mark && CURRENT->on_##FOR) { \ | ||||
| 33 | CURRENT->on_##FOR( CURRENT \ | ||||
| 34 | , parser->FOR##_mark \ | ||||
| 35 | , p - parser->FOR##_mark \ | ||||
| 36 | , CURRENT->number_of_headers \ | ||||
| 37 | ); \ | ||||
| 3177fb5d » | ry | 2008-07-18 | 38 | } | |
| e33da647 » | ry | 2008-07-31 | 39 | #define END_REQUEST \ | |
| 40 | if(CURRENT->on_complete) \ | ||||
| 41 | CURRENT->on_complete(CURRENT); \ | ||||
| e3d05885 » | ry | 2008-07-21 | 42 | CURRENT = NULL; | |
| db036d99 » | ry | 2008-07-13 | 43 | ||
| 44 | %%{ | ||||
| a1433934 » | ry | 2008-07-16 | 45 | machine ebb_request_parser; | |
| db036d99 » | ry | 2008-07-13 | 46 | ||
| 3177fb5d » | ry | 2008-07-18 | 47 | action mark_header_field { parser->header_field_mark = p; } | |
| 48 | action mark_header_value { parser->header_value_mark = p; } | ||||
| 49 | action mark_fragment { parser->fragment_mark = p; } | ||||
| 50 | action mark_query_string { parser->query_string_mark = p; } | ||||
| e33da647 » | ry | 2008-07-31 | 51 | action mark_request_path { parser->path_mark = p; } | |
| 52 | action mark_request_uri { parser->uri_mark = p; } | ||||
| db036d99 » | ry | 2008-07-13 | 53 | ||
| 123287d8 » | ry | 2008-07-20 | 54 | action method_copy { CURRENT->method = EBB_COPY; } | |
| 55 | action method_delete { CURRENT->method = EBB_DELETE; } | ||||
| 56 | action method_get { CURRENT->method = EBB_GET; } | ||||
| 57 | action method_head { CURRENT->method = EBB_HEAD; } | ||||
| 58 | action method_lock { CURRENT->method = EBB_LOCK; } | ||||
| 59 | action method_mkcol { CURRENT->method = EBB_MKCOL; } | ||||
| 60 | action method_move { CURRENT->method = EBB_MOVE; } | ||||
| 61 | action method_options { CURRENT->method = EBB_OPTIONS; } | ||||
| 62 | action method_post { CURRENT->method = EBB_POST; } | ||||
| 63 | action method_propfind { CURRENT->method = EBB_PROPFIND; } | ||||
| 64 | action method_proppatch { CURRENT->method = EBB_PROPPATCH; } | ||||
| 65 | action method_put { CURRENT->method = EBB_PUT; } | ||||
| 66 | action method_trace { CURRENT->method = EBB_TRACE; } | ||||
| 67 | action method_unlock { CURRENT->method = EBB_UNLOCK; } | ||||
| 8a85dac7 » | ry | 2008-07-19 | 68 | ||
| db036d99 » | ry | 2008-07-13 | 69 | action write_field { | |
| c3aab561 » | ry | 2008-07-15 | 70 | //printf("write_field!\n"); | |
| 3177fb5d » | ry | 2008-07-18 | 71 | HEADER_CALLBACK(header_field); | |
| 72 | parser->header_field_mark = NULL; | ||||
| db036d99 » | ry | 2008-07-13 | 73 | } | |
| 74 | |||||
| 75 | action write_value { | ||||
| c3aab561 » | ry | 2008-07-15 | 76 | //printf("write_value!\n"); | |
| 3177fb5d » | ry | 2008-07-18 | 77 | HEADER_CALLBACK(header_value); | |
| 78 | parser->header_value_mark = NULL; | ||||
| 79 | } | ||||
| 80 | |||||
| b1609204 » | ry | 2008-07-14 | 81 | action request_uri { | |
| 82 | //printf("request uri\n"); | ||||
| e33da647 » | ry | 2008-07-31 | 83 | CALLBACK(uri); | |
| 84 | parser->uri_mark = NULL; | ||||
| b1609204 » | ry | 2008-07-14 | 85 | } | |
| 86 | |||||
| 87 | action fragment { | ||||
| 88 | //printf("fragment\n"); | ||||
| 3177fb5d » | ry | 2008-07-18 | 89 | CALLBACK(fragment); | |
| 90 | parser->fragment_mark = NULL; | ||||
| b1609204 » | ry | 2008-07-14 | 91 | } | |
| 92 | |||||
| 93 | action query_string { | ||||
| 94 | //printf("query string\n"); | ||||
| 3177fb5d » | ry | 2008-07-18 | 95 | CALLBACK(query_string); | |
| 96 | parser->query_string_mark = NULL; | ||||
| b1609204 » | ry | 2008-07-14 | 97 | } | |
| 98 | |||||
| 99 | action request_path { | ||||
| 100 | //printf("request path\n"); | ||||
| e33da647 » | ry | 2008-07-31 | 101 | CALLBACK(path); | |
| 102 | parser->path_mark = NULL; | ||||
| b1609204 » | ry | 2008-07-14 | 103 | } | |
| 104 | |||||
| 5a49acff » | ry | 2008-07-13 | 105 | action content_length { | |
| b55e1255 » | ry | 2008-07-15 | 106 | //printf("content_length!\n"); | |
| c3aab561 » | ry | 2008-07-15 | 107 | CURRENT->content_length *= 10; | |
| 108 | CURRENT->content_length += *p - '0'; | ||||
| 5a49acff » | ry | 2008-07-13 | 109 | } | |
| 110 | |||||
| 0ca30982 » | ry | 2008-07-23 | 111 | action use_identity_encoding { CURRENT->transfer_encoding = EBB_IDENTITY; } | |
| 112 | action use_chunked_encoding { CURRENT->transfer_encoding = EBB_CHUNKED; } | ||||
| b1609204 » | ry | 2008-07-14 | 113 | ||
| 0ca30982 » | ry | 2008-07-23 | 114 | action set_keep_alive { CURRENT->keep_alive = TRUE; } | |
| 115 | action set_not_keep_alive { CURRENT->keep_alive = FALSE; } | ||||
| 5a49acff » | ry | 2008-07-13 | 116 | ||
| f8b67637 » | ry | 2008-07-19 | 117 | action multipart_boundary { | |
| 118 | if(CURRENT->multipart_boundary_len == EBB_MAX_MULTIPART_BOUNDARY_LEN) { | ||||
| 119 | cs = -1; | ||||
| 120 | fbreak; | ||||
| 121 | } | ||||
| 122 | CURRENT->multipart_boundary[CURRENT->multipart_boundary_len++] = *p; | ||||
| 123 | } | ||||
| 124 | |||||
| a2556cd6 » | ry | 2008-07-15 | 125 | action expect_continue { | |
| 126 | CURRENT->expect_continue = TRUE; | ||||
| 127 | } | ||||
| 128 | |||||
| 5a49acff » | ry | 2008-07-13 | 129 | action trailer { | |
| b55e1255 » | ry | 2008-07-15 | 130 | //printf("trailer\n"); | |
| 5a49acff » | ry | 2008-07-13 | 131 | /* not implemenetd yet. (do requests even have trailing headers?) */ | |
| 132 | } | ||||
| 133 | |||||
| 0ca02506 » | ry | 2008-07-14 | 134 | action version_major { | |
| c3aab561 » | ry | 2008-07-15 | 135 | CURRENT->version_major *= 10; | |
| 136 | CURRENT->version_major += *p - '0'; | ||||
| 0ca02506 » | ry | 2008-07-14 | 137 | } | |
| 138 | |||||
| 139 | action version_minor { | ||||
| c3aab561 » | ry | 2008-07-15 | 140 | CURRENT->version_minor *= 10; | |
| 141 | CURRENT->version_minor += *p - '0'; | ||||
| db036d99 » | ry | 2008-07-13 | 142 | } | |
| 143 | |||||
| 123287d8 » | ry | 2008-07-20 | 144 | action end_header_line { | |
| 145 | CURRENT->number_of_headers++; | ||||
| 146 | } | ||||
| 147 | |||||
| 148 | action end_headers { | ||||
| e33da647 » | ry | 2008-07-31 | 149 | if(CURRENT->on_headers_complete) | |
| 150 | CURRENT->on_headers_complete(CURRENT); | ||||
| 123287d8 » | ry | 2008-07-20 | 151 | } | |
| 152 | |||||
| db036d99 » | ry | 2008-07-13 | 153 | action add_to_chunk_size { | |
| b55e1255 » | ry | 2008-07-15 | 154 | //printf("add to chunk size\n"); | |
| db036d99 » | ry | 2008-07-13 | 155 | parser->chunk_size *= 16; | |
| 123287d8 » | ry | 2008-07-20 | 156 | /* XXX: this can be optimized slightly */ | |
| db036d99 » | ry | 2008-07-13 | 157 | if( 'A' <= *p && *p <= 'F') | |
| 158 | parser->chunk_size += *p - 'A' + 10; | ||||
| 159 | else if( 'a' <= *p && *p <= 'f') | ||||
| 160 | parser->chunk_size += *p - 'a' + 10; | ||||
| 161 | else if( '0' <= *p && *p <= '9') | ||||
| 162 | parser->chunk_size += *p - '0'; | ||||
| 163 | else | ||||
| 164 | assert(0 && "bad hex char"); | ||||
| 165 | } | ||||
| 166 | |||||
| 167 | action skip_chunk_data { | ||||
| b55e1255 » | ry | 2008-07-15 | 168 | //printf("skip chunk data\n"); | |
| 169 | //printf("chunk_size: %d\n", parser->chunk_size); | ||||
| db036d99 » | ry | 2008-07-13 | 170 | if(parser->chunk_size > REMAINING) { | |
| c3aab561 » | ry | 2008-07-15 | 171 | parser->eating = TRUE; | |
| e33da647 » | ry | 2008-07-31 | 172 | CURRENT->on_body(CURRENT, p, REMAINING); | |
| db036d99 » | ry | 2008-07-13 | 173 | parser->chunk_size -= REMAINING; | |
| 174 | fhold; | ||||
| 175 | fbreak; | ||||
| 176 | } else { | ||||
| e33da647 » | ry | 2008-07-31 | 177 | CURRENT->on_body(CURRENT, p, parser->chunk_size); | |
| db036d99 » | ry | 2008-07-13 | 178 | p += parser->chunk_size; | |
| 179 | parser->chunk_size = 0; | ||||
| c3aab561 » | ry | 2008-07-15 | 180 | parser->eating = FALSE; | |
| db036d99 » | ry | 2008-07-13 | 181 | fhold; | |
| 182 | fgoto chunk_end; | ||||
| 183 | } | ||||
| 184 | } | ||||
| 185 | |||||
| 186 | action end_chunked_body { | ||||
| b55e1255 » | ry | 2008-07-15 | 187 | //printf("end chunked body\n"); | |
| e3d05885 » | ry | 2008-07-21 | 188 | END_REQUEST; | |
| c3aab561 » | ry | 2008-07-15 | 189 | fret; // goto Request; | |
| db036d99 » | ry | 2008-07-13 | 190 | } | |
| 191 | |||||
| 5a49acff » | ry | 2008-07-13 | 192 | action start_req { | |
| e3d05885 » | ry | 2008-07-21 | 193 | assert(CURRENT == NULL); | |
| 3840ba81 » | ry | 2008-07-17 | 194 | CURRENT = parser->new_request(parser->data); | |
| 5a49acff » | ry | 2008-07-13 | 195 | } | |
| 196 | |||||
| 08a17ec7 » | ry | 2008-07-15 | 197 | action body_logic { | |
| 198 | if(CURRENT->transfer_encoding == EBB_CHUNKED) { | ||||
| 199 | fcall ChunkedBody; | ||||
| 200 | } else { | ||||
| 201 | /* | ||||
| 202 | * EAT BODY | ||||
| 203 | * this is very ugly. sorry. | ||||
| 204 | * | ||||
| 205 | */ | ||||
| 206 | if( CURRENT->content_length == 0) { | ||||
| 207 | |||||
| e3d05885 » | ry | 2008-07-21 | 208 | END_REQUEST; | |
| 08a17ec7 » | ry | 2008-07-15 | 209 | ||
| 210 | } else if( CURRENT->content_length < REMAINING ) { | ||||
| 211 | /* | ||||
| 212 | * | ||||
| 213 | * FINISH EATING THE BODY. there is still more | ||||
| 214 | * on the buffer - so we just let it continue | ||||
| 215 | * parsing after we're done | ||||
| 216 | * | ||||
| 217 | */ | ||||
| 218 | p += 1; | ||||
| e33da647 » | ry | 2008-07-31 | 219 | if( CURRENT->on_body ) | |
| 220 | CURRENT->on_body(CURRENT, p, CURRENT->content_length); | ||||
| 08a17ec7 » | ry | 2008-07-15 | 221 | ||
| 222 | p += CURRENT->content_length; | ||||
| 223 | CURRENT->body_read = CURRENT->content_length; | ||||
| 224 | |||||
| 225 | assert(0 <= REMAINING); | ||||
| 226 | |||||
| e3d05885 » | ry | 2008-07-21 | 227 | END_REQUEST; | |
| 08a17ec7 » | ry | 2008-07-15 | 228 | ||
| 229 | fhold; | ||||
| 230 | |||||
| 231 | } else { | ||||
| 232 | /* | ||||
| 233 | * The body is larger than the buffer | ||||
| 234 | * EAT REST OF BUFFER | ||||
| 235 | * there is still more to read though. this will | ||||
| a1433934 » | ry | 2008-07-16 | 236 | * be handled on the next invokion of ebb_request_parser_execute | |
| 08a17ec7 » | ry | 2008-07-15 | 237 | * right before we enter the state machine. | |
| 238 | * | ||||
| 239 | */ | ||||
| 240 | p += 1; | ||||
| 241 | size_t eat = REMAINING; | ||||
| 242 | |||||
| e33da647 » | ry | 2008-07-31 | 243 | if( CURRENT->on_body && eat > 0) | |
| 244 | CURRENT->on_body(CURRENT, p, eat); | ||||
| 08a17ec7 » | ry | 2008-07-15 | 245 | ||
| 246 | p += eat; | ||||
| 247 | CURRENT->body_read += eat; | ||||
| 6835e50f » | ry | 2008-07-15 | 248 | CURRENT->eating_body = TRUE; | |
| c1a5d8e5 » | ry | 2008-07-15 | 249 | //printf("eating body!\n"); | |
| 08a17ec7 » | ry | 2008-07-15 | 250 | ||
| 251 | assert(CURRENT->body_read < CURRENT->content_length); | ||||
| 252 | assert(REMAINING == 0); | ||||
| 253 | |||||
| 254 | fhold; fbreak; | ||||
| 255 | } | ||||
| 256 | } | ||||
| 257 | } | ||||
| 258 | |||||
| db036d99 » | ry | 2008-07-13 | 259 | # | |
| 260 | ## | ||||
| 261 | ### | ||||
| 262 | #### HTTP/1.1 STATE MACHINE | ||||
| 263 | ### | ||||
| c944c21f » | ry | 2008-07-14 | 264 | ## RequestHeaders and character types are from | |
| 265 | # Zed Shaw's beautiful Mongrel parser. | ||||
| db036d99 » | ry | 2008-07-13 | 266 | ||
| 267 | CRLF = "\r\n"; | ||||
| 268 | |||||
| 269 | # character types | ||||
| 270 | CTL = (cntrl | 127); | ||||
| 271 | safe = ("$" | "-" | "_" | "."); | ||||
| 272 | extra = ("!" | "*" | "'" | "(" | ")" | ","); | ||||
| 273 | reserved = (";" | "/" | "?" | ":" | "@" | "&" | "=" | "+"); | ||||
| 274 | unsafe = (CTL | " " | "\"" | "#" | "%" | "<" | ">"); | ||||
| 275 | national = any -- (alpha | digit | reserved | extra | safe | unsafe); | ||||
| 276 | unreserved = (alpha | digit | safe | extra | national); | ||||
| 277 | escape = ("%" xdigit xdigit); | ||||
| 278 | uchar = (unreserved | escape); | ||||
| 279 | pchar = (uchar | ":" | "@" | "&" | "=" | "+"); | ||||
| 280 | tspecials = ("(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\\" | "\"" | "/" | "[" | "]" | "?" | "=" | "{" | "}" | " " | "\t"); | ||||
| 281 | |||||
| 282 | # elements | ||||
| 283 | token = (ascii -- (CTL | tspecials)); | ||||
| f8b67637 » | ry | 2008-07-19 | 284 | quote = "\""; | |
| db036d99 » | ry | 2008-07-13 | 285 | # qdtext = token -- "\""; | |
| 286 | # quoted_pair = "\" ascii; | ||||
| 287 | # quoted_string = "\"" (qdtext | quoted_pair )* "\""; | ||||
| 288 | |||||
| 289 | # headers | ||||
| f8b67637 » | ry | 2008-07-19 | 290 | ||
| 8a85dac7 » | ry | 2008-07-19 | 291 | Method = ( "COPY" %method_copy | |
| 292 | | "DELETE" %method_delete | ||||
| 293 | | "GET" %method_get | ||||
| 294 | | "HEAD" %method_head | ||||
| 295 | | "LOCK" %method_lock | ||||
| 296 | | "MKCOL" %method_mkcol | ||||
| 297 | | "MOVE" %method_move | ||||
| 298 | | "OPTIONS" %method_options | ||||
| 299 | | "POST" %method_post | ||||
| 300 | | "PROPFIND" %method_propfind | ||||
| 301 | | "PROPPATCH" %method_proppatch | ||||
| 302 | | "PUT" %method_put | ||||
| 303 | | "TRACE" %method_trace | ||||
| 304 | | "UNLOCK" %method_unlock | ||||
| 123287d8 » | ry | 2008-07-20 | 305 | ); # Not allowing extension methods | |
| f8b67637 » | ry | 2008-07-19 | 306 | ||
| 307 | HTTP_Version = "HTTP/" digit+ $version_major "." digit+ $version_minor; | ||||
| 308 | |||||
| db036d99 » | ry | 2008-07-13 | 309 | scheme = ( alpha | digit | "+" | "-" | "." )* ; | |
| 310 | absolute_uri = (scheme ":" (uchar | reserved )*); | ||||
| 311 | path = ( pchar+ ( "/" pchar* )* ) ; | ||||
| 3177fb5d » | ry | 2008-07-18 | 312 | query = ( uchar | reserved )* >mark_query_string %query_string ; | |
| db036d99 » | ry | 2008-07-13 | 313 | param = ( pchar | "/" )* ; | |
| 314 | params = ( param ( ";" param )* ) ; | ||||
| b55e1255 » | ry | 2008-07-15 | 315 | rel_path = ( path? (";" params)? ) ; | |
| 3177fb5d » | ry | 2008-07-18 | 316 | absolute_path = ( "/"+ rel_path ) >mark_request_path %request_path ("?" query)?; | |
| 317 | Request_URI = ( "*" | absolute_uri | absolute_path ) >mark_request_uri %request_uri; | ||||
| 318 | Fragment = ( uchar | reserved )* >mark_fragment %fragment; | ||||
| b1609204 » | ry | 2008-07-14 | 319 | ||
| 08a17ec7 » | ry | 2008-07-15 | 320 | field_name = ( token -- ":" )+; | |
| f8b67637 » | ry | 2008-07-19 | 321 | Field_Name = field_name >mark_header_field %write_field; | |
| b1609204 » | ry | 2008-07-14 | 322 | ||
| f8b67637 » | ry | 2008-07-19 | 323 | field_value = ((any - " ") any*)?; | |
| 324 | Field_Value = field_value >mark_header_value %write_value; | ||||
| 325 | |||||
| 326 | hsep = ":" " "*; | ||||
| 327 | header = (field_name hsep field_value) :> CRLF; | ||||
| 328 | Header = ( ("Content-Length"i hsep digit+ $content_length) | ||||
| 0ca30982 » | ry | 2008-07-23 | 329 | | ("Connection"i hsep | |
| 330 | ( "Keep-Alive"i %set_keep_alive | ||||
| 331 | | "close"i %set_not_keep_alive | ||||
| 332 | ) | ||||
| 333 | ) | ||||
| f8b67637 » | ry | 2008-07-19 | 334 | | ("Content-Type"i hsep | |
| 335 | "multipart/form-data" any* | ||||
| 336 | "boundary=" quote token+ $multipart_boundary quote | ||||
| 337 | ) | ||||
| 338 | | ("Transfer-Encoding"i %use_chunked_encoding hsep "identity" %use_identity_encoding) | ||||
| 339 | | ("Expect"i hsep "100-continue"i %expect_continue) | ||||
| 340 | | ("Trailer"i hsep field_value %trailer) | ||||
| 341 | | (Field_Name hsep Field_Value) | ||||
| 342 | ) :> CRLF; | ||||
| b1609204 » | ry | 2008-07-14 | 343 | ||
| db036d99 » | ry | 2008-07-13 | 344 | Request_Line = ( Method " " Request_URI ("#" Fragment)? " " HTTP_Version CRLF ) ; | |
| 123287d8 » | ry | 2008-07-20 | 345 | RequestHeader = Request_Line (Header %end_header_line)* :> CRLF @end_headers; | |
| db036d99 » | ry | 2008-07-13 | 346 | ||
| 347 | # chunked message | ||||
| f8b67637 » | ry | 2008-07-19 | 348 | trailing_headers = header*; | |
| db036d99 » | ry | 2008-07-13 | 349 | #chunk_ext_val = token | quoted_string; | |
| 350 | chunk_ext_val = token*; | ||||
| 351 | chunk_ext_name = token*; | ||||
| 352 | chunk_extension = ( ";" " "* chunk_ext_name ("=" chunk_ext_val)? )*; | ||||
| 353 | last_chunk = "0"+ chunk_extension CRLF; | ||||
| 354 | chunk_size = (xdigit* [1-9a-fA-F] xdigit*) $add_to_chunk_size; | ||||
| 355 | chunk_end = CRLF; | ||||
| 356 | chunk_body = any >skip_chunk_data; | ||||
| 357 | chunk_begin = chunk_size chunk_extension CRLF; | ||||
| 358 | chunk = chunk_begin chunk_body chunk_end; | ||||
| c3aab561 » | ry | 2008-07-15 | 359 | ChunkedBody := chunk* last_chunk trailing_headers CRLF @end_chunked_body; | |
| 360 | |||||
| 08a17ec7 » | ry | 2008-07-15 | 361 | Request = RequestHeader >start_req @body_logic; | |
| c3aab561 » | ry | 2008-07-15 | 362 | ||
| 08a17ec7 » | ry | 2008-07-15 | 363 | main := Request+; # sequence of requests (for keep-alive) | |
| db036d99 » | ry | 2008-07-13 | 364 | }%% | |
| 365 | |||||
| 366 | %% write data; | ||||
| 367 | |||||
| 8b611115 » | ry | 2008-07-17 | 368 | #define COPYSTACK(dest, src) for(i = 0; i < EBB_RAGEL_STACK_SIZE; i++) { dest[i] = src[i]; } | |
| 369 | |||||
| 536351d7 » | ry | 2008-07-21 | 370 | void ebb_request_parser_init(ebb_request_parser *parser) | |
| db036d99 » | ry | 2008-07-13 | 371 | { | |
| c3aab561 » | ry | 2008-07-15 | 372 | int i; | |
| 373 | |||||
| db036d99 » | ry | 2008-07-13 | 374 | int cs = 0; | |
| c3aab561 » | ry | 2008-07-15 | 375 | int top = 0; | |
| 8b611115 » | ry | 2008-07-17 | 376 | int stack[EBB_RAGEL_STACK_SIZE]; | |
| db036d99 » | ry | 2008-07-13 | 377 | %% write init; | |
| 378 | parser->cs = cs; | ||||
| c3aab561 » | ry | 2008-07-15 | 379 | parser->top = top; | |
| 380 | COPYSTACK(parser->stack, stack); | ||||
| 381 | |||||
| db036d99 » | ry | 2008-07-13 | 382 | parser->chunk_size = 0; | |
| 383 | parser->eating = 0; | ||||
| c3aab561 » | ry | 2008-07-15 | 384 | ||
| 5a49acff » | ry | 2008-07-13 | 385 | parser->current_request = NULL; | |
| db036d99 » | ry | 2008-07-13 | 386 | ||
| 3177fb5d » | ry | 2008-07-18 | 387 | parser->header_field_mark = parser->header_value_mark = | |
| e33da647 » | ry | 2008-07-31 | 388 | parser->query_string_mark = parser->path_mark = | |
| 389 | parser->uri_mark = parser->fragment_mark = NULL; | ||||
| 3177fb5d » | ry | 2008-07-18 | 390 | ||
| 028aea9b » | ry | 2008-07-20 | 391 | parser->new_request = NULL; | |
| db036d99 » | ry | 2008-07-13 | 392 | } | |
| 393 | |||||
| 394 | |||||
| 395 | /** exec **/ | ||||
| 536351d7 » | ry | 2008-07-21 | 396 | size_t ebb_request_parser_execute(ebb_request_parser *parser, const char *buffer, size_t len) | |
| db036d99 » | ry | 2008-07-13 | 397 | { | |
| 398 | const char *p, *pe; | ||||
| 399 | int i, cs = parser->cs; | ||||
| 400 | |||||
| c3aab561 » | ry | 2008-07-15 | 401 | int top = parser->top; | |
| 8b611115 » | ry | 2008-07-17 | 402 | int stack[EBB_RAGEL_STACK_SIZE]; | |
| c3aab561 » | ry | 2008-07-15 | 403 | COPYSTACK(stack, parser->stack); | |
| 404 | |||||
| 3840ba81 » | ry | 2008-07-17 | 405 | assert(parser->new_request && "undefined callback"); | |
| c944c21f » | ry | 2008-07-14 | 406 | ||
| db036d99 » | ry | 2008-07-13 | 407 | p = buffer; | |
| 408 | pe = buffer+len; | ||||
| 409 | |||||
| 410 | if(0 < parser->chunk_size && parser->eating) { | ||||
| c3aab561 » | ry | 2008-07-15 | 411 | /* | |
| 412 | * | ||||
| 413 | * eat chunked body | ||||
| 414 | * | ||||
| 415 | */ | ||||
| b55e1255 » | ry | 2008-07-15 | 416 | //printf("eat chunk body (before parse)\n"); | |
| 9348f6b1 » | ry | 2008-07-14 | 417 | size_t eat = MIN(len, parser->chunk_size); | |
| db036d99 » | ry | 2008-07-13 | 418 | if(eat == parser->chunk_size) { | |
| 419 | parser->eating = FALSE; | ||||
| 420 | } | ||||
| e33da647 » | ry | 2008-07-31 | 421 | CURRENT->on_body(CURRENT, p, eat); | |
| db036d99 » | ry | 2008-07-13 | 422 | p += eat; | |
| 423 | parser->chunk_size -= eat; | ||||
| 424 | //printf("eat: %d\n", eat); | ||||
| 3177fb5d » | ry | 2008-07-18 | 425 | } else if( parser->current_request && CURRENT->eating_body ) { | |
| c3aab561 » | ry | 2008-07-15 | 426 | /* | |
| 427 | * | ||||
| 428 | * eat normal body | ||||
| 429 | * | ||||
| 430 | */ | ||||
| b55e1255 » | ry | 2008-07-15 | 431 | //printf("eat normal body (before parse)\n"); | |
| c3aab561 » | ry | 2008-07-15 | 432 | size_t eat = MIN(len, CURRENT->content_length - CURRENT->body_read); | |
| 433 | |||||
| e33da647 » | ry | 2008-07-31 | 434 | CURRENT->on_body(CURRENT, p, eat); | |
| c3aab561 » | ry | 2008-07-15 | 435 | p += eat; | |
| 436 | CURRENT->body_read += eat; | ||||
| 437 | |||||
| 6835e50f » | ry | 2008-07-15 | 438 | if(CURRENT->body_read == CURRENT->content_length) { | |
| e3d05885 » | ry | 2008-07-21 | 439 | END_REQUEST; | |
| 6835e50f » | ry | 2008-07-15 | 440 | } | |
| db036d99 » | ry | 2008-07-13 | 441 | } | |
| 442 | |||||
| 3177fb5d » | ry | 2008-07-18 | 443 | if(parser->header_field_mark) parser->header_field_mark = buffer; | |
| 444 | if(parser->header_value_mark) parser->header_value_mark = buffer; | ||||
| 445 | if(parser->fragment_mark) parser->fragment_mark = buffer; | ||||
| 446 | if(parser->query_string_mark) parser->query_string_mark = buffer; | ||||
| e33da647 » | ry | 2008-07-31 | 447 | if(parser->path_mark) parser->path_mark = buffer; | |
| 448 | if(parser->uri_mark) parser->uri_mark = buffer; | ||||
| db036d99 » | ry | 2008-07-13 | 449 | ||
| 450 | %% write exec; | ||||
| 451 | |||||
| 452 | parser->cs = cs; | ||||
| c3aab561 » | ry | 2008-07-15 | 453 | parser->top = top; | |
| 454 | COPYSTACK(parser->stack, stack); | ||||
| 455 | |||||
| 3177fb5d » | ry | 2008-07-18 | 456 | HEADER_CALLBACK(header_field); | |
| 457 | HEADER_CALLBACK(header_value); | ||||
| 458 | CALLBACK(fragment); | ||||
| 459 | CALLBACK(query_string); | ||||
| e33da647 » | ry | 2008-07-31 | 460 | CALLBACK(path); | |
| 461 | CALLBACK(uri); | ||||
| db036d99 » | ry | 2008-07-13 | 462 | ||
| 463 | assert(p <= pe && "buffer overflow after parsing execute"); | ||||
| 464 | |||||
| 465 | return(p - buffer); | ||||
| 466 | } | ||||
| 467 | |||||
| 536351d7 » | ry | 2008-07-21 | 468 | int ebb_request_parser_has_error(ebb_request_parser *parser) | |
| db036d99 » | ry | 2008-07-13 | 469 | { | |
| a1433934 » | ry | 2008-07-16 | 470 | return parser->cs == ebb_request_parser_error; | |
| db036d99 » | ry | 2008-07-13 | 471 | } | |
| 472 | |||||
| 536351d7 » | ry | 2008-07-21 | 473 | int ebb_request_parser_is_finished(ebb_request_parser *parser) | |
| db036d99 » | ry | 2008-07-13 | 474 | { | |
| a1433934 » | ry | 2008-07-16 | 475 | return parser->cs == ebb_request_parser_first_final; | |
| db036d99 » | ry | 2008-07-13 | 476 | } | |
| 477 | |||||
| 536351d7 » | ry | 2008-07-21 | 478 | void ebb_request_init(ebb_request *request) | |
| 0ca02506 » | ry | 2008-07-14 | 479 | { | |
| a2556cd6 » | ry | 2008-07-15 | 480 | request->expect_continue = FALSE; | |
| 6835e50f » | ry | 2008-07-15 | 481 | request->eating_body = 0; | |
| 6ef22be5 » | ry | 2008-07-15 | 482 | request->body_read = 0; | |
| 0ca02506 » | ry | 2008-07-14 | 483 | request->content_length = 0; | |
| 484 | request->version_major = 0; | ||||
| 485 | request->version_minor = 0; | ||||
| 3177fb5d » | ry | 2008-07-18 | 486 | request->number_of_headers = 0; | |
| 0ca02506 » | ry | 2008-07-14 | 487 | request->transfer_encoding = EBB_IDENTITY; | |
| f8b67637 » | ry | 2008-07-19 | 488 | request->multipart_boundary_len = 0; | |
| 0ca30982 » | ry | 2008-07-23 | 489 | request->keep_alive = -1; | |
| 028aea9b » | ry | 2008-07-20 | 490 | ||
| e33da647 » | ry | 2008-07-31 | 491 | request->on_complete = NULL; | |
| 492 | request->on_headers_complete = NULL; | ||||
| 493 | request->on_body = NULL; | ||||
| 494 | request->on_header_field = NULL; | ||||
| 495 | request->on_header_value = NULL; | ||||
| 496 | request->on_uri = NULL; | ||||
| 497 | request->on_fragment = NULL; | ||||
| 498 | request->on_path = NULL; | ||||
| 499 | request->on_query_string = NULL; | ||||
| 0ca02506 » | ry | 2008-07-14 | 500 | } | |
| 501 | |||||
| 0ca30982 » | ry | 2008-07-23 | 502 | int ebb_request_should_keep_alive(ebb_request *request) | |
| 503 | { | ||||
| 504 | if(request->keep_alive == -1) | ||||
| 505 | if(request->version_major == 1) | ||||
| 506 | return (request->version_minor != 0); | ||||
| 507 | else if(request->version_major == 0) | ||||
| 508 | return FALSE; | ||||
| 509 | else | ||||
| 510 | return TRUE; | ||||
| 511 | else | ||||
| 512 | return request->keep_alive; | ||||
| 513 | } | ||||
