diff --git a/src/core/crypto.c b/src/core/crypto.c index 8a51553447..dfae589aec 100644 --- a/src/core/crypto.c +++ b/src/core/crypto.c @@ -725,7 +725,7 @@ QuicCryptoWriteFrames( } _IRQL_requires_max_(PASSIVE_LEVEL) -void +BOOLEAN QuicCryptoOnLoss( _In_ QUIC_CRYPTO* Crypto, _In_ QUIC_SENT_FRAME_METADATA* FrameMetadata @@ -743,7 +743,7 @@ QuicCryptoOnLoss( // // Already completely acknowledged. // - return; + return FALSE; } else if (Start < Crypto->UnAckedOffset) { // // The 'lost' range overlaps with UNA. Move Start forward. @@ -767,7 +767,7 @@ QuicCryptoOnLoss( // // The SACK fully covers the whole 'lost' range. // - return; + return FALSE; } else { // @@ -825,12 +825,17 @@ QuicCryptoOnLoss( Crypto->InRecovery = TRUE; } - QuicSendSetSendFlag( - &Connection->Send, - QUIC_CONN_SEND_FLAG_CRYPTO); + BOOLEAN DataQueued = + QuicSendSetSendFlag( + &Connection->Send, + QUIC_CONN_SEND_FLAG_CRYPTO); QuicCryptoDumpSendState(Crypto); + + return DataQueued; } + + return FALSE; } _IRQL_requires_max_(PASSIVE_LEVEL) diff --git a/src/core/crypto.h b/src/core/crypto.h index 4a5eff16c9..73c7e675fc 100644 --- a/src/core/crypto.h +++ b/src/core/crypto.h @@ -182,10 +182,11 @@ QuicCryptoWriteFrames( ); // -// Called when a crypto frame is inferred to be lost. +// Called when a crypto frame is inferred to be lost. Returns TRUE if data is +// queued to be sent. // _IRQL_requires_max_(PASSIVE_LEVEL) -void +BOOLEAN QuicCryptoOnLoss( _In_ QUIC_CRYPTO* Crypto, _In_ QUIC_SENT_FRAME_METADATA* FrameMetadata diff --git a/src/core/loss_detection.c b/src/core/loss_detection.c index 9fd3845642..4cd2e509d4 100644 --- a/src/core/loss_detection.c +++ b/src/core/loss_detection.c @@ -46,7 +46,7 @@ #include "precomp.h" _IRQL_requires_max_(PASSIVE_LEVEL) -void +BOOLEAN QuicLossDetectionRetransmitFrames( _In_ QUIC_LOSS_DETECTION* LossDetection, _In_ QUIC_SENT_PACKET_METADATA* Packet @@ -513,45 +513,50 @@ QuicLossDetectionOnPacketAcknowledged( // // Marks all the frames in the packet that can be retransmitted as needing to be -// retransmitted. +// retransmitted. Returns TRUE if some new data was queued up to be sent. // _IRQL_requires_max_(PASSIVE_LEVEL) -void +BOOLEAN QuicLossDetectionRetransmitFrames( _In_ QUIC_LOSS_DETECTION* LossDetection, _In_ QUIC_SENT_PACKET_METADATA* Packet ) { QUIC_CONNECTION* Connection = QuicLossDetectionGetConnection(LossDetection); + BOOLEAN NewDataQueued = FALSE; for (uint8_t i = 0; i < Packet->FrameCount; i++) { switch (Packet->Frames[i].Type) { case QUIC_FRAME_PING: if (!Packet->Flags.IsPMTUD) { - QuicSendSetSendFlag( - &Connection->Send, - QUIC_CONN_SEND_FLAG_PING); + NewDataQueued |= + QuicSendSetSendFlag( + &Connection->Send, + QUIC_CONN_SEND_FLAG_PING); } break; case QUIC_FRAME_RESET_STREAM: - QuicSendSetStreamSendFlag( - &Connection->Send, - Packet->Frames[i].RESET_STREAM.Stream, - QUIC_STREAM_SEND_FLAG_SEND_ABORT); + NewDataQueued |= + QuicSendSetStreamSendFlag( + &Connection->Send, + Packet->Frames[i].RESET_STREAM.Stream, + QUIC_STREAM_SEND_FLAG_SEND_ABORT); break; case QUIC_FRAME_STOP_SENDING: - QuicSendSetStreamSendFlag( - &Connection->Send, - Packet->Frames[i].STOP_SENDING.Stream, - QUIC_STREAM_SEND_FLAG_RECV_ABORT); + NewDataQueued |= + QuicSendSetStreamSendFlag( + &Connection->Send, + Packet->Frames[i].STOP_SENDING.Stream, + QUIC_STREAM_SEND_FLAG_RECV_ABORT); break; case QUIC_FRAME_CRYPTO: - QuicCryptoOnLoss( - &Connection->Crypto, - &Packet->Frames[i]); + NewDataQueued |= + QuicCryptoOnLoss( + &Connection->Crypto, + &Packet->Frames[i]); break; case QUIC_FRAME_STREAM: @@ -562,41 +567,47 @@ QuicLossDetectionRetransmitFrames( case QUIC_FRAME_STREAM_5: case QUIC_FRAME_STREAM_6: case QUIC_FRAME_STREAM_7: - QuicStreamOnLoss( - Packet->Frames[i].STREAM.Stream, - &Packet->Frames[i]); + NewDataQueued |= + QuicStreamOnLoss( + Packet->Frames[i].STREAM.Stream, + &Packet->Frames[i]); break; case QUIC_FRAME_MAX_DATA: - QuicSendSetSendFlag( - &Connection->Send, - QUIC_CONN_SEND_FLAG_MAX_DATA); + NewDataQueued |= + QuicSendSetSendFlag( + &Connection->Send, + QUIC_CONN_SEND_FLAG_MAX_DATA); break; case QUIC_FRAME_MAX_STREAM_DATA: - QuicSendSetStreamSendFlag( - &Connection->Send, - Packet->Frames[i].MAX_STREAM_DATA.Stream, - QUIC_STREAM_SEND_FLAG_MAX_DATA); + NewDataQueued |= + QuicSendSetStreamSendFlag( + &Connection->Send, + Packet->Frames[i].MAX_STREAM_DATA.Stream, + QUIC_STREAM_SEND_FLAG_MAX_DATA); break; case QUIC_FRAME_MAX_STREAMS: - QuicSendSetSendFlag( - &Connection->Send, - QUIC_CONN_SEND_FLAG_MAX_STREAMS_BIDI); + NewDataQueued |= + QuicSendSetSendFlag( + &Connection->Send, + QUIC_CONN_SEND_FLAG_MAX_STREAMS_BIDI); break; case QUIC_FRAME_MAX_STREAMS_1: - QuicSendSetSendFlag( - &Connection->Send, - QUIC_CONN_SEND_FLAG_MAX_STREAMS_UNI); + NewDataQueued |= + QuicSendSetSendFlag( + &Connection->Send, + QUIC_CONN_SEND_FLAG_MAX_STREAMS_UNI); break; case QUIC_FRAME_STREAM_DATA_BLOCKED: - QuicSendSetStreamSendFlag( - &Connection->Send, - Packet->Frames[i].STREAM_DATA_BLOCKED.Stream, - QUIC_STREAM_SEND_FLAG_DATA_BLOCKED); + NewDataQueued |= + QuicSendSetStreamSendFlag( + &Connection->Send, + Packet->Frames[i].STREAM_DATA_BLOCKED.Stream, + QUIC_STREAM_SEND_FLAG_DATA_BLOCKED); break; case QUIC_FRAME_NEW_CONNECTION_ID: { @@ -610,9 +621,10 @@ QuicLossDetectionRetransmitFrames( if (SourceCid != NULL && !SourceCid->CID.Acknowledged) { SourceCid->CID.NeedsToSend = TRUE; - QuicSendSetSendFlag( - &Connection->Send, - QUIC_CONN_SEND_FLAG_NEW_CONNECTION_ID); + NewDataQueued |= + QuicSendSetSendFlag( + &Connection->Send, + QUIC_CONN_SEND_FLAG_NEW_CONNECTION_ID); } break; } @@ -626,9 +638,10 @@ QuicLossDetectionRetransmitFrames( if (DestCid != NULL) { QUIC_DBG_ASSERT(DestCid->CID.Retired); DestCid->CID.NeedsToSend = TRUE; - QuicSendSetSendFlag( - &Connection->Send, - QUIC_CONN_SEND_FLAG_RETIRE_CONNECTION_ID); + NewDataQueued |= + QuicSendSetSendFlag( + &Connection->Send, + QUIC_CONN_SEND_FLAG_RETIRE_CONNECTION_ID); } break; } @@ -637,20 +650,24 @@ QuicLossDetectionRetransmitFrames( QUIC_PATH* Path = QuicConnGetPathByID(Connection, Packet->PathId); if (Path != NULL && !Path->IsPeerValidated) { Path->SendChallenge = TRUE; - QuicSendSetSendFlag( - &Connection->Send, - QUIC_CONN_SEND_FLAG_PATH_CHALLENGE); + NewDataQueued |= + QuicSendSetSendFlag( + &Connection->Send, + QUIC_CONN_SEND_FLAG_PATH_CHALLENGE); } break; } case QUIC_FRAME_HANDSHAKE_DONE: - QuicSendSetSendFlag( - &Connection->Send, - QUIC_CONN_SEND_FLAG_HANDSHAKE_DONE); + NewDataQueued |= + QuicSendSetSendFlag( + &Connection->Send, + QUIC_CONN_SEND_FLAG_HANDSHAKE_DONE); break; } } + + return NewDataQueued; } // @@ -1324,8 +1341,8 @@ QuicLossDetectionScheduleProbe( Packet->PacketNumber, QuicPacketTraceType(Packet), QUIC_TRACE_PACKET_LOSS_PROBE); - QuicLossDetectionRetransmitFrames(LossDetection, Packet); - if (--NumPackets == 0) { + if (QuicLossDetectionRetransmitFrames(LossDetection, Packet) && + --NumPackets == 0) { return; } } diff --git a/src/core/send.c b/src/core/send.c index a22e8d44eb..6f85804f9d 100644 --- a/src/core/send.c +++ b/src/core/send.c @@ -185,7 +185,7 @@ QuicSendValidate( #endif _IRQL_requires_max_(DISPATCH_LEVEL) -void +BOOLEAN QuicSendSetSendFlag( _In_ QUIC_SEND* Send, _In_ uint32_t SendFlags @@ -245,6 +245,8 @@ QuicSendSetSendFlag( } QuicSendValidate(Send); + + return CanSetFlag; } _IRQL_requires_max_(DISPATCH_LEVEL) @@ -301,7 +303,7 @@ QuicSendUpdateAckState( } _IRQL_requires_max_(PASSIVE_LEVEL) -void +BOOLEAN QuicSendSetStreamSendFlag( _In_ QUIC_SEND* Send, _In_ QUIC_STREAM* Stream, @@ -313,7 +315,7 @@ QuicSendSetStreamSendFlag( // // Ignore all frames if the connection is closed. // - return; + return FALSE; } // @@ -358,6 +360,8 @@ QuicSendSetStreamSendFlag( } Stream->SendFlags |= SendFlags; } + + return SendFlags != 0; } _IRQL_requires_max_(PASSIVE_LEVEL) diff --git a/src/core/send.h b/src/core/send.h index 0570de4350..a6f2de1627 100644 --- a/src/core/send.h +++ b/src/core/send.h @@ -337,10 +337,10 @@ QuicSendProcessDelayedAckTimer( // // Indicates the connection has a given QUIC_CONN_SEND_FLAG_* that is ready -// to be sent. +// to be sent. Returns TRUE if the flag is (or already was) queued. // _IRQL_requires_max_(DISPATCH_LEVEL) -void +BOOLEAN QuicSendSetSendFlag( _In_ QUIC_SEND* Send, _In_ uint32_t SendFlag @@ -367,10 +367,10 @@ QuicSendUpdateAckState( // // Indicates the stream has a given QUIC_STREAM_SEND_FLAG_* that is ready -// to be sent. +// to be sent. Returns TRUE if the flag is (or already was) queued. // _IRQL_requires_max_(PASSIVE_LEVEL) -void +BOOLEAN QuicSendSetStreamSendFlag( _In_ QUIC_SEND* Send, _In_ QUIC_STREAM* Stream, diff --git a/src/core/stream.h b/src/core/stream.h index 1a03f49896..e25c7bd5eb 100644 --- a/src/core/stream.h +++ b/src/core/stream.h @@ -714,10 +714,11 @@ QuicStreamSendWrite( ); // -// Called when a stream frame is inferred to be lost. +// Called when a stream frame is inferred to be lost. Returns TRUE if data is +// queued to be sent. // _IRQL_requires_max_(PASSIVE_LEVEL) -void +BOOLEAN QuicStreamOnLoss( _In_ QUIC_STREAM* Stream, _In_ QUIC_SENT_FRAME_METADATA* FrameMetadata diff --git a/src/core/stream_send.c b/src/core/stream_send.c index 02cf62a318..e1f120bb99 100644 --- a/src/core/stream_send.c +++ b/src/core/stream_send.c @@ -1109,7 +1109,7 @@ QuicStreamSendWrite( } _IRQL_requires_max_(PASSIVE_LEVEL) -void +BOOLEAN QuicStreamOnLoss( _In_ QUIC_STREAM* Stream, _In_ QUIC_SENT_FRAME_METADATA* FrameMetadata @@ -1120,7 +1120,7 @@ QuicStreamOnLoss( // Ignore any STREAM frame packet loss if we have already aborted the // send path. // - return; + return FALSE; } uint32_t AddSendFlags = 0; @@ -1238,14 +1238,19 @@ QuicStreamOnLoss( Stream->Flags.InRecovery = TRUE; // TODO - Do we really need to be in recovery if no real data bytes need to be recovered? } - QuicSendSetStreamSendFlag( - &Stream->Connection->Send, - Stream, - AddSendFlags); + BOOLEAN DataQueued = + QuicSendSetStreamSendFlag( + &Stream->Connection->Send, + Stream, + AddSendFlags); QuicStreamSendDumpState(Stream); QuicStreamValidateRecoveryState(Stream); + + return DataQueued; } + + return FALSE; } _IRQL_requires_max_(PASSIVE_LEVEL)