Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions src/core/stream_recv.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ _IRQL_requires_max_(PASSIVE_LEVEL)
void
QuicStreamProcessReliableResetFrame(
_In_ QUIC_STREAM* Stream,
_In_ uint64_t FinalSize,
_In_ QUIC_VAR_INT ErrorCode,
_In_ QUIC_VAR_INT ReliableOffset
)
Expand All @@ -206,6 +207,70 @@ QuicStreamProcessReliableResetFrame(
return;
}

if (FinalSize < ReliableOffset) {
QuicTraceLogStreamWarning(
ResetEarly,
Stream,
"Reliable reset has final size less than reliable offset!");
QuicConnTransportError(Stream->Connection, QUIC_ERROR_FINAL_SIZE_ERROR);
return;
}

BOOLEAN CloseNow = Stream->RecvBuffer.BaseOffset >= ReliableOffset;

if (!Stream->Flags.RemoteCloseResetReliable && CloseNow) {
uint64_t TotalRecvLength = QuicRecvBufferGetTotalLength(&Stream->RecvBuffer);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you looking for Stream->RecvMaxLength?

if (TotalRecvLength > FinalSize) {
//
// The peer indicated a final offset less than what they have
// already sent to us. Kill the connection.
//
QuicTraceLogStreamWarning(
ResetEarly,
Stream,
"Tried to reset at earlier final size!");
QuicConnTransportError(Stream->Connection, QUIC_ERROR_FINAL_SIZE_ERROR);
return;
}

if (TotalRecvLength < FinalSize) {
//
// The final offset is indicating that more data was sent than we
// have actually received. Make sure to update our flow control
// accounting so we stay in sync with the peer.
//
uint64_t FlowControlIncrease = FinalSize - TotalRecvLength;
Stream->Connection->Send.OrderedStreamBytesReceived += FlowControlIncrease;
if (Stream->Connection->Send.OrderedStreamBytesReceived < FlowControlIncrease ||
Stream->Connection->Send.OrderedStreamBytesReceived > Stream->Connection->Send.MaxData) {
//
// The peer indicated a final offset more than allowed. Kill the
// connection.
//
QuicTraceLogStreamWarning(
ResetTooBig,
Stream,
"Tried to reset with too big final size!");
QuicConnTransportError(Stream->Connection, QUIC_ERROR_FINAL_SIZE_ERROR);
return;
}
}

uint64_t TotalReadLength = Stream->RecvBuffer.BaseOffset;
if (TotalReadLength < FinalSize) {
//
// The final offset is indicating that more data was sent than the
// app has completely read. Make sure to give the peer more credit
// as a result.
//
uint64_t FlowControlIncrease = FinalSize - TotalReadLength;
Stream->Connection->Send.MaxData += FlowControlIncrease;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we have a reason to give flow control here. More flow control will be granted as we receive bytes.

QuicSendSetSendFlag(
&Stream->Connection->Send,
QUIC_CONN_SEND_FLAG_MAX_DATA);
}
}

if (Stream->RecvMaxLength == 0 || ReliableOffset < Stream->RecvMaxLength) {
//
// As outlined in the spec, if we receive multiple CLOSE_STREAM frames, we only accept strictly
Expand Down Expand Up @@ -735,6 +800,7 @@ QuicStreamRecv(

QuicStreamProcessReliableResetFrame(
Stream,
Frame.FinalSize,
Frame.ErrorCode,
Frame.ReliableSize);

Expand Down
3 changes: 2 additions & 1 deletion src/core/stream_send.c
Original file line number Diff line number Diff line change
Expand Up @@ -1151,7 +1151,8 @@ QuicStreamSendWrite(
}

if (Stream->SendFlags & QUIC_STREAM_SEND_FLAG_RELIABLE_ABORT) {
QUIC_RELIABLE_RESET_STREAM_EX Frame = { Stream->ID, Stream->SendShutdownErrorCode, Stream->MaxSentLength, Stream->ReliableOffsetSend };
uint64_t FinalSize = CXPLAT_MAX(Stream->MaxSentLength, Stream->ReliableOffsetSend);
QUIC_RELIABLE_RESET_STREAM_EX Frame = { Stream->ID, Stream->SendShutdownErrorCode, FinalSize, Stream->ReliableOffsetSend };

if (QuicReliableResetFrameEncode(
&Frame,
Expand Down
Loading