Jens Geyer created THRIFT-6231:
----------------------------------

             Summary: C++ and D WebSocket servers take a frame header that 
arrives in more than one read for the end of the stream
                 Key: THRIFT-6231
                 URL: https://issues.apache.org/jira/browse/THRIFT-6231
             Project: Thrift
          Issue Type: Bug
          Components: C++ - Library, D - Library
            Reporter: Jens Geyer


{{TWebSocketServer::readFrame()}} in C++ and 
{{TServerWebSocketTransport.readFrame()}} in D read each part of a frame header 
-- the first two bytes, the 16- or 64-bit extended payload length, and the 
four-byte masking key -- with a single {{read()}} on the transport underneath, 
and take a short read for the end of the stream:

{code:cpp}
auto read = transport_->read(headerBuffer, 2);
if (read < 2) {
  return false;
}
{code}

A socket read returns whatever one {{recv()}} produced ({{TSocket::read}} in 
C++, {{TSocket.read}} in D), so a segment boundary that falls inside a frame 
header ends the connection. THRIFT-6178 made the payload read wait for the 
whole payload; the header reads were left as they were. Nothing unusual is 
needed on the client side: when frames follow one another on a connection, a 
boundary can fall anywhere in the stream, headers included.

Reproduced on master (C++) after the handshake, with a transport that serves 
one chunk per read as in {{lib/cpp/test/TWebSocketServerTest.cpp}}, and one 
well-formed, masked 11-byte frame carrying "hello":

||Frame delivered as||{{readAll(buf, 5)}} returns||
|one piece|5|
|1 byte, then the rest|0|
|2 bytes, then the rest|5|
|3 bytes, then the rest|0|
|4 bytes, then the rest|0|
|6 bytes, then the rest|5|
|8 bytes, then the rest|5|

The D transport reads its header the same way: served at most 1, 2 or 3 bytes 
per read, {{readFrame()}} returns {{false}} for the same frame; at 8 bytes per 
read it returns the payload.

Possible change: read the header fields with {{readAll()}} too, and turn 
{{END_OF_FILE}} into the {{return false}} the caller sees today -- as 
THRIFT-6178 does for the payload.

_Drafted with AI assistance (Claude Opus 5); reviewed and filed by Jens Geyer._



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to