@@ -38,7 +38,8 @@ DWORD CancelPendingIo(auto Handle, OVERLAPPED& Overlapped)
3838 {
3939 if constexpr (std::is_same_v<decltype (Handle), SOCKET>)
4040 {
41- if (!WSAGetOverlappedResult (Handle, &Overlapped, &bytesTransferred, true , nullptr ))
41+ DWORD flagsReturned{};
42+ if (!WSAGetOverlappedResult (Handle, &Overlapped, &bytesTransferred, true , &flagsReturned))
4243 {
4344 auto error = WSAGetLastError ();
4445 LOG_LAST_ERROR_IF (error != WSAECONNABORTED && error != WSA_OPERATION_ABORTED && error != WSAECONNRESET);
@@ -531,7 +532,7 @@ void HTTPChunkBasedReadHandle::OnRead(const gsl::span<char>& Input)
531532ReadSocketMessageHandle::ReadSocketMessageHandle (
532533 HandleWrapper&& MovedSocket,
533534 std::vector<gsl::byte>& Buffer,
534- std::optional<std:: vector<gsl::byte> >& PendingBytes,
535+ std::vector<gsl::byte>& PendingBytes,
535536 std::function<void (const gsl::span<gsl::byte>& Message)>&& OnMessage) :
536537 Socket(std::move(MovedSocket)), Buffer(Buffer), PendingBytes(PendingBytes), OnMessage(std::move(OnMessage))
537538{
@@ -542,20 +543,20 @@ ReadSocketMessageHandle::ReadSocketMessageHandle(
542543 Buffer.resize (sizeof (MESSAGE_HEADER));
543544 }
544545
545- if (! PendingBytes.has_value ())
546+ if (PendingBytes.empty ())
546547 {
547548 return ;
548549 }
549550
550551 // If bytes from a previously cancelled transaction are passed, process them now.
551- if (Buffer.size () < PendingBytes-> size ())
552+ if (Buffer.size () < PendingBytes. size ())
552553 {
553- Buffer.resize (PendingBytes-> size ());
554+ Buffer.resize (PendingBytes. size ());
554555 }
555556
556- std::copy (PendingBytes-> begin (), PendingBytes-> end (), Buffer.begin ());
557-
558- CurrentOffset = PendingBytes-> size ();
557+ std::copy (PendingBytes. begin (), PendingBytes. end (), Buffer.begin ());
558+ CurrentOffset = PendingBytes. size ();
559+ PendingBytes. clear ();
559560
560561 if (CurrentOffset < sizeof (MESSAGE_HEADER))
561562 {
@@ -569,24 +570,24 @@ ReadSocketMessageHandle::ReadSocketMessageHandle(
569570
570571ReadSocketMessageHandle::~ReadSocketMessageHandle ()
571572{
572- if (State == IOHandleStatus::Completed)
573- {
574- PendingBytes.reset ();
575- }
576- else if (State == IOHandleStatus::Pending)
573+ if (State != IOHandleStatus::Completed)
577574 {
578- // Cancel the pending receive and move any bytes already buffered for the in-flight message into PendingBytes
579- const auto socket = reinterpret_cast <SOCKET>(Socket.Get ());
580- auto receivedBytes = CancelPendingIo (socket, Overlapped);
575+ auto pendingSize = CurrentOffset;
576+
577+ if (State == IOHandleStatus::Pending)
578+ {
579+ // Cancel the pending receive and move any bytes already buffered for the in-flight message into PendingBytes
580+ const auto socket = reinterpret_cast <SOCKET>(Socket.Get ());
581+ pendingSize += CancelPendingIo (socket, Overlapped);
582+ }
581583
582- const auto totalBytes = CurrentOffset + receivedBytes;
583- if (totalBytes > 0 )
584+ if (pendingSize > 0 )
584585 {
585- WI_ASSERT (totalBytes <= Buffer.size ());
586- Buffer.resize (totalBytes);
587- PendingBytes.emplace (std::move (Buffer));
586+ WI_ASSERT (pendingSize <= Buffer.size ());
587+ PendingBytes = {Buffer.begin (), Buffer.begin () + pendingSize};
588588
589- WSL_LOG (" CanceledMessageRead" , TraceLoggingValue (totalBytes, " TotalBytes" ), TraceLoggingValue (socket, " Socket" ));
589+ WSL_LOG (
590+ " CanceledMessageRead" , TraceLoggingValue (pendingSize, " TotalBytes" ), TraceLoggingValue (Socket.Get (), " Socket" ));
590591 }
591592 }
592593}
@@ -663,7 +664,10 @@ bool ReadSocketMessageHandle::ProcessChunk()
663664 }
664665
665666 ReadingHeader = false ;
666- BytesRemaining = messageSize - CurrentOffset;
667+ if (CurrentOffset < messageSize)
668+ {
669+ BytesRemaining = messageSize - CurrentOffset;
670+ }
667671
668672 if (BytesRemaining > 0 )
669673 {
@@ -680,14 +684,10 @@ void ReadSocketMessageHandle::Schedule()
680684{
681685 WI_ASSERT (State == IOHandleStatus::Standby);
682686
683- // If a previous receive on this socket was aborted while bytes were already in our
684- // application buffer (see destructor), drain those chunks before issuing a new WSARecv.
685- while (State == IOHandleStatus::Standby && BytesRemaining == 0 )
687+ // Process previously received bytes, if any.
688+ if (BytesRemaining == 0 && !ProcessChunk ())
686689 {
687- if (!ProcessChunk ())
688- {
689- return ;
690- }
690+ return ; // Message has been fully received, not need to schedule a receive.
691691 }
692692
693693 ScheduleRecv ();
0 commit comments