http3 0.0.3
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 +7 -0
- data/.clang-format +1 -0
- data/.vscode/extensions.json +6 -0
- data/.vscode/settings.json +10 -0
- data/CHANGELOG.md +34 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/LICENSE-DEPENDENCIES.txt +66 -0
- data/LICENSE.txt +21 -0
- data/README.md +127 -0
- data/Rakefile +20 -0
- data/ext/http3/extconf.rb +48 -0
- data/ext/http3/nghttp3.c +347 -0
- data/ext/http3/nghttp3.h +105 -0
- data/ext/http3/nghttp3_callbacks.c +621 -0
- data/ext/http3/nghttp3_connection.c +1303 -0
- data/ext/http3/nghttp3_nv.c +87 -0
- data/ext/http3/nghttp3_qpack.c +656 -0
- data/ext/http3/nghttp3_settings.c +188 -0
- data/ext/http3/session.c +1017 -0
- data/lib/http3/rack_adapter.rb +162 -0
- data/lib/http3/request.rb +9 -0
- data/lib/http3/response.rb +21 -0
- data/lib/http3/server.rb +357 -0
- data/lib/http3/session.rb +193 -0
- data/lib/http3/version.rb +5 -0
- data/lib/http3.rb +16 -0
- data/sig/http3/nghttp3/callbacks.rbs +32 -0
- data/sig/http3/nghttp3/connection.rbs +101 -0
- data/sig/http3/nghttp3/error.rbs +48 -0
- data/sig/http3/nghttp3/info.rbs +9 -0
- data/sig/http3/nghttp3/nv.rbs +11 -0
- data/sig/http3/nghttp3/qpack.rbs +48 -0
- data/sig/http3/nghttp3/settings.rbs +27 -0
- data/sig/http3/rack_adapter.rbs +18 -0
- data/sig/http3/request.rbs +11 -0
- data/sig/http3/response.rbs +30 -0
- data/sig/http3/server.rbs +32 -0
- data/sig/http3/session.rbs +52 -0
- data/sig/http3.rbs +66 -0
- metadata +140 -0
|
@@ -0,0 +1,621 @@
|
|
|
1
|
+
#include "nghttp3.h"
|
|
2
|
+
|
|
3
|
+
#include <stddef.h>
|
|
4
|
+
|
|
5
|
+
VALUE rb_cNghttp3Callbacks;
|
|
6
|
+
|
|
7
|
+
typedef struct {
|
|
8
|
+
VALUE on_acked_stream_data;
|
|
9
|
+
VALUE on_stream_close;
|
|
10
|
+
VALUE on_recv_data;
|
|
11
|
+
VALUE on_deferred_consume;
|
|
12
|
+
VALUE on_begin_headers;
|
|
13
|
+
VALUE on_recv_header;
|
|
14
|
+
VALUE on_end_headers;
|
|
15
|
+
VALUE on_begin_trailers;
|
|
16
|
+
VALUE on_recv_trailer;
|
|
17
|
+
VALUE on_end_trailers;
|
|
18
|
+
VALUE on_stop_sending;
|
|
19
|
+
VALUE on_end_stream;
|
|
20
|
+
VALUE on_reset_stream;
|
|
21
|
+
VALUE on_shutdown;
|
|
22
|
+
VALUE on_recv_settings;
|
|
23
|
+
} CallbacksObj;
|
|
24
|
+
|
|
25
|
+
static void callbacks_mark(void *ptr) {
|
|
26
|
+
CallbacksObj *obj = (CallbacksObj *)ptr;
|
|
27
|
+
rb_gc_mark(obj->on_acked_stream_data);
|
|
28
|
+
rb_gc_mark(obj->on_stream_close);
|
|
29
|
+
rb_gc_mark(obj->on_recv_data);
|
|
30
|
+
rb_gc_mark(obj->on_deferred_consume);
|
|
31
|
+
rb_gc_mark(obj->on_begin_headers);
|
|
32
|
+
rb_gc_mark(obj->on_recv_header);
|
|
33
|
+
rb_gc_mark(obj->on_end_headers);
|
|
34
|
+
rb_gc_mark(obj->on_begin_trailers);
|
|
35
|
+
rb_gc_mark(obj->on_recv_trailer);
|
|
36
|
+
rb_gc_mark(obj->on_end_trailers);
|
|
37
|
+
rb_gc_mark(obj->on_stop_sending);
|
|
38
|
+
rb_gc_mark(obj->on_end_stream);
|
|
39
|
+
rb_gc_mark(obj->on_reset_stream);
|
|
40
|
+
rb_gc_mark(obj->on_shutdown);
|
|
41
|
+
rb_gc_mark(obj->on_recv_settings);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
static void callbacks_free(void *ptr) { xfree(ptr); }
|
|
45
|
+
|
|
46
|
+
static size_t callbacks_memsize(const void *ptr) {
|
|
47
|
+
return sizeof(CallbacksObj);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const rb_data_type_t callbacks_data_type = {
|
|
51
|
+
.wrap_struct_name = "nghttp3_callbacks_rb",
|
|
52
|
+
.function =
|
|
53
|
+
{
|
|
54
|
+
.dmark = callbacks_mark,
|
|
55
|
+
.dfree = callbacks_free,
|
|
56
|
+
.dsize = callbacks_memsize,
|
|
57
|
+
},
|
|
58
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
static VALUE callbacks_alloc(VALUE klass) {
|
|
62
|
+
CallbacksObj *obj;
|
|
63
|
+
VALUE self =
|
|
64
|
+
TypedData_Make_Struct(klass, CallbacksObj, &callbacks_data_type, obj);
|
|
65
|
+
obj->on_acked_stream_data = Qnil;
|
|
66
|
+
obj->on_stream_close = Qnil;
|
|
67
|
+
obj->on_recv_data = Qnil;
|
|
68
|
+
obj->on_deferred_consume = Qnil;
|
|
69
|
+
obj->on_begin_headers = Qnil;
|
|
70
|
+
obj->on_recv_header = Qnil;
|
|
71
|
+
obj->on_end_headers = Qnil;
|
|
72
|
+
obj->on_begin_trailers = Qnil;
|
|
73
|
+
obj->on_recv_trailer = Qnil;
|
|
74
|
+
obj->on_end_trailers = Qnil;
|
|
75
|
+
obj->on_stop_sending = Qnil;
|
|
76
|
+
obj->on_end_stream = Qnil;
|
|
77
|
+
obj->on_reset_stream = Qnil;
|
|
78
|
+
obj->on_shutdown = Qnil;
|
|
79
|
+
obj->on_recv_settings = Qnil;
|
|
80
|
+
return self;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/*
|
|
84
|
+
* call-seq:
|
|
85
|
+
* Callbacks.new -> Callbacks
|
|
86
|
+
*
|
|
87
|
+
* Creates a new Callbacks object for handling HTTP/3 events.
|
|
88
|
+
*/
|
|
89
|
+
static VALUE rb_nghttp3_callbacks_initialize(VALUE self) { return self; }
|
|
90
|
+
|
|
91
|
+
/* Callback setters - each takes a block and stores it */
|
|
92
|
+
|
|
93
|
+
/*
|
|
94
|
+
* call-seq:
|
|
95
|
+
* callbacks.on_acked_stream_data { |stream_id, datalen| ... } -> self
|
|
96
|
+
*
|
|
97
|
+
* Sets the callback for acknowledged stream data.
|
|
98
|
+
*/
|
|
99
|
+
static VALUE rb_nghttp3_callbacks_on_acked_stream_data(VALUE self) {
|
|
100
|
+
CallbacksObj *obj;
|
|
101
|
+
TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
|
|
102
|
+
obj->on_acked_stream_data = rb_block_proc();
|
|
103
|
+
return self;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/*
|
|
107
|
+
* call-seq:
|
|
108
|
+
* callbacks.on_stream_close { |stream_id, app_error_code| ... } -> self
|
|
109
|
+
*
|
|
110
|
+
* Sets the callback for stream close events.
|
|
111
|
+
*/
|
|
112
|
+
static VALUE rb_nghttp3_callbacks_on_stream_close(VALUE self) {
|
|
113
|
+
CallbacksObj *obj;
|
|
114
|
+
TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
|
|
115
|
+
obj->on_stream_close = rb_block_proc();
|
|
116
|
+
return self;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/*
|
|
120
|
+
* call-seq:
|
|
121
|
+
* callbacks.on_recv_data { |stream_id, data| ... } -> self
|
|
122
|
+
*
|
|
123
|
+
* Sets the callback for receiving data.
|
|
124
|
+
*/
|
|
125
|
+
static VALUE rb_nghttp3_callbacks_on_recv_data(VALUE self) {
|
|
126
|
+
CallbacksObj *obj;
|
|
127
|
+
TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
|
|
128
|
+
obj->on_recv_data = rb_block_proc();
|
|
129
|
+
return self;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/*
|
|
133
|
+
* call-seq:
|
|
134
|
+
* callbacks.on_deferred_consume { |stream_id, consumed| ... } -> self
|
|
135
|
+
*
|
|
136
|
+
* Sets the callback for deferred consume events.
|
|
137
|
+
*/
|
|
138
|
+
static VALUE rb_nghttp3_callbacks_on_deferred_consume(VALUE self) {
|
|
139
|
+
CallbacksObj *obj;
|
|
140
|
+
TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
|
|
141
|
+
obj->on_deferred_consume = rb_block_proc();
|
|
142
|
+
return self;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/*
|
|
146
|
+
* call-seq:
|
|
147
|
+
* callbacks.on_begin_headers { |stream_id| ... } -> self
|
|
148
|
+
*
|
|
149
|
+
* Sets the callback for the start of headers.
|
|
150
|
+
*/
|
|
151
|
+
static VALUE rb_nghttp3_callbacks_on_begin_headers(VALUE self) {
|
|
152
|
+
CallbacksObj *obj;
|
|
153
|
+
TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
|
|
154
|
+
obj->on_begin_headers = rb_block_proc();
|
|
155
|
+
return self;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/*
|
|
159
|
+
* call-seq:
|
|
160
|
+
* callbacks.on_recv_header { |stream_id, name, value, flags| ... } -> self
|
|
161
|
+
*
|
|
162
|
+
* Sets the callback for receiving headers.
|
|
163
|
+
*/
|
|
164
|
+
static VALUE rb_nghttp3_callbacks_on_recv_header(VALUE self) {
|
|
165
|
+
CallbacksObj *obj;
|
|
166
|
+
TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
|
|
167
|
+
obj->on_recv_header = rb_block_proc();
|
|
168
|
+
return self;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/*
|
|
172
|
+
* call-seq:
|
|
173
|
+
* callbacks.on_end_headers { |stream_id, fin| ... } -> self
|
|
174
|
+
*
|
|
175
|
+
* Sets the callback for the end of headers.
|
|
176
|
+
*/
|
|
177
|
+
static VALUE rb_nghttp3_callbacks_on_end_headers(VALUE self) {
|
|
178
|
+
CallbacksObj *obj;
|
|
179
|
+
TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
|
|
180
|
+
obj->on_end_headers = rb_block_proc();
|
|
181
|
+
return self;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/*
|
|
185
|
+
* call-seq:
|
|
186
|
+
* callbacks.on_begin_trailers { |stream_id| ... } -> self
|
|
187
|
+
*
|
|
188
|
+
* Sets the callback for the start of trailers.
|
|
189
|
+
*/
|
|
190
|
+
static VALUE rb_nghttp3_callbacks_on_begin_trailers(VALUE self) {
|
|
191
|
+
CallbacksObj *obj;
|
|
192
|
+
TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
|
|
193
|
+
obj->on_begin_trailers = rb_block_proc();
|
|
194
|
+
return self;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/*
|
|
198
|
+
* call-seq:
|
|
199
|
+
* callbacks.on_recv_trailer { |stream_id, name, value, flags| ... } -> self
|
|
200
|
+
*
|
|
201
|
+
* Sets the callback for receiving trailers.
|
|
202
|
+
*/
|
|
203
|
+
static VALUE rb_nghttp3_callbacks_on_recv_trailer(VALUE self) {
|
|
204
|
+
CallbacksObj *obj;
|
|
205
|
+
TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
|
|
206
|
+
obj->on_recv_trailer = rb_block_proc();
|
|
207
|
+
return self;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/*
|
|
211
|
+
* call-seq:
|
|
212
|
+
* callbacks.on_end_trailers { |stream_id, fin| ... } -> self
|
|
213
|
+
*
|
|
214
|
+
* Sets the callback for the end of trailers.
|
|
215
|
+
*/
|
|
216
|
+
static VALUE rb_nghttp3_callbacks_on_end_trailers(VALUE self) {
|
|
217
|
+
CallbacksObj *obj;
|
|
218
|
+
TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
|
|
219
|
+
obj->on_end_trailers = rb_block_proc();
|
|
220
|
+
return self;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/*
|
|
224
|
+
* call-seq:
|
|
225
|
+
* callbacks.on_stop_sending { |stream_id, app_error_code| ... } -> self
|
|
226
|
+
*
|
|
227
|
+
* Sets the callback for stop sending events.
|
|
228
|
+
*/
|
|
229
|
+
static VALUE rb_nghttp3_callbacks_on_stop_sending(VALUE self) {
|
|
230
|
+
CallbacksObj *obj;
|
|
231
|
+
TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
|
|
232
|
+
obj->on_stop_sending = rb_block_proc();
|
|
233
|
+
return self;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/*
|
|
237
|
+
* call-seq:
|
|
238
|
+
* callbacks.on_end_stream { |stream_id| ... } -> self
|
|
239
|
+
*
|
|
240
|
+
* Sets the callback for stream end events.
|
|
241
|
+
*/
|
|
242
|
+
static VALUE rb_nghttp3_callbacks_on_end_stream(VALUE self) {
|
|
243
|
+
CallbacksObj *obj;
|
|
244
|
+
TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
|
|
245
|
+
obj->on_end_stream = rb_block_proc();
|
|
246
|
+
return self;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/*
|
|
250
|
+
* call-seq:
|
|
251
|
+
* callbacks.on_reset_stream { |stream_id, app_error_code| ... } -> self
|
|
252
|
+
*
|
|
253
|
+
* Sets the callback for stream reset events.
|
|
254
|
+
*/
|
|
255
|
+
static VALUE rb_nghttp3_callbacks_on_reset_stream(VALUE self) {
|
|
256
|
+
CallbacksObj *obj;
|
|
257
|
+
TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
|
|
258
|
+
obj->on_reset_stream = rb_block_proc();
|
|
259
|
+
return self;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/*
|
|
263
|
+
* call-seq:
|
|
264
|
+
* callbacks.on_shutdown { |id| ... } -> self
|
|
265
|
+
*
|
|
266
|
+
* Sets the callback for shutdown events.
|
|
267
|
+
*/
|
|
268
|
+
static VALUE rb_nghttp3_callbacks_on_shutdown(VALUE self) {
|
|
269
|
+
CallbacksObj *obj;
|
|
270
|
+
TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
|
|
271
|
+
obj->on_shutdown = rb_block_proc();
|
|
272
|
+
return self;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/*
|
|
276
|
+
* call-seq:
|
|
277
|
+
* callbacks.on_recv_settings { |settings| ... } -> self
|
|
278
|
+
*
|
|
279
|
+
* Sets the callback for receiving SETTINGS frame.
|
|
280
|
+
*/
|
|
281
|
+
static VALUE rb_nghttp3_callbacks_on_recv_settings(VALUE self) {
|
|
282
|
+
CallbacksObj *obj;
|
|
283
|
+
TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
|
|
284
|
+
obj->on_recv_settings = rb_block_proc();
|
|
285
|
+
return self;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/* C callback wrapper functions - called by nghttp3 */
|
|
289
|
+
|
|
290
|
+
/* An argument for a Ruby callback, kept as C data until the protected body
|
|
291
|
+
* makes it a VALUE, so that nothing can raise outside rb_protect. */
|
|
292
|
+
typedef struct {
|
|
293
|
+
enum { CB_ARG_I64, CB_ARG_U64, CB_ARG_BOOL, CB_ARG_BYTES } kind;
|
|
294
|
+
union {
|
|
295
|
+
int64_t i64;
|
|
296
|
+
uint64_t u64;
|
|
297
|
+
int b;
|
|
298
|
+
struct {
|
|
299
|
+
const uint8_t *base;
|
|
300
|
+
size_t len;
|
|
301
|
+
} bytes;
|
|
302
|
+
} v;
|
|
303
|
+
} cb_arg;
|
|
304
|
+
|
|
305
|
+
#define CB_I64(x) ((cb_arg){.kind = CB_ARG_I64, .v.i64 = (x)})
|
|
306
|
+
#define CB_U64(x) ((cb_arg){.kind = CB_ARG_U64, .v.u64 = (x)})
|
|
307
|
+
#define CB_BOOL(x) ((cb_arg){.kind = CB_ARG_BOOL, .v.b = (x)})
|
|
308
|
+
#define CB_BYTES(vec) \
|
|
309
|
+
((cb_arg){.kind = CB_ARG_BYTES, .v.bytes = {(vec).base, (vec).len}})
|
|
310
|
+
|
|
311
|
+
typedef struct {
|
|
312
|
+
VALUE proc;
|
|
313
|
+
int argc;
|
|
314
|
+
const cb_arg *argv;
|
|
315
|
+
} cb_call;
|
|
316
|
+
|
|
317
|
+
static VALUE cb_arg_value(const cb_arg *arg) {
|
|
318
|
+
switch (arg->kind) {
|
|
319
|
+
case CB_ARG_I64:
|
|
320
|
+
return LL2NUM(arg->v.i64);
|
|
321
|
+
case CB_ARG_U64:
|
|
322
|
+
return ULL2NUM(arg->v.u64);
|
|
323
|
+
case CB_ARG_BOOL:
|
|
324
|
+
return arg->v.b ? Qtrue : Qfalse;
|
|
325
|
+
case CB_ARG_BYTES:
|
|
326
|
+
return rb_str_new((const char *)arg->v.bytes.base, arg->v.bytes.len);
|
|
327
|
+
}
|
|
328
|
+
return Qnil;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
static VALUE cb_call_body(VALUE arg) {
|
|
332
|
+
const cb_call *call = (const cb_call *)arg;
|
|
333
|
+
VALUE values[4];
|
|
334
|
+
for (int i = 0; i < call->argc; i++) {
|
|
335
|
+
values[i] = cb_arg_value(&call->argv[i]);
|
|
336
|
+
}
|
|
337
|
+
rb_proc_call(call->proc, rb_ary_new_from_values(call->argc, values));
|
|
338
|
+
return Qnil;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/* Call the block of obj's Callbacks stored at proc_offset in CallbacksObj,
|
|
342
|
+
* if there is one. Returns 0, or NGHTTP3_ERR_CALLBACK_FAILURE when it
|
|
343
|
+
* raised. */
|
|
344
|
+
static int cb_dispatch(ConnectionObj *obj, size_t proc_offset, int argc,
|
|
345
|
+
const cb_arg *argv) {
|
|
346
|
+
if (NIL_P(obj->callbacks)) {
|
|
347
|
+
return 0;
|
|
348
|
+
}
|
|
349
|
+
/* The type was checked when the connection was made. */
|
|
350
|
+
VALUE proc =
|
|
351
|
+
*(VALUE *)((char *)RTYPEDDATA_DATA(obj->callbacks) + proc_offset);
|
|
352
|
+
if (NIL_P(proc)) {
|
|
353
|
+
return 0;
|
|
354
|
+
}
|
|
355
|
+
cb_call call = {proc, argc, argv};
|
|
356
|
+
return nghttp3_rb_protect(obj, cb_call_body, (VALUE)&call);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
#define CB_DISPATCH(obj, field, ...) \
|
|
360
|
+
do { \
|
|
361
|
+
const cb_arg args_[] = {__VA_ARGS__}; \
|
|
362
|
+
return cb_dispatch((obj), offsetof(CallbacksObj, field), \
|
|
363
|
+
(int)(sizeof(args_) / sizeof(args_[0])), args_); \
|
|
364
|
+
} while (0)
|
|
365
|
+
|
|
366
|
+
typedef struct {
|
|
367
|
+
ConnectionObj *obj;
|
|
368
|
+
int64_t stream_id;
|
|
369
|
+
uint64_t datalen;
|
|
370
|
+
} stream_event;
|
|
371
|
+
|
|
372
|
+
static VALUE acked_body(VALUE arg) {
|
|
373
|
+
const stream_event *e = (const stream_event *)arg;
|
|
374
|
+
nghttp3_rb_conn_acked(e->obj, e->stream_id, e->datalen);
|
|
375
|
+
return Qnil;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
static VALUE stream_closed_body(VALUE arg) {
|
|
379
|
+
const stream_event *e = (const stream_event *)arg;
|
|
380
|
+
nghttp3_rb_conn_stream_closed(e->obj, e->stream_id);
|
|
381
|
+
return Qnil;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/* Let go of the body Strings acknowledged in full before the Ruby block
|
|
385
|
+
* runs, whether or not there is one. */
|
|
386
|
+
static int nghttp3_rb_acked_stream_data_callback(nghttp3_conn *conn,
|
|
387
|
+
int64_t stream_id,
|
|
388
|
+
uint64_t datalen,
|
|
389
|
+
void *conn_user_data,
|
|
390
|
+
void *stream_user_data) {
|
|
391
|
+
ConnectionObj *obj = conn_user_data;
|
|
392
|
+
stream_event e = {obj, stream_id, datalen};
|
|
393
|
+
if (nghttp3_rb_protect(obj, acked_body, (VALUE)&e) != 0) {
|
|
394
|
+
return NGHTTP3_ERR_CALLBACK_FAILURE;
|
|
395
|
+
}
|
|
396
|
+
CB_DISPATCH(obj, on_acked_stream_data, CB_I64(stream_id), CB_U64(datalen));
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
static int nghttp3_rb_stream_close_callback(nghttp3_conn *conn,
|
|
400
|
+
int64_t stream_id,
|
|
401
|
+
uint64_t app_error_code,
|
|
402
|
+
void *conn_user_data,
|
|
403
|
+
void *stream_user_data) {
|
|
404
|
+
ConnectionObj *obj = conn_user_data;
|
|
405
|
+
stream_event e = {obj, stream_id, 0};
|
|
406
|
+
if (nghttp3_rb_protect(obj, stream_closed_body, (VALUE)&e) != 0) {
|
|
407
|
+
return NGHTTP3_ERR_CALLBACK_FAILURE;
|
|
408
|
+
}
|
|
409
|
+
CB_DISPATCH(obj, on_stream_close, CB_I64(stream_id), CB_U64(app_error_code));
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
static int nghttp3_rb_recv_data_callback(nghttp3_conn *conn, int64_t stream_id,
|
|
413
|
+
const uint8_t *data, size_t datalen,
|
|
414
|
+
void *conn_user_data,
|
|
415
|
+
void *stream_user_data) {
|
|
416
|
+
nghttp3_vec vec = {(uint8_t *)data, datalen};
|
|
417
|
+
CB_DISPATCH((ConnectionObj *)conn_user_data, on_recv_data, CB_I64(stream_id),
|
|
418
|
+
CB_BYTES(vec));
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
static int nghttp3_rb_deferred_consume_callback(nghttp3_conn *conn,
|
|
422
|
+
int64_t stream_id,
|
|
423
|
+
size_t consumed,
|
|
424
|
+
void *conn_user_data,
|
|
425
|
+
void *stream_user_data) {
|
|
426
|
+
CB_DISPATCH((ConnectionObj *)conn_user_data, on_deferred_consume,
|
|
427
|
+
CB_I64(stream_id), CB_U64(consumed));
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
static int nghttp3_rb_begin_headers_callback(nghttp3_conn *conn,
|
|
431
|
+
int64_t stream_id,
|
|
432
|
+
void *conn_user_data,
|
|
433
|
+
void *stream_user_data) {
|
|
434
|
+
CB_DISPATCH((ConnectionObj *)conn_user_data, on_begin_headers,
|
|
435
|
+
CB_I64(stream_id));
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
static int nghttp3_rb_recv_header_callback(nghttp3_conn *conn,
|
|
439
|
+
int64_t stream_id, int32_t token,
|
|
440
|
+
nghttp3_rcbuf *name,
|
|
441
|
+
nghttp3_rcbuf *value, uint8_t flags,
|
|
442
|
+
void *conn_user_data,
|
|
443
|
+
void *stream_user_data) {
|
|
444
|
+
CB_DISPATCH((ConnectionObj *)conn_user_data, on_recv_header,
|
|
445
|
+
CB_I64(stream_id), CB_BYTES(nghttp3_rcbuf_get_buf(name)),
|
|
446
|
+
CB_BYTES(nghttp3_rcbuf_get_buf(value)), CB_U64(flags));
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
static int nghttp3_rb_end_headers_callback(nghttp3_conn *conn,
|
|
450
|
+
int64_t stream_id, int fin,
|
|
451
|
+
void *conn_user_data,
|
|
452
|
+
void *stream_user_data) {
|
|
453
|
+
CB_DISPATCH((ConnectionObj *)conn_user_data, on_end_headers,
|
|
454
|
+
CB_I64(stream_id), CB_BOOL(fin));
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
static int nghttp3_rb_begin_trailers_callback(nghttp3_conn *conn,
|
|
458
|
+
int64_t stream_id,
|
|
459
|
+
void *conn_user_data,
|
|
460
|
+
void *stream_user_data) {
|
|
461
|
+
CB_DISPATCH((ConnectionObj *)conn_user_data, on_begin_trailers,
|
|
462
|
+
CB_I64(stream_id));
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
static int nghttp3_rb_recv_trailer_callback(nghttp3_conn *conn,
|
|
466
|
+
int64_t stream_id, int32_t token,
|
|
467
|
+
nghttp3_rcbuf *name,
|
|
468
|
+
nghttp3_rcbuf *value, uint8_t flags,
|
|
469
|
+
void *conn_user_data,
|
|
470
|
+
void *stream_user_data) {
|
|
471
|
+
CB_DISPATCH((ConnectionObj *)conn_user_data, on_recv_trailer,
|
|
472
|
+
CB_I64(stream_id), CB_BYTES(nghttp3_rcbuf_get_buf(name)),
|
|
473
|
+
CB_BYTES(nghttp3_rcbuf_get_buf(value)), CB_U64(flags));
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
static int nghttp3_rb_end_trailers_callback(nghttp3_conn *conn,
|
|
477
|
+
int64_t stream_id, int fin,
|
|
478
|
+
void *conn_user_data,
|
|
479
|
+
void *stream_user_data) {
|
|
480
|
+
CB_DISPATCH((ConnectionObj *)conn_user_data, on_end_trailers,
|
|
481
|
+
CB_I64(stream_id), CB_BOOL(fin));
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
static int nghttp3_rb_stop_sending_callback(nghttp3_conn *conn,
|
|
485
|
+
int64_t stream_id,
|
|
486
|
+
uint64_t app_error_code,
|
|
487
|
+
void *conn_user_data,
|
|
488
|
+
void *stream_user_data) {
|
|
489
|
+
CB_DISPATCH((ConnectionObj *)conn_user_data, on_stop_sending,
|
|
490
|
+
CB_I64(stream_id), CB_U64(app_error_code));
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
static int nghttp3_rb_end_stream_callback(nghttp3_conn *conn, int64_t stream_id,
|
|
494
|
+
void *conn_user_data,
|
|
495
|
+
void *stream_user_data) {
|
|
496
|
+
CB_DISPATCH((ConnectionObj *)conn_user_data, on_end_stream,
|
|
497
|
+
CB_I64(stream_id));
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
static int nghttp3_rb_reset_stream_callback(nghttp3_conn *conn,
|
|
501
|
+
int64_t stream_id,
|
|
502
|
+
uint64_t app_error_code,
|
|
503
|
+
void *conn_user_data,
|
|
504
|
+
void *stream_user_data) {
|
|
505
|
+
CB_DISPATCH((ConnectionObj *)conn_user_data, on_reset_stream,
|
|
506
|
+
CB_I64(stream_id), CB_U64(app_error_code));
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
static int nghttp3_rb_shutdown_callback(nghttp3_conn *conn, int64_t id,
|
|
510
|
+
void *conn_user_data) {
|
|
511
|
+
CB_DISPATCH((ConnectionObj *)conn_user_data, on_shutdown, CB_I64(id));
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
typedef struct {
|
|
515
|
+
VALUE proc;
|
|
516
|
+
const nghttp3_settings *settings;
|
|
517
|
+
} settings_call;
|
|
518
|
+
|
|
519
|
+
static VALUE recv_settings_body(VALUE arg) {
|
|
520
|
+
const settings_call *call = (const settings_call *)arg;
|
|
521
|
+
const nghttp3_settings *settings = call->settings;
|
|
522
|
+
|
|
523
|
+
/* Create a Ruby hash with settings values */
|
|
524
|
+
VALUE rb_settings = rb_hash_new();
|
|
525
|
+
rb_hash_aset(rb_settings, ID2SYM(rb_intern("max_field_section_size")),
|
|
526
|
+
ULL2NUM(settings->max_field_section_size));
|
|
527
|
+
rb_hash_aset(rb_settings, ID2SYM(rb_intern("qpack_max_dtable_capacity")),
|
|
528
|
+
SIZET2NUM(settings->qpack_max_dtable_capacity));
|
|
529
|
+
rb_hash_aset(rb_settings,
|
|
530
|
+
ID2SYM(rb_intern("qpack_encoder_max_dtable_capacity")),
|
|
531
|
+
SIZET2NUM(settings->qpack_encoder_max_dtable_capacity));
|
|
532
|
+
rb_hash_aset(rb_settings, ID2SYM(rb_intern("qpack_blocked_streams")),
|
|
533
|
+
SIZET2NUM(settings->qpack_blocked_streams));
|
|
534
|
+
rb_hash_aset(rb_settings, ID2SYM(rb_intern("enable_connect_protocol")),
|
|
535
|
+
settings->enable_connect_protocol ? Qtrue : Qfalse);
|
|
536
|
+
rb_hash_aset(rb_settings, ID2SYM(rb_intern("h3_datagram")),
|
|
537
|
+
settings->h3_datagram ? Qtrue : Qfalse);
|
|
538
|
+
|
|
539
|
+
rb_proc_call(call->proc, rb_ary_new_from_values(1, &rb_settings));
|
|
540
|
+
return Qnil;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
static int nghttp3_rb_recv_settings_callback(nghttp3_conn *conn,
|
|
544
|
+
const nghttp3_settings *settings,
|
|
545
|
+
void *conn_user_data) {
|
|
546
|
+
ConnectionObj *obj = conn_user_data;
|
|
547
|
+
if (NIL_P(obj->callbacks)) {
|
|
548
|
+
return 0;
|
|
549
|
+
}
|
|
550
|
+
CallbacksObj *cb = RTYPEDDATA_DATA(obj->callbacks);
|
|
551
|
+
if (NIL_P(cb->on_recv_settings)) {
|
|
552
|
+
return 0;
|
|
553
|
+
}
|
|
554
|
+
settings_call call = {cb->on_recv_settings, settings};
|
|
555
|
+
return nghttp3_rb_protect(obj, recv_settings_body, (VALUE)&call);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/*
|
|
559
|
+
* Sets up the nghttp3_callbacks structure with our C wrapper functions.
|
|
560
|
+
* They are installed whether or not the connection has Callbacks, since
|
|
561
|
+
* acked_stream_data and stream_close also release the body Strings.
|
|
562
|
+
*/
|
|
563
|
+
void nghttp3_rb_setup_callbacks(nghttp3_callbacks *callbacks) {
|
|
564
|
+
callbacks->acked_stream_data = nghttp3_rb_acked_stream_data_callback;
|
|
565
|
+
callbacks->stream_close = nghttp3_rb_stream_close_callback;
|
|
566
|
+
callbacks->recv_data = nghttp3_rb_recv_data_callback;
|
|
567
|
+
callbacks->deferred_consume = nghttp3_rb_deferred_consume_callback;
|
|
568
|
+
callbacks->begin_headers = nghttp3_rb_begin_headers_callback;
|
|
569
|
+
callbacks->recv_header = nghttp3_rb_recv_header_callback;
|
|
570
|
+
callbacks->end_headers = nghttp3_rb_end_headers_callback;
|
|
571
|
+
callbacks->begin_trailers = nghttp3_rb_begin_trailers_callback;
|
|
572
|
+
callbacks->recv_trailer = nghttp3_rb_recv_trailer_callback;
|
|
573
|
+
callbacks->end_trailers = nghttp3_rb_end_trailers_callback;
|
|
574
|
+
callbacks->stop_sending = nghttp3_rb_stop_sending_callback;
|
|
575
|
+
callbacks->end_stream = nghttp3_rb_end_stream_callback;
|
|
576
|
+
callbacks->reset_stream = nghttp3_rb_reset_stream_callback;
|
|
577
|
+
callbacks->shutdown = nghttp3_rb_shutdown_callback;
|
|
578
|
+
callbacks->recv_settings = nghttp3_rb_recv_settings_callback;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
void Init_nghttp3_callbacks(void) {
|
|
582
|
+
rb_cNghttp3Callbacks =
|
|
583
|
+
rb_define_class_under(rb_mNghttp3, "Callbacks", rb_cObject);
|
|
584
|
+
|
|
585
|
+
rb_define_alloc_func(rb_cNghttp3Callbacks, callbacks_alloc);
|
|
586
|
+
|
|
587
|
+
rb_define_method(rb_cNghttp3Callbacks, "initialize",
|
|
588
|
+
rb_nghttp3_callbacks_initialize, 0);
|
|
589
|
+
|
|
590
|
+
/* Callback setters */
|
|
591
|
+
rb_define_method(rb_cNghttp3Callbacks, "on_acked_stream_data",
|
|
592
|
+
rb_nghttp3_callbacks_on_acked_stream_data, 0);
|
|
593
|
+
rb_define_method(rb_cNghttp3Callbacks, "on_stream_close",
|
|
594
|
+
rb_nghttp3_callbacks_on_stream_close, 0);
|
|
595
|
+
rb_define_method(rb_cNghttp3Callbacks, "on_recv_data",
|
|
596
|
+
rb_nghttp3_callbacks_on_recv_data, 0);
|
|
597
|
+
rb_define_method(rb_cNghttp3Callbacks, "on_deferred_consume",
|
|
598
|
+
rb_nghttp3_callbacks_on_deferred_consume, 0);
|
|
599
|
+
rb_define_method(rb_cNghttp3Callbacks, "on_begin_headers",
|
|
600
|
+
rb_nghttp3_callbacks_on_begin_headers, 0);
|
|
601
|
+
rb_define_method(rb_cNghttp3Callbacks, "on_recv_header",
|
|
602
|
+
rb_nghttp3_callbacks_on_recv_header, 0);
|
|
603
|
+
rb_define_method(rb_cNghttp3Callbacks, "on_end_headers",
|
|
604
|
+
rb_nghttp3_callbacks_on_end_headers, 0);
|
|
605
|
+
rb_define_method(rb_cNghttp3Callbacks, "on_begin_trailers",
|
|
606
|
+
rb_nghttp3_callbacks_on_begin_trailers, 0);
|
|
607
|
+
rb_define_method(rb_cNghttp3Callbacks, "on_recv_trailer",
|
|
608
|
+
rb_nghttp3_callbacks_on_recv_trailer, 0);
|
|
609
|
+
rb_define_method(rb_cNghttp3Callbacks, "on_end_trailers",
|
|
610
|
+
rb_nghttp3_callbacks_on_end_trailers, 0);
|
|
611
|
+
rb_define_method(rb_cNghttp3Callbacks, "on_stop_sending",
|
|
612
|
+
rb_nghttp3_callbacks_on_stop_sending, 0);
|
|
613
|
+
rb_define_method(rb_cNghttp3Callbacks, "on_end_stream",
|
|
614
|
+
rb_nghttp3_callbacks_on_end_stream, 0);
|
|
615
|
+
rb_define_method(rb_cNghttp3Callbacks, "on_reset_stream",
|
|
616
|
+
rb_nghttp3_callbacks_on_reset_stream, 0);
|
|
617
|
+
rb_define_method(rb_cNghttp3Callbacks, "on_shutdown",
|
|
618
|
+
rb_nghttp3_callbacks_on_shutdown, 0);
|
|
619
|
+
rb_define_method(rb_cNghttp3Callbacks, "on_recv_settings",
|
|
620
|
+
rb_nghttp3_callbacks_on_recv_settings, 0);
|
|
621
|
+
}
|