@@ -83,10 +83,10 @@ bool IsShortHeader(
83
83
}
84
84
} // namespace
85
85
86
- QuicPacket::QuicPacket (const char * diagnostic_label, size_t len) :
87
- data_{0 },
88
- len_ (len),
89
- diagnostic_label_ (diagnostic_label) {
86
+ QuicPacket::QuicPacket (const char * diagnostic_label, size_t len)
87
+ : data_{0 },
88
+ len_ (len),
89
+ diagnostic_label_ (diagnostic_label) {
90
90
CHECK_LE (len, MAX_PKTLEN);
91
91
}
92
92
@@ -100,8 +100,6 @@ const char* QuicPacket::diagnostic_label() const {
100
100
diagnostic_label_ : " unspecified" ;
101
101
}
102
102
103
- void QuicPacket::MemoryInfo (MemoryTracker* tracker) const {}
104
-
105
103
QuicSocketListener::~QuicSocketListener () {
106
104
if (socket_)
107
105
socket_->RemoveListener (this );
@@ -174,10 +172,10 @@ QuicEndpoint::QuicEndpoint(
174
172
QuicState* quic_state,
175
173
Local<Object> wrap,
176
174
QuicSocket* listener,
177
- Local<Object> udp_wrap) :
178
- BaseObject (quic_state->env (), wrap),
179
- listener_(listener),
180
- quic_state_(quic_state) {
175
+ Local<Object> udp_wrap)
176
+ : BaseObject(quic_state->env (), wrap),
177
+ listener_(listener),
178
+ quic_state_(quic_state) {
181
179
MakeWeak ();
182
180
udp_ = static_cast <UDPWrapBase*>(
183
181
udp_wrap->GetAlignedPointerFromInternalField (
@@ -187,7 +185,9 @@ QuicEndpoint::QuicEndpoint(
187
185
strong_ptr_.reset (udp_->GetAsyncWrap ());
188
186
}
189
187
190
- void QuicEndpoint::MemoryInfo (MemoryTracker* tracker) const {}
188
+ QuicEndpoint::~QuicEndpoint () {
189
+ udp_->set_listener (nullptr );
190
+ }
191
191
192
192
uv_buf_t QuicEndpoint::OnAlloc (size_t suggested_size) {
193
193
return AllocatedBuffer::AllocateManaged (env (), suggested_size).release ();
@@ -229,6 +229,14 @@ void QuicEndpoint::OnAfterBind() {
229
229
listener_->OnBind (this );
230
230
}
231
231
232
+ template <typename Fn>
233
+ void QuicSocketStatsTraits::ToString (const QuicSocket& ptr, Fn&& add_field) {
234
+ #define V (_n, name, label ) \
235
+ add_field (label, ptr.GetStat (&QuicSocketStats::name));
236
+ SOCKET_STATS (V)
237
+ #undef V
238
+ }
239
+
232
240
QuicSocket::QuicSocket (
233
241
QuicState* quic_state,
234
242
Local<Object> wrap,
@@ -240,17 +248,17 @@ QuicSocket::QuicSocket(
240
248
QlogMode qlog,
241
249
const uint8_t * session_reset_secret,
242
250
bool disable_stateless_reset)
243
- : AsyncWrap(quic_state->env (), wrap, AsyncWrap::PROVIDER_QUICSOCKET),
244
- StatsBase(quic_state->env (), wrap),
245
- alloc_info_(MakeAllocator()),
246
- options_(options),
247
- max_connections_(max_connections),
248
- max_connections_per_host_(max_connections_per_host),
249
- max_stateless_resets_per_host_(max_stateless_resets_per_host),
250
- retry_token_expiration_(retry_token_expiration),
251
- qlog_(qlog),
252
- server_alpn_(NGHTTP3_ALPN_H3),
253
- quic_state_(quic_state) {
251
+ : AsyncWrap(quic_state->env (), wrap, AsyncWrap::PROVIDER_QUICSOCKET),
252
+ StatsBase(quic_state->env (), wrap),
253
+ alloc_info_(MakeAllocator()),
254
+ options_(options),
255
+ max_connections_(max_connections),
256
+ max_connections_per_host_(max_connections_per_host),
257
+ max_stateless_resets_per_host_(max_stateless_resets_per_host),
258
+ retry_token_expiration_(retry_token_expiration),
259
+ qlog_(qlog),
260
+ server_alpn_(NGHTTP3_ALPN_H3),
261
+ quic_state_(quic_state) {
254
262
MakeWeak ();
255
263
PushListener (&default_listener_);
256
264
@@ -279,15 +287,13 @@ QuicSocket::~QuicSocket() {
279
287
if (listener == listener_)
280
288
RemoveListener (listener_);
281
289
282
- DebugStats ();
283
- }
290
+ // In a clean shutdown, all QuicSessions associated with the QuicSocket
291
+ // would have been destroyed explicitly. However, if the QuicSocket is
292
+ // garbage collected / freed before Destroy having been called, there
293
+ // may be sessions remaining. This is not really a good thing.
294
+ Debug (this , " Destroying with %d sessions remaining" , sessions_.size ());
284
295
285
- template <typename Fn>
286
- void QuicSocketStatsTraits::ToString (const QuicSocket& ptr, Fn&& add_field) {
287
- #define V (_n, name, label ) \
288
- add_field (label, ptr.GetStat (&QuicSocketStats::name));
289
- SOCKET_STATS (V)
290
- #undef V
296
+ DebugStats ();
291
297
}
292
298
293
299
void QuicSocket::MemoryInfo (MemoryTracker* tracker) const {
@@ -310,7 +316,6 @@ void QuicSocket::Listen(
310
316
const std::string& alpn,
311
317
uint32_t options) {
312
318
CHECK (sc);
313
- CHECK (!server_secure_context_);
314
319
CHECK (!is_flag_set (QUICSOCKET_FLAGS_SERVER_LISTENING));
315
320
Debug (this , " Starting to listen" );
316
321
server_session_config_.Set (quic_state (), preferred_address);
@@ -323,6 +328,7 @@ void QuicSocket::Listen(
323
328
}
324
329
325
330
void QuicSocket::OnError (QuicEndpoint* endpoint, ssize_t error) {
331
+ // TODO(@jasnell): What should we do with the endpoint?
326
332
Debug (this , " Reading data from UDP socket failed. Error %" PRId64, error);
327
333
listener_->OnError (error);
328
334
}
@@ -341,7 +347,7 @@ void QuicSocket::OnEndpointDone(QuicEndpoint* endpoint) {
341
347
}
342
348
343
349
void QuicSocket::OnBind (QuicEndpoint* endpoint) {
344
- const SocketAddress& local_address = endpoint->local_address ();
350
+ SocketAddress local_address = endpoint->local_address ();
345
351
bound_endpoints_[local_address] =
346
352
BaseObjectWeakPtr<QuicEndpoint>(endpoint);
347
353
Debug (this , " Endpoint %s bound" , local_address);
@@ -545,6 +551,13 @@ void QuicSocket::OnReceive(
545
551
IncrementStat (&QuicSocketStats::packets_ignored);
546
552
return ;
547
553
}
554
+
555
+ // The QuicSession was destroyed while it was being set up. There's
556
+ // no further processing we can do here.
557
+ if (session->is_destroyed ()) {
558
+ IncrementStat (&QuicSocketStats::packets_ignored);
559
+ return ;
560
+ }
548
561
}
549
562
550
563
CHECK (session);
@@ -683,6 +696,8 @@ bool QuicSocket::SendRetry(
683
696
}
684
697
685
698
// Shutdown a connection prematurely, before a QuicSession is created.
699
+ // This should only be called t the start of a session before the crypto
700
+ // keys have been established.
686
701
void QuicSocket::ImmediateConnectionClose (
687
702
const QuicCID& scid,
688
703
const QuicCID& dcid,
@@ -819,16 +834,28 @@ BaseObjectPtr<QuicSession> QuicSocket::AcceptInitialPacket(
819
834
820
835
listener_->OnSessionReady (session);
821
836
837
+ // It's possible that the session was destroyed while processing
838
+ // the ready callback. If it was, then we need to send an early
839
+ // CONNECTION_CLOSE.
840
+ if (session->is_destroyed ()) {
841
+ ImmediateConnectionClose (
842
+ QuicCID (hd.scid ),
843
+ QuicCID (hd.dcid ),
844
+ local_addr,
845
+ remote_addr,
846
+ NGTCP2_CONNECTION_REFUSED);
847
+ }
848
+
822
849
return session;
823
850
}
824
851
825
852
QuicSocket::SendWrap::SendWrap (
826
853
QuicState* quic_state,
827
854
Local<Object> req_wrap_obj,
828
855
size_t total_length)
829
- : ReqWrap(quic_state->env (), req_wrap_obj, PROVIDER_QUICSOCKET),
830
- total_length_(total_length),
831
- quic_state_(quic_state) {
856
+ : ReqWrap(quic_state->env (), req_wrap_obj, PROVIDER_QUICSOCKET),
857
+ total_length_(total_length),
858
+ quic_state_(quic_state) {
832
859
}
833
860
834
861
std::string QuicSocket::SendWrap::MemoryInfoName () const {
@@ -1093,7 +1120,7 @@ void QuicSocketStopListening(const FunctionCallbackInfo<Value>& args) {
1093
1120
socket->StopListening ();
1094
1121
}
1095
1122
1096
- void QuicSocketset_server_busy (const FunctionCallbackInfo<Value>& args) {
1123
+ void QuicSocketSetServerBusy (const FunctionCallbackInfo<Value>& args) {
1097
1124
QuicSocket* socket;
1098
1125
ASSIGN_OR_RETURN_UNWRAP (&socket, args.Holder ());
1099
1126
CHECK_EQ (args.Length (), 1 );
@@ -1164,7 +1191,7 @@ void QuicSocket::Initialize(
1164
1191
QuicSocketSetDiagnosticPacketLoss);
1165
1192
env->SetProtoMethod (socket,
1166
1193
" setServerBusy" ,
1167
- QuicSocketset_server_busy );
1194
+ QuicSocketSetServerBusy );
1168
1195
env->SetProtoMethod (socket,
1169
1196
" stopListening" ,
1170
1197
QuicSocketStopListening);
0 commit comments