raptor 0.22.3 → 0.23.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +30 -0
- data/Dockerfile +3 -1
- data/README.md +38 -31
- data/docs/raptor-vs-puma.md +44 -38
- data/docs/talk.md +1295 -0
- data/ext/raptor_bpf/reuseport_select.bpf.c +18 -9
- data/ext/raptor_http/extconf.rb +2 -0
- data/ext/raptor_http/raptor_http.c +91 -119
- data/ext/raptor_http2/raptor_http2.c +272 -223
- data/ext/raptor_native/raptor_native.c +38 -20
- data/lib/rackup/handler/raptor.rb +12 -11
- data/lib/raptor/binder.rb +12 -12
- data/lib/raptor/cli.rb +18 -18
- data/lib/raptor/cluster.rb +44 -44
- data/lib/raptor/control_server.rb +3 -2
- data/lib/raptor/detached_body.rb +6 -2
- data/lib/raptor/http.rb +7 -5
- data/lib/raptor/http1.rb +232 -207
- data/lib/raptor/http2.rb +312 -265
- data/lib/raptor/reactor.rb +138 -148
- data/lib/raptor/reuseport_bpf.rb +62 -38
- data/lib/raptor/server.rb +45 -34
- data/lib/raptor/stats.rb +15 -3
- data/lib/raptor/thread_locals.rb +4 -3
- data/lib/raptor/version.rb +1 -1
- data/sig/generated/rackup/handler/raptor.rbs +2 -1
- data/sig/generated/raptor/binder.rbs +9 -9
- data/sig/generated/raptor/cli.rbs +6 -6
- data/sig/generated/raptor/cluster.rbs +9 -9
- data/sig/generated/raptor/control_server.rbs +2 -1
- data/sig/generated/raptor/detached_body.rbs +5 -1
- data/sig/generated/raptor/http.rbs +3 -3
- data/sig/generated/raptor/http1.rbs +100 -91
- data/sig/generated/raptor/http2.rbs +200 -189
- data/sig/generated/raptor/reactor.rbs +107 -118
- data/sig/generated/raptor/reuseport_bpf.rbs +54 -17
- data/sig/generated/raptor/server.rbs +26 -26
- data/sig/generated/raptor/stats.rbs +3 -2
- data/sig/generated/raptor/thread_locals.rbs +4 -3
- metadata +2 -2
- data/docs/brisrails-talk.md +0 -2398
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
#include "ruby.h"
|
|
2
|
-
#include <string.h>
|
|
3
2
|
#include <stdint.h>
|
|
3
|
+
#include <string.h>
|
|
4
4
|
|
|
5
|
-
#define
|
|
6
|
-
#define
|
|
7
|
-
#define
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
#define FRAME_HEADER_SIZE 9
|
|
6
|
+
#define DEFAULT_HEADER_TABLE_SIZE 4096
|
|
7
|
+
#define ENTRY_OVERHEAD 32
|
|
8
|
+
// Largest decoded request header list, matching the HTTP/1.1 header section
|
|
9
|
+
// limit. Fields are sized as in RFC 7541 section 4.1, so fields indexed from
|
|
10
|
+
// the dynamic table count at their full decoded size.
|
|
11
|
+
#define MAX_HEADER_LIST_SIZE (112 * 1024)
|
|
12
|
+
#define CONNECTION_PREFACE "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
|
|
10
13
|
|
|
11
14
|
#define FRAME_DATA 0x0
|
|
12
15
|
#define FRAME_HEADERS 0x1
|
|
@@ -19,12 +22,6 @@
|
|
|
19
22
|
#define FRAME_WINDOW_UPDATE 0x8
|
|
20
23
|
#define FRAME_CONTINUATION 0x9
|
|
21
24
|
|
|
22
|
-
#define FLAG_END_STREAM 0x1
|
|
23
|
-
#define FLAG_END_HEADERS 0x4
|
|
24
|
-
#define FLAG_PADDED 0x8
|
|
25
|
-
#define FLAG_PRIORITY 0x20
|
|
26
|
-
#define FLAG_ACK 0x1
|
|
27
|
-
|
|
28
25
|
#define SETTINGS_HEADER_TABLE_SIZE 0x1
|
|
29
26
|
#define SETTINGS_ENABLE_PUSH 0x2
|
|
30
27
|
#define SETTINGS_MAX_CONCURRENT_STREAMS 0x3
|
|
@@ -32,21 +29,41 @@
|
|
|
32
29
|
#define SETTINGS_MAX_FRAME_SIZE 0x5
|
|
33
30
|
#define SETTINGS_MAX_HEADER_LIST_SIZE 0x6
|
|
34
31
|
|
|
35
|
-
#define STATIC_TABLE_SIZE 61
|
|
36
|
-
|
|
37
32
|
#define HUFFMAN_ACCEPTED 1
|
|
38
33
|
#define HUFFMAN_SYM (1 << 1)
|
|
39
34
|
#define HUFFMAN_FAIL_STATE 0x100
|
|
40
35
|
|
|
41
|
-
static VALUE cHttp2Parser;
|
|
42
36
|
static VALUE eHttp2ParserError;
|
|
37
|
+
static ID id_type;
|
|
38
|
+
static ID id_length;
|
|
39
|
+
static ID id_flags;
|
|
40
|
+
static ID id_stream_id;
|
|
41
|
+
static ID id_payload;
|
|
42
|
+
static ID id_data;
|
|
43
|
+
static ID id_headers;
|
|
44
|
+
static ID id_priority;
|
|
45
|
+
static ID id_rst_stream;
|
|
46
|
+
static ID id_settings;
|
|
47
|
+
static ID id_push_promise;
|
|
48
|
+
static ID id_ping;
|
|
49
|
+
static ID id_goaway;
|
|
50
|
+
static ID id_window_update;
|
|
51
|
+
static ID id_continuation;
|
|
52
|
+
static ID id_unknown;
|
|
53
|
+
static ID id_header_table_size;
|
|
54
|
+
static ID id_enable_push;
|
|
55
|
+
static ID id_max_concurrent_streams;
|
|
56
|
+
static ID id_initial_window_size;
|
|
57
|
+
static ID id_max_frame_size;
|
|
58
|
+
static ID id_max_header_list_size;
|
|
43
59
|
|
|
44
60
|
typedef struct {
|
|
45
61
|
const char *name;
|
|
46
62
|
const char *value;
|
|
47
63
|
} hpack_static_entry;
|
|
48
64
|
|
|
49
|
-
|
|
65
|
+
// RFC 7541 Appendix A. HPACK indexes are 1-based, so slot 0 is a placeholder.
|
|
66
|
+
static const hpack_static_entry static_table[] = {
|
|
50
67
|
{NULL, NULL},
|
|
51
68
|
{":authority", ""},
|
|
52
69
|
{":method", "GET"},
|
|
@@ -111,12 +128,15 @@ static const hpack_static_entry STATIC_TABLE[] = {
|
|
|
111
128
|
{"www-authenticate", ""}
|
|
112
129
|
};
|
|
113
130
|
|
|
131
|
+
#define STATIC_TABLE_SIZE ((long)(sizeof(static_table) / sizeof(static_table[0])) - 1)
|
|
132
|
+
|
|
114
133
|
typedef struct {
|
|
115
134
|
uint32_t code;
|
|
116
135
|
uint8_t bits;
|
|
117
136
|
} huffman_entry;
|
|
118
137
|
|
|
119
|
-
|
|
138
|
+
// RFC 7541 Appendix B: one code per byte value plus EOS.
|
|
139
|
+
static const huffman_entry huffman_table[257] = {
|
|
120
140
|
{0x1ff8, 13}, {0x7fffd8, 23}, {0xfffffe2, 28}, {0xfffffe3, 28},
|
|
121
141
|
{0xfffffe4, 28}, {0xfffffe5, 28}, {0xfffffe6, 28}, {0xfffffe7, 28},
|
|
122
142
|
{0xfffffe8, 28}, {0xffffea, 24}, {0x3ffffffc, 30}, {0xfffffe9, 28},
|
|
@@ -285,16 +305,15 @@ static int hpack_decode_string(const uint8_t *buf, size_t len, size_t *pos, VALU
|
|
|
285
305
|
if (*pos + str_len > len) return -1;
|
|
286
306
|
|
|
287
307
|
if (huffman) {
|
|
288
|
-
|
|
289
|
-
|
|
308
|
+
// The shortest Huffman code is five bits, bounding the decoded length.
|
|
309
|
+
size_t decoded_cap = str_len * 8 / 5;
|
|
310
|
+
VALUE decoded = rb_str_new(NULL, (long)decoded_cap);
|
|
290
311
|
size_t decoded_len;
|
|
291
312
|
|
|
292
|
-
if (hpack_decode_huffman(buf + *pos, (size_t)str_len, decoded, decoded_cap, &decoded_len) < 0)
|
|
293
|
-
rb_raise(rb_eRuntimeError, "HPACK Huffman decode error");
|
|
294
|
-
return -1;
|
|
295
|
-
}
|
|
313
|
+
if (hpack_decode_huffman(buf + *pos, (size_t)str_len, (uint8_t *)RSTRING_PTR(decoded), decoded_cap, &decoded_len) < 0) return -1;
|
|
296
314
|
|
|
297
|
-
|
|
315
|
+
rb_str_set_len(decoded, (long)decoded_len);
|
|
316
|
+
*out_str = decoded;
|
|
298
317
|
} else {
|
|
299
318
|
*out_str = rb_str_new((const char *)(buf + *pos), (long)str_len);
|
|
300
319
|
}
|
|
@@ -306,7 +325,7 @@ static int hpack_decode_string(const uint8_t *buf, size_t len, size_t *pos, VALU
|
|
|
306
325
|
static size_t hpack_huffman_encode_len(const uint8_t *src, size_t src_len) {
|
|
307
326
|
size_t bits = 0;
|
|
308
327
|
for (size_t i = 0; i < src_len; i++)
|
|
309
|
-
bits +=
|
|
328
|
+
bits += huffman_table[src[i]].bits;
|
|
310
329
|
return (bits + 7) / 8;
|
|
311
330
|
}
|
|
312
331
|
|
|
@@ -316,8 +335,8 @@ static size_t hpack_huffman_encode(const uint8_t *src, size_t src_len, uint8_t *
|
|
|
316
335
|
int remaining = 0;
|
|
317
336
|
|
|
318
337
|
for (size_t i = 0; i < src_len; i++) {
|
|
319
|
-
uint32_t code =
|
|
320
|
-
uint8_t bits =
|
|
338
|
+
uint32_t code = huffman_table[src[i]].code;
|
|
339
|
+
uint8_t bits = huffman_table[src[i]].bits;
|
|
321
340
|
|
|
322
341
|
current = (current << bits) | code;
|
|
323
342
|
remaining += bits;
|
|
@@ -336,26 +355,33 @@ static size_t hpack_huffman_encode(const uint8_t *src, size_t src_len, uint8_t *
|
|
|
336
355
|
return pos;
|
|
337
356
|
}
|
|
338
357
|
|
|
339
|
-
|
|
340
|
-
|
|
358
|
+
// Encodes into the Ruby buffer to avoid stack allocations sized by header values.
|
|
359
|
+
static void hpack_append_huffman(VALUE buf, const uint8_t *src, size_t src_len, size_t huff_len) {
|
|
360
|
+
long offset = RSTRING_LEN(buf);
|
|
361
|
+
rb_str_resize(buf, offset + (long)huff_len);
|
|
362
|
+
hpack_huffman_encode(src, src_len, (uint8_t *)RSTRING_PTR(buf) + offset);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
static int hpack_table_lookup(VALUE dyn_table, long index, VALUE *name, VALUE *value) {
|
|
366
|
+
if (index < 1) return -1;
|
|
341
367
|
|
|
342
368
|
if (index <= STATIC_TABLE_SIZE) {
|
|
343
|
-
*name = rb_str_new_cstr(
|
|
344
|
-
*value = rb_str_new_cstr(
|
|
345
|
-
return
|
|
369
|
+
*name = rb_str_new_cstr(static_table[index].name);
|
|
370
|
+
*value = rb_str_new_cstr(static_table[index].value);
|
|
371
|
+
return 0;
|
|
346
372
|
}
|
|
347
373
|
|
|
348
374
|
long dyn_index = index - STATIC_TABLE_SIZE - 1;
|
|
349
|
-
if (dyn_index >= RARRAY_LEN(dyn_table)) return
|
|
375
|
+
if (dyn_index >= RARRAY_LEN(dyn_table)) return -1;
|
|
350
376
|
|
|
351
377
|
VALUE entry = rb_ary_entry(dyn_table, dyn_index);
|
|
352
378
|
*name = rb_ary_entry(entry, 0);
|
|
353
379
|
*value = rb_ary_entry(entry, 1);
|
|
354
|
-
return
|
|
380
|
+
return 0;
|
|
355
381
|
}
|
|
356
382
|
|
|
357
|
-
static VALUE
|
|
358
|
-
long entry_size = RSTRING_LEN(name) + RSTRING_LEN(value) +
|
|
383
|
+
static VALUE hpack_dynamic_table_add(VALUE dyn_table, VALUE name, VALUE value, long max_size) {
|
|
384
|
+
long entry_size = RSTRING_LEN(name) + RSTRING_LEN(value) + ENTRY_OVERHEAD;
|
|
359
385
|
|
|
360
386
|
VALUE new_table = rb_ary_new();
|
|
361
387
|
VALUE new_entry = rb_ary_new_from_args(2, rb_str_freeze(rb_str_dup(name)), rb_str_freeze(rb_str_dup(value)));
|
|
@@ -366,7 +392,7 @@ static VALUE dynamic_table_add(VALUE dyn_table, VALUE name, VALUE value, long ma
|
|
|
366
392
|
VALUE existing = rb_ary_entry(dyn_table, i);
|
|
367
393
|
VALUE ename = rb_ary_entry(existing, 0);
|
|
368
394
|
VALUE evalue = rb_ary_entry(existing, 1);
|
|
369
|
-
long esize = RSTRING_LEN(ename) + RSTRING_LEN(evalue) +
|
|
395
|
+
long esize = RSTRING_LEN(ename) + RSTRING_LEN(evalue) + ENTRY_OVERHEAD;
|
|
370
396
|
|
|
371
397
|
if (current_size + esize > max_size) break;
|
|
372
398
|
|
|
@@ -377,7 +403,7 @@ static VALUE dynamic_table_add(VALUE dyn_table, VALUE name, VALUE value, long ma
|
|
|
377
403
|
return new_table;
|
|
378
404
|
}
|
|
379
405
|
|
|
380
|
-
static VALUE
|
|
406
|
+
static VALUE hpack_dynamic_table_evict(VALUE dyn_table, long max_size) {
|
|
381
407
|
long current_size = 0;
|
|
382
408
|
long keep = 0;
|
|
383
409
|
|
|
@@ -385,7 +411,7 @@ static VALUE dynamic_table_evict(VALUE dyn_table, long max_size) {
|
|
|
385
411
|
VALUE entry = rb_ary_entry(dyn_table, i);
|
|
386
412
|
VALUE name = rb_ary_entry(entry, 0);
|
|
387
413
|
VALUE value = rb_ary_entry(entry, 1);
|
|
388
|
-
long esize = RSTRING_LEN(name) + RSTRING_LEN(value) +
|
|
414
|
+
long esize = RSTRING_LEN(name) + RSTRING_LEN(value) + ENTRY_OVERHEAD;
|
|
389
415
|
|
|
390
416
|
if (current_size + esize > max_size) break;
|
|
391
417
|
|
|
@@ -405,61 +431,68 @@ static int hpack_decode_header_block(const uint8_t *buf, size_t len,
|
|
|
405
431
|
VALUE headers_out, VALUE *dyn_table,
|
|
406
432
|
long *max_table_size) {
|
|
407
433
|
size_t pos = 0;
|
|
434
|
+
size_t list_size = 0;
|
|
408
435
|
|
|
409
436
|
while (pos < len) {
|
|
410
437
|
uint8_t byte = buf[pos];
|
|
411
438
|
|
|
412
439
|
if (byte & 0x80) {
|
|
413
|
-
|
|
440
|
+
// Indexed header field (RFC 7541 6.1).
|
|
414
441
|
uint64_t index;
|
|
415
442
|
if (hpack_decode_int(buf, len, &pos, 7, &index) < 0) return -1;
|
|
416
443
|
if (index == 0) return -1;
|
|
417
444
|
|
|
418
445
|
VALUE name, value;
|
|
419
|
-
if (
|
|
446
|
+
if (hpack_table_lookup(*dyn_table, (long)index, &name, &value) < 0) return -1;
|
|
420
447
|
|
|
421
448
|
rb_ary_push(headers_out, rb_ary_new_from_args(2, name, value));
|
|
449
|
+
list_size += RSTRING_LEN(name) + RSTRING_LEN(value) + ENTRY_OVERHEAD;
|
|
450
|
+
if (list_size > MAX_HEADER_LIST_SIZE) return -1;
|
|
422
451
|
|
|
423
452
|
} else if ((byte & 0xc0) == 0x40) {
|
|
424
|
-
|
|
453
|
+
// Literal header field with incremental indexing (RFC 7541 6.2.1).
|
|
425
454
|
uint64_t index;
|
|
426
455
|
if (hpack_decode_int(buf, len, &pos, 6, &index) < 0) return -1;
|
|
427
456
|
|
|
428
457
|
VALUE name, value;
|
|
429
458
|
if (index > 0) {
|
|
430
459
|
VALUE dummy;
|
|
431
|
-
if (
|
|
460
|
+
if (hpack_table_lookup(*dyn_table, (long)index, &name, &dummy) < 0) return -1;
|
|
432
461
|
} else {
|
|
433
462
|
if (hpack_decode_string(buf, len, &pos, &name) < 0) return -1;
|
|
434
463
|
}
|
|
435
464
|
if (hpack_decode_string(buf, len, &pos, &value) < 0) return -1;
|
|
436
465
|
|
|
437
466
|
rb_ary_push(headers_out, rb_ary_new_from_args(2, name, value));
|
|
438
|
-
|
|
467
|
+
list_size += RSTRING_LEN(name) + RSTRING_LEN(value) + ENTRY_OVERHEAD;
|
|
468
|
+
if (list_size > MAX_HEADER_LIST_SIZE) return -1;
|
|
469
|
+
*dyn_table = hpack_dynamic_table_add(*dyn_table, name, value, *max_table_size);
|
|
439
470
|
|
|
440
471
|
} else if ((byte & 0xf0) == 0x00 || (byte & 0xf0) == 0x10) {
|
|
441
|
-
|
|
472
|
+
// Literal header field without indexing or never indexed (RFC 7541 6.2.2, 6.2.3).
|
|
442
473
|
uint64_t index;
|
|
443
474
|
if (hpack_decode_int(buf, len, &pos, 4, &index) < 0) return -1;
|
|
444
475
|
|
|
445
476
|
VALUE name, value;
|
|
446
477
|
if (index > 0) {
|
|
447
478
|
VALUE dummy;
|
|
448
|
-
if (
|
|
479
|
+
if (hpack_table_lookup(*dyn_table, (long)index, &name, &dummy) < 0) return -1;
|
|
449
480
|
} else {
|
|
450
481
|
if (hpack_decode_string(buf, len, &pos, &name) < 0) return -1;
|
|
451
482
|
}
|
|
452
483
|
if (hpack_decode_string(buf, len, &pos, &value) < 0) return -1;
|
|
453
484
|
|
|
454
485
|
rb_ary_push(headers_out, rb_ary_new_from_args(2, name, value));
|
|
486
|
+
list_size += RSTRING_LEN(name) + RSTRING_LEN(value) + ENTRY_OVERHEAD;
|
|
487
|
+
if (list_size > MAX_HEADER_LIST_SIZE) return -1;
|
|
455
488
|
|
|
456
489
|
} else if ((byte & 0xe0) == 0x20) {
|
|
457
|
-
|
|
490
|
+
// Dynamic table size update (RFC 7541 6.3).
|
|
458
491
|
uint64_t new_size;
|
|
459
492
|
if (hpack_decode_int(buf, len, &pos, 5, &new_size) < 0) return -1;
|
|
460
|
-
if (new_size >
|
|
493
|
+
if (new_size > DEFAULT_HEADER_TABLE_SIZE) return -1;
|
|
461
494
|
*max_table_size = (long)new_size;
|
|
462
|
-
*dyn_table =
|
|
495
|
+
*dyn_table = hpack_dynamic_table_evict(*dyn_table, *max_table_size);
|
|
463
496
|
|
|
464
497
|
} else {
|
|
465
498
|
return -1;
|
|
@@ -487,8 +520,8 @@ static VALUE hpack_encode_header_block(VALUE headers) {
|
|
|
487
520
|
|
|
488
521
|
int found_index = 0;
|
|
489
522
|
for (int idx = 1; idx <= STATIC_TABLE_SIZE; idx++) {
|
|
490
|
-
if (strlen(
|
|
491
|
-
memcmp(
|
|
523
|
+
if (strlen(static_table[idx].name) == name_len &&
|
|
524
|
+
memcmp(static_table[idx].name, name_ptr, name_len) == 0) {
|
|
492
525
|
found_index = idx;
|
|
493
526
|
break;
|
|
494
527
|
}
|
|
@@ -496,35 +529,31 @@ static VALUE hpack_encode_header_block(VALUE headers) {
|
|
|
496
529
|
|
|
497
530
|
if (found_index > 0) {
|
|
498
531
|
int_len = hpack_encode_int(int_buf, found_index, 4, 0x00);
|
|
499
|
-
|
|
532
|
+
rb_str_cat(buf, (const char *)int_buf, int_len);
|
|
500
533
|
} else {
|
|
501
|
-
|
|
534
|
+
rb_str_cat(buf, "\x00", 1);
|
|
502
535
|
|
|
503
536
|
size_t huff_len = hpack_huffman_encode_len(name_ptr, name_len);
|
|
504
537
|
if (huff_len < name_len) {
|
|
505
538
|
int_len = hpack_encode_int(int_buf, huff_len, 7, 0x80);
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
hpack_huffman_encode(name_ptr, name_len, huff_buf);
|
|
509
|
-
rb_str_buf_cat(buf, (const char *)huff_buf, huff_len);
|
|
539
|
+
rb_str_cat(buf, (const char *)int_buf, int_len);
|
|
540
|
+
hpack_append_huffman(buf, name_ptr, name_len, huff_len);
|
|
510
541
|
} else {
|
|
511
542
|
int_len = hpack_encode_int(int_buf, name_len, 7, 0x00);
|
|
512
|
-
|
|
513
|
-
|
|
543
|
+
rb_str_cat(buf, (const char *)int_buf, int_len);
|
|
544
|
+
rb_str_cat(buf, (const char *)name_ptr, name_len);
|
|
514
545
|
}
|
|
515
546
|
}
|
|
516
547
|
|
|
517
548
|
size_t huff_len = hpack_huffman_encode_len(value_ptr, value_len);
|
|
518
549
|
if (huff_len < value_len) {
|
|
519
550
|
int_len = hpack_encode_int(int_buf, huff_len, 7, 0x80);
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
hpack_huffman_encode(value_ptr, value_len, huff_buf);
|
|
523
|
-
rb_str_buf_cat(buf, (const char *)huff_buf, huff_len);
|
|
551
|
+
rb_str_cat(buf, (const char *)int_buf, int_len);
|
|
552
|
+
hpack_append_huffman(buf, value_ptr, value_len, huff_len);
|
|
524
553
|
} else {
|
|
525
554
|
int_len = hpack_encode_int(int_buf, value_len, 7, 0x00);
|
|
526
|
-
|
|
527
|
-
|
|
555
|
+
rb_str_cat(buf, (const char *)int_buf, int_len);
|
|
556
|
+
rb_str_cat(buf, (const char *)value_ptr, value_len);
|
|
528
557
|
}
|
|
529
558
|
}
|
|
530
559
|
|
|
@@ -541,73 +570,30 @@ static void parse_frame_header(const uint8_t *buf, frame_header *fh) {
|
|
|
541
570
|
|
|
542
571
|
static VALUE frame_type_sym(uint8_t type) {
|
|
543
572
|
switch (type) {
|
|
544
|
-
case FRAME_DATA: return ID2SYM(
|
|
545
|
-
case FRAME_HEADERS: return ID2SYM(
|
|
546
|
-
case FRAME_PRIORITY: return ID2SYM(
|
|
547
|
-
case FRAME_RST_STREAM: return ID2SYM(
|
|
548
|
-
case FRAME_SETTINGS: return ID2SYM(
|
|
549
|
-
case FRAME_PUSH_PROMISE: return ID2SYM(
|
|
550
|
-
case FRAME_PING: return ID2SYM(
|
|
551
|
-
case FRAME_GOAWAY: return ID2SYM(
|
|
552
|
-
case FRAME_WINDOW_UPDATE: return ID2SYM(
|
|
553
|
-
case FRAME_CONTINUATION: return ID2SYM(
|
|
554
|
-
default: return ID2SYM(
|
|
573
|
+
case FRAME_DATA: return ID2SYM(id_data);
|
|
574
|
+
case FRAME_HEADERS: return ID2SYM(id_headers);
|
|
575
|
+
case FRAME_PRIORITY: return ID2SYM(id_priority);
|
|
576
|
+
case FRAME_RST_STREAM: return ID2SYM(id_rst_stream);
|
|
577
|
+
case FRAME_SETTINGS: return ID2SYM(id_settings);
|
|
578
|
+
case FRAME_PUSH_PROMISE: return ID2SYM(id_push_promise);
|
|
579
|
+
case FRAME_PING: return ID2SYM(id_ping);
|
|
580
|
+
case FRAME_GOAWAY: return ID2SYM(id_goaway);
|
|
581
|
+
case FRAME_WINDOW_UPDATE: return ID2SYM(id_window_update);
|
|
582
|
+
case FRAME_CONTINUATION: return ID2SYM(id_continuation);
|
|
583
|
+
default: return ID2SYM(id_unknown);
|
|
555
584
|
}
|
|
556
585
|
}
|
|
557
586
|
|
|
558
|
-
static
|
|
559
|
-
static void h2_parser_free(void *ptr) { xfree(ptr); }
|
|
560
|
-
static size_t h2_parser_memsize(const void *ptr) { return sizeof(raptor_h2_parser); }
|
|
561
|
-
|
|
562
|
-
static const rb_data_type_t h2_parser_type = {
|
|
563
|
-
"raptor_http2_parser",
|
|
564
|
-
{h2_parser_mark, h2_parser_free, h2_parser_memsize},
|
|
565
|
-
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
|
|
566
|
-
};
|
|
567
|
-
|
|
568
|
-
static VALUE h2_parser_alloc(VALUE klass) {
|
|
569
|
-
raptor_h2_parser *parser;
|
|
570
|
-
VALUE obj = TypedData_Make_Struct(klass, raptor_h2_parser, &h2_parser_type, parser);
|
|
571
|
-
parser->max_table_size = HTTP2_DEFAULT_HEADER_TABLE_SIZE;
|
|
572
|
-
return obj;
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
static VALUE h2_parse_headers(VALUE self, VALUE header_block, VALUE dyn_table) {
|
|
576
|
-
raptor_h2_parser *parser;
|
|
577
|
-
TypedData_Get_Struct(self, raptor_h2_parser, &h2_parser_type, parser);
|
|
578
|
-
|
|
579
|
-
Check_Type(header_block, T_STRING);
|
|
580
|
-
Check_Type(dyn_table, T_ARRAY);
|
|
581
|
-
|
|
582
|
-
const uint8_t *buf = (const uint8_t *)RSTRING_PTR(header_block);
|
|
583
|
-
size_t len = RSTRING_LEN(header_block);
|
|
584
|
-
|
|
585
|
-
VALUE headers = rb_ary_new();
|
|
586
|
-
VALUE table = rb_ary_dup(dyn_table);
|
|
587
|
-
long max_size = parser->max_table_size;
|
|
588
|
-
|
|
589
|
-
if (hpack_decode_header_block(buf, len, headers, &table, &max_size) < 0)
|
|
590
|
-
rb_raise(eHttp2ParserError, "HPACK header block decode error");
|
|
591
|
-
|
|
592
|
-
parser->max_table_size = max_size;
|
|
593
|
-
return rb_ary_new_from_args(2, headers, table);
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
static VALUE h2_encode_headers(VALUE self, VALUE headers) {
|
|
597
|
-
(void)self;
|
|
598
|
-
Check_Type(headers, T_ARRAY);
|
|
599
|
-
return hpack_encode_header_block(headers);
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
static const char *const HOP_BY_HOP_HEADERS[] = {
|
|
587
|
+
static const char *const hop_by_hop_headers[] = {
|
|
603
588
|
"connection", "transfer-encoding", "keep-alive", "upgrade", "proxy-connection"
|
|
604
589
|
};
|
|
605
|
-
|
|
590
|
+
|
|
591
|
+
#define NUM_HOP_BY_HOP_HEADERS (sizeof(hop_by_hop_headers) / sizeof(hop_by_hop_headers[0]))
|
|
606
592
|
|
|
607
593
|
static int is_hop_by_hop(const char *name, long name_len) {
|
|
608
594
|
for (size_t i = 0; i < NUM_HOP_BY_HOP_HEADERS; i++) {
|
|
609
|
-
size_t hbh_len = strlen(
|
|
610
|
-
if ((long)hbh_len == name_len && memcmp(name,
|
|
595
|
+
size_t hbh_len = strlen(hop_by_hop_headers[i]);
|
|
596
|
+
if ((long)hbh_len == name_len && memcmp(name, hop_by_hop_headers[i], hbh_len) == 0) return 1;
|
|
611
597
|
}
|
|
612
598
|
return 0;
|
|
613
599
|
}
|
|
@@ -622,8 +608,7 @@ static VALUE ascii_lowercase_str(VALUE str) {
|
|
|
622
608
|
return lower;
|
|
623
609
|
}
|
|
624
610
|
|
|
625
|
-
static int response_headers_iter(VALUE key, VALUE value, VALUE
|
|
626
|
-
VALUE pairs = data;
|
|
611
|
+
static int response_headers_iter(VALUE key, VALUE value, VALUE pairs) {
|
|
627
612
|
if (!RB_TYPE_P(key, T_STRING)) return ST_CONTINUE;
|
|
628
613
|
|
|
629
614
|
VALUE lowered = ascii_lowercase_str(key);
|
|
@@ -638,78 +623,96 @@ static int response_headers_iter(VALUE key, VALUE value, VALUE data) {
|
|
|
638
623
|
long entries = RARRAY_LEN(value);
|
|
639
624
|
for (long i = 0; i < entries; i++) {
|
|
640
625
|
VALUE entry = RARRAY_AREF(value, i);
|
|
641
|
-
|
|
642
|
-
rb_ary_push(pairs, rb_ary_new_from_args(2, lowered, str));
|
|
626
|
+
rb_ary_push(pairs, rb_ary_new_from_args(2, lowered, rb_obj_as_string(entry)));
|
|
643
627
|
}
|
|
644
628
|
} else {
|
|
645
|
-
|
|
646
|
-
rb_ary_push(pairs, rb_ary_new_from_args(2, lowered, str));
|
|
629
|
+
rb_ary_push(pairs, rb_ary_new_from_args(2, lowered, rb_obj_as_string(value)));
|
|
647
630
|
}
|
|
648
631
|
return ST_CONTINUE;
|
|
649
632
|
}
|
|
650
633
|
|
|
651
|
-
static
|
|
652
|
-
(
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
634
|
+
static int build_settings_iter(VALUE key, VALUE val, VALUE buf) {
|
|
635
|
+
ID key_id = SYM2ID(key);
|
|
636
|
+
|
|
637
|
+
uint16_t id;
|
|
638
|
+
if (key_id == id_header_table_size) id = SETTINGS_HEADER_TABLE_SIZE;
|
|
639
|
+
else if (key_id == id_enable_push) id = SETTINGS_ENABLE_PUSH;
|
|
640
|
+
else if (key_id == id_max_concurrent_streams) id = SETTINGS_MAX_CONCURRENT_STREAMS;
|
|
641
|
+
else if (key_id == id_initial_window_size) id = SETTINGS_INITIAL_WINDOW_SIZE;
|
|
642
|
+
else if (key_id == id_max_frame_size) id = SETTINGS_MAX_FRAME_SIZE;
|
|
643
|
+
else if (key_id == id_max_header_list_size) id = SETTINGS_MAX_HEADER_LIST_SIZE;
|
|
644
|
+
else return ST_CONTINUE;
|
|
645
|
+
|
|
646
|
+
uint32_t v = NUM2UINT(val);
|
|
647
|
+
uint8_t entry[6];
|
|
648
|
+
entry[0] = (id >> 8) & 0xff;
|
|
649
|
+
entry[1] = id & 0xff;
|
|
650
|
+
entry[2] = (v >> 24) & 0xff;
|
|
651
|
+
entry[3] = (v >> 16) & 0xff;
|
|
652
|
+
entry[4] = (v >> 8) & 0xff;
|
|
653
|
+
entry[5] = v & 0xff;
|
|
654
|
+
rb_str_cat(buf, (const char *)entry, sizeof(entry));
|
|
655
|
+
return ST_CONTINUE;
|
|
660
656
|
}
|
|
661
657
|
|
|
662
|
-
static
|
|
663
|
-
(
|
|
664
|
-
|
|
658
|
+
static size_t h2_parser_memsize(const void *ptr) {
|
|
659
|
+
return sizeof(raptor_h2_parser);
|
|
660
|
+
}
|
|
665
661
|
|
|
666
|
-
|
|
667
|
-
|
|
662
|
+
static const rb_data_type_t h2_parser_type = {
|
|
663
|
+
.wrap_struct_name = "raptor_http2_parser",
|
|
664
|
+
.function = {
|
|
665
|
+
.dfree = RUBY_TYPED_DEFAULT_FREE,
|
|
666
|
+
.dsize = h2_parser_memsize,
|
|
667
|
+
},
|
|
668
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
|
669
|
+
};
|
|
668
670
|
|
|
669
|
-
|
|
671
|
+
static VALUE h2_parser_alloc(VALUE klass) {
|
|
672
|
+
raptor_h2_parser *parser;
|
|
673
|
+
VALUE obj = TypedData_Make_Struct(klass, raptor_h2_parser, &h2_parser_type, parser);
|
|
674
|
+
parser->max_table_size = DEFAULT_HEADER_TABLE_SIZE;
|
|
675
|
+
return obj;
|
|
670
676
|
}
|
|
671
677
|
|
|
672
|
-
static VALUE
|
|
673
|
-
(void)self;
|
|
678
|
+
static VALUE h2_parser_parse_frame(VALUE self, VALUE buffer) {
|
|
674
679
|
Check_Type(buffer, T_STRING);
|
|
675
680
|
|
|
676
681
|
const uint8_t *buf = (const uint8_t *)RSTRING_PTR(buffer);
|
|
677
682
|
size_t len = RSTRING_LEN(buffer);
|
|
678
683
|
|
|
679
|
-
if (len <
|
|
684
|
+
if (len < FRAME_HEADER_SIZE) return Qnil;
|
|
680
685
|
|
|
681
686
|
frame_header fh;
|
|
682
687
|
parse_frame_header(buf, &fh);
|
|
683
688
|
|
|
684
|
-
size_t total =
|
|
689
|
+
size_t total = FRAME_HEADER_SIZE + fh.length;
|
|
685
690
|
if (len < total) return Qnil;
|
|
686
691
|
|
|
687
692
|
VALUE frame = rb_hash_new();
|
|
688
|
-
rb_hash_aset(frame, ID2SYM(
|
|
689
|
-
rb_hash_aset(frame, ID2SYM(
|
|
690
|
-
rb_hash_aset(frame, ID2SYM(
|
|
691
|
-
rb_hash_aset(frame, ID2SYM(
|
|
692
|
-
rb_hash_aset(frame, ID2SYM(
|
|
693
|
+
rb_hash_aset(frame, ID2SYM(id_type), frame_type_sym(fh.type));
|
|
694
|
+
rb_hash_aset(frame, ID2SYM(id_length), UINT2NUM(fh.length));
|
|
695
|
+
rb_hash_aset(frame, ID2SYM(id_flags), UINT2NUM(fh.flags));
|
|
696
|
+
rb_hash_aset(frame, ID2SYM(id_stream_id), UINT2NUM(fh.stream_id));
|
|
697
|
+
rb_hash_aset(frame, ID2SYM(id_payload), rb_str_new((const char *)(buf + FRAME_HEADER_SIZE), fh.length));
|
|
693
698
|
|
|
694
699
|
return rb_ary_new_from_args(2, frame, SIZET2NUM(total));
|
|
695
700
|
}
|
|
696
701
|
|
|
697
|
-
static VALUE
|
|
698
|
-
(void)self;
|
|
699
|
-
|
|
702
|
+
static VALUE h2_parser_build_frame(VALUE self, VALUE type, VALUE flags, VALUE stream_id, VALUE payload) {
|
|
700
703
|
uint8_t frame_type;
|
|
701
704
|
ID type_id = SYM2ID(type);
|
|
702
705
|
|
|
703
|
-
if (type_id ==
|
|
704
|
-
else if (type_id ==
|
|
705
|
-
else if (type_id ==
|
|
706
|
-
else if (type_id ==
|
|
707
|
-
else if (type_id ==
|
|
708
|
-
else if (type_id ==
|
|
709
|
-
else if (type_id ==
|
|
710
|
-
else if (type_id ==
|
|
711
|
-
else if (type_id ==
|
|
712
|
-
else if (type_id ==
|
|
706
|
+
if (type_id == id_data) frame_type = FRAME_DATA;
|
|
707
|
+
else if (type_id == id_headers) frame_type = FRAME_HEADERS;
|
|
708
|
+
else if (type_id == id_priority) frame_type = FRAME_PRIORITY;
|
|
709
|
+
else if (type_id == id_rst_stream) frame_type = FRAME_RST_STREAM;
|
|
710
|
+
else if (type_id == id_settings) frame_type = FRAME_SETTINGS;
|
|
711
|
+
else if (type_id == id_push_promise) frame_type = FRAME_PUSH_PROMISE;
|
|
712
|
+
else if (type_id == id_ping) frame_type = FRAME_PING;
|
|
713
|
+
else if (type_id == id_goaway) frame_type = FRAME_GOAWAY;
|
|
714
|
+
else if (type_id == id_window_update) frame_type = FRAME_WINDOW_UPDATE;
|
|
715
|
+
else if (type_id == id_continuation) frame_type = FRAME_CONTINUATION;
|
|
713
716
|
else rb_raise(rb_eArgError, "unknown frame type");
|
|
714
717
|
|
|
715
718
|
uint8_t frame_flags = (uint8_t)NUM2UINT(flags);
|
|
@@ -718,7 +721,7 @@ static VALUE h2_build_frame(VALUE self, VALUE type, VALUE flags, VALUE stream_id
|
|
|
718
721
|
const char *payload_ptr = NIL_P(payload) ? "" : RSTRING_PTR(payload);
|
|
719
722
|
size_t payload_len = NIL_P(payload) ? 0 : RSTRING_LEN(payload);
|
|
720
723
|
|
|
721
|
-
uint8_t header[
|
|
724
|
+
uint8_t header[FRAME_HEADER_SIZE];
|
|
722
725
|
header[0] = (payload_len >> 16) & 0xff;
|
|
723
726
|
header[1] = (payload_len >> 8) & 0xff;
|
|
724
727
|
header[2] = payload_len & 0xff;
|
|
@@ -729,18 +732,57 @@ static VALUE h2_build_frame(VALUE self, VALUE type, VALUE flags, VALUE stream_id
|
|
|
729
732
|
header[7] = (sid >> 8) & 0xff;
|
|
730
733
|
header[8] = sid & 0xff;
|
|
731
734
|
|
|
732
|
-
VALUE result = rb_str_new((const char *)header,
|
|
733
|
-
|
|
735
|
+
VALUE result = rb_str_new((const char *)header, FRAME_HEADER_SIZE);
|
|
736
|
+
rb_str_cat(result, payload_ptr, payload_len);
|
|
734
737
|
return result;
|
|
735
738
|
}
|
|
736
739
|
|
|
737
|
-
static VALUE
|
|
738
|
-
|
|
739
|
-
|
|
740
|
+
static VALUE h2_parser_parse_headers(VALUE self, VALUE header_block, VALUE dyn_table) {
|
|
741
|
+
raptor_h2_parser *parser;
|
|
742
|
+
TypedData_Get_Struct(self, raptor_h2_parser, &h2_parser_type, parser);
|
|
743
|
+
|
|
744
|
+
Check_Type(header_block, T_STRING);
|
|
745
|
+
Check_Type(dyn_table, T_ARRAY);
|
|
746
|
+
|
|
747
|
+
const uint8_t *buf = (const uint8_t *)RSTRING_PTR(header_block);
|
|
748
|
+
size_t len = RSTRING_LEN(header_block);
|
|
749
|
+
|
|
750
|
+
VALUE headers = rb_ary_new();
|
|
751
|
+
VALUE table = rb_ary_dup(dyn_table);
|
|
752
|
+
long max_size = parser->max_table_size;
|
|
753
|
+
|
|
754
|
+
if (hpack_decode_header_block(buf, len, headers, &table, &max_size) < 0)
|
|
755
|
+
rb_raise(eHttp2ParserError, "HPACK header block decode error");
|
|
756
|
+
|
|
757
|
+
parser->max_table_size = max_size;
|
|
758
|
+
return rb_ary_new_from_args(2, headers, table);
|
|
740
759
|
}
|
|
741
760
|
|
|
742
|
-
static VALUE
|
|
743
|
-
(
|
|
761
|
+
static VALUE h2_parser_encode_headers(VALUE self, VALUE headers) {
|
|
762
|
+
Check_Type(headers, T_ARRAY);
|
|
763
|
+
return hpack_encode_header_block(headers);
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
static VALUE h2_parser_encode_response_headers(VALUE self, VALUE status, VALUE headers) {
|
|
767
|
+
Check_Type(headers, T_HASH);
|
|
768
|
+
|
|
769
|
+
VALUE pairs = rb_ary_new();
|
|
770
|
+
rb_ary_push(pairs, rb_ary_new_from_args(2, rb_str_new_lit(":status"), rb_obj_as_string(status)));
|
|
771
|
+
rb_hash_foreach(headers, response_headers_iter, pairs);
|
|
772
|
+
|
|
773
|
+
return hpack_encode_header_block(pairs);
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
static VALUE h2_parser_encode_response_trailers(VALUE self, VALUE trailers) {
|
|
777
|
+
Check_Type(trailers, T_HASH);
|
|
778
|
+
|
|
779
|
+
VALUE pairs = rb_ary_new();
|
|
780
|
+
rb_hash_foreach(trailers, response_headers_iter, pairs);
|
|
781
|
+
|
|
782
|
+
return hpack_encode_header_block(pairs);
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
static VALUE h2_parser_parse_settings(VALUE self, VALUE payload) {
|
|
744
786
|
Check_Type(payload, T_STRING);
|
|
745
787
|
|
|
746
788
|
const uint8_t *buf = (const uint8_t *)RSTRING_PTR(payload);
|
|
@@ -758,60 +800,38 @@ static VALUE h2_parse_settings(VALUE self, VALUE payload) {
|
|
|
758
800
|
|
|
759
801
|
switch (id) {
|
|
760
802
|
case SETTINGS_HEADER_TABLE_SIZE:
|
|
761
|
-
rb_hash_aset(settings, ID2SYM(
|
|
803
|
+
rb_hash_aset(settings, ID2SYM(id_header_table_size), UINT2NUM(val));
|
|
804
|
+
break;
|
|
762
805
|
case SETTINGS_ENABLE_PUSH:
|
|
763
|
-
rb_hash_aset(settings, ID2SYM(
|
|
806
|
+
rb_hash_aset(settings, ID2SYM(id_enable_push), UINT2NUM(val));
|
|
807
|
+
break;
|
|
764
808
|
case SETTINGS_MAX_CONCURRENT_STREAMS:
|
|
765
|
-
rb_hash_aset(settings, ID2SYM(
|
|
809
|
+
rb_hash_aset(settings, ID2SYM(id_max_concurrent_streams), UINT2NUM(val));
|
|
810
|
+
break;
|
|
766
811
|
case SETTINGS_INITIAL_WINDOW_SIZE:
|
|
767
|
-
rb_hash_aset(settings, ID2SYM(
|
|
812
|
+
rb_hash_aset(settings, ID2SYM(id_initial_window_size), UINT2NUM(val));
|
|
813
|
+
break;
|
|
768
814
|
case SETTINGS_MAX_FRAME_SIZE:
|
|
769
|
-
rb_hash_aset(settings, ID2SYM(
|
|
815
|
+
rb_hash_aset(settings, ID2SYM(id_max_frame_size), UINT2NUM(val));
|
|
816
|
+
break;
|
|
770
817
|
case SETTINGS_MAX_HEADER_LIST_SIZE:
|
|
771
|
-
rb_hash_aset(settings, ID2SYM(
|
|
818
|
+
rb_hash_aset(settings, ID2SYM(id_max_header_list_size), UINT2NUM(val));
|
|
819
|
+
break;
|
|
772
820
|
}
|
|
773
821
|
}
|
|
774
822
|
|
|
775
823
|
return settings;
|
|
776
824
|
}
|
|
777
825
|
|
|
778
|
-
static VALUE
|
|
779
|
-
(void)self;
|
|
826
|
+
static VALUE h2_parser_build_settings(VALUE self, VALUE settings) {
|
|
780
827
|
Check_Type(settings, T_HASH);
|
|
781
828
|
|
|
782
829
|
VALUE buf = rb_str_buf_new(36);
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
for (long i = 0; i < RARRAY_LEN(keys); i++) {
|
|
786
|
-
VALUE key = rb_ary_entry(keys, i);
|
|
787
|
-
VALUE val = rb_hash_aref(settings, key);
|
|
788
|
-
ID key_id = SYM2ID(key);
|
|
789
|
-
|
|
790
|
-
uint16_t id;
|
|
791
|
-
if (key_id == rb_intern("header_table_size")) id = SETTINGS_HEADER_TABLE_SIZE;
|
|
792
|
-
else if (key_id == rb_intern("enable_push")) id = SETTINGS_ENABLE_PUSH;
|
|
793
|
-
else if (key_id == rb_intern("max_concurrent_streams")) id = SETTINGS_MAX_CONCURRENT_STREAMS;
|
|
794
|
-
else if (key_id == rb_intern("initial_window_size")) id = SETTINGS_INITIAL_WINDOW_SIZE;
|
|
795
|
-
else if (key_id == rb_intern("max_frame_size")) id = SETTINGS_MAX_FRAME_SIZE;
|
|
796
|
-
else if (key_id == rb_intern("max_header_list_size")) id = SETTINGS_MAX_HEADER_LIST_SIZE;
|
|
797
|
-
else continue;
|
|
798
|
-
|
|
799
|
-
uint32_t v = NUM2UINT(val);
|
|
800
|
-
uint8_t entry[6];
|
|
801
|
-
entry[0] = (id >> 8) & 0xff;
|
|
802
|
-
entry[1] = id & 0xff;
|
|
803
|
-
entry[2] = (v >> 24) & 0xff;
|
|
804
|
-
entry[3] = (v >> 16) & 0xff;
|
|
805
|
-
entry[4] = (v >> 8) & 0xff;
|
|
806
|
-
entry[5] = v & 0xff;
|
|
807
|
-
rb_str_buf_cat(buf, (const char *)entry, 6);
|
|
808
|
-
}
|
|
809
|
-
|
|
830
|
+
rb_hash_foreach(settings, build_settings_iter, buf);
|
|
810
831
|
return buf;
|
|
811
832
|
}
|
|
812
833
|
|
|
813
|
-
static VALUE
|
|
814
|
-
(void)self;
|
|
834
|
+
static VALUE h2_parser_parse_window_update(VALUE self, VALUE payload) {
|
|
815
835
|
Check_Type(payload, T_STRING);
|
|
816
836
|
|
|
817
837
|
if (RSTRING_LEN(payload) != 4)
|
|
@@ -824,22 +844,51 @@ static VALUE h2_parse_window_update(VALUE self, VALUE payload) {
|
|
|
824
844
|
return UINT2NUM(increment);
|
|
825
845
|
}
|
|
826
846
|
|
|
847
|
+
static VALUE h2_parser_connection_preface(VALUE self) {
|
|
848
|
+
return rb_str_new_lit(CONNECTION_PREFACE);
|
|
849
|
+
}
|
|
850
|
+
|
|
827
851
|
RUBY_FUNC_EXPORTED void Init_raptor_http2(void) {
|
|
828
852
|
rb_ext_ractor_safe(true);
|
|
829
853
|
|
|
830
854
|
VALUE mRaptor = rb_define_module("Raptor");
|
|
831
|
-
cHttp2Parser = rb_define_class_under(mRaptor, "Http2Parser", rb_cObject);
|
|
855
|
+
VALUE cHttp2Parser = rb_define_class_under(mRaptor, "Http2Parser", rb_cObject);
|
|
832
856
|
eHttp2ParserError = rb_define_class_under(mRaptor, "Http2ParserError", rb_eStandardError);
|
|
857
|
+
rb_define_const(cHttp2Parser, "MAX_HEADER_LIST_SIZE", INT2NUM(MAX_HEADER_LIST_SIZE));
|
|
858
|
+
|
|
859
|
+
id_type = rb_intern("type");
|
|
860
|
+
id_length = rb_intern("length");
|
|
861
|
+
id_flags = rb_intern("flags");
|
|
862
|
+
id_stream_id = rb_intern("stream_id");
|
|
863
|
+
id_payload = rb_intern("payload");
|
|
864
|
+
id_data = rb_intern("data");
|
|
865
|
+
id_headers = rb_intern("headers");
|
|
866
|
+
id_priority = rb_intern("priority");
|
|
867
|
+
id_rst_stream = rb_intern("rst_stream");
|
|
868
|
+
id_settings = rb_intern("settings");
|
|
869
|
+
id_push_promise = rb_intern("push_promise");
|
|
870
|
+
id_ping = rb_intern("ping");
|
|
871
|
+
id_goaway = rb_intern("goaway");
|
|
872
|
+
id_window_update = rb_intern("window_update");
|
|
873
|
+
id_continuation = rb_intern("continuation");
|
|
874
|
+
id_unknown = rb_intern("unknown");
|
|
875
|
+
id_header_table_size = rb_intern("header_table_size");
|
|
876
|
+
id_enable_push = rb_intern("enable_push");
|
|
877
|
+
id_max_concurrent_streams = rb_intern("max_concurrent_streams");
|
|
878
|
+
id_initial_window_size = rb_intern("initial_window_size");
|
|
879
|
+
id_max_frame_size = rb_intern("max_frame_size");
|
|
880
|
+
id_max_header_list_size = rb_intern("max_header_list_size");
|
|
833
881
|
|
|
834
882
|
rb_define_alloc_func(cHttp2Parser, h2_parser_alloc);
|
|
835
|
-
rb_define_method(cHttp2Parser, "parse_frame",
|
|
836
|
-
rb_define_method(cHttp2Parser, "
|
|
837
|
-
rb_define_method(cHttp2Parser, "
|
|
838
|
-
rb_define_method(cHttp2Parser, "
|
|
839
|
-
rb_define_method(cHttp2Parser, "
|
|
840
|
-
rb_define_method(cHttp2Parser, "
|
|
841
|
-
rb_define_method(cHttp2Parser, "
|
|
842
|
-
rb_define_method(cHttp2Parser, "
|
|
843
|
-
rb_define_method(cHttp2Parser, "parse_window_update",
|
|
844
|
-
|
|
883
|
+
rb_define_method(cHttp2Parser, "parse_frame", h2_parser_parse_frame, 1);
|
|
884
|
+
rb_define_method(cHttp2Parser, "build_frame", h2_parser_build_frame, 4);
|
|
885
|
+
rb_define_method(cHttp2Parser, "parse_headers", h2_parser_parse_headers, 2);
|
|
886
|
+
rb_define_method(cHttp2Parser, "encode_headers", h2_parser_encode_headers, 1);
|
|
887
|
+
rb_define_method(cHttp2Parser, "encode_response_headers", h2_parser_encode_response_headers, 2);
|
|
888
|
+
rb_define_method(cHttp2Parser, "encode_response_trailers", h2_parser_encode_response_trailers, 1);
|
|
889
|
+
rb_define_method(cHttp2Parser, "parse_settings", h2_parser_parse_settings, 1);
|
|
890
|
+
rb_define_method(cHttp2Parser, "build_settings", h2_parser_build_settings, 1);
|
|
891
|
+
rb_define_method(cHttp2Parser, "parse_window_update", h2_parser_parse_window_update, 1);
|
|
892
|
+
|
|
893
|
+
rb_define_singleton_method(cHttp2Parser, "connection_preface", h2_parser_connection_preface, 0);
|
|
845
894
|
}
|