h1p 0.1 → 0.4

Sign up to get free protection for your applications and to get access to all the features.
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
  }