h1p 0.1 → 0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/ext/h1p/h1p.c CHANGED
@@ -20,10 +20,11 @@ ID ID_call;
20
20
  ID ID_downcase;
21
21
  ID ID_eof_p;
22
22
  ID ID_eq;
23
- ID ID_parser_read_method;
23
+ ID ID_read_method;
24
24
  ID ID_read;
25
25
  ID ID_readpartial;
26
26
  ID ID_to_i;
27
+ ID ID_upcase;
27
28
 
28
29
  static VALUE mPolyphony = Qnil;
29
30
  static VALUE cError;
@@ -36,6 +37,8 @@ VALUE STR_pseudo_method;
36
37
  VALUE STR_pseudo_path;
37
38
  VALUE STR_pseudo_protocol;
38
39
  VALUE STR_pseudo_rx;
40
+ VALUE STR_pseudo_status;
41
+ VALUE STR_pseudo_status_message;
39
42
 
40
43
  VALUE STR_chunked;
41
44
  VALUE STR_content_length;
@@ -45,6 +48,9 @@ VALUE SYM_backend_read;
45
48
  VALUE SYM_backend_recv;
46
49
  VALUE SYM_stock_readpartial;
47
50
 
51
+ VALUE SYM_client;
52
+ VALUE SYM_server;
53
+
48
54
  enum read_method {
49
55
  method_readpartial, // receiver.readpartial(len, buf, pos, raise_on_eof: false) (Polyphony-specific)
50
56
  method_backend_read, // Polyphony.backend_read (Polyphony-specific)
@@ -53,17 +59,27 @@ enum read_method {
53
59
  method_stock_readpartial // receiver.readpartial(len)
54
60
  };
55
61
 
62
+ enum parser_mode {
63
+ mode_server,
64
+ mode_client
65
+ };
66
+
56
67
  typedef struct parser {
68
+ enum parser_mode mode;
57
69
  VALUE io;
58
70
  VALUE buffer;
59
71
  VALUE headers;
60
- int pos;
61
72
  int current_request_rx;
62
73
 
63
74
  enum read_method read_method;
64
75
  int body_read_mode;
65
76
  int body_left;
66
77
  int request_completed;
78
+
79
+ char *buf_ptr;
80
+ int buf_len;
81
+ int buf_pos;
82
+
67
83
  } Parser_t;
68
84
 
69
85
  VALUE cParser = Qnil;
@@ -107,8 +123,8 @@ static inline void get_polyphony() {
107
123
  }
108
124
 
109
125
  enum read_method detect_read_method(VALUE io) {
110
- if (rb_respond_to(io, ID_parser_read_method)) {
111
- VALUE method = rb_funcall(io, ID_parser_read_method, 0);
126
+ if (rb_respond_to(io, ID_read_method)) {
127
+ VALUE method = rb_funcall(io, ID_read_method, 0);
112
128
  if (method == SYM_stock_readpartial) return method_stock_readpartial;
113
129
 
114
130
  get_polyphony();
@@ -121,17 +137,24 @@ enum read_method detect_read_method(VALUE io) {
121
137
  return method_call;
122
138
  }
123
139
  else
124
- rb_raise(rb_eRuntimeError, "Provided reader should be a callable or respond to #__parser_read_method__");
140
+ rb_raise(rb_eRuntimeError, "Provided reader should be a callable or respond to #__read_method__");
141
+ }
142
+
143
+ enum parser_mode parse_parser_mode(VALUE mode) {
144
+ if (mode == SYM_server) return mode_server;
145
+ if (mode == SYM_client) return mode_client;
146
+
147
+ rb_raise(rb_eRuntimeError, "Invalid parser mode specified");
125
148
  }
126
149
 
127
- VALUE Parser_initialize(VALUE self, VALUE io) {
150
+ VALUE Parser_initialize(VALUE self, VALUE io, VALUE mode) {
128
151
  Parser_t *parser;
129
152
  GetParser(self, parser);
130
153
 
154
+ parser->mode = parse_parser_mode(mode);
131
155
  parser->io = io;
132
156
  parser->buffer = rb_str_new_literal("");
133
157
  parser->headers = Qnil;
134
- parser->pos = 0;
135
158
 
136
159
  // pre-allocate the buffer
137
160
  rb_str_modify_expand(parser->buffer, INITIAL_BUFFER_SIZE);
@@ -139,95 +162,109 @@ VALUE Parser_initialize(VALUE self, VALUE io) {
139
162
  parser->read_method = detect_read_method(io);
140
163
  parser->body_read_mode = BODY_READ_MODE_UNKNOWN;
141
164
  parser->body_left = 0;
165
+
166
+ parser->buf_ptr = 0;
167
+ parser->buf_len = 0;
168
+ parser->buf_pos = 0;
169
+
142
170
  return self;
143
171
  }
144
172
 
145
173
  ////////////////////////////////////////////////////////////////////////////////
146
174
 
147
175
  #define str_downcase(str) (rb_funcall((str), ID_downcase, 0))
176
+ #define str_upcase(str) (rb_funcall((str), ID_upcase, 0))
148
177
 
149
- #define FILL_BUFFER_OR_GOTO_EOF(state) { if (!fill_buffer(state)) goto eof; }
178
+ #define FILL_BUFFER_OR_GOTO_EOF(parser) { if (!fill_buffer(parser)) goto eof; }
150
179
 
151
- #define BUFFER_POS(state) ((state)->parser->pos)
152
- #define BUFFER_LEN(state) ((state)->len)
153
- #define BUFFER_CUR(state) ((state)->ptr[(state)->parser->pos])
154
- #define BUFFER_AT(state, pos) ((state)->ptr[pos])
155
- #define BUFFER_PTR(state, pos) ((state)->ptr + pos)
156
- #define BUFFER_STR(state, pos, len) (rb_obj_freeze(rb_utf8_str_new((state)->ptr + pos, len)))
157
- #define BUFFER_STR_DOWNCASE(state, pos, len) (rb_obj_freeze(str_downcase(rb_utf8_str_new((state)->ptr + pos, len))))
180
+ #define BUFFER_POS(parser) ((parser)->buf_pos)
181
+ #define BUFFER_LEN(parser) ((parser)->buf_len)
182
+ #define BUFFER_CUR(parser) ((parser)->buf_ptr[(parser)->buf_pos])
183
+ #define BUFFER_AT(parser, pos) ((parser)->buf_ptr[pos])
184
+ #define BUFFER_PTR(parser, pos) ((parser)->buf_ptr + pos)
185
+ #define BUFFER_STR(parser, pos, len) (rb_obj_freeze(rb_utf8_str_new((parser)->buf_ptr + pos, len)))
186
+ #define BUFFER_STR_DOWNCASE(parser, pos, len) (rb_obj_freeze(str_downcase(rb_utf8_str_new((parser)->buf_ptr + pos, len))))
187
+ #define BUFFER_STR_UPCASE(parser, pos, len) (rb_obj_freeze(str_upcase(rb_utf8_str_new((parser)->buf_ptr + pos, len))))
158
188
 
159
- #define INC_BUFFER_POS(state) { \
160
- BUFFER_POS(state)++; \
161
- if (BUFFER_POS(state) == BUFFER_LEN(state)) FILL_BUFFER_OR_GOTO_EOF(state); \
189
+ #define INC_BUFFER_POS(parser) { \
190
+ BUFFER_POS(parser)++; \
191
+ if (BUFFER_POS(parser) == BUFFER_LEN(parser)) FILL_BUFFER_OR_GOTO_EOF(parser); \
162
192
  }
163
193
 
164
- #define INC_BUFFER_POS_NO_FILL(state) BUFFER_POS(state)++;
194
+ #define INC_BUFFER_POS_NO_FILL(parser) BUFFER_POS(parser)++;
165
195
 
166
- #define INC_BUFFER_POS_UTF8(state, len) { \
167
- unsigned char c = BUFFER_CUR(state); \
196
+ #define INC_BUFFER_POS_UTF8(parser, len) { \
197
+ unsigned char c = BUFFER_CUR(parser); \
168
198
  if ((c & 0xf0) == 0xf0) { \
169
- while (BUFFER_LEN(state) - BUFFER_POS(state) < 4) FILL_BUFFER_OR_GOTO_EOF(state); \
170
- BUFFER_POS(state) += 4; \
199
+ while (BUFFER_LEN(parser) - BUFFER_POS(parser) < 4) FILL_BUFFER_OR_GOTO_EOF(parser); \
200
+ BUFFER_POS(parser) += 4; \
171
201
  len += 4; \
172
202
  } \
173
203
  else if ((c & 0xe0) == 0xe0) { \
174
- while (BUFFER_LEN(state) - BUFFER_POS(state) < 3) FILL_BUFFER_OR_GOTO_EOF(state); \
175
- BUFFER_POS(state) += 3; \
204
+ while (BUFFER_LEN(parser) - BUFFER_POS(parser) < 3) FILL_BUFFER_OR_GOTO_EOF(parser); \
205
+ BUFFER_POS(parser) += 3; \
176
206
  len += 3; \
177
207
  } \
178
208
  else if ((c & 0xc0) == 0xc0) { \
179
- while (BUFFER_LEN(state) - BUFFER_POS(state) < 2) FILL_BUFFER_OR_GOTO_EOF(state); \
180
- BUFFER_POS(state) += 2; \
209
+ while (BUFFER_LEN(parser) - BUFFER_POS(parser) < 2) FILL_BUFFER_OR_GOTO_EOF(parser); \
210
+ BUFFER_POS(parser) += 2; \
181
211
  len += 2; \
182
212
  } \
183
213
  else { \
184
- BUFFER_POS(state)++; \
214
+ BUFFER_POS(parser)++; \
185
215
  len ++; \
186
- if (BUFFER_POS(state) == BUFFER_LEN(state)) FILL_BUFFER_OR_GOTO_EOF(state); \
216
+ if (BUFFER_POS(parser) == BUFFER_LEN(parser)) FILL_BUFFER_OR_GOTO_EOF(parser); \
187
217
  } \
188
218
  }
189
219
 
190
- #define INIT_PARSER_STATE(state) { \
191
- (state)->len = RSTRING_LEN((state)->parser->buffer); \
192
- if (BUFFER_POS(state) == BUFFER_LEN(state)) \
193
- FILL_BUFFER_OR_GOTO_EOF(state) \
220
+ #define INIT_PARSER_STATE(parser) { \
221
+ (parser)->buf_len = RSTRING_LEN((parser)->buffer); \
222
+ if (BUFFER_POS(parser) == BUFFER_LEN(parser)) \
223
+ FILL_BUFFER_OR_GOTO_EOF(parser) \
194
224
  else \
195
- (state)->ptr = RSTRING_PTR((state)->parser->buffer); \
225
+ (parser)->buf_ptr = RSTRING_PTR((parser)->buffer); \
196
226
  }
197
227
 
198
228
  #define RAISE_BAD_REQUEST(msg) rb_raise(cError, msg)
199
229
 
200
- #define SET_HEADER_VALUE_FROM_BUFFER(state, headers, key, pos, len) { \
201
- VALUE value = BUFFER_STR(state, pos, len); \
202
- rb_hash_aset(headers, key, value); \
230
+ #define SET_HEADER_VALUE_FROM_BUFFER(parser, key, pos, len) { \
231
+ VALUE value = BUFFER_STR(parser, pos, len); \
232
+ rb_hash_aset(parser->headers, key, value); \
203
233
  RB_GC_GUARD(value); \
204
234
  }
205
235
 
206
- #define SET_HEADER_DOWNCASE_VALUE_FROM_BUFFER(state, headers, key, pos, len) { \
207
- VALUE value = BUFFER_STR_DOWNCASE(state, pos, len); \
208
- rb_hash_aset(headers, key, value); \
236
+ #define SET_HEADER_DOWNCASE_VALUE_FROM_BUFFER(parser, key, pos, len) { \
237
+ VALUE value = BUFFER_STR_DOWNCASE(parser, pos, len); \
238
+ rb_hash_aset(parser->headers, key, value); \
209
239
  RB_GC_GUARD(value); \
210
240
  }
