Project

General

Profile

Bug #7039 » 0002-Process-last-payload-fragment-in-ws13-continuation.patch

Bruce Toll, 05/08/2019 03:39 PM

View differences:

src/http/RequestParser.C
LOG_DEBUG("ws: reading payload, remains = " << remainder_);
/*
* At this point, care must be taken that data bracketed by dataBegin and dataEnd is consumed
*/
if (remainder_ == 0) {
/*
* If this frame is marked final (the common case), then the state is set to
* Request::Complete which causes the loop to exit and the payload fragment
* will get consumed by the code which follows the loop.
*/
if (wsFrameType_ & 0x80)
state = Request::Complete;
/*
* If this frame is not final, then we expect a continuation frame.
* Since we are still in status Request::Partial, the loop will not exit UNLESS
* (begin == end), indicating that we have processed all data that was available
* at the call to parseWebSocketMessage.
*
* If more data is available, e.g. the continuation frame is already partially
* or fully available, then (begin < end). In that case, this payload fragment
* will be lost unless it is consumed here (or code is restructured...)
*
* Care must be taken to resume the loop correctly after consuming this
* payload so that any available data is processed. Thus, unlike in the similar
* code that follows the loop, it is not possible to return unless reporting an error.
* Likewise, an appendBlock is not added for this case.
*
* NOTE: We set dataBegin = dataEnd for the case when (begin == end)
* so that when we exit the loop, we do not process the same payload fragment
* a second time....
*/
else {
LOG_DEBUG("ws: (last payload, not complete): " << (dataEnd - dataBegin) << "," << state);
if (dataBegin < dataEnd) {
char* beg = &*dataBegin;
char* end = &*dataEnd;
#ifdef WTHTTP_WITH_ZLIB
if (frameCompressed_) {
Reply::ws_opcode opcode = (Reply::ws_opcode)(wsFrameType_ & 0x0F);
bool hasMore = false;
char buffer[16 * 1024];
do {
read_ = 0;
bool ret1 = inflate(reinterpret_cast<unsigned char*>(&*beg),
end - beg, reinterpret_cast<unsigned char*>(buffer), hasMore);
if(!ret1) return Request::Error;
reply->consumeWebSocketMessage(opcode, &buffer[0], &buffer[read_], Request::Partial);
} while (hasMore);
dataBegin = dataEnd;
}
#endif
wsState_ = ws13_frame_start;
}
// handle uncompressed frame
if (!frameCompressed_) {
Reply::ws_opcode opcode = (Reply::ws_opcode)(wsFrameType_ & 0x0F);
reply->consumeWebSocketMessage(opcode, beg, end, state);
dataBegin = dataEnd;
}
}
}
break;
wsState_ = ws13_frame_start;
}
break;
}
default:
assert(false);
(1-1/3)