nghttp3 0.0.1

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.
@@ -0,0 +1,713 @@
1
+ #include "nghttp3.h"
2
+
3
+ VALUE rb_cNghttp3Callbacks;
4
+
5
+ typedef struct {
6
+ VALUE on_acked_stream_data;
7
+ VALUE on_stream_close;
8
+ VALUE on_recv_data;
9
+ VALUE on_deferred_consume;
10
+ VALUE on_begin_headers;
11
+ VALUE on_recv_header;
12
+ VALUE on_end_headers;
13
+ VALUE on_begin_trailers;
14
+ VALUE on_recv_trailer;
15
+ VALUE on_end_trailers;
16
+ VALUE on_stop_sending;
17
+ VALUE on_end_stream;
18
+ VALUE on_reset_stream;
19
+ VALUE on_shutdown;
20
+ VALUE on_recv_settings;
21
+ } CallbacksObj;
22
+
23
+ static void callbacks_mark(void *ptr) {
24
+ CallbacksObj *obj = (CallbacksObj *)ptr;
25
+ rb_gc_mark(obj->on_acked_stream_data);
26
+ rb_gc_mark(obj->on_stream_close);
27
+ rb_gc_mark(obj->on_recv_data);
28
+ rb_gc_mark(obj->on_deferred_consume);
29
+ rb_gc_mark(obj->on_begin_headers);
30
+ rb_gc_mark(obj->on_recv_header);
31
+ rb_gc_mark(obj->on_end_headers);
32
+ rb_gc_mark(obj->on_begin_trailers);
33
+ rb_gc_mark(obj->on_recv_trailer);
34
+ rb_gc_mark(obj->on_end_trailers);
35
+ rb_gc_mark(obj->on_stop_sending);
36
+ rb_gc_mark(obj->on_end_stream);
37
+ rb_gc_mark(obj->on_reset_stream);
38
+ rb_gc_mark(obj->on_shutdown);
39
+ rb_gc_mark(obj->on_recv_settings);
40
+ }
41
+
42
+ static void callbacks_free(void *ptr) { xfree(ptr); }
43
+
44
+ static size_t callbacks_memsize(const void *ptr) {
45
+ return sizeof(CallbacksObj);
46
+ }
47
+
48
+ const rb_data_type_t callbacks_data_type = {
49
+ .wrap_struct_name = "nghttp3_callbacks_rb",
50
+ .function =
51
+ {
52
+ .dmark = callbacks_mark,
53
+ .dfree = callbacks_free,
54
+ .dsize = callbacks_memsize,
55
+ },
56
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
57
+ };
58
+
59
+ static VALUE callbacks_alloc(VALUE klass) {
60
+ CallbacksObj *obj;
61
+ VALUE self =
62
+ TypedData_Make_Struct(klass, CallbacksObj, &callbacks_data_type, obj);
63
+ obj->on_acked_stream_data = Qnil;
64
+ obj->on_stream_close = Qnil;
65
+ obj->on_recv_data = Qnil;
66
+ obj->on_deferred_consume = Qnil;
67
+ obj->on_begin_headers = Qnil;
68
+ obj->on_recv_header = Qnil;
69
+ obj->on_end_headers = Qnil;
70
+ obj->on_begin_trailers = Qnil;
71
+ obj->on_recv_trailer = Qnil;
72
+ obj->on_end_trailers = Qnil;
73
+ obj->on_stop_sending = Qnil;
74
+ obj->on_end_stream = Qnil;
75
+ obj->on_reset_stream = Qnil;
76
+ obj->on_shutdown = Qnil;
77
+ obj->on_recv_settings = Qnil;
78
+ return self;
79
+ }
80
+
81
+ /*
82
+ * call-seq:
83
+ * Callbacks.new -> Callbacks
84
+ *
85
+ * Creates a new Callbacks object for handling HTTP/3 events.
86
+ */
87
+ static VALUE rb_nghttp3_callbacks_initialize(VALUE self) { return self; }
88
+
89
+ /* Callback setters - each takes a block and stores it */
90
+
91
+ /*
92
+ * call-seq:
93
+ * callbacks.on_acked_stream_data { |stream_id, datalen| ... } -> self
94
+ *
95
+ * Sets the callback for acknowledged stream data.
96
+ */
97
+ static VALUE rb_nghttp3_callbacks_on_acked_stream_data(VALUE self) {
98
+ CallbacksObj *obj;
99
+ TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
100
+ obj->on_acked_stream_data = rb_block_proc();
101
+ return self;
102
+ }
103
+
104
+ /*
105
+ * call-seq:
106
+ * callbacks.on_stream_close { |stream_id, app_error_code| ... } -> self
107
+ *
108
+ * Sets the callback for stream close events.
109
+ */
110
+ static VALUE rb_nghttp3_callbacks_on_stream_close(VALUE self) {
111
+ CallbacksObj *obj;
112
+ TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
113
+ obj->on_stream_close = rb_block_proc();
114
+ return self;
115
+ }
116
+
117
+ /*
118
+ * call-seq:
119
+ * callbacks.on_recv_data { |stream_id, data| ... } -> self
120
+ *
121
+ * Sets the callback for receiving data.
122
+ */
123
+ static VALUE rb_nghttp3_callbacks_on_recv_data(VALUE self) {
124
+ CallbacksObj *obj;
125
+ TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
126
+ obj->on_recv_data = rb_block_proc();
127
+ return self;
128
+ }
129
+
130
+ /*
131
+ * call-seq:
132
+ * callbacks.on_deferred_consume { |stream_id, consumed| ... } -> self
133
+ *
134
+ * Sets the callback for deferred consume events.
135
+ */
136
+ static VALUE rb_nghttp3_callbacks_on_deferred_consume(VALUE self) {
137
+ CallbacksObj *obj;
138
+ TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
139
+ obj->on_deferred_consume = rb_block_proc();
140
+ return self;
141
+ }
142
+
143
+ /*
144
+ * call-seq:
145
+ * callbacks.on_begin_headers { |stream_id| ... } -> self
146
+ *
147
+ * Sets the callback for the start of headers.
148
+ */
149
+ static VALUE rb_nghttp3_callbacks_on_begin_headers(VALUE self) {
150
+ CallbacksObj *obj;
151
+ TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
152
+ obj->on_begin_headers = rb_block_proc();
153
+ return self;
154
+ }
155
+
156
+ /*
157
+ * call-seq:
158
+ * callbacks.on_recv_header { |stream_id, name, value, flags| ... } -> self
159
+ *
160
+ * Sets the callback for receiving headers.
161
+ */
162
+ static VALUE rb_nghttp3_callbacks_on_recv_header(VALUE self) {
163
+ CallbacksObj *obj;
164
+ TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
165
+ obj->on_recv_header = rb_block_proc();
166
+ return self;
167
+ }
168
+
169
+ /*
170
+ * call-seq:
171
+ * callbacks.on_end_headers { |stream_id, fin| ... } -> self
172
+ *
173
+ * Sets the callback for the end of headers.
174
+ */
175
+ static VALUE rb_nghttp3_callbacks_on_end_headers(VALUE self) {
176
+ CallbacksObj *obj;
177
+ TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
178
+ obj->on_end_headers = rb_block_proc();
179
+ return self;
180
+ }
181
+
182
+ /*
183
+ * call-seq:
184
+ * callbacks.on_begin_trailers { |stream_id| ... } -> self
185
+ *
186
+ * Sets the callback for the start of trailers.
187
+ */
188
+ static VALUE rb_nghttp3_callbacks_on_begin_trailers(VALUE self) {
189
+ CallbacksObj *obj;
190
+ TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
191
+ obj->on_begin_trailers = rb_block_proc();
192
+ return self;
193
+ }
194
+
195
+ /*
196
+ * call-seq:
197
+ * callbacks.on_recv_trailer { |stream_id, name, value, flags| ... } -> self
198
+ *
199
+ * Sets the callback for receiving trailers.
200
+ */
201
+ static VALUE rb_nghttp3_callbacks_on_recv_trailer(VALUE self) {
202
+ CallbacksObj *obj;
203
+ TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
204
+ obj->on_recv_trailer = rb_block_proc();
205
+ return self;
206
+ }
207
+
208
+ /*
209
+ * call-seq:
210
+ * callbacks.on_end_trailers { |stream_id, fin| ... } -> self
211
+ *
212
+ * Sets the callback for the end of trailers.
213
+ */
214
+ static VALUE rb_nghttp3_callbacks_on_end_trailers(VALUE self) {
215
+ CallbacksObj *obj;
216
+ TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
217
+ obj->on_end_trailers = rb_block_proc();
218
+ return self;
219
+ }
220
+
221
+ /*
222
+ * call-seq:
223
+ * callbacks.on_stop_sending { |stream_id, app_error_code| ... } -> self
224
+ *
225
+ * Sets the callback for stop sending events.
226
+ */
227
+ static VALUE rb_nghttp3_callbacks_on_stop_sending(VALUE self) {
228
+ CallbacksObj *obj;
229
+ TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
230
+ obj->on_stop_sending = rb_block_proc();
231
+ return self;
232
+ }
233
+
234
+ /*
235
+ * call-seq:
236
+ * callbacks.on_end_stream { |stream_id| ... } -> self
237
+ *
238
+ * Sets the callback for stream end events.
239
+ */
240
+ static VALUE rb_nghttp3_callbacks_on_end_stream(VALUE self) {
241
+ CallbacksObj *obj;
242
+ TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
243
+ obj->on_end_stream = rb_block_proc();
244
+ return self;
245
+ }
246
+
247
+ /*
248
+ * call-seq:
249
+ * callbacks.on_reset_stream { |stream_id, app_error_code| ... } -> self
250
+ *
251
+ * Sets the callback for stream reset events.
252
+ */
253
+ static VALUE rb_nghttp3_callbacks_on_reset_stream(VALUE self) {
254
+ CallbacksObj *obj;
255
+ TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
256
+ obj->on_reset_stream = rb_block_proc();
257
+ return self;
258
+ }
259
+
260
+ /*
261
+ * call-seq:
262
+ * callbacks.on_shutdown { |id| ... } -> self
263
+ *
264
+ * Sets the callback for shutdown events.
265
+ */
266
+ static VALUE rb_nghttp3_callbacks_on_shutdown(VALUE self) {
267
+ CallbacksObj *obj;
268
+ TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
269
+ obj->on_shutdown = rb_block_proc();
270
+ return self;
271
+ }
272
+
273
+ /*
274
+ * call-seq:
275
+ * callbacks.on_recv_settings { |settings| ... } -> self
276
+ *
277
+ * Sets the callback for receiving SETTINGS frame.
278
+ */
279
+ static VALUE rb_nghttp3_callbacks_on_recv_settings(VALUE self) {
280
+ CallbacksObj *obj;
281
+ TypedData_Get_Struct(self, CallbacksObj, &callbacks_data_type, obj);
282
+ obj->on_recv_settings = rb_block_proc();
283
+ return self;
284
+ }
285
+
286
+ /* C callback wrapper functions - called by nghttp3 */
287
+
288
+ static int nghttp3_rb_acked_stream_data_callback(nghttp3_conn *conn,
289
+ int64_t stream_id,
290
+ uint64_t datalen,
291
+ void *conn_user_data,
292
+ void *stream_user_data) {
293
+ VALUE rb_conn = (VALUE)conn_user_data;
294
+ VALUE rb_callbacks = nghttp3_rb_get_callbacks(rb_conn);
295
+
296
+ if (NIL_P(rb_callbacks))
297
+ return 0;
298
+
299
+ CallbacksObj *cb;
300
+ TypedData_Get_Struct(rb_callbacks, CallbacksObj, &callbacks_data_type, cb);
301
+
302
+ if (NIL_P(cb->on_acked_stream_data))
303
+ return 0;
304
+
305
+ VALUE args[2] = {LL2NUM(stream_id), ULL2NUM(datalen)};
306
+ rb_proc_call(cb->on_acked_stream_data, rb_ary_new_from_values(2, args));
307
+
308
+ return 0;
309
+ }
310
+
311
+ static int nghttp3_rb_stream_close_callback(nghttp3_conn *conn,
312
+ int64_t stream_id,
313
+ uint64_t app_error_code,
314
+ void *conn_user_data,
315
+ void *stream_user_data) {
316
+ VALUE rb_conn = (VALUE)conn_user_data;
317
+ VALUE rb_callbacks = nghttp3_rb_get_callbacks(rb_conn);
318
+
319
+ if (NIL_P(rb_callbacks))
320
+ return 0;
321
+
322
+ CallbacksObj *cb;
323
+ TypedData_Get_Struct(rb_callbacks, CallbacksObj, &callbacks_data_type, cb);
324
+
325
+ if (NIL_P(cb->on_stream_close))
326
+ return 0;
327
+
328
+ VALUE args[2] = {LL2NUM(stream_id), ULL2NUM(app_error_code)};
329
+ rb_proc_call(cb->on_stream_close, rb_ary_new_from_values(2, args));
330
+
331
+ return 0;
332
+ }
333
+
334
+ static int nghttp3_rb_recv_data_callback(nghttp3_conn *conn, int64_t stream_id,
335
+ const uint8_t *data, size_t datalen,
336
+ void *conn_user_data,
337
+ void *stream_user_data) {
338
+ VALUE rb_conn = (VALUE)conn_user_data;
339
+ VALUE rb_callbacks = nghttp3_rb_get_callbacks(rb_conn);
340
+
341
+ if (NIL_P(rb_callbacks))
342
+ return 0;
343
+
344
+ CallbacksObj *cb;
345
+ TypedData_Get_Struct(rb_callbacks, CallbacksObj, &callbacks_data_type, cb);
346
+
347
+ if (NIL_P(cb->on_recv_data))
348
+ return 0;
349
+
350
+ VALUE rb_data = rb_str_new((const char *)data, datalen);
351
+ VALUE args[2] = {LL2NUM(stream_id), rb_data};
352
+ rb_proc_call(cb->on_recv_data, rb_ary_new_from_values(2, args));
353
+
354
+ return 0;
355
+ }
356
+
357
+ static int nghttp3_rb_deferred_consume_callback(nghttp3_conn *conn,
358
+ int64_t stream_id,
359
+ size_t consumed,
360
+ void *conn_user_data,
361
+ void *stream_user_data) {
362
+ VALUE rb_conn = (VALUE)conn_user_data;
363
+ VALUE rb_callbacks = nghttp3_rb_get_callbacks(rb_conn);
364
+
365
+ if (NIL_P(rb_callbacks))
366
+ return 0;
367
+
368
+ CallbacksObj *cb;
369
+ TypedData_Get_Struct(rb_callbacks, CallbacksObj, &callbacks_data_type, cb);
370
+
371
+ if (NIL_P(cb->on_deferred_consume))
372
+ return 0;
373
+
374
+ VALUE args[2] = {LL2NUM(stream_id), SIZET2NUM(consumed)};
375
+ rb_proc_call(cb->on_deferred_consume, rb_ary_new_from_values(2, args));
376
+
377
+ return 0;
378
+ }
379
+
380
+ static int nghttp3_rb_begin_headers_callback(nghttp3_conn *conn,
381
+ int64_t stream_id,
382
+ void *conn_user_data,
383
+ void *stream_user_data) {
384
+ VALUE rb_conn = (VALUE)conn_user_data;
385
+ VALUE rb_callbacks = nghttp3_rb_get_callbacks(rb_conn);
386
+
387
+ if (NIL_P(rb_callbacks))
388
+ return 0;
389
+
390
+ CallbacksObj *cb;
391
+ TypedData_Get_Struct(rb_callbacks, CallbacksObj, &callbacks_data_type, cb);
392
+
393
+ if (NIL_P(cb->on_begin_headers))
394
+ return 0;
395
+
396
+ VALUE args[1] = {LL2NUM(stream_id)};
397
+ rb_proc_call(cb->on_begin_headers, rb_ary_new_from_values(1, args));
398
+
399
+ return 0;
400
+ }
401
+
402
+ static int nghttp3_rb_recv_header_callback(nghttp3_conn *conn,
403
+ int64_t stream_id, int32_t token,
404
+ nghttp3_rcbuf *name,
405
+ nghttp3_rcbuf *value, uint8_t flags,
406
+ void *conn_user_data,
407
+ void *stream_user_data) {
408
+ VALUE rb_conn = (VALUE)conn_user_data;
409
+ VALUE rb_callbacks = nghttp3_rb_get_callbacks(rb_conn);
410
+
411
+ if (NIL_P(rb_callbacks))
412
+ return 0;
413
+
414
+ CallbacksObj *cb;
415
+ TypedData_Get_Struct(rb_callbacks, CallbacksObj, &callbacks_data_type, cb);
416
+
417
+ if (NIL_P(cb->on_recv_header))
418
+ return 0;
419
+
420
+ nghttp3_vec name_vec = nghttp3_rcbuf_get_buf(name);
421
+ nghttp3_vec value_vec = nghttp3_rcbuf_get_buf(value);
422
+
423
+ VALUE rb_name = rb_str_new((const char *)name_vec.base, name_vec.len);
424
+ VALUE rb_value = rb_str_new((const char *)value_vec.base, value_vec.len);
425
+
426
+ VALUE args[4] = {LL2NUM(stream_id), rb_name, rb_value, UINT2NUM(flags)};
427
+ rb_proc_call(cb->on_recv_header, rb_ary_new_from_values(4, args));
428
+
429
+ return 0;
430
+ }
431
+
432
+ static int nghttp3_rb_end_headers_callback(nghttp3_conn *conn,
433
+ int64_t stream_id, int fin,
434
+ void *conn_user_data,
435
+ void *stream_user_data) {
436
+ VALUE rb_conn = (VALUE)conn_user_data;
437
+ VALUE rb_callbacks = nghttp3_rb_get_callbacks(rb_conn);
438
+
439
+ if (NIL_P(rb_callbacks))
440
+ return 0;
441
+
442
+ CallbacksObj *cb;
443
+ TypedData_Get_Struct(rb_callbacks, CallbacksObj, &callbacks_data_type, cb);
444
+
445
+ if (NIL_P(cb->on_end_headers))
446
+ return 0;
447
+
448
+ VALUE args[2] = {LL2NUM(stream_id), fin ? Qtrue : Qfalse};
449
+ rb_proc_call(cb->on_end_headers, rb_ary_new_from_values(2, args));
450
+
451
+ return 0;
452
+ }
453
+
454
+ static int nghttp3_rb_begin_trailers_callback(nghttp3_conn *conn,
455
+ int64_t stream_id,
456
+ void *conn_user_data,
457
+ void *stream_user_data) {
458
+ VALUE rb_conn = (VALUE)conn_user_data;
459
+ VALUE rb_callbacks = nghttp3_rb_get_callbacks(rb_conn);
460
+
461
+ if (NIL_P(rb_callbacks))
462
+ return 0;
463
+
464
+ CallbacksObj *cb;
465
+ TypedData_Get_Struct(rb_callbacks, CallbacksObj, &callbacks_data_type, cb);
466
+
467
+ if (NIL_P(cb->on_begin_trailers))
468
+ return 0;
469
+
470
+ VALUE args[1] = {LL2NUM(stream_id)};
471
+ rb_proc_call(cb->on_begin_trailers, rb_ary_new_from_values(1, args));
472
+
473
+ return 0;
474
+ }
475
+
476
+ static int nghttp3_rb_recv_trailer_callback(nghttp3_conn *conn,
477
+ int64_t stream_id, int32_t token,
478
+ nghttp3_rcbuf *name,
479
+ nghttp3_rcbuf *value, uint8_t flags,
480
+ void *conn_user_data,
481
+ void *stream_user_data) {
482
+ VALUE rb_conn = (VALUE)conn_user_data;
483
+ VALUE rb_callbacks = nghttp3_rb_get_callbacks(rb_conn);
484
+
485
+ if (NIL_P(rb_callbacks))
486
+ return 0;
487
+
488
+ CallbacksObj *cb;
489
+ TypedData_Get_Struct(rb_callbacks, CallbacksObj, &callbacks_data_type, cb);
490
+
491
+ if (NIL_P(cb->on_recv_trailer))
492
+ return 0;
493
+
494
+ nghttp3_vec name_vec = nghttp3_rcbuf_get_buf(name);
495
+ nghttp3_vec value_vec = nghttp3_rcbuf_get_buf(value);
496
+
497
+ VALUE rb_name = rb_str_new((const char *)name_vec.base, name_vec.len);
498
+ VALUE rb_value = rb_str_new((const char *)value_vec.base, value_vec.len);
499
+
500
+ VALUE args[4] = {LL2NUM(stream_id), rb_name, rb_value, UINT2NUM(flags)};
501
+ rb_proc_call(cb->on_recv_trailer, rb_ary_new_from_values(4, args));
502
+
503
+ return 0;
504
+ }
505
+
506
+ static int nghttp3_rb_end_trailers_callback(nghttp3_conn *conn,
507
+ int64_t stream_id, int fin,
508
+ void *conn_user_data,
509
+ void *stream_user_data) {
510
+ VALUE rb_conn = (VALUE)conn_user_data;
511
+ VALUE rb_callbacks = nghttp3_rb_get_callbacks(rb_conn);
512
+
513
+ if (NIL_P(rb_callbacks))
514
+ return 0;
515
+
516
+ CallbacksObj *cb;
517
+ TypedData_Get_Struct(rb_callbacks, CallbacksObj, &callbacks_data_type, cb);
518
+
519
+ if (NIL_P(cb->on_end_trailers))
520
+ return 0;
521
+
522
+ VALUE args[2] = {LL2NUM(stream_id), fin ? Qtrue : Qfalse};
523
+ rb_proc_call(cb->on_end_trailers, rb_ary_new_from_values(2, args));
524
+
525
+ return 0;
526
+ }
527
+
528
+ static int nghttp3_rb_stop_sending_callback(nghttp3_conn *conn,
529
+ int64_t stream_id,
530
+ uint64_t app_error_code,
531
+ void *conn_user_data,
532
+ void *stream_user_data) {
533
+ VALUE rb_conn = (VALUE)conn_user_data;
534
+ VALUE rb_callbacks = nghttp3_rb_get_callbacks(rb_conn);
535
+
536
+ if (NIL_P(rb_callbacks))
537
+ return 0;
538
+
539
+ CallbacksObj *cb;
540
+ TypedData_Get_Struct(rb_callbacks, CallbacksObj, &callbacks_data_type, cb);
541
+
542
+ if (NIL_P(cb->on_stop_sending))
543
+ return 0;
544
+
545
+ VALUE args[2] = {LL2NUM(stream_id), ULL2NUM(app_error_code)};
546
+ rb_proc_call(cb->on_stop_sending, rb_ary_new_from_values(2, args));
547
+
548
+ return 0;
549
+ }
550
+
551
+ static int nghttp3_rb_end_stream_callback(nghttp3_conn *conn, int64_t stream_id,
552
+ void *conn_user_data,
553
+ void *stream_user_data) {
554
+ VALUE rb_conn = (VALUE)conn_user_data;
555
+ VALUE rb_callbacks = nghttp3_rb_get_callbacks(rb_conn);
556
+
557
+ if (NIL_P(rb_callbacks))
558
+ return 0;
559
+
560
+ CallbacksObj *cb;
561
+ TypedData_Get_Struct(rb_callbacks, CallbacksObj, &callbacks_data_type, cb);
562
+
563
+ if (NIL_P(cb->on_end_stream))
564
+ return 0;
565
+
566
+ VALUE args[1] = {LL2NUM(stream_id)};
567
+ rb_proc_call(cb->on_end_stream, rb_ary_new_from_values(1, args));
568
+
569
+ return 0;
570
+ }
571
+
572
+ static int nghttp3_rb_reset_stream_callback(nghttp3_conn *conn,
573
+ int64_t stream_id,
574
+ uint64_t app_error_code,
575
+ void *conn_user_data,
576
+ void *stream_user_data) {
577
+ VALUE rb_conn = (VALUE)conn_user_data;
578
+ VALUE rb_callbacks = nghttp3_rb_get_callbacks(rb_conn);
579
+
580
+ if (NIL_P(rb_callbacks))
581
+ return 0;
582
+
583
+ CallbacksObj *cb;
584
+ TypedData_Get_Struct(rb_callbacks, CallbacksObj, &callbacks_data_type, cb);
585
+
586
+ if (NIL_P(cb->on_reset_stream))
587
+ return 0;
588
+
589
+ VALUE args[2] = {LL2NUM(stream_id), ULL2NUM(app_error_code)};
590
+ rb_proc_call(cb->on_reset_stream, rb_ary_new_from_values(2, args));
591
+
592
+ return 0;
593
+ }
594
+
595
+ static int nghttp3_rb_shutdown_callback(nghttp3_conn *conn, int64_t id,
596
+ void *conn_user_data) {
597
+ VALUE rb_conn = (VALUE)conn_user_data;
598
+ VALUE rb_callbacks = nghttp3_rb_get_callbacks(rb_conn);
599
+
600
+ if (NIL_P(rb_callbacks))
601
+ return 0;
602
+
603
+ CallbacksObj *cb;
604
+ TypedData_Get_Struct(rb_callbacks, CallbacksObj, &callbacks_data_type, cb);
605
+
606
+ if (NIL_P(cb->on_shutdown))
607
+ return 0;
608
+
609
+ VALUE args[1] = {LL2NUM(id)};
610
+ rb_proc_call(cb->on_shutdown, rb_ary_new_from_values(1, args));
611
+
612
+ return 0;
613
+ }
614
+
615
+ static int nghttp3_rb_recv_settings_callback(nghttp3_conn *conn,
616
+ const nghttp3_settings *settings,
617
+ void *conn_user_data) {
618
+ VALUE rb_conn = (VALUE)conn_user_data;
619
+ VALUE rb_callbacks = nghttp3_rb_get_callbacks(rb_conn);
620
+
621
+ if (NIL_P(rb_callbacks))
622
+ return 0;
623
+
624
+ CallbacksObj *cb;
625
+ TypedData_Get_Struct(rb_callbacks, CallbacksObj, &callbacks_data_type, cb);
626
+
627
+ if (NIL_P(cb->on_recv_settings))
628
+ return 0;
629
+
630
+ /* Create a Ruby hash with settings values */
631
+ VALUE rb_settings = rb_hash_new();
632
+ rb_hash_aset(rb_settings, ID2SYM(rb_intern("max_field_section_size")),
633
+ ULL2NUM(settings->max_field_section_size));
634
+ rb_hash_aset(rb_settings, ID2SYM(rb_intern("qpack_max_dtable_capacity")),
635
+ SIZET2NUM(settings->qpack_max_dtable_capacity));
636
+ rb_hash_aset(rb_settings,
637
+ ID2SYM(rb_intern("qpack_encoder_max_dtable_capacity")),
638
+ SIZET2NUM(settings->qpack_encoder_max_dtable_capacity));
639
+ rb_hash_aset(rb_settings, ID2SYM(rb_intern("qpack_blocked_streams")),
640
+ SIZET2NUM(settings->qpack_blocked_streams));
641
+ rb_hash_aset(rb_settings, ID2SYM(rb_intern("enable_connect_protocol")),
642
+ settings->enable_connect_protocol ? Qtrue : Qfalse);
643
+ rb_hash_aset(rb_settings, ID2SYM(rb_intern("h3_datagram")),
644
+ settings->h3_datagram ? Qtrue : Qfalse);
645
+
646
+ VALUE args[1] = {rb_settings};
647
+ rb_proc_call(cb->on_recv_settings, rb_ary_new_from_values(1, args));
648
+
649
+ return 0;
650
+ }
651
+
652
+ /*
653
+ * Sets up the nghttp3_callbacks structure with our C wrapper functions.
654
+ */
655
+ void nghttp3_rb_setup_callbacks(nghttp3_callbacks *callbacks) {
656
+ callbacks->acked_stream_data = nghttp3_rb_acked_stream_data_callback;
657
+ callbacks->stream_close = nghttp3_rb_stream_close_callback;
658
+ callbacks->recv_data = nghttp3_rb_recv_data_callback;
659
+ callbacks->deferred_consume = nghttp3_rb_deferred_consume_callback;
660
+ callbacks->begin_headers = nghttp3_rb_begin_headers_callback;
661
+ callbacks->recv_header = nghttp3_rb_recv_header_callback;
662
+ callbacks->end_headers = nghttp3_rb_end_headers_callback;
663
+ callbacks->begin_trailers = nghttp3_rb_begin_trailers_callback;
664
+ callbacks->recv_trailer = nghttp3_rb_recv_trailer_callback;
665
+ callbacks->end_trailers = nghttp3_rb_end_trailers_callback;
666
+ callbacks->stop_sending = nghttp3_rb_stop_sending_callback;
667
+ callbacks->end_stream = nghttp3_rb_end_stream_callback;
668
+ callbacks->reset_stream = nghttp3_rb_reset_stream_callback;
669
+ callbacks->shutdown = nghttp3_rb_shutdown_callback;
670
+ callbacks->recv_settings = nghttp3_rb_recv_settings_callback;
671
+ }
672
+
673
+ void Init_nghttp3_callbacks(void) {
674
+ rb_cNghttp3Callbacks =
675
+ rb_define_class_under(rb_mNghttp3, "Callbacks", rb_cObject);
676
+
677
+ rb_define_alloc_func(rb_cNghttp3Callbacks, callbacks_alloc);
678
+
679
+ rb_define_method(rb_cNghttp3Callbacks, "initialize",
680
+ rb_nghttp3_callbacks_initialize, 0);
681
+
682
+ /* Callback setters */
683
+ rb_define_method(rb_cNghttp3Callbacks, "on_acked_stream_data",
684
+ rb_nghttp3_callbacks_on_acked_stream_data, 0);
685
+ rb_define_method(rb_cNghttp3Callbacks, "on_stream_close",
686
+ rb_nghttp3_callbacks_on_stream_close, 0);
687
+ rb_define_method(rb_cNghttp3Callbacks, "on_recv_data",
688
+ rb_nghttp3_callbacks_on_recv_data, 0);
689
+ rb_define_method(rb_cNghttp3Callbacks, "on_deferred_consume",
690
+ rb_nghttp3_callbacks_on_deferred_consume, 0);
691
+ rb_define_method(rb_cNghttp3Callbacks, "on_begin_headers",
692
+ rb_nghttp3_callbacks_on_begin_headers, 0);
693
+ rb_define_method(rb_cNghttp3Callbacks, "on_recv_header",
694
+ rb_nghttp3_callbacks_on_recv_header, 0);
695
+ rb_define_method(rb_cNghttp3Callbacks, "on_end_headers",
696
+ rb_nghttp3_callbacks_on_end_headers, 0);
697
+ rb_define_method(rb_cNghttp3Callbacks, "on_begin_trailers",
698
+ rb_nghttp3_callbacks_on_begin_trailers, 0);
699
+ rb_define_method(rb_cNghttp3Callbacks, "on_recv_trailer",
700
+ rb_nghttp3_callbacks_on_recv_trailer, 0);
701
+ rb_define_method(rb_cNghttp3Callbacks, "on_end_trailers",
702
+ rb_nghttp3_callbacks_on_end_trailers, 0);
703
+ rb_define_method(rb_cNghttp3Callbacks, "on_stop_sending",
704
+ rb_nghttp3_callbacks_on_stop_sending, 0);
705
+ rb_define_method(rb_cNghttp3Callbacks, "on_end_stream",
706
+ rb_nghttp3_callbacks_on_end_stream, 0);
707
+ rb_define_method(rb_cNghttp3Callbacks, "on_reset_stream",
708
+ rb_nghttp3_callbacks_on_reset_stream, 0);
709
+ rb_define_method(rb_cNghttp3Callbacks, "on_shutdown",
710
+ rb_nghttp3_callbacks_on_shutdown, 0);
711
+ rb_define_method(rb_cNghttp3Callbacks, "on_recv_settings",
712
+ rb_nghttp3_callbacks_on_recv_settings, 0);
713
+ }