211
241
 
212
- #define CONSUME_CRLF(state) { \
213
- INC_BUFFER_POS(state); \
214
- if (BUFFER_CUR(state) != '\n') goto bad_request; \
215
- INC_BUFFER_POS(state); \
242
+ #define SET_HEADER_UPCASE_VALUE_FROM_BUFFER(parser, key, pos, len) { \
243
+ VALUE value = BUFFER_STR_UPCASE(parser, pos, len); \
244
+ rb_hash_aset(parser->headers, key, value); \
245
+ RB_GC_GUARD(value); \
246
+ }
247
+
248
+ #define SET_HEADER_VALUE_INT(parser, key, value) { \
249
+ rb_hash_aset(parser->headers, key, INT2NUM(value)); \
250
+ }
251
+
252
+ #define CONSUME_CRLF(parser) { \
253
+ INC_BUFFER_POS(parser); \
254
+ if (BUFFER_CUR(parser) != '\n') goto bad_request; \
255
+ INC_BUFFER_POS(parser); \
216
256
  }
217
257
 
218
- #define CONSUME_CRLF_NO_FILL(state) { \
219
- INC_BUFFER_POS(state); \
220
- if (BUFFER_CUR(state) != '\n') goto bad_request; \
221
- INC_BUFFER_POS_NO_FILL(state); \
258
+ #define CONSUME_CRLF_NO_FILL(parser) { \
259
+ INC_BUFFER_POS(parser); \
260
+ if (BUFFER_CUR(parser) != '\n') goto bad_request; \
261
+ INC_BUFFER_POS_NO_FILL(parser); \
222
262
  }
