control_tower 1.0

Sign up to get free protection for your applications and to get access to all the features.
data/bin/control_tower ADDED
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env macruby
2
+ # This file is covered by the Ruby license. See COPYING for more details.
3
+ # Copyright (C) 2009-2010, Apple Inc. All rights reserved.
4
+
5
+ require 'control_tower'
6
+ require 'optparse'
7
+
8
+ # Some default values
9
+ @options = {
10
+ :rackup => './config.ru',
11
+ :port => '3000',
12
+ :host => '0.0.0.0',
13
+ :concurrent => false
14
+ }
15
+
16
+ OptionParser.new do |opts|
17
+ opts.on("-R", "--rackup FILE", "Rack-up Configuration File") do |rackup|
18
+ @options[:rackup] = rackup
19
+ end
20
+
21
+ opts.on("-p", "--port PORT", Integer, "Port on which to run the server (default: 3000)") do |port|
22
+ @options[:port] = port
23
+ end
24
+
25
+ opts.on("-a", "--address HOST", "Address to bind server to (default: 0.0.0.0)") do |host|
26
+ @options[:host] = host
27
+ end
28
+
29
+ opts.on("-c", "--[no-]concurrency", "Handle requests concurrently") do |concurrent|
30
+ @options[:concurrent] = concurrent
31
+ end
32
+ end.parse!
33
+
34
+ unless File.exist?(@options[:rackup])
35
+ $stderr.puts "Rack-up config file `#{@options[:rackup]}' doesn't exist!"
36
+ exit 1
37
+ end
38
+
39
+ # Under construction...everything is development!
40
+ ENV['RACK_ENV'] = 'development'
41
+
42
+ rackup_config = File.read(@options[:rackup])
43
+ app = eval("Rack::Builder.new { #{rackup_config} }").to_app
44
+
45
+ # Let's get to business!
46
+ server = ControlTower::Server.new(app, @options)
47
+ if server
48
+ puts "You are cleared for take-off!"
49
+ puts "Listening on #{@options[:host]}:#{@options[:port]}"
50
+ server.start
51
+ else
52
+ puts "Mayday! Mayday! Eject! Eject!\n#{$!}"
53
+ exit 1
54
+ end
@@ -0,0 +1,28 @@
1
+ /*
2
+ * This file is covered by the Ruby license. See COPYING for more details.
3
+ * Copyright (C) 2009-2010, Apple Inc. All rights reserved.
4
+ */
5
+
6
+ #include "http11_parser.h"
7
+ #import <Foundation/Foundation.h>
8
+
9
+ #define SERVER_SOFTWARE @"Control Tower v1.0"
10
+
11
+ @interface CTParser : NSObject
12
+ {
13
+ http_parser *_parser;
14
+ }
15
+
16
+ - (id)init;
17
+ - (void)reset;
18
+
19
+ - (NSNumber *)parseData:(NSData *)dataBuf forEnvironment:(NSDictionary *)env startingAt:(NSNumber *)startingPos;
20
+ - (NSNumber *)parseData:(NSData *)dataBuf forEnvironment:(NSDictionary *)env;
21
+
22
+ - (BOOL)errorCond;
23
+ - (BOOL)finished;
24
+ - (NSNumber *)nread;
25
+
26
+ - (void)finalize;
27
+
28
+ @end
@@ -0,0 +1,217 @@
1
+ /*
2
+ * This file is covered by the Ruby license. See COPYING for more details.
3
+ * Copyright (C) 2009-2010, Apple Inc. All rights reserved.
4
+ */
5
+
6
+ #import "CTParser.h"
7
+
8
+ #pragma mark Parser Callbacks
9
+
10
+ #define DEF_MAX_LENGTH(N, val) const size_t MAX_##N##_LENGTH = val
11
+
12
+ #define VALIDATE_MAX_LENGTH(len, N) \
13
+ if (len > MAX_##N##_LENGTH) { \
14
+ [NSException raise:@"ParserFieldLengthError" \
15
+ format:@"HTTP element " # N " is longer than the " \
16
+ # len " character allowed length."]; \
17
+ }
18
+
19
+ #define PARSE_FIELD(field) \
20
+ static void \
21
+ parse_##field(void *env, const char *at, size_t length) \
22
+ { \
23
+ VALIDATE_MAX_LENGTH(length, field) \
24
+ NSString *val = [[NSString alloc] initWithBytes:at length:length \
25
+ encoding:NSUTF8StringEncoding]; \
26
+ [(NSMutableDictionary *)env setObject:val forKey:@"" #field]; \
27
+ }
28
+
29
+ // Max field lengths
30
+ DEF_MAX_LENGTH(FIELD_NAME, 256);
31
+ DEF_MAX_LENGTH(FIELD_VALUE, 80 * 1024);
32
+ DEF_MAX_LENGTH(REQUEST_METHOD, 256);
33
+ DEF_MAX_LENGTH(REQUEST_URI, 1024 * 12);
34
+ DEF_MAX_LENGTH(FRAGMENT, 1024);
35
+ DEF_MAX_LENGTH(PATH_INFO, 1024);
36
+ DEF_MAX_LENGTH(QUERY_STRING, (1024 * 10));
37
+ DEF_MAX_LENGTH(HTTP_VERSION, 256);
38
+ DEF_MAX_LENGTH(HEADER, (1024 * (80 + 32)));
39
+
40
+ static void
41
+ parse_HTTP_FIELD(void *env, const char *field, size_t flen, const char *value,
42
+ size_t vlen)
43
+ {
44
+ VALIDATE_MAX_LENGTH(flen, FIELD_NAME);
45
+ VALIDATE_MAX_LENGTH(vlen, FIELD_VALUE);
46
+
47
+ NSString *val = [[NSString alloc] initWithBytes:value length:vlen
48
+ encoding:NSUTF8StringEncoding];
49
+
50
+ NSString *key;
51
+ if (strncmp(field, "HOST", 4) == 0) {
52
+ key = @"HTTP_HOST";
53
+ }
54
+ else if (strncmp(field, "REFERER", 4) == 0) {
55
+ key = @"HTTP_REFERER";
56
+ }
57
+ else if (strncmp(field, "CACHE_CONTROL", 4) == 0) {
58
+ key = @"HTTP_CACHE_CONTROL";
59
+ }
60
+ else if (strncmp(field, "COOKIE", 4) == 0) {
61
+ key = @"HTTP_COOKIE";
62
+ }
63
+ else if (strncmp(field, "CONNECTION", 4) == 0) {
64
+ key = @"HTTP_CONNECTION";
65
+ }
66
+ else {
67
+ key = [@"HTTP_" stringByAppendingString:[[NSString alloc]
68
+ initWithBytes:field length:flen encoding:NSUTF8StringEncoding]];
69
+ }
70
+ [(NSMutableDictionary *)env setObject:val forKey:key];
71
+ }
72
+
73
+ // Parsing callback functions
74
+ PARSE_FIELD(REQUEST_METHOD);
75
+ PARSE_FIELD(REQUEST_URI);
76
+ PARSE_FIELD(FRAGMENT);
77
+ PARSE_FIELD(PATH_INFO);
78
+ PARSE_FIELD(QUERY_STRING);
79
+ PARSE_FIELD(HTTP_VERSION);
80
+
81
+ static void
82
+ header_done(void *env, const char *at, size_t length)
83
+ {
84
+ NSMutableDictionary *environment = (NSMutableDictionary *)env;
85
+ NSString *contentLength = [environment objectForKey:@"HTTP_CONTENT_LENGTH"];
86
+ if (contentLength != nil) {
87
+ [environment setObject:contentLength forKey:@"CONTENT_LENGTH"];
88
+ }
89
+
90
+ NSString *contentType = [environment objectForKey:@"HTTP_CONTENT_TYPE"];
91
+ if (contentType != nil) {
92
+ [environment setObject:contentType forKey:@"CONTENT_TYPE"];
93
+ }
94
+
95
+ [environment setObject:@"CGI/1.2" forKey:@"GATEWAY_INTERFACE"];
96
+
97
+ NSString *hostString = [environment objectForKey:@"HTTP_HOST"];
98
+ NSString *serverName = nil;
99
+ NSString *serverPort = nil;
100
+ if (hostString != nil) {
101
+ NSRange colon_pos = [hostString rangeOfString:@":"];
102
+ if (colon_pos.location != NSNotFound) {
103
+ serverName = [hostString substringToIndex:colon_pos.location];
104
+ serverPort = [hostString substringFromIndex:colon_pos.location+1];
105
+ }
106
+ else {
107
+ serverName = [NSString stringWithString:hostString];
108
+ serverPort = @"80";
109
+ }
110
+ [environment setObject:serverName forKey:@"SERVER_NAME"];
111
+ [environment setObject:serverPort forKey:@"SERVER_PORT"];
112
+ }
113
+
114
+ [environment setObject:@"HTTP/1.1" forKey:@"SERVER_PROTOCOL"];
115
+ [environment setObject:SERVER_SOFTWARE forKey:@"SERVER_SOFTWARE"];
116
+ [environment setObject:@"" forKey:@"SCRIPT_NAME"];
117
+
118
+ // We don't do tls yet
119
+ [environment setObject:@"http" forKey:@"rack.url_scheme"];
120
+
121
+ // To satisfy Rack specs...
122
+ if ([environment objectForKey:@"QUERY_STRING"] == nil) {
123
+ [environment setObject:@"" forKey:@"QUERY_STRING"];
124
+ }
125
+
126
+ // If we've been given any part of the body, put it here
127
+ NSMutableData *body = [[NSMutableData alloc] init];
128
+ [body appendData:[NSData dataWithBytes:at length:length]];
129
+ [environment setObject:body forKey:@"rack.input"];
130
+ }
131
+
132
+ @implementation CTParser
133
+
134
+ - (id)init
135
+ {
136
+ self = [super init];
137
+ if (self != nil) {
138
+ _parser = malloc(sizeof(http_parser));
139
+ assert(_parser != NULL);
140
+
141
+ // Setup the callbacks
142
+ _parser->http_field = parse_HTTP_FIELD;
143
+ _parser->request_method = parse_REQUEST_METHOD;
144
+ _parser->request_uri = parse_REQUEST_URI;
145
+ _parser->fragment = parse_FRAGMENT;
146
+ _parser->request_path = parse_PATH_INFO;
147
+ _parser->query_string = parse_QUERY_STRING;
148
+ _parser->http_version = parse_HTTP_VERSION;
149
+ _parser->header_done = header_done;
150
+
151
+ http_parser_init(_parser);
152
+ }
153
+ return self;
154
+ }
155
+
156
+ - (void)reset
157
+ {
158
+ http_parser_init(_parser);
159
+ }
160
+
161
+ - (NSNumber *)parseData:(NSData *)dataBuf
162
+ forEnvironment:(NSMutableDictionary *)env
163
+ startingAt:(NSNumber *)startingPos
164
+ {
165
+ const char *data = [dataBuf bytes];
166
+ size_t length = [dataBuf length] - 1; // ignore \0 sentinel
167
+ size_t offset = [startingPos unsignedLongValue];
168
+ _parser->data = env;
169
+
170
+ http_parser_execute(_parser, data, length, offset);
171
+ if (http_parser_has_error(_parser)) {
172
+ [NSException raise:@"CTParserError"
173
+ format:@"Invalid HTTP format, parsing failed."];
174
+ }
175
+
176
+ NSNumber *headerLength = [NSNumber numberWithUnsignedLong:_parser->nread];
177
+ VALIDATE_MAX_LENGTH([headerLength unsignedLongValue], HEADER);
178
+ return headerLength;
179
+ }
180
+
181
+ - (NSNumber *)parseData:(NSData *)dataBuf forEnvironment:(NSDictionary *)env
182
+ {
183
+ return [self parseData:dataBuf forEnvironment:env startingAt:0];
184
+ }
185
+
186
+ - (BOOL)errorCond
187
+ {
188
+ return http_parser_has_error(_parser);
189
+ }
190
+
191
+ - (BOOL)finished
192
+ {
193
+ return http_parser_is_finished(_parser);
194
+ }
195
+
196
+ - (NSNumber *)nread
197
+ {
198
+ return [NSNumber numberWithInt:_parser->nread];
199
+ }
200
+
201
+ - (void)finalize
202
+ {
203
+ if (_parser != NULL) {
204
+ free(_parser);
205
+ _parser = NULL;
206
+ }
207
+ [super finalize];
208
+ }
209
+
210
+ @end
211
+
212
+ void
213
+ Init_CTParser(void)
214
+ {
215
+ // Do nothing. This function is required by the MacRuby runtime when this
216
+ // file is compiled as a C extension bundle.
217
+ }
@@ -0,0 +1,3 @@
1
+ require 'mkmf'
2
+ $CFLAGS << ' -fobjc-gc -g '
3
+ create_makefile("CTParser")
@@ -0,0 +1,1086 @@
1
+ /**
2
+ * Copyright (c) 2005 Zed A. Shaw
3
+ * You can redistribute it and/or modify it under the same terms as Ruby.
4
+ */
5
+ #include "http11_parser.h"
6
+ #include <stdio.h>
7
+ #include <assert.h>
8
+ #include <stdlib.h>
9
+ #include <ctype.h>
10
+ #include <string.h>
11
+
12
+ /*
13
+ * capitalizes all lower-case ASCII characters,
14
+ * converts dashes to underscores.
15
+ */
16
+ static void snake_upcase_char(char *c)
17
+ {
18
+ if (*c >= 'a' && *c <= 'z')
19
+ *c &= ~0x20;
20
+ else if (*c == '-')
21
+ *c = '_';
22
+ }
23
+
24
+ #define LEN(AT, FPC) (FPC - buffer - parser->AT)
25
+ #define MARK(M,FPC) (parser->M = (FPC) - buffer)
26
+ #define PTR_TO(F) (buffer + parser->F)
27
+
28
+ static const int http_parser_start = 1;
29
+ static const int http_parser_first_final = 57;
30
+ static const int http_parser_error = 0;
31
+
32
+ static const int http_parser_en_main = 1;
33
+
34
+ int http_parser_init(http_parser *parser) {
35
+ int cs = 0;
36
+
37
+ cs = http_parser_start;
38
+ parser->cs = cs;
39
+ parser->body_start = 0;
40
+ parser->content_len = 0;
41
+ parser->mark = 0;
42
+ parser->nread = 0;
43
+ parser->field_len = 0;
44
+ parser->field_start = 0;
45
+
46
+ return(1);
47
+ }
48
+
49
+
50
+ size_t http_parser_execute(http_parser *parser, const char *buffer, size_t len, size_t off) {
51
+ const char *p, *pe;
52
+ int cs = parser->cs;
53
+
54
+ assert(off <= len && "offset past end of buffer");
55
+
56
+ p = buffer+off;
57
+ pe = buffer+len;
58
+
59
+ assert(*pe == '\0' && "pointer does not end on NUL");
60
+ assert(pe - p == len - off && "pointers aren't same distance");
61
+
62
+
63
+
64
+ if ( p == pe )
65
+ goto _out;
66
+ switch ( cs )
67
+ {
68
+ case 1:
69
+ switch( (*p) ) {
70
+ case 36: goto tr0;
71
+ case 95: goto tr0;
72
+ }
73
+ if ( (*p) < 48 ) {
74
+ if ( 45 <= (*p) && (*p) <= 46 )
75
+ goto tr0;
76
+ } else if ( (*p) > 57 ) {
77
+ if ( 65 <= (*p) && (*p) <= 90 )
78
+ goto tr0;
79
+ } else
80
+ goto tr0;
81
+ goto st0;
82
+ st0:
83
+ goto _out0;
84
+ tr0:
85
+ MARK(mark, p);
86
+ goto st2;
87
+ st2:
88
+ if ( ++p == pe )
89
+ goto _out2;
90
+ case 2:
91
+ switch( (*p) ) {
92
+ case 32: goto tr2;
93
+ case 36: goto st38;
94
+ case 95: goto st38;
95
+ }
96
+ if ( (*p) < 48 ) {
97
+ if ( 45 <= (*p) && (*p) <= 46 )
98
+ goto st38;
99
+ } else if ( (*p) > 57 ) {
100
+ if ( 65 <= (*p) && (*p) <= 90 )
101
+ goto st38;
102
+ } else
103
+ goto st38;
104
+ goto st0;
105
+ tr2:
106
+ if(parser->request_method != NULL)
107
+ parser->request_method(parser->data, PTR_TO(mark), LEN(mark, p));
108
+ goto st3;
109
+ st3:
110
+ if ( ++p == pe )
111
+ goto _out3;
112
+ case 3:
113
+ switch( (*p) ) {
114
+ case 42: goto tr4;
115
+ case 43: goto tr5;
116
+ case 47: goto tr6;
117
+ case 58: goto tr7;
118
+ }
119
+ if ( (*p) < 65 ) {
120
+ if ( 45 <= (*p) && (*p) <= 57 )
121
+ goto tr5;
122
+ } else if ( (*p) > 90 ) {
123
+ if ( 97 <= (*p) && (*p) <= 122 )
124
+ goto tr5;
125
+ } else
126
+ goto tr5;
127
+ goto st0;
128
+ tr4:
129
+ MARK(mark, p);
130
+ goto st4;
131
+ st4:
132
+ if ( ++p == pe )
133
+ goto _out4;
134
+ case 4:
135
+ switch( (*p) ) {
136
+ case 32: goto tr8;
137
+ case 35: goto tr9;
138
+ }
139
+ goto st0;
140
+ tr8:
141
+ if(parser->request_uri != NULL)
142
+ parser->request_uri(parser->data, PTR_TO(mark), LEN(mark, p));
143
+ goto st5;
144
+ tr30:
145
+ if(parser->fragment != NULL)
146
+ parser->fragment(parser->data, PTR_TO(mark), LEN(mark, p));
147
+ goto st5;
148
+ tr40:
149
+ if(parser->request_path != NULL)
150
+ parser->request_path(parser->data, PTR_TO(mark), LEN(mark,p));
151
+ if(parser->request_uri != NULL)
152
+ parser->request_uri(parser->data, PTR_TO(mark), LEN(mark, p));
153
+ goto st5;
154
+ tr51:
155
+ MARK(query_start, p);
156
+ if(parser->query_string != NULL)
157
+ parser->query_string(parser->data, PTR_TO(query_start), LEN(query_start, p));
158
+ if(parser->request_uri != NULL)
159
+ parser->request_uri(parser->data, PTR_TO(mark), LEN(mark, p));
160
+ goto st5;
161
+ tr55:
162
+ if(parser->query_string != NULL)
163
+ parser->query_string(parser->data, PTR_TO(query_start), LEN(query_start, p));
164
+ if(parser->request_uri != NULL)
165
+ parser->request_uri(parser->data, PTR_TO(mark), LEN(mark, p));
166
+ goto st5;
167
+ st5:
168
+ if ( ++p == pe )
169
+ goto _out5;
170
+ case 5:
171
+ if ( (*p) == 72 )
172
+ goto tr10;
173
+ goto st0;
174
+ tr10:
175
+ MARK(mark, p);
176
+ goto st6;
177
+ st6:
178
+ if ( ++p == pe )
179
+ goto _out6;
180
+ case 6:
181
+ if ( (*p) == 84 )
182
+ goto st7;
183
+ goto st0;
184
+ st7:
185
+ if ( ++p == pe )
186
+ goto _out7;
187
+ case 7:
188
+ if ( (*p) == 84 )
189
+ goto st8;
190
+ goto st0;
191
+ st8:
192
+ if ( ++p == pe )
193
+ goto _out8;
194
+ case 8:
195
+ if ( (*p) == 80 )
196
+ goto st9;
197
+ goto st0;
198
+ st9:
199
+ if ( ++p == pe )
200
+ goto _out9;
201
+ case 9:
202
+ if ( (*p) == 47 )
203
+ goto st10;
204
+ goto st0;
205
+ st10:
206
+ if ( ++p == pe )
207
+ goto _out10;
208
+ case 10:
209
+ if ( 48 <= (*p) && (*p) <= 57 )
210
+ goto st11;
211
+ goto st0;
212
+ st11:
213
+ if ( ++p == pe )
214
+ goto _out11;
215
+ case 11:
216
+ if ( (*p) == 46 )
217
+ goto st12;
218
+ if ( 48 <= (*p) && (*p) <= 57 )
219
+ goto st11;
220
+ goto st0;
221
+ st12:
222
+ if ( ++p == pe )
223
+ goto _out12;
224
+ case 12:
225
+ if ( 48 <= (*p) && (*p) <= 57 )
226
+ goto st13;
227
+ goto st0;
228
+ st13:
229
+ if ( ++p == pe )
230
+ goto _out13;
231
+ case 13:
232
+ if ( (*p) == 13 )
233
+ goto tr18;
234
+ if ( 48 <= (*p) && (*p) <= 57 )
235
+ goto st13;
236
+ goto st0;
237
+ tr18:
238
+ if(parser->http_version != NULL)
239
+ parser->http_version(parser->data, PTR_TO(mark), LEN(mark, p));
240
+ goto st14;
241
+ tr26:
242
+ if(parser->http_field != NULL) {
243
+ parser->http_field(parser->data, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, p));
244
+ }
245
+ goto st14;
246
+ st14:
247
+ if ( ++p == pe )
248
+ goto _out14;
249
+ case 14:
250
+ if ( (*p) == 10 )
251
+ goto st15;
252
+ goto st0;
253
+ st15:
254
+ if ( ++p == pe )
255
+ goto _out15;
256
+ case 15:
257
+ switch( (*p) ) {
258
+ case 13: goto st16;
259
+ case 33: goto tr21;
260
+ case 124: goto tr21;
261
+ case 126: goto tr21;
262
+ }
263
+ if ( (*p) < 45 ) {
264
+ if ( (*p) > 39 ) {
265
+ if ( 42 <= (*p) && (*p) <= 43 )
266
+ goto tr21;
267
+ } else if ( (*p) >= 35 )
268
+ goto tr21;
269
+ } else if ( (*p) > 46 ) {
270
+ if ( (*p) < 65 ) {
271
+ if ( 48 <= (*p) && (*p) <= 57 )
272
+ goto tr21;
273
+ } else if ( (*p) > 90 ) {
274
+ if ( 94 <= (*p) && (*p) <= 122 )
275
+ goto tr21;
276
+ } else
277
+ goto tr21;
278
+ } else
279
+ goto tr21;
280
+ goto st0;
281
+ st16:
282
+ if ( ++p == pe )
283
+ goto _out16;
284
+ case 16:
285
+ if ( (*p) == 10 )
286
+ goto tr22;
287
+ goto st0;
288
+ tr22:
289
+ parser->body_start = p - buffer + 1;
290
+ if(parser->header_done != NULL)
291
+ parser->header_done(parser->data, p + 1, pe - p - 1);
292
+ goto _out57;
293
+ goto st57;
294
+ st57:
295
+ if ( ++p == pe )
296
+ goto _out57;
297
+ case 57:
298
+ goto st0;
299
+ tr21:
300
+ MARK(field_start, p);
301
+ snake_upcase_char((char *)p);
302
+ goto st17;
303
+ tr23:
304
+ snake_upcase_char((char *)p);
305
+ goto st17;
306
+ st17:
307
+ if ( ++p == pe )
308
+ goto _out17;
309
+ case 17:
310
+ switch( (*p) ) {
311
+ case 33: goto tr23;
312
+ case 58: goto tr24;
313
+ case 124: goto tr23;
314
+ case 126: goto tr23;
315
+ }
316
+ if ( (*p) < 45 ) {
317
+ if ( (*p) > 39 ) {
318
+ if ( 42 <= (*p) && (*p) <= 43 )
319
+ goto tr23;
320
+ } else if ( (*p) >= 35 )
321
+ goto tr23;
322
+ } else if ( (*p) > 46 ) {
323
+ if ( (*p) < 65 ) {
324
+ if ( 48 <= (*p) && (*p) <= 57 )
325
+ goto tr23;
326
+ } else if ( (*p) > 90 ) {
327
+ if ( 94 <= (*p) && (*p) <= 122 )
328
+ goto tr23;
329
+ } else
330
+ goto tr23;
331
+ } else
332
+ goto tr23;
333
+ goto st0;
334
+ tr24:
335
+ parser->field_len = LEN(field_start, p);
336
+ goto st18;
337
+ tr27:
338
+ MARK(mark, p);
339
+ goto st18;
340
+ st18:
341
+ if ( ++p == pe )
342
+ goto _out18;
343
+ case 18:
344
+ switch( (*p) ) {
345
+ case 13: goto tr26;
346
+ case 32: goto tr27;
347
+ }
348
+ goto tr25;
349
+ tr25:
350
+ MARK(mark, p);
351
+ goto st19;
352
+ st19:
353
+ if ( ++p == pe )
354
+ goto _out19;
355
+ case 19:
356
+ if ( (*p) == 13 )
357
+ goto tr26;
358
+ goto st19;
359
+ tr9:
360
+ if(parser->request_uri != NULL)
361
+ parser->request_uri(parser->data, PTR_TO(mark), LEN(mark, p));
362
+ goto st20;
363
+ tr41:
364
+ if(parser->request_path != NULL)
365
+ parser->request_path(parser->data, PTR_TO(mark), LEN(mark,p));
366
+ if(parser->request_uri != NULL)
367
+ parser->request_uri(parser->data, PTR_TO(mark), LEN(mark, p));
368
+ goto st20;
369
+ tr52:
370
+ MARK(query_start, p);
371
+ if(parser->query_string != NULL)
372
+ parser->query_string(parser->data, PTR_TO(query_start), LEN(query_start, p));
373
+ if(parser->request_uri != NULL)
374
+ parser->request_uri(parser->data, PTR_TO(mark), LEN(mark, p));
375
+ goto st20;
376
+ tr56:
377
+ if(parser->query_string != NULL)
378
+ parser->query_string(parser->data, PTR_TO(query_start), LEN(query_start, p));
379
+ if(parser->request_uri != NULL)
380
+ parser->request_uri(parser->data, PTR_TO(mark), LEN(mark, p));
381
+ goto st20;
382
+ st20:
383
+ if ( ++p == pe )
384
+ goto _out20;
385
+ case 20:
386
+ switch( (*p) ) {
387
+ case 32: goto tr30;
388
+ case 35: goto st0;
389
+ case 37: goto tr31;
390
+ case 127: goto st0;
391
+ }
392
+ if ( 0 <= (*p) && (*p) <= 31 )
393
+ goto st0;
394
+ goto tr29;
395
+ tr29:
396
+ MARK(mark, p);
397
+ goto st21;
398
+ st21:
399
+ if ( ++p == pe )
400
+ goto _out21;
401
+ case 21:
402
+ switch( (*p) ) {
403
+ case 32: goto tr30;
404
+ case 35: goto st0;
405
+ case 37: goto st22;
406
+ case 127: goto st0;
407
+ }
408
+ if ( 0 <= (*p) && (*p) <= 31 )
409
+ goto st0;
410
+ goto st21;
411
+ tr31:
412
+ MARK(mark, p);
413
+ goto st22;
414
+ st22:
415
+ if ( ++p == pe )
416
+ goto _out22;
417
+ case 22:
418
+ if ( (*p) < 65 ) {
419
+ if ( 48 <= (*p) && (*p) <= 57 )
420
+ goto st23;
421
+ } else if ( (*p) > 70 ) {
422
+ if ( 97 <= (*p) && (*p) <= 102 )
423
+ goto st23;
424
+ } else
425
+ goto st23;
426
+ goto st0;
427
+ st23:
428
+ if ( ++p == pe )
429
+ goto _out23;
430
+ case 23:
431
+ if ( (*p) < 65 ) {
432
+ if ( 48 <= (*p) && (*p) <= 57 )
433
+ goto st21;
434
+ } else if ( (*p) > 70 ) {
435
+ if ( 97 <= (*p) && (*p) <= 102 )
436
+ goto st21;
437
+ } else
438
+ goto st21;
439
+ goto st0;
440
+ tr5:
441
+ MARK(mark, p);
442
+ goto st24;
443
+ st24:
444
+ if ( ++p == pe )
445
+ goto _out24;
446
+ case 24:
447
+ switch( (*p) ) {
448
+ case 43: goto st24;
449
+ case 58: goto st25;
450
+ }
451
+ if ( (*p) < 48 ) {
452
+ if ( 45 <= (*p) && (*p) <= 46 )
453
+ goto st24;
454
+ } else if ( (*p) > 57 ) {
455
+ if ( (*p) > 90 ) {
456
+ if ( 97 <= (*p) && (*p) <= 122 )
457
+ goto st24;
458
+ } else if ( (*p) >= 65 )
459
+ goto st24;
460
+ } else
461
+ goto st24;
462
+ goto st0;
463
+ tr7:
464
+ MARK(mark, p);
465
+ goto st25;
466
+ st25:
467
+ if ( ++p == pe )
468
+ goto _out25;
469
+ case 25:
470
+ switch( (*p) ) {
471
+ case 32: goto tr8;
472
+ case 35: goto tr9;
473
+ case 37: goto st26;
474
+ case 127: goto st0;
475
+ }
476
+ if ( 0 <= (*p) && (*p) <= 31 )
477
+ goto st0;
478
+ goto st25;
479
+ st26:
480
+ if ( ++p == pe )
481
+ goto _out26;
482
+ case 26:
483
+ if ( (*p) < 65 ) {
484
+ if ( 48 <= (*p) && (*p) <= 57 )
485
+ goto st27;
486
+ } else if ( (*p) > 70 ) {
487
+ if ( 97 <= (*p) && (*p) <= 102 )
488
+ goto st27;
489
+ } else
490
+ goto st27;
491
+ goto st0;
492
+ st27:
493
+ if ( ++p == pe )
494
+ goto _out27;
495
+ case 27:
496
+ if ( (*p) < 65 ) {
497
+ if ( 48 <= (*p) && (*p) <= 57 )
498
+ goto st25;
499
+ } else if ( (*p) > 70 ) {
500
+ if ( 97 <= (*p) && (*p) <= 102 )
501
+ goto st25;
502
+ } else
503
+ goto st25;
504
+ goto st0;
505
+ tr6:
506
+ MARK(mark, p);
507
+ goto st28;
508
+ st28:
509
+ if ( ++p == pe )
510
+ goto _out28;
511
+ case 28:
512
+ switch( (*p) ) {
513
+ case 32: goto tr40;
514
+ case 35: goto tr41;
515
+ case 37: goto st29;
516
+ case 59: goto tr43;
517
+ case 63: goto tr44;
518
+ case 127: goto st0;
519
+ }
520
+ if ( 0 <= (*p) && (*p) <= 31 )
521
+ goto st0;
522
+ goto st28;
523
+ st29:
524
+ if ( ++p == pe )
525
+ goto _out29;
526
+ case 29:
527
+ if ( (*p) < 65 ) {
528
+ if ( 48 <= (*p) && (*p) <= 57 )
529
+ goto st30;
530
+ } else if ( (*p) > 70 ) {
531
+ if ( 97 <= (*p) && (*p) <= 102 )
532
+ goto st30;
533
+ } else
534
+ goto st30;
535
+ goto st0;
536
+ st30:
537
+ if ( ++p == pe )
538
+ goto _out30;
539
+ case 30:
540
+ if ( (*p) < 65 ) {
541
+ if ( 48 <= (*p) && (*p) <= 57 )
542
+ goto st28;
543
+ } else if ( (*p) > 70 ) {
544
+ if ( 97 <= (*p) && (*p) <= 102 )
545
+ goto st28;
546
+ } else
547
+ goto st28;
548
+ goto st0;
549
+ tr43:
550
+ if(parser->request_path != NULL)
551
+ parser->request_path(parser->data, PTR_TO(mark), LEN(mark,p));
552
+ goto st31;
553
+ st31:
554
+ if ( ++p == pe )
555
+ goto _out31;
556
+ case 31:
557
+ switch( (*p) ) {
558
+ case 32: goto tr8;
559
+ case 35: goto tr9;
560
+ case 37: goto st32;
561
+ case 63: goto st34;
562
+ case 127: goto st0;
563
+ }
564
+ if ( 0 <= (*p) && (*p) <= 31 )
565
+ goto st0;
566
+ goto st31;
567
+ st32:
568
+ if ( ++p == pe )
569
+ goto _out32;
570
+ case 32:
571
+ if ( (*p) < 65 ) {
572
+ if ( 48 <= (*p) && (*p) <= 57 )
573
+ goto st33;
574
+ } else if ( (*p) > 70 ) {
575
+ if ( 97 <= (*p) && (*p) <= 102 )
576
+ goto st33;
577
+ } else
578
+ goto st33;
579
+ goto st0;
580
+ st33:
581
+ if ( ++p == pe )
582
+ goto _out33;
583
+ case 33:
584
+ if ( (*p) < 65 ) {
585
+ if ( 48 <= (*p) && (*p) <= 57 )
586
+ goto st31;
587
+ } else if ( (*p) > 70 ) {
588
+ if ( 97 <= (*p) && (*p) <= 102 )
589
+ goto st31;
590
+ } else
591
+ goto st31;
592
+ goto st0;
593
+ tr44:
594
+ if(parser->request_path != NULL)
595
+ parser->request_path(parser->data, PTR_TO(mark), LEN(mark,p));
596
+ goto st34;
597
+ st34:
598
+ if ( ++p == pe )
599
+ goto _out34;
600
+ case 34:
601
+ switch( (*p) ) {
602
+ case 32: goto tr51;
603
+ case 35: goto tr52;
604
+ case 37: goto tr53;
605
+ case 127: goto st0;
606
+ }
607
+ if ( 0 <= (*p) && (*p) <= 31 )
608
+ goto st0;
609
+ goto tr50;
610
+ tr50:
611
+ MARK(query_start, p);
612
+ goto st35;
613
+ st35:
614
+ if ( ++p == pe )
615
+ goto _out35;
616
+ case 35:
617
+ switch( (*p) ) {
618
+ case 32: goto tr55;
619
+ case 35: goto tr56;
620
+ case 37: goto st36;
621
+ case 127: goto st0;
622
+ }
623
+ if ( 0 <= (*p) && (*p) <= 31 )
624
+ goto st0;
625
+ goto st35;
626
+ tr53:
627
+ MARK(query_start, p);
628
+ goto st36;
629
+ st36:
630
+ if ( ++p == pe )
631
+ goto _out36;
632
+ case 36:
633
+ if ( (*p) < 65 ) {
634
+ if ( 48 <= (*p) && (*p) <= 57 )
635
+ goto st37;
636
+ } else if ( (*p) > 70 ) {
637
+ if ( 97 <= (*p) && (*p) <= 102 )
638
+ goto st37;
639
+ } else
640
+ goto st37;
641
+ goto st0;
642
+ st37:
643
+ if ( ++p == pe )
644
+ goto _out37;
645
+ case 37:
646
+ if ( (*p) < 65 ) {
647
+ if ( 48 <= (*p) && (*p) <= 57 )
648
+ goto st35;
649
+ } else if ( (*p) > 70 ) {
650
+ if ( 97 <= (*p) && (*p) <= 102 )
651
+ goto st35;
652
+ } else
653
+ goto st35;
654
+ goto st0;
655
+ st38:
656
+ if ( ++p == pe )
657
+ goto _out38;
658
+ case 38:
659
+ switch( (*p) ) {
660
+ case 32: goto tr2;
661
+ case 36: goto st39;
662
+ case 95: goto st39;
663
+ }
664
+ if ( (*p) < 48 ) {
665
+ if ( 45 <= (*p) && (*p) <= 46 )
666
+ goto st39;
667
+ } else if ( (*p) > 57 ) {
668
+ if ( 65 <= (*p) && (*p) <= 90 )
669
+ goto st39;
670
+ } else
671
+ goto st39;
672
+ goto st0;
673
+ st39:
674
+ if ( ++p == pe )
675
+ goto _out39;
676
+ case 39:
677
+ switch( (*p) ) {
678
+ case 32: goto tr2;
679
+ case 36: goto st40;
680
+ case 95: goto st40;
681
+ }
682
+ if ( (*p) < 48 ) {
683
+ if ( 45 <= (*p) && (*p) <= 46 )
684
+ goto st40;
685
+ } else if ( (*p) > 57 ) {
686
+ if ( 65 <= (*p) && (*p) <= 90 )
687
+ goto st40;
688
+ } else
689
+ goto st40;
690
+ goto st0;
691
+ st40:
692
+ if ( ++p == pe )
693
+ goto _out40;
694
+ case 40:
695
+ switch( (*p) ) {
696
+ case 32: goto tr2;
697
+ case 36: goto st41;
698
+ case 95: goto st41;
699
+ }
700
+ if ( (*p) < 48 ) {
701
+ if ( 45 <= (*p) && (*p) <= 46 )
702
+ goto st41;
703
+ } else if ( (*p) > 57 ) {
704
+ if ( 65 <= (*p) && (*p) <= 90 )
705
+ goto st41;
706
+ } else
707
+ goto st41;
708
+ goto st0;
709
+ st41:
710
+ if ( ++p == pe )
711
+ goto _out41;
712
+ case 41:
713
+ switch( (*p) ) {
714
+ case 32: goto tr2;
715
+ case 36: goto st42;
716
+ case 95: goto st42;
717
+ }
718
+ if ( (*p) < 48 ) {
719
+ if ( 45 <= (*p) && (*p) <= 46 )
720
+ goto st42;
721
+ } else if ( (*p) > 57 ) {
722
+ if ( 65 <= (*p) && (*p) <= 90 )
723
+ goto st42;
724
+ } else
725
+ goto st42;
726
+ goto st0;
727
+ st42:
728
+ if ( ++p == pe )
729
+ goto _out42;
730
+ case 42:
731
+ switch( (*p) ) {
732
+ case 32: goto tr2;
733
+ case 36: goto st43;
734
+ case 95: goto st43;
735
+ }
736
+ if ( (*p) < 48 ) {
737
+ if ( 45 <= (*p) && (*p) <= 46 )
738
+ goto st43;
739
+ } else if ( (*p) > 57 ) {
740
+ if ( 65 <= (*p) && (*p) <= 90 )
741
+ goto st43;
742
+ } else
743
+ goto st43;
744
+ goto st0;
745
+ st43:
746
+ if ( ++p == pe )
747
+ goto _out43;
748
+ case 43:
749
+ switch( (*p) ) {
750
+ case 32: goto tr2;
751
+ case 36: goto st44;
752
+ case 95: goto st44;
753
+ }
754
+ if ( (*p) < 48 ) {
755
+ if ( 45 <= (*p) && (*p) <= 46 )
756
+ goto st44;
757
+ } else if ( (*p) > 57 ) {
758
+ if ( 65 <= (*p) && (*p) <= 90 )
759
+ goto st44;
760
+ } else
761
+ goto st44;
762
+ goto st0;
763
+ st44:
764
+ if ( ++p == pe )
765
+ goto _out44;
766
+ case 44:
767
+ switch( (*p) ) {
768
+ case 32: goto tr2;
769
+ case 36: goto st45;
770
+ case 95: goto st45;
771
+ }
772
+ if ( (*p) < 48 ) {
773
+ if ( 45 <= (*p) && (*p) <= 46 )
774
+ goto st45;
775
+ } else if ( (*p) > 57 ) {
776
+ if ( 65 <= (*p) && (*p) <= 90 )
777
+ goto st45;
778
+ } else
779
+ goto st45;
780
+ goto st0;
781
+ st45:
782
+ if ( ++p == pe )
783
+ goto _out45;
784
+ case 45:
785
+ switch( (*p) ) {
786
+ case 32: goto tr2;
787
+ case 36: goto st46;
788
+ case 95: goto st46;
789
+ }
790
+ if ( (*p) < 48 ) {
791
+ if ( 45 <= (*p) && (*p) <= 46 )
792
+ goto st46;
793
+ } else if ( (*p) > 57 ) {
794
+ if ( 65 <= (*p) && (*p) <= 90 )
795
+ goto st46;
796
+ } else
797
+ goto st46;
798
+ goto st0;
799
+ st46:
800
+ if ( ++p == pe )
801
+ goto _out46;
802
+ case 46:
803
+ switch( (*p) ) {
804
+ case 32: goto tr2;
805
+ case 36: goto st47;
806
+ case 95: goto st47;
807
+ }
808
+ if ( (*p) < 48 ) {
809
+ if ( 45 <= (*p) && (*p) <= 46 )
810
+ goto st47;
811
+ } else if ( (*p) > 57 ) {
812
+ if ( 65 <= (*p) && (*p) <= 90 )
813
+ goto st47;
814
+ } else
815
+ goto st47;
816
+ goto st0;
817
+ st47:
818
+ if ( ++p == pe )
819
+ goto _out47;
820
+ case 47:
821
+ switch( (*p) ) {
822
+ case 32: goto tr2;
823
+ case 36: goto st48;
824
+ case 95: goto st48;
825
+ }
826
+ if ( (*p) < 48 ) {
827
+ if ( 45 <= (*p) && (*p) <= 46 )
828
+ goto st48;
829
+ } else if ( (*p) > 57 ) {
830
+ if ( 65 <= (*p) && (*p) <= 90 )
831
+ goto st48;
832
+ } else
833
+ goto st48;
834
+ goto st0;
835
+ st48:
836
+ if ( ++p == pe )
837
+ goto _out48;
838
+ case 48:
839
+ switch( (*p) ) {
840
+ case 32: goto tr2;
841
+ case 36: goto st49;
842
+ case 95: goto st49;
843
+ }
844
+ if ( (*p) < 48 ) {
845
+ if ( 45 <= (*p) && (*p) <= 46 )
846
+ goto st49;
847
+ } else if ( (*p) > 57 ) {
848
+ if ( 65 <= (*p) && (*p) <= 90 )
849
+ goto st49;
850
+ } else
851
+ goto st49;
852
+ goto st0;
853
+ st49:
854
+ if ( ++p == pe )
855
+ goto _out49;
856
+ case 49:
857
+ switch( (*p) ) {
858
+ case 32: goto tr2;
859
+ case 36: goto st50;
860
+ case 95: goto st50;
861
+ }
862
+ if ( (*p) < 48 ) {
863
+ if ( 45 <= (*p) && (*p) <= 46 )
864
+ goto st50;
865
+ } else if ( (*p) > 57 ) {
866
+ if ( 65 <= (*p) && (*p) <= 90 )
867
+ goto st50;
868
+ } else
869
+ goto st50;
870
+ goto st0;
871
+ st50:
872
+ if ( ++p == pe )
873
+ goto _out50;
874
+ case 50:
875
+ switch( (*p) ) {
876
+ case 32: goto tr2;
877
+ case 36: goto st51;
878
+ case 95: goto st51;
879
+ }
880
+ if ( (*p) < 48 ) {
881
+ if ( 45 <= (*p) && (*p) <= 46 )
882
+ goto st51;
883
+ } else if ( (*p) > 57 ) {
884
+ if ( 65 <= (*p) && (*p) <= 90 )
885
+ goto st51;
886
+ } else
887
+ goto st51;
888
+ goto st0;
889
+ st51:
890
+ if ( ++p == pe )
891
+ goto _out51;
892
+ case 51:
893
+ switch( (*p) ) {
894
+ case 32: goto tr2;
895
+ case 36: goto st52;
896
+ case 95: goto st52;
897
+ }
898
+ if ( (*p) < 48 ) {
899
+ if ( 45 <= (*p) && (*p) <= 46 )
900
+ goto st52;
901
+ } else if ( (*p) > 57 ) {
902
+ if ( 65 <= (*p) && (*p) <= 90 )
903
+ goto st52;
904
+ } else
905
+ goto st52;
906
+ goto st0;
907
+ st52:
908
+ if ( ++p == pe )
909
+ goto _out52;
910
+ case 52:
911
+ switch( (*p) ) {
912
+ case 32: goto tr2;
913
+ case 36: goto st53;
914
+ case 95: goto st53;
915
+ }
916
+ if ( (*p) < 48 ) {
917
+ if ( 45 <= (*p) && (*p) <= 46 )
918
+ goto st53;
919
+ } else if ( (*p) > 57 ) {
920
+ if ( 65 <= (*p) && (*p) <= 90 )
921
+ goto st53;
922
+ } else
923
+ goto st53;
924
+ goto st0;
925
+ st53:
926
+ if ( ++p == pe )
927
+ goto _out53;
928
+ case 53:
929
+ switch( (*p) ) {
930
+ case 32: goto tr2;
931
+ case 36: goto st54;
932
+ case 95: goto st54;
933
+ }
934
+ if ( (*p) < 48 ) {
935
+ if ( 45 <= (*p) && (*p) <= 46 )
936
+ goto st54;
937
+ } else if ( (*p) > 57 ) {
938
+ if ( 65 <= (*p) && (*p) <= 90 )
939
+ goto st54;
940
+ } else
941
+ goto st54;
942
+ goto st0;
943
+ st54:
944
+ if ( ++p == pe )
945
+ goto _out54;
946
+ case 54:
947
+ switch( (*p) ) {
948
+ case 32: goto tr2;
949
+ case 36: goto st55;
950
+ case 95: goto st55;
951
+ }
952
+ if ( (*p) < 48 ) {
953
+ if ( 45 <= (*p) && (*p) <= 46 )
954
+ goto st55;
955
+ } else if ( (*p) > 57 ) {
956
+ if ( 65 <= (*p) && (*p) <= 90 )
957
+ goto st55;
958
+ } else
959
+ goto st55;
960
+ goto st0;
961
+ st55:
962
+ if ( ++p == pe )
963
+ goto _out55;
964
+ case 55:
965
+ switch( (*p) ) {
966
+ case 32: goto tr2;
967
+ case 36: goto st56;
968
+ case 95: goto st56;
969
+ }
970
+ if ( (*p) < 48 ) {
971
+ if ( 45 <= (*p) && (*p) <= 46 )
972
+ goto st56;
973
+ } else if ( (*p) > 57 ) {
974
+ if ( 65 <= (*p) && (*p) <= 90 )
975
+ goto st56;
976
+ } else
977
+ goto st56;
978
+ goto st0;
979
+ st56:
980
+ if ( ++p == pe )
981
+ goto _out56;
982
+ case 56:
983
+ if ( (*p) == 32 )
984
+ goto tr2;
985
+ goto st0;
986
+ }
987
+ _out0: cs = 0; goto _out;
988
+ _out2: cs = 2; goto _out;
989
+ _out3: cs = 3; goto _out;
990
+ _out4: cs = 4; goto _out;
991
+ _out5: cs = 5; goto _out;
992
+ _out6: cs = 6; goto _out;
993
+ _out7: cs = 7; goto _out;
994
+ _out8: cs = 8; goto _out;
995
+ _out9: cs = 9; goto _out;
996
+ _out10: cs = 10; goto _out;
997
+ _out11: cs = 11; goto _out;
998
+ _out12: cs = 12; goto _out;
999
+ _out13: cs = 13; goto _out;
1000
+ _out14: cs = 14; goto _out;
1001
+ _out15: cs = 15; goto _out;
1002
+ _out16: cs = 16; goto _out;
1003
+ _out57: cs = 57; goto _out;
1004
+ _out17: cs = 17; goto _out;
1005
+ _out18: cs = 18; goto _out;
1006
+ _out19: cs = 19; goto _out;
1007
+ _out20: cs = 20; goto _out;
1008
+ _out21: cs = 21; goto _out;
1009
+ _out22: cs = 22; goto _out;
1010
+ _out23: cs = 23; goto _out;
1011
+ _out24: cs = 24; goto _out;
1012
+ _out25: cs = 25; goto _out;
1013
+ _out26: cs = 26; goto _out;
1014
+ _out27: cs = 27; goto _out;
1015
+ _out28: cs = 28; goto _out;
1016
+ _out29: cs = 29; goto _out;
1017
+ _out30: cs = 30; goto _out;
1018
+ _out31: cs = 31; goto _out;
1019
+ _out32: cs = 32; goto _out;
1020
+ _out33: cs = 33; goto _out;
1021
+ _out34: cs = 34; goto _out;
1022
+ _out35: cs = 35; goto _out;
1023
+ _out36: cs = 36; goto _out;
1024
+ _out37: cs = 37; goto _out;
1025
+ _out38: cs = 38; goto _out;
1026
+ _out39: cs = 39; goto _out;
1027
+ _out40: cs = 40; goto _out;
1028
+ _out41: cs = 41; goto _out;
1029
+ _out42: cs = 42; goto _out;
1030
+ _out43: cs = 43; goto _out;
1031
+ _out44: cs = 44; goto _out;
1032
+ _out45: cs = 45; goto _out;
1033
+ _out46: cs = 46; goto _out;
1034
+ _out47: cs = 47; goto _out;
1035
+ _out48: cs = 48; goto _out;
1036
+ _out49: cs = 49; goto _out;
1037
+ _out50: cs = 50; goto _out;
1038
+ _out51: cs = 51; goto _out;
1039
+ _out52: cs = 52; goto _out;
1040
+ _out53: cs = 53; goto _out;
1041
+ _out54: cs = 54; goto _out;
1042
+ _out55: cs = 55; goto _out;
1043
+ _out56: cs = 56; goto _out;
1044
+
1045
+ _out:
1046
+ parser->cs = cs;
1047
+ parser->nread += p - (buffer + off);
1048
+
1049
+ assert(p <= pe && "buffer overflow after parsing execute");
1050
+ assert(parser->nread <= len && "nread longer than length");
1051
+ assert(parser->body_start <= len && "body starts after buffer end");
1052
+ assert(parser->mark < len && "mark is after buffer end");
1053
+ assert(parser->field_len <= len && "field has length longer than whole buffer");
1054
+ assert(parser->field_start < len && "field starts after buffer end");
1055
+
1056
+ if(parser->body_start) {
1057
+ /* final \r\n combo encountered so stop right here */
1058
+
1059
+ parser->nread++;
1060
+ }
1061
+
1062
+ return(parser->nread);
1063
+ }
1064
+
1065
+ int http_parser_finish(http_parser *parser)
1066
+ {
1067
+ int cs = parser->cs;
1068
+
1069
+ parser->cs = cs;
1070
+
1071
+ if (http_parser_has_error(parser) ) {
1072
+ return -1;
1073
+ } else if (http_parser_is_finished(parser) ) {
1074
+ return 1;
1075
+ } else {
1076
+ return 0;
1077
+ }
1078
+ }
1079
+
1080
+ int http_parser_has_error(http_parser *parser) {
1081
+ return parser->cs == http_parser_error;
1082
+ }
1083
+
1084
+ int http_parser_is_finished(http_parser *parser) {
1085
+ return parser->cs == http_parser_first_final;
1086
+ }