em-http-request 0.2.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of em-http-request might be problematic. Click here for more details.

@@ -0,0 +1,53 @@
1
+ require 'mkmf'
2
+
3
+ libs = []
4
+
5
+ $defs << "-DRUBY_VERSION_CODE=#{RUBY_VERSION.gsub(/\D/, '')}"
6
+
7
+ if have_func('rb_thread_blocking_region')
8
+ $defs << '-DHAVE_RB_THREAD_BLOCKING_REGION'
9
+ end
10
+
11
+ if have_func('rb_str_set_len')
12
+ $defs << '-DHAVE_RB_STR_SET_LEN'
13
+ end
14
+
15
+ if have_header('sys/select.h')
16
+ $defs << '-DEV_USE_SELECT'
17
+ end
18
+
19
+ if have_header('poll.h')
20
+ $defs << '-DEV_USE_POLL'
21
+ end
22
+
23
+ if have_header('sys/epoll.h')
24
+ $defs << '-DEV_USE_EPOLL'
25
+ end
26
+
27
+ if have_header('sys/event.h') and have_header('sys/queue.h')
28
+ $defs << '-DEV_USE_KQUEUE'
29
+ end
30
+
31
+ if have_header('port.h')
32
+ $defs << '-DEV_USE_PORT'
33
+ end
34
+
35
+ if have_header('openssl/ssl.h')
36
+ $defs << '-DHAVE_OPENSSL_SSL_H'
37
+ libs << '-lssl -lcrypto'
38
+ end
39
+
40
+ # ncpu detection specifics
41
+ case RUBY_PLATFORM
42
+ when /linux/
43
+ $defs << '-DHAVE_LINUX_PROCFS'
44
+ else
45
+ if have_func('sysctlbyname', ['sys/param.h', 'sys/sysctl.h'])
46
+ $defs << '-DHAVE_SYSCTLBYNAME'
47
+ end
48
+ end
49
+
50
+ $LIBS << ' ' << libs.join(' ')
51
+
52
+ dir_config('em_buffer')
53
+ create_makefile('em_buffer')
@@ -0,0 +1,14 @@
1
+ #ifndef ext_help_h
2
+ #define ext_help_h
3
+
4
+ #define RAISE_NOT_NULL(T) if(T == NULL) rb_raise(rb_eArgError, "NULL found for " # T " when shouldn't be.");
5
+ #define DATA_GET(from,type,name) Data_Get_Struct(from,type,name); RAISE_NOT_NULL(name);
6
+ #define REQUIRE_TYPE(V, T) if(TYPE(V) != T) rb_raise(rb_eTypeError, "Wrong argument type for " # V " required " # T);
7
+
8
+ #ifdef DEBUG
9
+ #define TRACE() fprintf(stderr, "> %s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__)
10
+ #else
11
+ #define TRACE()
12
+ #endif
13
+
14
+ #endif
@@ -0,0 +1,6 @@
1
+ require 'mkmf'
2
+
3
+ dir_config("http11_client")
4
+ have_library("c", "main")
5
+
6
+ create_makefile("http11_client")
@@ -0,0 +1,302 @@
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
+
6
+ #include "ruby.h"
7
+ #include "ext_help.h"
8
+ #include <assert.h>
9
+ #include <string.h>
10
+ #include "http11_parser.h"
11
+ #include <ctype.h>
12
+
13
+ static VALUE mEm;
14
+ static VALUE cHttpClientParser;
15
+ static VALUE eHttpClientParserError;
16
+
17
+ #define id_reason rb_intern("@http_reason")
18
+ #define id_status rb_intern("@http_status")
19
+ #define id_version rb_intern("@http_version")
20
+ #define id_body rb_intern("@http_body")
21
+ #define id_chunk_size rb_intern("@http_chunk_size")
22
+ #define id_last_chunk rb_intern("@last_chunk")
23
+
24
+ void client_http_field(void *data, const char *field, size_t flen, const char *value, size_t vlen)
25
+ {
26
+ char *ch, *end;
27
+ VALUE req = (VALUE)data;
28
+ VALUE v = Qnil;
29
+ VALUE f = Qnil;
30
+
31
+ v = rb_str_new(value, vlen);
32
+ f = rb_str_new(field, flen);
33
+
34
+ /* Yes Children, rb_str_upcase_bang isn't even available as an intern.h function.
35
+ * how incredibly handy to not have that. Nope, I have to do it by hand.*/
36
+ for(ch = RSTRING_PTR(f), end = ch + RSTRING_LEN(f); ch < end; ch++) {
37
+ if(*ch == '-') {
38
+ *ch = '_';
39
+ } else {
40
+ *ch = toupper(*ch);
41
+ }
42
+ }
43
+
44
+ rb_hash_aset(req, f, v);
45
+ }
46
+
47
+ void client_reason_phrase(void *data, const char *at, size_t length)
48
+ {
49
+ VALUE req = (VALUE)data;
50
+ VALUE v = Qnil;
51
+
52
+ v = rb_str_new(at, length);
53
+
54
+ rb_ivar_set(req, id_reason, v);
55
+ }
56
+
57
+ void client_status_code(void *data, const char *at, size_t length)
58
+ {
59
+ VALUE req = (VALUE)data;
60
+ VALUE v = Qnil;
61
+
62
+ v = rb_str_new(at, length);
63
+
64
+ rb_ivar_set(req, id_status, v);
65
+ }
66
+
67
+ void client_http_version(void *data, const char *at, size_t length)
68
+ {
69
+ VALUE req = (VALUE)data;
70
+ VALUE v = Qnil;
71
+
72
+ v = rb_str_new(at, length);
73
+
74
+ rb_ivar_set(req, id_version, v);
75
+ }
76
+
77
+ /** Finalizes the request header to have a bunch of stuff that's
78
+ needed. */
79
+ void client_header_done(void *data, const char *at, size_t length)
80
+ {
81
+ VALUE req = (VALUE)data;
82
+ VALUE v = Qnil;
83
+
84
+ v = rb_str_new(at, length);
85
+ rb_ivar_set(req, id_body, v);
86
+ }
87
+
88
+ void client_chunk_size(void *data, const char *at, size_t length)
89
+ {
90
+ VALUE req = (VALUE)data;
91
+ VALUE v = Qnil;
92
+
93
+ if(length <= 0) {
94
+ rb_raise(eHttpClientParserError, "Chunked Encoding gave <= 0 chunk size.");
95
+ }
96
+
97
+ v = rb_str_new(at, length);
98
+
99
+ rb_ivar_set(req, id_chunk_size, v);
100
+ }
101
+
102
+ void client_last_chunk(void *data, const char *at, size_t length) {
103
+ VALUE req = (VALUE)data;
104
+ rb_ivar_set(req, id_last_chunk,Qtrue);
105
+ }
106
+
107
+
108
+ void HttpClientParser_free(void *data) {
109
+ TRACE();
110
+
111
+ if(data) {
112
+ free(data);
113
+ }
114
+ }
115
+
116
+
117
+ VALUE HttpClientParser_alloc(VALUE klass)
118
+ {
119
+ VALUE obj;
120
+ httpclient_parser *hp = ALLOC_N(httpclient_parser, 1);
121
+ TRACE();
122
+ hp->http_field = client_http_field;
123
+ hp->status_code = client_status_code;
124
+ hp->reason_phrase = client_reason_phrase;
125
+ hp->http_version = client_http_version;
126
+ hp->header_done = client_header_done;
127
+ hp->chunk_size = client_chunk_size;
128
+ hp->last_chunk = client_last_chunk;
129
+ httpclient_parser_init(hp);
130
+
131
+ obj = Data_Wrap_Struct(klass, NULL, HttpClientParser_free, hp);
132
+
133
+ return obj;
134
+ }
135
+
136
+
137
+ /**
138
+ * call-seq:
139
+ * parser.new -> parser
140
+ *
141
+ * Creates a new parser.
142
+ */
143
+ VALUE HttpClientParser_init(VALUE self)
144
+ {
145
+ httpclient_parser *http = NULL;
146
+ DATA_GET(self, httpclient_parser, http);
147
+ httpclient_parser_init(http);
148
+
149
+ return self;
150
+ }
151
+
152
+
153
+ /**
154
+ * call-seq:
155
+ * parser.reset -> nil
156
+ *
157
+ * Resets the parser to it's initial state so that you can reuse it
158
+ * rather than making new ones.
159
+ */
160
+ VALUE HttpClientParser_reset(VALUE self)
161
+ {
162
+ httpclient_parser *http = NULL;
163
+ DATA_GET(self, httpclient_parser, http);
164
+ httpclient_parser_init(http);
165
+
166
+ return Qnil;
167
+ }
168
+
169
+
170
+ /**
171
+ * call-seq:
172
+ * parser.finish -> true/false
173
+ *
174
+ * Finishes a parser early which could put in a "good" or bad state.
175
+ * You should call reset after finish it or bad things will happen.
176
+ */
177
+ VALUE HttpClientParser_finish(VALUE self)
178
+ {
179
+ httpclient_parser *http = NULL;
180
+ DATA_GET(self, httpclient_parser, http);
181
+ httpclient_parser_finish(http);
182
+
183
+ return httpclient_parser_is_finished(http) ? Qtrue : Qfalse;
184
+ }
185
+
186
+
187
+ /**
188
+ * call-seq:
189
+ * parser.execute(req_hash, data, start) -> Integer
190
+ *
191
+ * Takes a Hash and a String of data, parses the String of data filling in the Hash
192
+ * returning an Integer to indicate how much of the data has been read. No matter
193
+ * what the return value, you should call HttpClientParser#finished? and HttpClientParser#error?
194
+ * to figure out if it's done parsing or there was an error.
195
+ *
196
+ * This function now throws an exception when there is a parsing error. This makes
197
+ * the logic for working with the parser much easier. You can still test for an
198
+ * error, but now you need to wrap the parser with an exception handling block.
199
+ *
200
+ * The third argument allows for parsing a partial request and then continuing
201
+ * the parsing from that position. It needs all of the original data as well
202
+ * so you have to append to the data buffer as you read.
203
+ */
204
+ VALUE HttpClientParser_execute(VALUE self, VALUE req_hash, VALUE data, VALUE start)
205
+ {
206
+ httpclient_parser *http = NULL;
207
+ int from = 0;
208
+ char *dptr = NULL;
209
+ long dlen = 0;
210
+
211
+ REQUIRE_TYPE(req_hash, T_HASH);
212
+ REQUIRE_TYPE(data, T_STRING);
213
+ REQUIRE_TYPE(start, T_FIXNUM);
214
+
215
+ DATA_GET(self, httpclient_parser, http);
216
+
217
+ from = FIX2INT(start);
218
+ dptr = RSTRING_PTR(data);
219
+ dlen = RSTRING_LEN(data);
220
+
221
+ if(from >= dlen) {
222
+ rb_raise(eHttpClientParserError, "Requested start is after data buffer end.");
223
+ } else {
224
+ http->data = (void *)req_hash;
225
+ httpclient_parser_execute(http, dptr, dlen, from);
226
+
227
+ if(httpclient_parser_has_error(http)) {
228
+ rb_raise(eHttpClientParserError, "Invalid HTTP format, parsing fails.");
229
+ } else {
230
+ return INT2FIX(httpclient_parser_nread(http));
231
+ }
232
+ }
233
+ }
234
+
235
+
236
+
237
+ /**
238
+ * call-seq:
239
+ * parser.error? -> true/false
240
+ *
241
+ * Tells you whether the parser is in an error state.
242
+ */
243
+ VALUE HttpClientParser_has_error(VALUE self)
244
+ {
245
+ httpclient_parser *http = NULL;
246
+ DATA_GET(self, httpclient_parser, http);
247
+
248
+ return httpclient_parser_has_error(http) ? Qtrue : Qfalse;
249
+ }
250
+
251
+
252
+ /**
253
+ * call-seq:
254
+ * parser.finished? -> true/false
255
+ *
256
+ * Tells you whether the parser is finished or not and in a good state.
257
+ */
258
+ VALUE HttpClientParser_is_finished(VALUE self)
259
+ {
260
+ httpclient_parser *http = NULL;
261
+ DATA_GET(self, httpclient_parser, http);
262
+
263
+ return httpclient_parser_is_finished(http) ? Qtrue : Qfalse;
264
+ }
265
+
266
+
267
+ /**
268
+ * call-seq:
269
+ * parser.nread -> Integer
270
+ *
271
+ * Returns the amount of data processed so far during this processing cycle. It is
272
+ * set to 0 on initialize or reset calls and is incremented each time execute is called.
273
+ */
274
+ VALUE HttpClientParser_nread(VALUE self)
275
+ {
276
+ httpclient_parser *http = NULL;
277
+ DATA_GET(self, httpclient_parser, http);
278
+
279
+ return INT2FIX(http->nread);
280
+ }
281
+
282
+
283
+
284
+ void Init_http11_client()
285
+ {
286
+
287
+ mEm = rb_define_module("EventMachine");
288
+
289
+ eHttpClientParserError = rb_define_class_under(mEm, "HttpClientParserError", rb_eIOError);
290
+
291
+ cHttpClientParser = rb_define_class_under(mEm, "HttpClientParser", rb_cObject);
292
+ rb_define_alloc_func(cHttpClientParser, HttpClientParser_alloc);
293
+ rb_define_method(cHttpClientParser, "initialize", HttpClientParser_init,0);
294
+ rb_define_method(cHttpClientParser, "reset", HttpClientParser_reset,0);
295
+ rb_define_method(cHttpClientParser, "finish", HttpClientParser_finish,0);
296
+ rb_define_method(cHttpClientParser, "execute", HttpClientParser_execute,3);
297
+ rb_define_method(cHttpClientParser, "error?", HttpClientParser_has_error,0);
298
+ rb_define_method(cHttpClientParser, "finished?", HttpClientParser_is_finished,0);
299
+ rb_define_method(cHttpClientParser, "nread", HttpClientParser_nread,0);
300
+ }
301
+
302
+
@@ -0,0 +1,418 @@
1
+
2
+ #line 1 "http11_parser.rl"
3
+ /**
4
+ * Copyright (c) 2005 Zed A. Shaw
5
+ * You can redistribute it and/or modify it under the same terms as Ruby.
6
+ */
7
+
8
+ #include "http11_parser.h"
9
+ #include <stdio.h>
10
+ #include <assert.h>
11
+ #include <stdlib.h>
12
+ #include <ctype.h>
13
+ #include <string.h>
14
+
15
+ #define LEN(AT, FPC) (FPC - buffer - parser->AT)
16
+ #define MARK(M,FPC) (parser->M = (FPC) - buffer)
17
+ #define PTR_TO(F) (buffer + parser->F)
18
+ #define L(M) fprintf(stderr, "" # M "\n");
19
+
20
+
21
+ /** machine **/
22
+
23
+ #line 95 "http11_parser.rl"
24
+
25
+
26
+ /** Data **/
27
+
28
+ #line 29 "http11_parser.c"
29
+ static const char _httpclient_parser_actions[] = {
30
+ 0, 1, 0, 1, 1, 1, 2, 1,
31
+ 3, 1, 4, 1, 5, 1, 7, 1,
32
+ 8, 1, 10, 2, 0, 5, 2, 2,
33
+ 3, 2, 3, 4, 2, 4, 10, 2,
34
+ 6, 0, 2, 8, 10, 2, 9, 10,
35
+ 2, 10, 9, 3, 2, 3, 4, 3,
36
+ 4, 9, 10, 3, 4, 10, 9, 3,
37
+ 6, 0, 5, 3, 8, 10, 9, 4,
38
+ 2, 3, 4, 10, 5, 2, 3, 4,
39
+ 9, 10, 5, 2, 3, 4, 10, 9
40
+
41
+ };
42
+
43
+ static const short _httpclient_parser_key_offsets[] = {
44
+ 0, 0, 11, 12, 24, 29, 30, 31,
45
+ 43, 58, 80, 95, 116, 131, 153, 168,
46
+ 189, 204, 223, 238, 256, 257, 258, 259,
47
+ 260, 262, 265, 267, 270, 272, 274, 276,
48
+ 279, 281, 298, 314, 317, 319, 320, 322
49
+ };
50
+
51
+ static const char _httpclient_parser_trans_keys[] = {
52
+ 10, 13, 48, 59, 72, 49, 57, 65,
53
+ 70, 97, 102, 10, 10, 13, 32, 59,
54
+ 9, 12, 48, 57, 65, 70, 97, 102,
55
+ 10, 13, 32, 9, 12, 10, 10, 10,
56
+ 13, 32, 59, 9, 12, 48, 57, 65,
57
+ 70, 97, 102, 33, 124, 126, 35, 39,
58
+ 42, 43, 45, 46, 48, 57, 65, 90,
59
+ 94, 122, 10, 13, 32, 33, 59, 61,
60
+ 124, 126, 9, 12, 35, 39, 42, 43,
61
+ 45, 46, 48, 57, 65, 90, 94, 122,
62
+ 33, 124, 126, 35, 39, 42, 43, 45,
63
+ 46, 48, 57, 65, 90, 94, 122, 10,
64
+ 13, 32, 33, 59, 124, 126, 9, 12,
65
+ 35, 39, 42, 43, 45, 46, 48, 57,
66
+ 65, 90, 94, 122, 33, 124, 126, 35,
67
+ 39, 42, 43, 45, 46, 48, 57, 65,
68
+ 90, 94, 122, 10, 13, 32, 33, 59,
69
+ 61, 124, 126, 9, 12, 35, 39, 42,
70
+ 43, 45, 46, 48, 57, 65, 90, 94,
71
+ 122, 33, 124, 126, 35, 39, 42, 43,
72
+ 45, 46, 48, 57, 65, 90, 94, 122,
73
+ 10, 13, 32, 33, 59, 124, 126, 9,
74
+ 12, 35, 39, 42, 43, 45, 46, 48,
75
+ 57, 65, 90, 94, 122, 33, 124, 126,
76
+ 35, 39, 42, 43, 45, 46, 48, 57,
77
+ 65, 90, 94, 122, 10, 13, 33, 59,
78
+ 61, 124, 126, 35, 39, 42, 43, 45,
79
+ 46, 48, 57, 65, 90, 94, 122, 33,
80
+ 124, 126, 35, 39, 42, 43, 45, 46,
81
+ 48, 57, 65, 90, 94, 122, 10, 13,
82
+ 33, 59, 124, 126, 35, 39, 42, 43,
83
+ 45, 46, 48, 57, 65, 90, 94, 122,
84
+ 84, 84, 80, 47, 48, 57, 46, 48,
85
+ 57, 48, 57, 32, 48, 57, 48, 57,
86
+ 48, 57, 48, 57, 10, 13, 32, 10,
87
+ 13, 10, 13, 33, 124, 126, 35, 39,
88
+ 42, 43, 45, 46, 48, 57, 65, 90,
89
+ 94, 122, 33, 58, 124, 126, 35, 39,
90
+ 42, 43, 45, 46, 48, 57, 65, 90,
91
+ 94, 122, 10, 13, 32, 10, 13, 10,
92
+ 10, 13, 0
93
+ };
94
+
95
+ static const char _httpclient_parser_single_lengths[] = {
96
+ 0, 5, 1, 4, 3, 1, 1, 4,
97
+ 3, 8, 3, 7, 3, 8, 3, 7,
98
+ 3, 7, 3, 6, 1, 1, 1, 1,
99
+ 0, 1, 0, 1, 0, 0, 0, 3,
100
+ 2, 5, 4, 3, 2, 1, 2, 0
101
+ };
102
+
103
+ static const char _httpclient_parser_range_lengths[] = {
104
+ 0, 3, 0, 4, 1, 0, 0, 4,
105
+ 6, 7, 6, 7, 6, 7, 6, 7,
106
+ 6, 6, 6, 6, 0, 0, 0, 0,
107
+ 1, 1, 1, 1, 1, 1, 1, 0,
108
+ 0, 6, 6, 0, 0, 0, 0, 0
109
+ };
110
+
111
+ static const short _httpclient_parser_index_offsets[] = {
112
+ 0, 0, 9, 11, 20, 25, 27, 29,
113
+ 38, 48, 64, 74, 89, 99, 115, 125,
114
+ 140, 150, 164, 174, 187, 189, 191, 193,
115
+ 195, 197, 200, 202, 205, 207, 209, 211,
116
+ 215, 218, 230, 241, 245, 248, 250, 253
117
+ };
118
+
119
+ static const char _httpclient_parser_indicies[] = {
120
+ 0, 2, 3, 5, 6, 4, 4, 4,
121
+ 1, 0, 1, 8, 9, 7, 11, 7,
122
+ 10, 10, 10, 1, 13, 14, 12, 12,
123
+ 1, 13, 1, 15, 1, 16, 17, 7,
124
+ 18, 7, 10, 10, 10, 1, 19, 19,
125
+ 19, 19, 19, 19, 19, 19, 19, 1,
126
+ 21, 22, 20, 23, 24, 25, 23, 23,
127
+ 20, 23, 23, 23, 23, 23, 23, 1,
128
+ 26, 26, 26, 26, 26, 26, 26, 26,
129
+ 26, 1, 28, 29, 27, 30, 31, 30,
130
+ 30, 27, 30, 30, 30, 30, 30, 30,
131
+ 1, 32, 32, 32, 32, 32, 32, 32,
132
+ 32, 32, 1, 33, 34, 20, 35, 36,
133
+ 37, 35, 35, 20, 35, 35, 35, 35,
134
+ 35, 35, 1, 38, 38, 38, 38, 38,
135
+ 38, 38, 38, 38, 1, 39, 40, 27,
136
+ 41, 42, 41, 41, 27, 41, 41, 41,
137
+ 41, 41, 41, 1, 43, 43, 43, 43,
138
+ 43, 43, 43, 43, 43, 1, 44, 45,
139
+ 46, 47, 48, 46, 46, 46, 46, 46,
140
+ 46, 46, 46, 1, 49, 49, 49, 49,
141
+ 49, 49, 49, 49, 49, 1, 50, 51,
142
+ 52, 53, 52, 52, 52, 52, 52, 52,
143
+ 52, 52, 1, 54, 1, 55, 1, 56,
144
+ 1, 57, 1, 58, 1, 59, 58, 1,
145
+ 60, 1, 61, 60, 1, 62, 1, 63,
146
+ 1, 64, 1, 66, 67, 68, 65, 70,
147
+ 71, 69, 13, 14, 72, 72, 72, 72,
148
+ 72, 72, 72, 72, 72, 1, 73, 74,
149
+ 73, 73, 73, 73, 73, 73, 73, 73,
150
+ 1, 76, 77, 78, 75, 80, 81, 79,
151
+ 82, 1, 84, 85, 83, 1, 0
152
+ };
153
+
154
+ static const char _httpclient_parser_trans_targs[] = {
155
+ 39, 0, 2, 3, 7, 16, 20, 4,
156
+ 39, 6, 7, 12, 4, 39, 5, 39,
157
+ 39, 5, 8, 9, 4, 39, 5, 9,
158
+ 8, 10, 11, 4, 39, 5, 11, 8,
159
+ 13, 39, 6, 13, 12, 14, 15, 39,
160
+ 6, 15, 12, 17, 39, 2, 17, 16,
161
+ 18, 19, 39, 2, 19, 16, 21, 22,
162
+ 23, 24, 25, 26, 27, 28, 29, 30,
163
+ 31, 32, 33, 37, 38, 32, 33, 37,
164
+ 34, 34, 35, 36, 33, 37, 35, 36,
165
+ 33, 37, 33, 32, 33, 37
166
+ };
167
+
168
+ static const char _httpclient_parser_trans_actions[] = {
169
+ 37, 0, 0, 1, 1, 0, 1, 15,
170
+ 59, 15, 0, 15, 0, 17, 0, 40,
171
+ 34, 15, 15, 3, 43, 63, 43, 0,
172
+ 43, 22, 7, 9, 28, 9, 0, 9,
173
+ 3, 74, 43, 0, 43, 22, 7, 51,
174
+ 9, 0, 9, 3, 68, 43, 0, 43,
175
+ 22, 7, 47, 9, 0, 9, 0, 0,
176
+ 0, 0, 0, 0, 0, 13, 1, 0,
177
+ 0, 31, 55, 55, 31, 0, 11, 11,
178
+ 3, 0, 5, 7, 25, 25, 7, 0,
179
+ 9, 9, 0, 1, 19, 19
180
+ };
181
+
182
+ static const int httpclient_parser_start = 1;
183
+ static const int httpclient_parser_first_final = 39;
184
+ static const int httpclient_parser_error = 0;
185
+
186
+ static const int httpclient_parser_en_main = 1;
187
+
188
+
189
+ #line 99 "http11_parser.rl"
190
+
191
+ int httpclient_parser_init(httpclient_parser *parser) {
192
+ int cs = 0;
193
+
194
+ #line 195 "http11_parser.c"
195
+ {
196
+ cs = httpclient_parser_start;
197
+ }
198
+
199
+ #line 103 "http11_parser.rl"
200
+ parser->cs = cs;
201
+ parser->body_start = 0;
202
+ parser->content_len = 0;
203
+ parser->mark = 0;
204
+ parser->nread = 0;
205
+ parser->field_len = 0;
206
+ parser->field_start = 0;
207
+
208
+ return(1);
209
+ }
210
+
211
+
212
+ /** exec **/
213
+ size_t httpclient_parser_execute(httpclient_parser *parser, const char *buffer, size_t len, size_t off) {
214
+ const char *p, *pe;
215
+ int cs = parser->cs;
216
+
217
+ assert(off <= len && "offset past end of buffer");
218
+
219
+ p = buffer+off;
220
+ pe = buffer+len;
221
+
222
+ assert(*pe == '\0' && "pointer does not end on NUL");
223
+ assert(pe - p == len - off && "pointers aren't same distance");
224
+
225
+
226
+
227
+ #line 228 "http11_parser.c"
228
+ {
229
+ int _klen;
230
+ unsigned int _trans;
231
+ const char *_acts;
232
+ unsigned int _nacts;
233
+ const char *_keys;
234
+
235
+ if ( p == pe )
236
+ goto _test_eof;
237
+ if ( cs == 0 )
238
+ goto _out;
239
+ _resume:
240
+ _keys = _httpclient_parser_trans_keys + _httpclient_parser_key_offsets[cs];
241
+ _trans = _httpclient_parser_index_offsets[cs];
242
+
243
+ _klen = _httpclient_parser_single_lengths[cs];
244
+ if ( _klen > 0 ) {
245
+ const char *_lower = _keys;
246
+ const char *_mid;
247
+ const char *_upper = _keys + _klen - 1;
248
+ while (1) {
249
+ if ( _upper < _lower )
250
+ break;
251
+
252
+ _mid = _lower + ((_upper-_lower) >> 1);
253
+ if ( (*p) < *_mid )
254
+ _upper = _mid - 1;
255
+ else if ( (*p) > *_mid )
256
+ _lower = _mid + 1;
257
+ else {
258
+ _trans += (_mid - _keys);
259
+ goto _match;
260
+ }
261
+ }
262
+ _keys += _klen;
263
+ _trans += _klen;
264
+ }
265
+
266
+ _klen = _httpclient_parser_range_lengths[cs];
267
+ if ( _klen > 0 ) {
268
+ const char *_lower = _keys;
269
+ const char *_mid;
270
+ const char *_upper = _keys + (_klen<<1) - 2;
271
+ while (1) {
272
+ if ( _upper < _lower )
273
+ break;
274
+
275
+ _mid = _lower + (((_upper-_lower) >> 1) & ~1);
276
+ if ( (*p) < _mid[0] )
277
+ _upper = _mid - 2;
278
+ else if ( (*p) > _mid[1] )
279
+ _lower = _mid + 2;
280
+ else {
281
+ _trans += ((_mid - _keys)>>1);
282
+ goto _match;
283
+ }
284
+ }
285
+ _trans += _klen;
286
+ }
287
+
288
+ _match:
289
+ _trans = _httpclient_parser_indicies[_trans];
290
+ cs = _httpclient_parser_trans_targs[_trans];
291
+
292
+ if ( _httpclient_parser_trans_actions[_trans] == 0 )
293
+ goto _again;
294
+
295
+ _acts = _httpclient_parser_actions + _httpclient_parser_trans_actions[_trans];
296
+ _nacts = (unsigned int) *_acts++;
297
+ while ( _nacts-- > 0 )
298
+ {
299
+ switch ( *_acts++ )
300
+ {
301
+ case 0:
302
+ #line 23 "http11_parser.rl"
303
+ {MARK(mark, p); }
304
+ break;
305
+ case 1:
306
+ #line 25 "http11_parser.rl"
307
+ { MARK(field_start, p); }
308
+ break;
309
+ case 2:
310
+ #line 27 "http11_parser.rl"
311
+ {
312
+ parser->field_len = LEN(field_start, p);
313
+ }
314
+ break;
315
+ case 3:
316
+ #line 31 "http11_parser.rl"
317
+ { MARK(mark, p); }
318
+ break;
319
+ case 4:
320
+ #line 33 "http11_parser.rl"
321
+ {
322
+ parser->http_field(parser->data, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, p));
323
+ }
324
+ break;
325
+ case 5:
326
+ #line 37 "http11_parser.rl"
327
+ {
328
+ parser->reason_phrase(parser->data, PTR_TO(mark), LEN(mark, p));
329
+ }
330
+ break;
331
+ case 6:
332
+ #line 41 "http11_parser.rl"
333
+ {
334
+ parser->status_code(parser->data, PTR_TO(mark), LEN(mark, p));
335
+ }
336
+ break;
337
+ case 7:
338
+ #line 45 "http11_parser.rl"
339
+ {
340
+ parser->http_version(parser->data, PTR_TO(mark), LEN(mark, p));
341
+ }
342
+ break;
343
+ case 8:
344
+ #line 49 "http11_parser.rl"
345
+ {
346
+ parser->chunk_size(parser->data, PTR_TO(mark), LEN(mark, p));
347
+ }
348
+ break;
349
+ case 9:
350
+ #line 53 "http11_parser.rl"
351
+ {
352
+ parser->last_chunk(parser->data, NULL, 0);
353
+ }
354
+ break;
355
+ case 10:
356
+ #line 57 "http11_parser.rl"
357
+ {
358
+ parser->body_start = p - buffer + 1;
359
+ if(parser->header_done != NULL)
360
+ parser->header_done(parser->data, p + 1, pe - p - 1);
361
+ {p++; goto _out; }
362
+ }
363
+ break;
364
+ #line 365 "http11_parser.c"
365
+ }
366
+ }
367
+
368
+ _again:
369
+ if ( cs == 0 )
370
+ goto _out;
371
+ if ( ++p != pe )
372
+ goto _resume;
373
+ _test_eof: {}
374
+ _out: {}
375
+ }
376
+
377
+ #line 130 "http11_parser.rl"
378
+
379
+ parser->cs = cs;
380
+ parser->nread += p - (buffer + off);
381
+
382
+ assert(p <= pe && "buffer overflow after parsing execute");
383
+ assert(parser->nread <= len && "nread longer than length");
384
+ assert(parser->body_start <= len && "body starts after buffer end");
385
+ assert(parser->mark < len && "mark is after buffer end");
386
+ assert(parser->field_len <= len && "field has length longer than whole buffer");
387
+ assert(parser->field_start < len && "field starts after buffer end");
388
+
389
+ if(parser->body_start) {
390
+ /* final \r\n combo encountered so stop right here */
391
+ parser->nread = parser->body_start;
392
+ }
393
+
394
+ return(parser->nread);
395
+ }
396
+
397
+ int httpclient_parser_finish(httpclient_parser *parser)
398
+ {
399
+ int cs = parser->cs;
400
+
401
+ parser->cs = cs;
402
+
403
+ if (httpclient_parser_has_error(parser) ) {
404
+ return -1;
405
+ } else if (httpclient_parser_is_finished(parser) ) {
406
+ return 1;
407
+ } else {
408
+ return 0;
409
+ }
410
+ }
411
+
412
+ int httpclient_parser_has_error(httpclient_parser *parser) {
413
+ return parser->cs == httpclient_parser_error;
414
+ }
415
+
416
+ int httpclient_parser_is_finished(httpclient_parser *parser) {
417
+ return parser->cs == httpclient_parser_first_final;
418
+ }