223
263
 
224
264
  #define GLOBAL_STR(v, s) v = rb_str_new_literal(s); rb_global_variable(&v); rb_obj_freeze(v)
225
265
 
226
- struct parser_state {
227
- struct parser *parser;
228
- char *ptr;
229
- int len;
230
- };
266
+ // case-insensitive compare
267
+ #define CMP_CI(parser, down, up) ((BUFFER_CUR(parser) == down) || (BUFFER_CUR(parser) == up))
231
268
 
232
269
  ////////////////////////////////////////////////////////////////////////////////
233
270
 
@@ -261,9 +298,9 @@ static inline VALUE parser_io_read(Parser_t *parser, VALUE maxlen, VALUE buf, VA
261
298
  return rb_funcall(mPolyphony, ID_backend_read, 5, parser->io, buf, maxlen, Qfalse, buf_pos);
262
299
  case method_backend_recv:
263
300
  return rb_funcall(mPolyphony, ID_backend_recv, 4, parser->io, buf, maxlen, buf_pos);
264
- case method_readpartial:
301
+ case method_readpartial:
265
302
  return rb_funcall(parser-> io, ID_readpartial, 4, maxlen, buf, buf_pos, Qfalse);
266
- case method_call:
303
+ case method_call:
267
304
  return io_call(parser ->io, maxlen, buf, buf_pos);
268
305
  case method_stock_readpartial:
269
306
  return io_stock_readpartial(parser->io, maxlen, buf, buf_pos);
@@ -272,37 +309,37 @@ static inline VALUE parser_io_read(Parser_t *parser, VALUE maxlen, VALUE buf, VA
272
309
  }
273
310
  }
274
311
 
