Skip to content

Commit 26e7c69

Browse files
dm385an-tao
andauthored
Add support for continuation frame in WebSocketMessageParser (#2320)
Co-authored-by: antao <[email protected]>
1 parent 8d640ba commit 26e7c69

File tree

1 file changed

+36
-13
lines changed

1 file changed

+36
-13
lines changed

lib/src/WebSocketConnectionImpl.cc

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <json/value.h>
1818
#include <json/writer.h>
1919
#include <thread>
20+
#include <limits>
2021

2122
using namespace drogon;
2223

@@ -268,14 +269,14 @@ bool WebSocketMessageParser::parse(trantor::MsgBuffer *buffer)
268269
{
269270
// According to the rfc6455
270271
gotAll_ = false;
271-
if (buffer->readableBytes() >= 2)
272+
while (buffer->readableBytes() >= 2)
272273
{
273274
unsigned char opcode = (*buffer)[0] & 0x0f;
274275
bool isControlFrame = false;
275276
switch (opcode)
276277
{
277278
case 0:
278-
// continuation frame
279+
LOG_TRACE << "continuation frame";
279280
break;
280281
case 1:
281282
type_ = WebSocketMessageType::Text;
@@ -327,8 +328,13 @@ bool WebSocketMessageParser::parse(trantor::MsgBuffer *buffer)
327328
{
328329
indexFirstMask = 10;
329330
}
330-
if (indexFirstMask > 2 && buffer->readableBytes() >= indexFirstMask)
331+
if (indexFirstMask > 2)
331332
{
333+
if (buffer->readableBytes() < indexFirstMask)
334+
{
335+
// Not enough data yet, wait for more.
336+
return true;
337+
}
332338
if (isControlFrame)
333339
{
334340
// rfc6455-5.5
@@ -344,14 +350,17 @@ bool WebSocketMessageParser::parse(trantor::MsgBuffer *buffer)
344350
}
345351
else if (indexFirstMask == 10)
346352
{
347-
length = (unsigned char)(*buffer)[2];
348-
length = (length << 8) + (unsigned char)(*buffer)[3];
349-
length = (length << 8) + (unsigned char)(*buffer)[4];
350-
length = (length << 8) + (unsigned char)(*buffer)[5];
351-
length = (length << 8) + (unsigned char)(*buffer)[6];
352-
length = (length << 8) + (unsigned char)(*buffer)[7];
353-
length = (length << 8) + (unsigned char)(*buffer)[8];
354-
length = (length << 8) + (unsigned char)(*buffer)[9];
353+
length = 0;
354+
for (int i = 2; i <= 9; ++i)
355+
{
356+
if (length > ((std::numeric_limits<size_t>::max)() >> 8))
357+
{
358+
LOG_ERROR
359+
<< "Payload length too large to handle safely";
360+
return false;
361+
}
362+
length = (length << 8) + (unsigned char)(*buffer)[i];
363+
}
355364
}
356365
else
357366
{
@@ -380,9 +389,16 @@ bool WebSocketMessageParser::parse(trantor::MsgBuffer *buffer)
380389
{
381390
message_[oldLen + i] = (rawData[i] ^ masks[i % 4]);
382391
}
392+
buffer->retrieve(indexFirstMask + 4 + length);
383393
if (isFin)
394+
{
384395
gotAll_ = true;
385-
buffer->retrieve(indexFirstMask + 4 + length);
396+
return true;
397+
}
398+
}
399+
else
400+
{
401+
// Not enough data yet, wait for more.
386402
return true;
387403
}
388404
}
@@ -392,9 +408,16 @@ bool WebSocketMessageParser::parse(trantor::MsgBuffer *buffer)
392408
{
393409
auto rawData = buffer->peek() + indexFirstMask;
394410
message_.append(rawData, length);
411+
buffer->retrieve(indexFirstMask + length);
395412
if (isFin)
413+
{
396414
gotAll_ = true;
397-
buffer->retrieve(indexFirstMask + length);
415+
return true;
416+
}
417+
}
418+
else
419+
{
420+
// Not enough data yet, wait for more.
398421
return true;
399422
}
400423
}

0 commit comments

Comments
 (0)