quic 0.0.5 → 0.0.7
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 +18 -0
- data/LICENSE-DEPENDENCIES.txt +2 -2
- data/README.md +1 -1
- data/ext/quic/connection_common.c +116 -425
- data/ext/quic/connection_common.h +31 -5
- data/ext/quic/ext_api.c +7 -5
- data/ext/quic/extconf.rb +5 -5
- data/ext/quic/include/quic/ext.h +22 -1
- data/ext/quic/stream.c +434 -45
- data/ext/quic/stream.h +68 -22
- data/lib/quic/connection.rb +11 -0
- data/lib/quic/version.rb +1 -1
- data/sig/quic.rbs +14 -12
- metadata +3 -3
data/ext/quic/stream.h
CHANGED
|
@@ -1,27 +1,47 @@
|
|
|
1
1
|
#ifndef QUIC_STREAM_H
|
|
2
2
|
#define QUIC_STREAM_H 1
|
|
3
3
|
|
|
4
|
+
#include "connection_common.h"
|
|
4
5
|
#include "quic.h"
|
|
5
6
|
|
|
6
7
|
extern VALUE rb_cQUICStream;
|
|
7
8
|
|
|
8
9
|
void Init_quic_stream(VALUE rb_mQUICArg);
|
|
9
10
|
|
|
10
|
-
/*
|
|
11
|
-
|
|
11
|
+
/* One write's bytes, kept until the peer acknowledges them. Outside the
|
|
12
|
+
Ruby heap: ngtcp2 keeps pointers into data to retransmit from, and
|
|
13
|
+
GC.compact moves an embedded String. */
|
|
14
|
+
typedef struct quic_send_chunk {
|
|
15
|
+
struct quic_send_chunk *next;
|
|
16
|
+
size_t len;
|
|
17
|
+
uint8_t data[];
|
|
18
|
+
} quic_send_chunk;
|
|
12
19
|
|
|
13
20
|
typedef struct {
|
|
21
|
+
/* The QUIC::Stream wrapping this struct, for the stream callbacks, which
|
|
22
|
+
get the struct from ngtcp2's stream_user_data. It needs no mark, as it
|
|
23
|
+
holds the struct; quic_stream_compact follows it when GC.compact moves
|
|
24
|
+
it. */
|
|
25
|
+
VALUE self;
|
|
14
26
|
int64_t stream_id;
|
|
15
|
-
/*
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
27
|
+
/* The send buffer: what #write queued and the peer has not acknowledged,
|
|
28
|
+
as chunks in stream order. Every offset below is a position in the
|
|
29
|
+
stream. The buffer is freed only where ngtcp2 can no longer read it:
|
|
30
|
+
as the peer acknowledges it, when the stream closes, and in dfree. */
|
|
31
|
+
quic_send_chunk *send_head;
|
|
32
|
+
quic_send_chunk *send_tail;
|
|
33
|
+
/* The chunk holding the next byte to hand to ngtcp2 (sent_offset), and
|
|
34
|
+
where in it; NULL once everything queued has been handed over. That
|
|
35
|
+
chunk ends after sent_offset, which acked_offset never passes, so an
|
|
36
|
+
acknowledgement never frees it. */
|
|
37
|
+
quic_send_chunk *send_next;
|
|
38
|
+
size_t send_next_off;
|
|
39
|
+
uint64_t head_offset; /* where send_head->data[0] sits */
|
|
40
|
+
uint64_t queued_offset; /* just past the last byte queued */
|
|
41
|
+
uint64_t sent_offset; /* just past the last byte handed to ngtcp2 */
|
|
42
|
+
uint64_t acked_offset; /* just past the last byte acknowledged */
|
|
43
|
+
/* What the chunks take from xmalloc, headers included; part of dsize. */
|
|
44
|
+
size_t buffered;
|
|
25
45
|
bool fin_received; /* recv_stream_data delivered FIN */
|
|
26
46
|
bool fin_sent; /* #write(fin: true) queued FIN */
|
|
27
47
|
bool fin_flushed; /* write_pkt actually wrote the FIN frame */
|
|
@@ -29,10 +49,13 @@ typedef struct {
|
|
|
29
49
|
bool closed; /* stream_close callback fired */
|
|
30
50
|
uint64_t close_app_error_code;
|
|
31
51
|
bool close_has_app_error_code;
|
|
32
|
-
/* The send side is shut: the peer's STOP_SENDING
|
|
33
|
-
reported the send side shut while
|
|
34
|
-
|
|
35
|
-
skips the stream
|
|
52
|
+
/* The send side is shut (quic_stream_stop): the peer's STOP_SENDING
|
|
53
|
+
arrived, #reset was called, ngtcp2 reported the send side shut while
|
|
54
|
+
writing, or the stream closed. Nothing queued goes out any more,
|
|
55
|
+
#write_pkt skips the stream, and what it had not sent no longer counts
|
|
56
|
+
in quic_conn_t.stream_unsent. The send buffer stays until the stream
|
|
57
|
+
closes: ngtcp2 may still hold pointers into it at this point
|
|
58
|
+
(recv_stop_sending runs before it drops the stream's queued frames). */
|
|
36
59
|
bool stopped;
|
|
37
60
|
uint64_t stop_app_error_code; /* the STOP_SENDING's, 0 if none arrived */
|
|
38
61
|
/* Set once a peer-initiated stream has been pushed onto the owning
|
|
@@ -46,12 +69,35 @@ typedef struct {
|
|
|
46
69
|
bool peer_stream_held;
|
|
47
70
|
} quic_stream_t;
|
|
48
71
|
|
|
49
|
-
|
|
72
|
+
/* What a connection without a stream handler does with its streams, as
|
|
73
|
+
QUIC::Streams. connection_common.c hands its ngtcp2 stream callbacks and
|
|
74
|
+
#write_pkt here, and keeps only the choice between this and the
|
|
75
|
+
handler. */
|
|
50
76
|
|
|
51
|
-
/*
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
77
|
+
/* Make a QUIC::Stream for stream_id, a stream #open_bidi_stream or
|
|
78
|
+
#open_uni_stream has just opened on the connection self (wrapping c),
|
|
79
|
+
and register it. Returns the Stream. */
|
|
80
|
+
VALUE quic_stream_open_local(VALUE self, quic_conn_t *c, int64_t stream_id);
|
|
81
|
+
|
|
82
|
+
/* The ngtcp2 stream callbacks. s is the stream's stream_user_data: NULL for
|
|
83
|
+
a stream whose QUIC::Stream could not be made, which they ignore. Those
|
|
84
|
+
returning int return 0, or NGTCP2_ERR_CALLBACK_FAILURE when Ruby code
|
|
85
|
+
raised; the exception waits in c->pending_exc. */
|
|
86
|
+
int quic_stream_on_open(quic_conn_t *c, int64_t stream_id);
|
|
87
|
+
int quic_stream_on_recv_data(quic_conn_t *c, quic_stream_t *s, uint32_t flags,
|
|
88
|
+
const uint8_t *data, size_t datalen);
|
|
89
|
+
void quic_stream_on_acked(quic_stream_t *s, uint64_t offset, uint64_t datalen);
|
|
90
|
+
int quic_stream_on_close(quic_conn_t *c, quic_stream_t *s, int64_t stream_id,
|
|
91
|
+
uint32_t flags, uint64_t app_error_code);
|
|
92
|
+
void quic_stream_on_reset(quic_stream_t *s, uint64_t app_error_code);
|
|
93
|
+
void quic_stream_on_recv_stop_sending(quic_conn_t *c, quic_stream_t *s,
|
|
94
|
+
uint64_t app_error_code);
|
|
95
|
+
|
|
96
|
+
/* #write_pkt for the connection self (wrapping c): build the next packet
|
|
97
|
+
into dest, with data from the first stream in @streams that has any.
|
|
98
|
+
Returns what ngtcp2_conn_writev_stream returned. Raises nothing. */
|
|
99
|
+
ngtcp2_ssize quic_streams_write_pkt(VALUE self, quic_conn_t *c,
|
|
100
|
+
ngtcp2_path *path, ngtcp2_pkt_info *pi,
|
|
101
|
+
uint8_t *dest, size_t destlen);
|
|
56
102
|
|
|
57
103
|
#endif /* QUIC_STREAM_H */
|
data/lib/quic/connection.rb
CHANGED
|
@@ -108,6 +108,17 @@ module QUIC
|
|
|
108
108
|
stream
|
|
109
109
|
end
|
|
110
110
|
|
|
111
|
+
# Send an application CONNECTION_CLOSE carrying error_code and reason and
|
|
112
|
+
# enter the closing period. Raises QUIC::Error::NotBound unless #bind was
|
|
113
|
+
# called, except on a connection an Endpoint made, whose CONNECTION_CLOSE
|
|
114
|
+
# goes out through Endpoint#write_pkt. A no-op once the connection is
|
|
115
|
+
# closing or draining.
|
|
116
|
+
def close(error_code: 0, reason: nil)
|
|
117
|
+
packet = _close(error_code, reason)
|
|
118
|
+
@sock.send(packet, 0) if packet
|
|
119
|
+
nil
|
|
120
|
+
end
|
|
121
|
+
|
|
111
122
|
private
|
|
112
123
|
|
|
113
124
|
# A C stream handler (quic/ext.h) registered on the connection owns
|
data/lib/quic/version.rb
CHANGED
data/sig/quic.rbs
CHANGED
|
@@ -321,21 +321,23 @@ module QUIC
|
|
|
321
321
|
|
|
322
322
|
# Blocks (by internally calling #pump_once on the owning Client or
|
|
323
323
|
# Server) until the peer's flow control window has room for the full
|
|
324
|
-
# payload, then queues all bytes and returns data.bytesize.
|
|
325
|
-
#
|
|
326
|
-
#
|
|
327
|
-
#
|
|
328
|
-
#
|
|
329
|
-
#
|
|
324
|
+
# payload, then queues all bytes and returns data.bytesize. The window is
|
|
325
|
+
# the smaller of the stream's and the connection's, and the connection's
|
|
326
|
+
# is shared with what the other streams of the connection have queued
|
|
327
|
+
# but not yet sent. Requires the owning connection to be bound to a
|
|
328
|
+
# socket via #bind; raises QUIC::Error::NotBound otherwise. Raises
|
|
329
|
+
# QUIC::Error::StreamClosed, while waiting too, once the stream has been
|
|
330
|
+
# reset or closed, or the peer has sent STOP_SENDING. STOP_SENDING also
|
|
331
|
+
# drops what was queued but not yet sent.
|
|
330
332
|
def write: (String data, ?fin: bool) -> Integer
|
|
331
333
|
|
|
332
334
|
# Non-blocking variant. Queues as much of `data` as the current flow
|
|
333
|
-
# control window allows and returns the byte count actually
|
|
334
|
-
# Raises QUIC::Error::WaitWritable (mixed in with
|
|
335
|
-
# the window is zero and the payload is non-empty,
|
|
336
|
-
# QUIC::Error::StreamClosed as #write does. If only a partial prefix
|
|
337
|
-
# accepted, `fin: true` is NOT propagated; the caller must re-issue
|
|
338
|
-
# `fin: true` on the trailing chunk.
|
|
335
|
+
# control window (see #write) allows and returns the byte count actually
|
|
336
|
+
# queued. Raises QUIC::Error::WaitWritable (mixed in with
|
|
337
|
+
# IO::WaitWritable) when the window is zero and the payload is non-empty,
|
|
338
|
+
# and QUIC::Error::StreamClosed as #write does. If only a partial prefix
|
|
339
|
+
# is accepted, `fin: true` is NOT propagated; the caller must re-issue
|
|
340
|
+
# with `fin: true` on the trailing chunk.
|
|
339
341
|
def write_nonblock: (String data, ?fin: bool) -> Integer
|
|
340
342
|
def eof?: () -> bool
|
|
341
343
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: quic
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yusuke Nakamura
|
|
@@ -93,14 +93,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
93
93
|
requirements:
|
|
94
94
|
- - ">="
|
|
95
95
|
- !ruby/object:Gem::Version
|
|
96
|
-
version:
|
|
96
|
+
version: '0'
|
|
97
97
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
98
98
|
requirements:
|
|
99
99
|
- - ">="
|
|
100
100
|
- !ruby/object:Gem::Version
|
|
101
101
|
version: '0'
|
|
102
102
|
requirements: []
|
|
103
|
-
rubygems_version: 4.0.
|
|
103
|
+
rubygems_version: 4.0.20
|
|
104
104
|
specification_version: 4
|
|
105
105
|
summary: Thin Ruby binding around ngtcp2 for the QUIC transport protocol, using picotls
|
|
106
106
|
for TLS 1.3 over the system OpenSSL.
|