275
- static inline int fill_buffer(struct parser_state *state) {
276
- VALUE ret = parser_io_read(state->parser, NUM_max_headers_read_length, state->parser->buffer, NUM_buffer_end);
312
+ static inline int fill_buffer(Parser_t *parser) {
313
+ VALUE ret = parser_io_read(parser, NUM_max_headers_read_length, parser->buffer, NUM_buffer_end);
277
314
  if (ret == Qnil) return 0;
278
315
 
279
- state->parser->buffer = ret;
280
- int len = RSTRING_LEN(state->parser->buffer);
281
- int read_bytes = len - state->len;
316
+ parser->buffer = ret;
317
+ int len = RSTRING_LEN(parser->buffer);
318
+ int read_bytes = len - parser->buf_len;
282
319
  if (!read_bytes) return 0;
283
-
284
- state->ptr = RSTRING_PTR(state->parser->buffer);
285
- state->len = len;
320
+
321
+ parser->buf_ptr = RSTRING_PTR(parser->buffer);
322
+ parser->buf_len = len;
286
323
  return read_bytes;
287
324
  }
288
325
 
289
- static inline void buffer_trim(struct parser_state *state) {
290
- int len = RSTRING_LEN(state->parser->buffer);
291
- int pos = state->parser->pos;
326
+ static inline void buffer_trim(Parser_t *parser) {
327
+ int len = RSTRING_LEN(parser->buffer);
328
+ int pos = parser->buf_pos;
292
329
  int left = len - pos;
293
330
 
294
331
  // The buffer is trimmed only if length and position thresholds are passed,
295
- // *and* position is past the halfway point.
296
- if (len < BUFFER_TRIM_MIN_LEN ||
332
+ // *and* position is past the halfway point.
333
+ if (len < BUFFER_TRIM_MIN_LEN ||
297
334
  pos < BUFFER_TRIM_MIN_POS ||
298
335
  left >= pos) return;
299
336
 
300
337
  if (left > 0) {
301
- char *ptr = RSTRING_PTR(state->parser->buffer);
338
+ char *ptr = RSTRING_PTR(parser->buffer);
302
339
  memcpy(ptr, ptr + pos, left);
303
340
  }
304
- rb_str_set_len(state->parser->buffer, left);
305
- state->parser->pos = 0;
341
+ rb_str_set_len(parser->buffer, left);
342
+ parser->buf_pos = 0;
306
343
  }
307
344
 
308
345
  static inline void str_append_from_buffer(VALUE str, char *ptr, int len) {
@@ -314,28 +351,28 @@ static inline void str_append_from_buffer(VALUE str, char *ptr, int len) {
314
351
 
315
352
  ////////////////////////////////////////////////////////////////////////////////
316
353
 
317
- static inline int parse_method(struct parser_state *state, VALUE headers) {
318
- int pos = BUFFER_POS(state);
354
+ static inline int parse_request_line_method(Parser_t *parser) {
355
+ int pos = BUFFER_POS(parser);
319
356
  int len = 0;
320
357
 
321
358
  while (1) {
322
- switch (BUFFER_CUR(state)) {
359
+ switch (BUFFER_CUR(parser)) {
323
360
  case ' ':
324
361
  if (len < 1 || len > MAX_METHOD_LENGTH) goto bad_request;
325
- INC_BUFFER_POS(state);
362
+ INC_BUFFER_POS(parser);
326
363
  goto done;
327
364
  case '\r':
328
365
  case '\n':
329
366
  goto bad_request;
330
367
  default:
331
- INC_BUFFER_POS(state);
368
+ INC_BUFFER_POS(parser);
332
369
  len++;
333
- // INC_BUFFER_POS_UTF8(state, len);
370
+ // INC_BUFFER_POS_UTF8(parser, len);
334
371
  if (len > MAX_METHOD_LENGTH) goto bad_request;
335
372
  }
336
373
  }
337
374
  done:
338
- SET_HEADER_DOWNCASE_VALUE_FROM_BUFFER(state, headers, STR_pseudo_method, pos, len);
375
+ SET_HEADER_UPCASE_VALUE_FROM_BUFFER(parser, STR_pseudo_method, pos, len);
339
376
  return 1;
340
377
  bad_request:
341
378
  RAISE_BAD_REQUEST("Invalid method");
@@ -343,28 +380,28 @@ eof:
343
380
  return 0;
344
381
  }
345
382
 
346
- static int parse_request_target(struct parser_state *state, VALUE headers) {
347
- while (BUFFER_CUR(state) == ' ') INC_BUFFER_POS(state);
348
- int pos = BUFFER_POS(state);
383
+ static int parse_request_line_target(Parser_t *parser) {
384
+ while (BUFFER_CUR(parser) == ' ') INC_BUFFER_POS(parser);
385
+ int pos = BUFFER_POS(parser);
349
386
  int len = 0;
350
387
  while (1) {
351
- switch (BUFFER_CUR(state)) {
388
+ switch (BUFFER_CUR(parser)) {
352
389
  case ' ':
353
390
  if (len < 1 || len > MAX_PATH_LENGTH) goto bad_request;
354
- INC_BUFFER_POS(state);
391
+ INC_BUFFER_POS(parser);
355
392
  goto done;
356
393
  case '\r':
357
394
  case '\n':
358
395
  goto bad_request;
359
396
  default:
360
- INC_BUFFER_POS(state);
397
+ INC_BUFFER_POS(parser);
361
398
  len++;
362
- // INC_BUFFER_POS_UTF8(state, len);
399
+ // INC_BUFFER_POS_UTF8(parser, len);
363
400
  if (len > MAX_PATH_LENGTH) goto bad_request;
364
401
  }
365
402
  }
366
403
  done:
367
- SET_HEADER_VALUE_FROM_BUFFER(state, headers, STR_pseudo_path, pos, len);
404
+ SET_HEADER_VALUE_FROM_BUFFER(parser, STR_pseudo_path, pos, len);
368
405
  return 1;
369
406
  bad_request:
370
407
  RAISE_BAD_REQUEST("Invalid request target");
@@ -372,34 +409,31 @@ eof:
372
409
  return 0;
373
410
  }
374
411
 
375
- // case-insensitive compare
376
- #define CMP_CI(state, down, up) ((BUFFER_CUR(state) == down) || (BUFFER_CUR(state) == up))
377
-
378
- static int parse_protocol(struct parser_state *state, VALUE headers) {
379
- while (BUFFER_CUR(state) == ' ') INC_BUFFER_POS(state);
380
- int pos = BUFFER_POS(state);
412
+ static int parse_request_line_protocol(Parser_t *parser) {
413
+ while (BUFFER_CUR(parser) == ' ') INC_BUFFER_POS(parser);
414
+ int pos = BUFFER_POS(parser);
381
415
  int len = 0;
382
416
 
383
- if (CMP_CI(state, 'H', 'h')) INC_BUFFER_POS(state) else goto bad_request;
384
- if (CMP_CI(state, 'T', 't')) INC_BUFFER_POS(state) else goto bad_request;
385
- if (CMP_CI(state, 'T', 't')) INC_BUFFER_POS(state) else goto bad_request;
386
- if (CMP_CI(state, 'P', 'p')) INC_BUFFER_POS(state) else goto bad_request;
387
- if (BUFFER_CUR(state) == '/') INC_BUFFER_POS(state) else goto bad_request;
388
- if (BUFFER_CUR(state) == '1') INC_BUFFER_POS(state) else goto bad_request;
417
+ if (CMP_CI(parser, 'H', 'h')) INC_BUFFER_POS(parser) else goto bad_request;
418
+ if (CMP_CI(parser, 'T', 't')) INC_BUFFER_POS(parser) else goto bad_request;
419
+ if (CMP_CI(parser, 'T', 't')) INC_BUFFER_POS(parser) else goto bad_request;
420
+ if (CMP_CI(parser, 'P', 'p')) INC_BUFFER_POS(parser) else goto bad_request;
421
+ if (BUFFER_CUR(parser) == '/') INC_BUFFER_POS(parser) else goto bad_request;
422
+ if (BUFFER_CUR(parser) == '1') INC_BUFFER_POS(parser) else goto bad_request;
389
423
  len = 6;
390
424
  while (1) {
391
- switch (BUFFER_CUR(state)) {
425
+ switch (BUFFER_CUR(parser)) {
392
426
  case '\r':
393
- CONSUME_CRLF(state);
427
+ CONSUME_CRLF(parser);
394
428
  goto done;
395
429
  case '\n':
396
- INC_BUFFER_POS(state);
430
+ INC_BUFFER_POS(parser);
397
431
  goto done;
398
432
  case '.':
399
- INC_BUFFER_POS(state);
400
- char c = BUFFER_CUR(state);
433
+ INC_BUFFER_POS(parser);
434
+ char c = BUFFER_CUR(parser);
401
435
  if (c == '0' || c == '1') {
402
- INC_BUFFER_POS(state);
436
+ INC_BUFFER_POS(parser);
403
437
  len += 2;
404
438
  continue;
405
439
  }
@@ -410,7 +444,7 @@ static int parse_protocol(struct parser_state *state, VALUE headers) {
410
444
  }
411
445
  done:
412
446
  if (len < 6 || len > 8) goto bad_request;
413
- SET_HEADER_DOWNCASE_VALUE_FROM_BUFFER(state, headers, STR_pseudo_protocol, pos, len);
447
+ SET_HEADER_DOWNCASE_VALUE_FROM_BUFFER(parser, STR_pseudo_protocol, pos, len);
414
448
  return 1;
415
449
  bad_request:
416
450
  RAISE_BAD_REQUEST("Invalid protocol");
@@ -418,48 +452,159 @@ eof:
418
452
  return 0;
419
453
  }
420
454
 
421
- int parse_request_line(struct parser_state *state, VALUE headers) {
422
- if (!parse_method(state, headers)) goto eof;
423
- if (!parse_request_target(state, headers)) goto eof;
424
- if (!parse_protocol(state, headers)) goto eof;
455
+ static inline int parse_request_line(Parser_t *parser) {
456
+ if (!parse_request_line_method(parser)) goto eof;
457
+ if (!parse_request_line_target(parser)) goto eof;
458
+ if (!parse_request_line_protocol(parser)) goto eof;
425
459
 
426
460
  return 1;
427
461
  eof:
428
462
  return 0;
429
463
  }
430
464
 
431
- static inline int parse_header_key(struct parser_state *state, VALUE *key) {
432
- int pos = BUFFER_POS(state);
465
+ static inline int parse_status_line_protocol(Parser_t *parser) {
466
+ int pos = BUFFER_POS(parser);
433
467
  int len = 0;
434
468
 
469
+ if (CMP_CI(parser, 'H', 'h')) INC_BUFFER_POS(parser) else goto bad_request;
470
+ if (CMP_CI(parser, 'T', 't')) INC_BUFFER_POS(parser) else goto bad_request;
471
+ if (CMP_CI(parser, 'T', 't')) INC_BUFFER_POS(parser) else goto bad_request;
472
+ if (CMP_CI(parser, 'P', 'p')) INC_BUFFER_POS(parser) else goto bad_request;
473
+ if (BUFFER_CUR(parser) == '/') INC_BUFFER_POS(parser) else goto bad_request;
474
+ if (BUFFER_CUR(parser) == '1') INC_BUFFER_POS(parser) else goto bad_request;
475
+ len = 6;
435
476
  while (1) {
436
- switch (BUFFER_CUR(state)) {
477
+ switch (BUFFER_CUR(parser)) {
478
+ case '.':
479
+ INC_BUFFER_POS(parser);
480
+ char c = BUFFER_CUR(parser);
481
+ if (c == '0' || c == '1') {
482
+ INC_BUFFER_POS(parser);
483
+ len += 2;
484
+ continue;
485
+ }
486
+ goto bad_request;
487
+ case ' ':
488
+ INC_BUFFER_POS(parser);
489
+ goto done;
490
+ default:
491
+ goto bad_request;
492
+ }
493
+ }
494
+ done:
495
+ if (len < 6 || len > 8) goto bad_request;
496
+ SET_HEADER_DOWNCASE_VALUE_FROM_BUFFER(parser, STR_pseudo_protocol, pos, len);
497
+ return 1;
498
+ bad_request:
499
+ RAISE_BAD_REQUEST("Invalid protocol");
500
+ eof:
501
+ return 0;
502
+ }
503
+
504
+ static inline int parse_status_line_status(Parser_t *parser) {
505
+ while (BUFFER_CUR(parser) == ' ') INC_BUFFER_POS(parser);
506
+ int len = 0;
507
+ int status = 0;
508
+ while (1) {
509
+ if (len > 4) goto bad_request;
510
+
511
+ char c = BUFFER_CUR(parser);
512
+ if (c >= '0' && c <= '9') {
513
+ status = status * 10 + (c - '0');
514
+ len += 1;
515
+ INC_BUFFER_POS(parser);
516
+ continue;
517
+ }
518
+ switch (c) {
519
+ case ' ':
520
+ INC_BUFFER_POS(parser);
521
+ goto done;
522
+ case '\r':
523
+ case '\n':
524
+ goto done;
525
+ default:
526
+ goto bad_request;
527
+ }
528
+ }
529
+ done:
530
+ SET_HEADER_VALUE_INT(parser, STR_pseudo_status, status);
531
+ return 1;
532
+ bad_request:
533
+ RAISE_BAD_REQUEST("Invalid response status");
534
+ eof:
535
+ return 0;
536
+ }
537
+
538
+ static inline int parse_status_line_status_message(Parser_t *parser) {
539
+ while (BUFFER_CUR(parser) == ' ') INC_BUFFER_POS(parser);
540
+ int pos = BUFFER_POS(parser);
541
+ int len = 0;
542
+ while (1) {
543
+ switch (BUFFER_CUR(parser)) {
544
+ case '\r':
545
+ CONSUME_CRLF(parser);
546
+ goto done;
547
+ case '\n':
548
+ INC_BUFFER_POS(parser);
549
+ goto done;
550
+ default:
551
+ INC_BUFFER_POS(parser);
552
+ len++;
553
+ if (len > MAX_STATUS_MESSAGE_LENGTH) goto bad_request;
554
+ }
555
+ }
556
+ done:
557
+ SET_HEADER_VALUE_FROM_BUFFER(parser, STR_pseudo_status_message, pos, len);
558
+ return 1;
559
+ bad_request:
560
+ RAISE_BAD_REQUEST("Invalid request target");
561
+ eof:
562
+ return 0;
563
+ }
564
+
565
+
566
+ static inline int parse_status_line(Parser_t *parser) {
567
+ if (!parse_status_line_protocol(parser)) goto eof;
568
+ if (!parse_status_line_status(parser)) goto eof;
569
+ if (!parse_status_line_status_message(parser)) goto eof;
570
+
571
+ return 1;
572
+ eof:
573
+ return 0;
574
+ }
575
+
576
+ static inline int parse_header_key(Parser_t *parser, VALUE *key) {
577
+ int pos = BUFFER_POS(parser);
578
+ int len = 0;
579
+
580
+ while (1) {
581
+ switch (BUFFER_CUR(parser)) {
437
582
  case ' ':
438
583
  goto bad_request;
439
584
  case ':':
440
585
  if (len < 1 || len > MAX_HEADER_KEY_LENGTH)
441
586
  goto bad_request;
442
- INC_BUFFER_POS(state);
587
+ INC_BUFFER_POS(parser);
443
588
  goto done;
444
589
  case '\r':
445
- if (BUFFER_POS(state) > pos) goto bad_request;
446
- CONSUME_CRLF_NO_FILL(state);
590
+ if (BUFFER_POS(parser) > pos) goto bad_request;
591
+ CONSUME_CRLF_NO_FILL(parser);
447
592
  goto done;
448
593
  case '\n':
449
- if (BUFFER_POS(state) > pos) goto bad_request;
594
+ if (BUFFER_POS(parser) > pos) goto bad_request;
450
595
 
451
- INC_BUFFER_POS_NO_FILL(state);
596
+ INC_BUFFER_POS_NO_FILL(parser);
452
597
  goto done;
453
598
  default:
454
- INC_BUFFER_POS(state);
599
+ INC_BUFFER_POS(parser);
455
600
  len++;
456
- // INC_BUFFER_POS_UTF8(state, len);
601
+ // INC_BUFFER_POS_UTF8(parser, len);
457
602
  if (len > MAX_HEADER_KEY_LENGTH) goto bad_request;
458
603
  }
459
604
  }
460
605
  done:
461
606
  if (len == 0) return -1;
462
- (*key) = BUFFER_STR_DOWNCASE(state, pos, len);
607
+ (*key) = BUFFER_STR_DOWNCASE(parser, pos, len);
463
608
  return 1;
464
609
  bad_request:
465
610
  RAISE_BAD_REQUEST("Invalid header key");
@@ -467,28 +612,28 @@ eof:
467
612
  return 0;
468
613
  }
469
614
 
470
- static inline int parse_header_value(struct parser_state *state, VALUE *value) {
471
- while (BUFFER_CUR(state) == ' ') INC_BUFFER_POS(state);
615
+ static inline int parse_header_value(Parser_t *parser, VALUE *value) {
616
+ while (BUFFER_CUR(parser) == ' ') INC_BUFFER_POS(parser);
472
617
 
473
- int pos = BUFFER_POS(state);
618
+ int pos = BUFFER_POS(parser);
474
619
  int len = 0;
475
620
 
476
621
  while (1) {
477
- switch (BUFFER_CUR(state)) {
622
+ switch (BUFFER_CUR(parser)) {
478
623
  case '\r':
479
- CONSUME_CRLF(state);
624
+ CONSUME_CRLF(parser);
480
625
  goto done;
481
626
  case '\n':
482
- INC_BUFFER_POS(state);
627
+ INC_BUFFER_POS(parser);
483
628
  goto done;
484
629
  default:
485
- INC_BUFFER_POS_UTF8(state, len);
630
+ INC_BUFFER_POS_UTF8(parser, len);
486
631
  if (len > MAX_HEADER_VALUE_LENGTH) goto bad_request;
487
632
  }
488
633
  }
489
634
  done:
490
635
  if (len < 1 || len > MAX_HEADER_VALUE_LENGTH) goto bad_request;
491
- (*value) = BUFFER_STR(state, pos, len);
636
+ (*value) = BUFFER_STR(parser, pos, len);
492
637
  return 1;
493
638
  bad_request:
494
639
  RAISE_BAD_REQUEST("Invalid header value");
@@ -496,27 +641,27 @@ eof:
496
641
  return 0;
497
642
  }
498
643
 
499
- static inline int parse_header(struct parser_state *state, VALUE headers) {
644
+ static inline int parse_header(Parser_t *parser) {
500
645
  VALUE key, value;
501
646
 
502
- switch (parse_header_key(state, &key)) {
647
+ switch (parse_header_key(parser, &key)) {
503
648
  case -1: return -1;
504
649
  case 0: goto eof;
505
650
  }
506
651
 
507
- if (!parse_header_value(state, &value)) goto eof;
652
+ if (!parse_header_value(parser, &value)) goto eof;
508
653
 
509
- VALUE existing = rb_hash_aref(headers, key);
654
+ VALUE existing = rb_hash_aref(parser->headers, key);
510
655
  if (existing != Qnil) {
511
656
  if (TYPE(existing) != T_ARRAY) {
512
657
  existing = rb_ary_new3(2, existing, value);
513
- rb_hash_aset(headers, key, existing);
658
+ rb_hash_aset(parser->headers, key, existing);
514
659
  }
515
660
  else
516
661
  rb_ary_push(existing, value);
517
662
  }
518
663
  else
519
- rb_hash_aset(headers, key, value);
664
+ rb_hash_aset(parser->headers, key, value);
520
665
 
521
666
  RB_GC_GUARD(existing);
522
667
  RB_GC_GUARD(key);
@@ -527,36 +672,41 @@ eof:
527
672
  }
528
673
 
529
674
  VALUE Parser_parse_headers(VALUE self) {
530
- struct parser_state state;
531
- GetParser(self, state.parser);
532
- state.parser->headers = rb_hash_new();
675
+ Parser_t *parser;
676
+ GetParser(self, parser);
677
+ parser->headers = rb_hash_new();
533
678
 
534
- buffer_trim(&state);
535
- int initial_pos = state.parser->pos;
536
- INIT_PARSER_STATE(&state);
537
- state.parser->current_request_rx = 0;
679
+ buffer_trim(parser);
680
+ int initial_pos = parser->buf_pos;
681
+ INIT_PARSER_STATE(parser);
682
+ parser->current_request_rx = 0;
538
683
 
539
- if (!parse_request_line(&state, state.parser->headers)) goto eof;
684
+ if (parser->mode == mode_server) {
685
+ if (!parse_request_line(parser)) goto eof;
686
+ }
687
+ else {
688
+ if (!parse_status_line(parser)) goto eof;
689
+ }
540
690
 
541
691
  int header_count = 0;
542
692
  while (1) {
543
693
  if (header_count > MAX_HEADER_COUNT) RAISE_BAD_REQUEST("Too many headers");
544
- switch (parse_header(&state, state.parser->headers)) {
694
+ switch (parse_header(parser)) {
545
695
  case -1: goto done; // empty header => end of headers
546
696
  case 0: goto eof;
547
697
  }
548
698
  header_count++;
549
699
  }
550
700
  eof:
551
- state.parser->headers = Qnil;
701
+ parser->headers = Qnil;
552
702
  done:
553
- state.parser->body_read_mode = BODY_READ_MODE_UNKNOWN;
554
- int read_bytes = BUFFER_POS(&state) - initial_pos;
703
+ parser->body_read_mode = BODY_READ_MODE_UNKNOWN;
704
+ int read_bytes = BUFFER_POS(parser) - initial_pos;
555
705
 
556
- state.parser->current_request_rx += read_bytes;
557
- if (state.parser->headers != Qnil)
558
- rb_hash_aset(state.parser->headers, STR_pseudo_rx, INT2NUM(read_bytes));
559
- return state.parser->headers;
706
+ parser->current_request_rx += read_bytes;
707
+ if (parser->headers != Qnil)
708
+ rb_hash_aset(parser->headers, STR_pseudo_rx, INT2NUM(read_bytes));
709
+ return parser->headers;
560
710
  }
561
711
 
562
712
  ////////////////////////////////////////////////////////////////////////////////
@@ -585,13 +735,13 @@ VALUE read_body_with_content_length(Parser_t *parser, int read_entire_body, int
585
735
  VALUE body = Qnil;
586
736
 
587
737
  int len = RSTRING_LEN(parser->buffer);
588
- int pos = parser->pos;
738
+ int pos = BUFFER_POS(parser);
589
739
 
590
740
  if (pos < len) {
591
741
  int available = len - pos;
592
742
  if (available > parser->body_left) available = parser->body_left;
593
743
  body = rb_str_new(RSTRING_PTR(parser->buffer) + pos, available);
594
- parser->pos += available;
744
+ BUFFER_POS(parser) += available;
595
745
  parser->current_request_rx += available;
596
746
  parser->body_left -= available;
597
747
  if (!parser->body_left) parser->request_completed = 1;
@@ -601,7 +751,7 @@ VALUE read_body_with_content_length(Parser_t *parser, int read_entire_body, int
601
751
  len = 0;
602
752
  }
603
753
  if (buffered_only) return body;
604
-
754
+
605
755
  while (parser->body_left) {
606
756
  int maxlen = parser->body_left <= MAX_BODY_READ_LENGTH ? parser->body_left : MAX_BODY_READ_LENGTH;
607
757
  VALUE tmp_buf = parser_io_read(parser, INT2NUM(maxlen), Qnil, NUM_buffer_start);
@@ -630,34 +780,34 @@ int chunked_encoding_p(VALUE transfer_encoding) {
630
780
  return rb_funcall(str_downcase(transfer_encoding), ID_eq, 1, STR_chunked) == Qtrue;
631
781
  }
632
782
 
633
- int parse_chunk_size(struct parser_state *state, int *chunk_size) {
783
+ int parse_chunk_size(Parser_t *parser, int *chunk_size) {
634
784
  int len = 0;
635
785
  int value = 0;
636
- int initial_pos = BUFFER_POS(state);
786
+ int initial_pos = BUFFER_POS(parser);
637
787
 
638
788
  while (1) {
639
- char c = BUFFER_CUR(state);
789
+ char c = BUFFER_CUR(parser);
640
790
  if ((c >= '0') && (c <= '9')) value = (value << 4) + (c - '0');
641
791
  else if ((c >= 'a') && (c <= 'f')) value = (value << 4) + (c - 'a' + 10);
642
792
  else if ((c >= 'A') && (c <= 'F')) value = (value << 4) + (c - 'A' + 10);
643
793
  else switch (c) {
644
794
  case '\r':
645
- CONSUME_CRLF_NO_FILL(state);
795
+ CONSUME_CRLF_NO_FILL(parser);
646
796
  goto done;
647
797
  case '\n':
648
- INC_BUFFER_POS_NO_FILL(state);
798
+ INC_BUFFER_POS_NO_FILL(parser);
649
799
  goto done;
650
800
  default:
651
801
  goto bad_request;
652
802
  }
653
- INC_BUFFER_POS(state);
803
+ INC_BUFFER_POS(parser);
654
804
  len++;
655
805
  if (len >= MAX_CHUNKED_ENCODING_CHUNK_SIZE_LENGTH) goto bad_request;
656
806
  }
657
807
  done:
658
808
  if (len == 0) goto bad_request;
659
809
  (*chunk_size) = value;
660
- state->parser->current_request_rx += BUFFER_POS(state) - initial_pos;
810
+ parser->current_request_rx += BUFFER_POS(parser) - initial_pos;
661
811
  return 1;
662
812
  bad_request:
663
813
  RAISE_BAD_REQUEST("Invalid chunk size");
@@ -665,20 +815,20 @@ eof:
665
815
  return 0;
666
816
  }
667
817
 
668
- int read_body_chunk_with_chunked_encoding(struct parser_state *state, VALUE *body, int chunk_size, int buffered_only) {
669
- int len = RSTRING_LEN(state->parser->buffer);
670
- int pos = state->parser->pos;
818
+ int read_body_chunk_with_chunked_encoding(Parser_t *parser, VALUE *body, int chunk_size, int buffered_only) {
819
+ int len = RSTRING_LEN(parser->buffer);
820
+ int pos = BUFFER_POS(parser);
671
821
  int left = chunk_size;
672
822
 
673
823
  if (pos < len) {
674
824
  int available = len - pos;
675
825
  if (available > left) available = left;
676
826
  if (*body != Qnil)
677
- str_append_from_buffer(*body, RSTRING_PTR(state->parser->buffer) + pos, available);
827
+ str_append_from_buffer(*body, RSTRING_PTR(parser->buffer) + pos, available);
678
828
  else
679
- *body = rb_str_new(RSTRING_PTR(state->parser->buffer) + pos, available);
680
- state->parser->pos += available;
681
- state->parser->current_request_rx += available;
829
+ *body = rb_str_new(RSTRING_PTR(parser->buffer) + pos, available);
830
+ BUFFER_POS(parser) += available;
831
+ parser->current_request_rx += available;
682
832
  left -= available;
683
833
  }
684
834
  if (buffered_only) return 1;
@@ -686,14 +836,14 @@ int read_body_chunk_with_chunked_encoding(struct parser_state *state, VALUE *bod
686
836
  while (left) {
687
837
  int maxlen = left <= MAX_BODY_READ_LENGTH ? left : MAX_BODY_READ_LENGTH;
688
838
 
689
- VALUE tmp_buf = parser_io_read(state->parser, INT2NUM(maxlen), Qnil, NUM_buffer_start);
839
+ VALUE tmp_buf = parser_io_read(parser, INT2NUM(maxlen), Qnil, NUM_buffer_start);
690
840
  if (tmp_buf == Qnil) goto eof;
691
841
  if (*body != Qnil)
692
842
  rb_str_append(*body, tmp_buf);
693
843
  else
694
844
  *body = tmp_buf;
695
845
  int read_bytes = RSTRING_LEN(tmp_buf);
696
- state->parser->current_request_rx += read_bytes;
846
+ parser->current_request_rx += read_bytes;
697
847
  left -= read_bytes;
698
848
  RB_GC_GUARD(tmp_buf);
699
849
  }
@@ -702,46 +852,44 @@ eof:
702
852
  return 0;
703
853
  }
704
854
 
705
- static inline int parse_chunk_postfix(struct parser_state *state) {
706
- int initial_pos = BUFFER_POS(state);
707
- if (initial_pos == BUFFER_LEN(state)) FILL_BUFFER_OR_GOTO_EOF(state);
708
- switch (BUFFER_CUR(state)) {
855
+ static inline int parse_chunk_postfix(Parser_t *parser) {
856
+ int initial_pos = BUFFER_POS(parser);
857
+ if (initial_pos == BUFFER_LEN(parser)) FILL_BUFFER_OR_GOTO_EOF(parser);
858
+ switch (BUFFER_CUR(parser)) {
709
859
  case '\r':
710
- CONSUME_CRLF_NO_FILL(state);
860
+ CONSUME_CRLF_NO_FILL(parser);
711
861
  goto done;
712
862
  case '\n':
713
- INC_BUFFER_POS_NO_FILL(state);
863
+ INC_BUFFER_POS_NO_FILL(parser);
714
864
  goto done;
715
865
  default:
716
866
  goto bad_request;
717
867
  }
718
868
  done:
719
- state->parser->current_request_rx += BUFFER_POS(state) - initial_pos;
869
+ parser->current_request_rx += BUFFER_POS(parser) - initial_pos;
720
870
  return 1;
721
871
  bad_request:
722
- RAISE_BAD_REQUEST("Invalid protocol");
872
+ RAISE_BAD_REQUEST("Invalid chunk");
723
873
  eof:
724
874
  return 0;
725
875
  }
726
876
 
727
877
  VALUE read_body_with_chunked_encoding(Parser_t *parser, int read_entire_body, int buffered_only) {
728
- struct parser_state state;
729
- state.parser = parser;
730
- buffer_trim(&state);
731
- INIT_PARSER_STATE(&state);
878
+ buffer_trim(parser);
879
+ INIT_PARSER_STATE(parser);
732
880
  VALUE body = Qnil;
733
881
 
734
882
  while (1) {
735
883
  int chunk_size = 0;
736
- if (BUFFER_POS(&state) == BUFFER_LEN(&state)) FILL_BUFFER_OR_GOTO_EOF(&state);
737
- if (!parse_chunk_size(&state, &chunk_size)) goto bad_request;
738
-
884
+ if (BUFFER_POS(parser) == BUFFER_LEN(parser)) FILL_BUFFER_OR_GOTO_EOF(parser);
885
+ if (!parse_chunk_size(parser, &chunk_size)) goto bad_request;
886
+
739
887
  if (chunk_size) {
740
- if (!read_body_chunk_with_chunked_encoding(&state, &body, chunk_size, buffered_only)) goto bad_request;
888
+ if (!read_body_chunk_with_chunked_encoding(parser, &body, chunk_size, buffered_only)) goto bad_request;
741
889
  }
742
890
  else parser->request_completed = 1;
743
891
 
744
- if (!parse_chunk_postfix(&state)) goto bad_request;
892
+ if (!parse_chunk_postfix(parser)) goto bad_request;
745
893
  if (!chunk_size || !read_entire_body) goto done;
746
894
  }
747
895
  bad_request:
@@ -749,7 +897,7 @@ bad_request:
749
897
  eof:
750
898
  RAISE_BAD_REQUEST("Incomplete request body");
751
899
  done:
752
- rb_hash_aset(parser->headers, STR_pseudo_rx, INT2NUM(state.parser->current_request_rx));
900
+ rb_hash_aset(parser->headers, STR_pseudo_rx, INT2NUM(parser->current_request_rx));
753
901
  RB_GC_GUARD(body);
754
902
  return body;
755
903
  }
@@ -763,7 +911,7 @@ static inline void detect_body_read_mode(Parser_t *parser) {
763
911
  parser->request_completed = 0;
764
912
  return;
765
913
  }
766
-
914
+
767
915
  VALUE transfer_encoding = rb_hash_aref(parser->headers, STR_transfer_encoding);
768
916
  if (chunked_encoding_p(transfer_encoding)) {
769
917
  parser->body_read_mode = BODY_READ_MODE_CHUNKED;
@@ -817,7 +965,7 @@ void Init_H1P() {
817
965
  rb_gc_register_mark_object(cError);
818
966
 
819
967
  // backend methods
820
- rb_define_method(cParser, "initialize", Parser_initialize, 1);
968
+ rb_define_method(cParser, "initialize", Parser_initialize, 2);
821
969
  rb_define_method(cParser, "parse_headers", Parser_parse_headers, 0);
822
970
  rb_define_method(cParser, "read_body", Parser_read_body, 0);
823
971
  rb_define_method(cParser, "read_body_chunk", Parser_read_body_chunk, 1);
@@ -830,27 +978,33 @@ void Init_H1P() {
830
978
  ID_downcase = rb_intern("downcase");
831
979
  ID_eof_p = rb_intern("eof?");
832
980
  ID_eq = rb_intern("==");
833
- ID_parser_read_method = rb_intern("__parser_read_method__");
981
+ ID_read_method = rb_intern("__read_method__");
834
982
  ID_read = rb_intern("read");
835
983
  ID_readpartial = rb_intern("readpartial");
836
984
  ID_to_i = rb_intern("to_i");
985
+ ID_upcase = rb_intern("upcase");
837
986
 
838
987
  NUM_max_headers_read_length = INT2NUM(MAX_HEADERS_READ_LENGTH);
839
988
  NUM_buffer_start = INT2NUM(0);
840
989
  NUM_buffer_end = INT2NUM(-1);
841
990
 
842
- GLOBAL_STR(STR_pseudo_method, ":method");
843
- GLOBAL_STR(STR_pseudo_path, ":path");
844
- GLOBAL_STR(STR_pseudo_protocol, ":protocol");
845
- GLOBAL_STR(STR_pseudo_rx, ":rx");
991
+ GLOBAL_STR(STR_pseudo_method, ":method");
992
+ GLOBAL_STR(STR_pseudo_path, ":path");
993
+ GLOBAL_STR(STR_pseudo_protocol, ":protocol");
994
+ GLOBAL_STR(STR_pseudo_rx, ":rx");
995
+ GLOBAL_STR(STR_pseudo_status, ":status");
996
+ GLOBAL_STR(STR_pseudo_status_message, ":status_message");
846
997
 
847
- GLOBAL_STR(STR_chunked, "chunked");
848
- GLOBAL_STR(STR_content_length, "content-length");
849
- GLOBAL_STR(STR_transfer_encoding, "transfer-encoding");
998
+ GLOBAL_STR(STR_chunked, "chunked");
999
+ GLOBAL_STR(STR_content_length, "content-length");
1000
+ GLOBAL_STR(STR_transfer_encoding, "transfer-encoding");
850
1001
 
851
1002
  SYM_backend_read = ID2SYM(ID_backend_read);
852
1003
  SYM_backend_recv = ID2SYM(ID_backend_recv);
853
1004
  SYM_stock_readpartial = ID2SYM(rb_intern("stock_readpartial"));
1005
+
1006
+ SYM_client = ID2SYM(rb_intern("client"));
1007
+ SYM_server = ID2SYM(rb_intern("server"));
854
1008
 
855
1009
  rb_global_variable(&mH1P);
856
1010
  }