quic 0.0.3 → 0.0.4

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.
@@ -38,7 +38,7 @@ typedef struct {
38
38
  /* Filled by quic_override_verify_cb during the handshake so that a failed
39
39
  read_pkt can raise CertificateVerifyFailed with the X509 error. */
40
40
  bool verify_failed;
41
- int verify_result; /* X509_V_ERR_*, 0 when the server sent no certificate */
41
+ int verify_result; /* X509_V_ERR_*, 0 when the server sent no certificate */
42
42
  /* The TLS native handle handed to ngtcp2 (&cptls, not cptls.ptls). */
43
43
  ngtcp2_crypto_picotls_ctx cptls;
44
44
  /* [0]: QUIC transport params, filled in by ngtcp2; [1]: terminator. */
@@ -87,8 +87,9 @@ typedef struct {
87
87
  recv_stream_data queues for #accept_stream. */
88
88
  bool is_server;
89
89
  /* <qlog_dir>/<SCID>.sqlog while ngtcp2 writes qlog to it, else NULL.
90
- Closed on NGTCP2_QLOG_WRITE_FLAG_FIN, which ngtcp2_conn_del sends at
91
- the latest. */
90
+ quic_conn_close_qlog closes it as soon as the connection ends;
91
+ NGTCP2_QLOG_WRITE_FLAG_FIN, sent by ngtcp2_conn_del, closes one still
92
+ open when the connection is freed. */
92
93
  FILE *qlog;
93
94
  /* The rest is for a connection a QUIC::Endpoint made, and stays zero (nil)
94
95
  otherwise. endpoint is the Endpoint whose table holds this connection,
@@ -130,14 +131,14 @@ ngtcp2_tstamp quic_now(void);
130
131
  *path. Returns the packet's length, 0 when there is nothing to send, or a
131
132
  negative ngtcp2 error. Never raises for the connection's own failures: an
132
133
  exception from a Ruby callback is left in c->pending_exc. */
133
- ngtcp2_ssize quic_conn_write_pkt_raw(VALUE self, quic_conn_t *c, ngtcp2_path *path,
134
- uint8_t *dest);
134
+ ngtcp2_ssize quic_conn_write_pkt_raw(VALUE self, quic_conn_t *c,
135
+ ngtcp2_path *path, uint8_t *dest);
135
136
 
136
137
  /* Feed one datagram to the connection, as #read_pkt does, and return what
137
138
  ngtcp2_conn_read_pkt returned. Like quic_conn_write_pkt_raw, it leaves an
138
139
  exception from a Ruby callback in c->pending_exc. */
139
- int quic_conn_read_pkt_raw(quic_conn_t *c, const ngtcp2_path *path, const uint8_t *data,
140
- size_t datalen);
140
+ int quic_conn_read_pkt_raw(quic_conn_t *c, const ngtcp2_path *path,
141
+ const uint8_t *data, size_t datalen);
141
142
 
142
143
  /* The exception #read_pkt raises for rv, an error ngtcp2_conn_read_pkt
143
144
  returned: a CryptoError (or CertificateVerifyFailed) with the TLS alert
@@ -149,8 +150,9 @@ VALUE quic_conn_error_new(quic_conn_t *c, int rv);
149
150
  (a QUIC::TLSContext). ep is the Endpoint that will hold it (its object
150
151
  ep_owner), or NULL for Server.accept. Raises if ngtcp2 or picotls cannot
151
152
  set the connection up. */
152
- VALUE quic_server_conn_new(VALUE klass, const ngtcp2_pkt_hd *hd, const ngtcp2_path *path,
153
- VALUE tls_context, VALUE transport_params, VALUE settings_v,
153
+ VALUE quic_server_conn_new(VALUE klass, const ngtcp2_pkt_hd *hd,
154
+ const ngtcp2_path *path, VALUE tls_context,
155
+ VALUE transport_params, VALUE settings_v,
154
156
  quic_endpoint_t *ep, VALUE ep_owner);
155
157
 
156
158
  quic_conn_t *quic_conn_get(VALUE self);
@@ -181,7 +183,8 @@ VALUE quic_path_value(VALUE value, const char *name);
181
183
  the list's entries point into. Both are stored in *list and *buf as soon
182
184
  as they are allocated, for the caller to release with xfree even when
183
185
  this raises. An empty Array allocates nothing and sets *count to 0. */
184
- void quic_copy_alpn(VALUE alpn_ary, ptls_iovec_t **list, size_t *count, uint8_t **buf);
186
+ void quic_copy_alpn(VALUE alpn_ary, ptls_iovec_t **list, size_t *count,
187
+ uint8_t **buf);
185
188
 
186
189
  /* Copy settings.alpn into memory owned by c (c->alpn / c->alpn_buf). An
187
190
  empty list leaves c->alpn_count at 0. */
@@ -201,7 +204,13 @@ void quic_fill_settings(ngtcp2_settings *settings, VALUE st);
201
204
  qlog there. c->scid must be set. A file that cannot be opened only goes
202
205
  without qlog: QUIC::Settings#check_qlog_dir already caught a wrong
203
206
  directory when the connection or Endpoint was set up. */
204
- void quic_conn_open_qlog(quic_conn_t *c, VALUE settings_v, ngtcp2_settings *settings);
207
+ void quic_conn_open_qlog(quic_conn_t *c, VALUE settings_v,
208
+ ngtcp2_settings *settings);
209
+
210
+ /* Close c's qlog file, if open. Called wherever the connection ends, so
211
+ that the file does not wait for GC; what ngtcp2 logs afterwards goes
212
+ nowhere. */
213
+ void quic_conn_close_qlog(quic_conn_t *c);
205
214
 
206
215
  /* Zero *callbacks and fill in everything both endpoints share. The caller
207
216
  adds the endpoint specific ones (client_initial / recv_retry, or
@@ -7,17 +7,15 @@ NORETURN(static void quic_server_raise_unacceptable(void));
7
7
 
8
8
  /* The first datagram cannot start a connection. code stays nil: this is
9
9
  _accept's own verdict, not an ngtcp2 error passed through. */
10
- static void
11
- quic_server_raise_unacceptable(void)
12
- {
10
+ static void quic_server_raise_unacceptable(void) {
13
11
  rb_raise(rb_eQUICErrorProto, "not an acceptable Initial packet");
14
12
  }
15
13
 
16
14
  VALUE
17
- quic_server_conn_new(VALUE klass, const ngtcp2_pkt_hd *hd, const ngtcp2_path *path,
18
- VALUE tls_context, VALUE transport_params, VALUE settings_v,
19
- quic_endpoint_t *ep, VALUE ep_owner)
20
- {
15
+ quic_server_conn_new(VALUE klass, const ngtcp2_pkt_hd *hd,
16
+ const ngtcp2_path *path, VALUE tls_context,
17
+ VALUE transport_params, VALUE settings_v,
18
+ quic_endpoint_t *ep, VALUE ep_owner) {
21
19
  VALUE self = quic_conn_alloc(klass);
22
20
  quic_conn_t *c = quic_conn_get(self);
23
21
  c->owner = self;
@@ -50,8 +48,10 @@ quic_server_conn_new(VALUE klass, const ngtcp2_pkt_hd *hd, const ngtcp2_path *pa
50
48
  /* Only an Endpoint can answer with a Stateless Reset, for a CID it no
51
49
  longer knows, so only its connections announce a token. */
52
50
  if (ep != NULL) {
53
- if (quic_endpoint_generate_reset_token(ep, params.stateless_reset_token, &c->scid) != 0) {
54
- rb_raise(rb_eRuntimeError, "ngtcp2_crypto_generate_stateless_reset_token failed");
51
+ if (quic_endpoint_generate_reset_token(ep, params.stateless_reset_token,
52
+ &c->scid) != 0) {
53
+ rb_raise(rb_eRuntimeError,
54
+ "ngtcp2_crypto_generate_stateless_reset_token failed");
55
55
  }
56
56
  params.stateless_reset_token_present = 1;
57
57
  }
@@ -66,19 +66,23 @@ quic_server_conn_new(VALUE klass, const ngtcp2_pkt_hd *hd, const ngtcp2_path *pa
66
66
 
67
67
  ngtcp2_settings settings;
68
68
  quic_fill_settings(&settings, settings_v);
69
+ /* Every raise below closes it first. */
69
70
  quic_conn_open_qlog(c, settings_v, &settings);
70
71
 
71
72
  c->conn_ref.get_conn = quic_conn_get_conn;
72
73
  c->conn_ref.user_data = c;
73
74
 
74
- int rv = ngtcp2_conn_server_new(&c->conn, &c->dcid, &c->scid, path, hd->version,
75
- &callbacks, &settings, &params, NULL, c);
75
+ int rv =
76
+ ngtcp2_conn_server_new(&c->conn, &c->dcid, &c->scid, path, hd->version,
77
+ &callbacks, &settings, &params, NULL, c);
76
78
  if (rv != 0) {
79
+ quic_conn_close_qlog(c);
77
80
  quic_raise_ngtcp2_error(rv);
78
81
  }
79
82
 
80
83
  c->cptls.ptls = ptls_server_new(&c->tls->ctx);
81
84
  if (c->cptls.ptls == NULL) {
85
+ quic_conn_close_qlog(c);
82
86
  rb_raise(rb_eRuntimeError, "ptls_server_new failed");
83
87
  }
84
88
  /* Let ngtcp2's crypto callbacks resolve the ngtcp2_conn from the ptls_t. */
@@ -89,7 +93,9 @@ quic_server_conn_new(VALUE klass, const ngtcp2_pkt_hd *hd, const ngtcp2_path *pa
89
93
  c->tls_exts[1].type = UINT16_MAX;
90
94
  c->cptls.handshake_properties.additional_extensions = c->tls_exts;
91
95
  if (ngtcp2_crypto_picotls_configure_server_session(&c->cptls) != 0) {
92
- rb_raise(rb_eRuntimeError, "ngtcp2_crypto_picotls_configure_server_session failed");
96
+ quic_conn_close_qlog(c);
97
+ rb_raise(rb_eRuntimeError,
98
+ "ngtcp2_crypto_picotls_configure_server_session failed");
93
99
  }
94
100
 
95
101
  ngtcp2_conn_set_tls_native_handle(c->conn, &c->cptls);
@@ -105,35 +111,41 @@ quic_server_conn_new(VALUE klass, const ngtcp2_pkt_hd *hd, const ngtcp2_path *pa
105
111
  /* Build a server connection from the first datagram a client sent. Only the
106
112
  ngtcp2_conn and the TLS session are set up here; QUIC::Connection::Server
107
113
  .accept feeds that datagram to #read_pkt afterwards. */
108
- static VALUE
109
- quic_server_accept(int argc, VALUE *argv, VALUE klass)
110
- {
114
+ static VALUE quic_server_accept(int argc, VALUE *argv, VALUE klass) {
111
115
  VALUE opts = Qnil;
112
116
  rb_scan_args(argc, argv, "0:", &opts);
113
117
  if (NIL_P(opts)) {
114
- rb_raise(rb_eArgError,
115
- "missing keywords: initial_packet, local_sockaddr, remote_sockaddr, "
116
- "certificate_path, private_key_path, transport_params, settings");
118
+ rb_raise(
119
+ rb_eArgError,
120
+ "missing keywords: initial_packet, local_sockaddr, remote_sockaddr, "
121
+ "certificate_path, private_key_path, transport_params, settings");
117
122
  }
118
123
 
119
- VALUE initial_packet = rb_hash_aref(opts, ID2SYM(rb_intern("initial_packet")));
120
- VALUE local_sockaddr = rb_hash_aref(opts, ID2SYM(rb_intern("local_sockaddr")));
121
- VALUE remote_sockaddr = rb_hash_aref(opts, ID2SYM(rb_intern("remote_sockaddr")));
122
- VALUE certificate_path = rb_hash_aref(opts, ID2SYM(rb_intern("certificate_path")));
123
- VALUE private_key_path = rb_hash_aref(opts, ID2SYM(rb_intern("private_key_path")));
124
- VALUE transport_params = rb_hash_aref(opts, ID2SYM(rb_intern("transport_params")));
125
- VALUE settings_v = rb_hash_aref(opts, ID2SYM(rb_intern("settings")));
126
-
127
- if (NIL_P(initial_packet) || NIL_P(local_sockaddr) || NIL_P(remote_sockaddr) ||
128
- NIL_P(certificate_path) || NIL_P(private_key_path) ||
129
- NIL_P(transport_params) || NIL_P(settings_v)) {
124
+ VALUE initial_packet =
125
+ rb_hash_aref(opts, ID2SYM(rb_intern("initial_packet")));
126
+ VALUE local_sockaddr =
127
+ rb_hash_aref(opts, ID2SYM(rb_intern("local_sockaddr")));
128
+ VALUE remote_sockaddr =
129
+ rb_hash_aref(opts, ID2SYM(rb_intern("remote_sockaddr")));
130
+ VALUE certificate_path =
131
+ rb_hash_aref(opts, ID2SYM(rb_intern("certificate_path")));
132
+ VALUE private_key_path =
133
+ rb_hash_aref(opts, ID2SYM(rb_intern("private_key_path")));
134
+ VALUE transport_params =
135
+ rb_hash_aref(opts, ID2SYM(rb_intern("transport_params")));
136
+ VALUE settings_v = rb_hash_aref(opts, ID2SYM(rb_intern("settings")));
137
+
138
+ if (NIL_P(initial_packet) || NIL_P(local_sockaddr) ||
139
+ NIL_P(remote_sockaddr) || NIL_P(certificate_path) ||
140
+ NIL_P(private_key_path) || NIL_P(transport_params) || NIL_P(settings_v)) {
130
141
  rb_raise(rb_eArgError,
131
- "all keywords required: initial_packet, local_sockaddr, remote_sockaddr, "
142
+ "all keywords required: initial_packet, local_sockaddr, "
143
+ "remote_sockaddr, "
132
144
  "certificate_path, private_key_path, transport_params, settings");
133
145
  }
134
146
 
135
- quic_require_binary(initial_packet, "initial_packet");
136
- quic_require_sockaddr(local_sockaddr, "local_sockaddr");
147
+ quic_require_binary(initial_packet, "initial_packet");
148
+ quic_require_sockaddr(local_sockaddr, "local_sockaddr");
137
149
  quic_require_sockaddr(remote_sockaddr, "remote_sockaddr");
138
150
  certificate_path = quic_path_value(certificate_path, "certificate_path");
139
151
  private_key_path = quic_path_value(private_key_path, "private_key_path");
@@ -143,44 +155,51 @@ quic_server_accept(int argc, VALUE *argv, VALUE klass)
143
155
 
144
156
  /* ngtcp2_pkt_decode_version_cid asserts datalen > 0, and ngtcp2 is built
145
157
  with assertions enabled, so an empty datagram would abort the process. */
146
- if (datalen == 0) quic_server_raise_unacceptable();
158
+ if (datalen == 0)
159
+ quic_server_raise_unacceptable();
147
160
 
148
161
  ngtcp2_version_cid vc;
149
162
  int rv = ngtcp2_pkt_decode_version_cid(&vc, data, datalen, QUIC_SCID_LEN);
150
163
  if (rv == NGTCP2_ERR_VERSION_NEGOTIATION) {
151
164
  rb_raise(rb_eQUICErrorProto,
152
- "unsupported QUIC version 0x%08x (Version Negotiation is not implemented)",
165
+ "unsupported QUIC version 0x%08x (Version Negotiation is not "
166
+ "implemented)",
153
167
  (unsigned int)vc.version);
154
168
  }
155
- if (rv != 0) quic_server_raise_unacceptable();
169
+ if (rv != 0)
170
+ quic_server_raise_unacceptable();
156
171
 
157
172
  /* Unlike vc, hd holds the CIDs by value, so it outlives the packet buffer.
158
173
  A token (address validation) is accepted without checking it: no Retry
159
174
  is ever sent, so a well-behaved client does not send one. */
160
175
  ngtcp2_pkt_hd hd;
161
- if (ngtcp2_accept(&hd, data, datalen) != 0) quic_server_raise_unacceptable();
176
+ if (ngtcp2_accept(&hd, data, datalen) != 0)
177
+ quic_server_raise_unacceptable();
162
178
 
163
179
  /* A context of this connection's own, as one made by
164
180
  QUIC::TLSContext.server. verify_mode, ca_file and ca_path are not read,
165
181
  since no client certificate is requested. */
166
- VALUE tls_context = quic_tls_context_server_new(
167
- certificate_path, private_key_path, rb_funcall(settings_v, rb_intern("alpn"), 0));
182
+ VALUE tls_context =
183
+ quic_tls_context_server_new(certificate_path, private_key_path,
184
+ rb_funcall(settings_v, rb_intern("alpn"), 0));
168
185
 
169
186
  ngtcp2_path path = {
170
- {(struct sockaddr *)RSTRING_PTR(local_sockaddr), (ngtcp2_socklen)RSTRING_LEN(local_sockaddr)},
171
- {(struct sockaddr *)RSTRING_PTR(remote_sockaddr), (ngtcp2_socklen)RSTRING_LEN(remote_sockaddr)},
172
- NULL,
187
+ {(struct sockaddr *)RSTRING_PTR(local_sockaddr),
188
+ (ngtcp2_socklen)RSTRING_LEN(local_sockaddr)},
189
+ {(struct sockaddr *)RSTRING_PTR(remote_sockaddr),
190
+ (ngtcp2_socklen)RSTRING_LEN(remote_sockaddr)},
191
+ NULL,
173
192
  };
174
193
 
175
- return quic_server_conn_new(klass, &hd, &path, tls_context, transport_params, settings_v,
176
- NULL, Qnil);
194
+ return quic_server_conn_new(klass, &hd, &path, tls_context, transport_params,
195
+ settings_v, NULL, Qnil);
177
196
  }
178
197
 
179
- void
180
- Init_quic_connection_server(VALUE rb_mQUICConnectionArg)
181
- {
182
- rb_cQUICConnectionServer = rb_define_class_under(rb_mQUICConnectionArg, "Server", rb_cObject);
198
+ void Init_quic_connection_server(VALUE rb_mQUICConnectionArg) {
199
+ rb_cQUICConnectionServer =
200
+ rb_define_class_under(rb_mQUICConnectionArg, "Server", rb_cObject);
183
201
  rb_define_alloc_func(rb_cQUICConnectionServer, quic_conn_alloc);
184
- rb_define_singleton_method(rb_cQUICConnectionServer, "_accept", quic_server_accept, -1);
202
+ rb_define_singleton_method(rb_cQUICConnectionServer, "_accept",
203
+ quic_server_accept, -1);
185
204
  quic_conn_define_shared_methods(rb_cQUICConnectionServer);
186
205
  }