Skip to content

Commit 3ba37a3

Browse files
authored
Resend Close Frames (#5107) (#5140)
1 parent 6e20c4a commit 3ba37a3

File tree

7 files changed

+50
-3
lines changed

7 files changed

+50
-3
lines changed

src/core/api.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,7 +1194,8 @@ MsQuicStreamSend(
11941194
Oper->Type = QUIC_OPER_TYPE_API_CALL;
11951195
Oper->API_CALL.Context = &Connection->BackupApiContext;
11961196
Oper->API_CALL.Context->Type = QUIC_API_TYPE_CONN_SHUTDOWN;
1197-
Oper->API_CALL.Context->CONN_SHUTDOWN.Flags = QUIC_CONNECTION_SHUTDOWN_FLAG_SILENT;
1197+
Oper->API_CALL.Context->CONN_SHUTDOWN.Flags =
1198+
QUIC_CONNECTION_SHUTDOWN_FLAG_SILENT | QUIC_CONNECTION_SHUTDOWN_FLAG_STATUS;
11981199
Oper->API_CALL.Context->CONN_SHUTDOWN.ErrorCode = (QUIC_VAR_INT)QUIC_STATUS_OUT_OF_MEMORY;
11991200
Oper->API_CALL.Context->CONN_SHUTDOWN.RegistrationShutdown = FALSE;
12001201
Oper->API_CALL.Context->CONN_SHUTDOWN.TransportShutdown = TRUE;
@@ -1359,7 +1360,8 @@ MsQuicStreamReceiveComplete(
13591360
Oper->Type = QUIC_OPER_TYPE_API_CALL;
13601361
Oper->API_CALL.Context = &Connection->BackupApiContext;
13611362
Oper->API_CALL.Context->Type = QUIC_API_TYPE_CONN_SHUTDOWN;
1362-
Oper->API_CALL.Context->CONN_SHUTDOWN.Flags = QUIC_CONNECTION_SHUTDOWN_FLAG_SILENT;
1363+
Oper->API_CALL.Context->CONN_SHUTDOWN.Flags =
1364+
QUIC_CONNECTION_SHUTDOWN_FLAG_SILENT | QUIC_CONNECTION_SHUTDOWN_FLAG_STATUS;
13631365
Oper->API_CALL.Context->CONN_SHUTDOWN.ErrorCode = (QUIC_VAR_INT)QUIC_STATUS_INVALID_STATE;
13641366
Oper->API_CALL.Context->CONN_SHUTDOWN.RegistrationShutdown = FALSE;
13651367
Oper->API_CALL.Context->CONN_SHUTDOWN.TransportShutdown = TRUE;

src/core/api.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@
55
66
--*/
77

8+
//
9+
// Private flag of the QUIC_CONNECTION_SHUTDOWN_FLAGS enum used for indicating
10+
// the type of error code being passed in. Not exposed to apps because they
11+
// should not be using different types of errors directly.
12+
//
13+
#define QUIC_CONNECTION_SHUTDOWN_FLAG_STATUS ((QUIC_CONNECTION_SHUTDOWN_FLAGS)0x8000)
14+
815
_IRQL_requires_max_(PASSIVE_LEVEL)
916
QUIC_STATUS
1017
QUIC_API

src/core/binding.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1342,7 +1342,8 @@ QuicBindingCreateConnection(
13421342
Oper->Type = QUIC_OPER_TYPE_API_CALL;
13431343
Oper->API_CALL.Context = &NewConnection->BackupApiContext;
13441344
Oper->API_CALL.Context->Type = QUIC_API_TYPE_CONN_SHUTDOWN;
1345-
Oper->API_CALL.Context->CONN_SHUTDOWN.Flags = QUIC_CONNECTION_SHUTDOWN_FLAG_SILENT;
1345+
Oper->API_CALL.Context->CONN_SHUTDOWN.Flags =
1346+
QUIC_CONNECTION_SHUTDOWN_FLAG_SILENT | QUIC_CONNECTION_SHUTDOWN_FLAG_STATUS;
13461347
Oper->API_CALL.Context->CONN_SHUTDOWN.ErrorCode = (QUIC_VAR_INT)QUIC_STATUS_INTERNAL_ERROR;
13471348
Oper->API_CALL.Context->CONN_SHUTDOWN.RegistrationShutdown = FALSE;
13481349
Oper->API_CALL.Context->CONN_SHUTDOWN.TransportShutdown = TRUE;

src/core/connection.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,9 @@ QuicConnShutdown(
432432
(!Connection->State.Started && QuicConnIsClient(Connection))) {
433433
CloseFlags |= QUIC_CLOSE_SILENT;
434434
}
435+
if (Flags & QUIC_CONNECTION_SHUTDOWN_FLAG_STATUS) {
436+
CloseFlags |= QUIC_CLOSE_QUIC_STATUS;
437+
}
435438

436439
QuicConnCloseLocally(Connection, CloseFlags, ErrorCode, NULL);
437440
}
@@ -703,6 +706,13 @@ QuicConnQueueOper(
703706
CXPLAT_DBG_ASSERT(QuicConnIsServer(Connection));
704707
CXPLAT_DBG_ASSERT(Connection->SourceCids.Next != NULL || CxPlatIsRandomMemoryFailureEnabled());
705708
}
709+
if (Oper->Type == QUIC_OPER_TYPE_API_CALL) {
710+
if (Oper->API_CALL.Context->Type == QUIC_API_TYPE_CONN_SHUTDOWN) {
711+
CXPLAT_DBG_ASSERT(
712+
(Oper->API_CALL.Context->CONN_SHUTDOWN.ErrorCode <= QUIC_VAR_INT_MAX) ||
713+
(Oper->API_CALL.Context->CONN_SHUTDOWN.Flags & QUIC_CONNECTION_SHUTDOWN_FLAG_STATUS));
714+
}
715+
}
706716
#endif
707717
if (QuicOperationEnqueue(&Connection->OperQ, Connection->Partition, Oper)) {
708718
//
@@ -1591,6 +1601,7 @@ QuicConnTryClose(
15911601
Connection->CloseErrorCode = QUIC_ERROR_INTERNAL_ERROR;
15921602
} else {
15931603
Connection->CloseStatus = QuicErrorCodeToStatus(ErrorCode);
1604+
CXPLAT_DBG_ASSERT(ErrorCode <= QUIC_VAR_INT_MAX);
15941605
Connection->CloseErrorCode = ErrorCode;
15951606
if (QuicErrorIsProtocolError(ErrorCode)) {
15961607
QuicPerfCounterIncrement(
@@ -4411,6 +4422,19 @@ QuicConnRecvFrames(
44114422
uint16_t PayloadLength = Packet->PayloadLength;
44124423
uint64_t RecvTime = CxPlatTimeUs64();
44134424

4425+
//
4426+
// In closing state, respond to any packet with a new close frame (rate-limited).
4427+
//
4428+
if (Closed && !Connection->State.ShutdownComplete) {
4429+
if (RecvTime - Connection->LastCloseResponseTimeUs >= QUIC_CLOSING_RESPONSE_MIN_INTERVAL) {
4430+
QuicSendSetSendFlag(
4431+
&Connection->Send,
4432+
Connection->State.AppClosed ?
4433+
QUIC_CONN_SEND_FLAG_APPLICATION_CLOSE :
4434+
QUIC_CONN_SEND_FLAG_CONNECTION_CLOSE);
4435+
}
4436+
}
4437+
44144438
if (QuicConnIsClient(Connection) &&
44154439
!Connection->State.GotFirstServerResponse) {
44164440
Connection->State.GotFirstServerResponse = TRUE;

src/core/connection.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,12 @@ typedef struct QUIC_CONNECTION {
536536
//
537537
uint64_t EarliestExpirationTime;
538538

539+
//
540+
// Timestamp (us) of when we last queued up a connection close (or
541+
// application close) response to be sent.
542+
//
543+
uint64_t LastCloseResponseTimeUs;
544+
539545
//
540546
// Receive packet queue.
541547
//

src/core/quicdef.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,12 @@ CXPLAT_STATIC_ASSERT(
318318
//
319319
#define QUIC_DEFAULT_HANDSHAKE_IDLE_TIMEOUT 10000
320320

321+
//
322+
// Minimum interval (in microseconds) between CONNECTION_CLOSE responses in
323+
// closing state.
324+
//
325+
#define QUIC_CLOSING_RESPONSE_MIN_INTERVAL 5000
326+
321327
//
322328
// The default value for keep alives being enabled or not.
323329
//

src/core/send.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ QuicSendSetSendFlag(
307307
}
308308

309309
if (IsCloseFrame) {
310+
Connection->LastCloseResponseTimeUs = CxPlatTimeUs64();
310311
QuicSendClear(Send);
311312
}
312313

0 commit comments

Comments
 (0)