Bug #7039 » 0002-Process-last-payload-fragment-in-ws13-continuation.patch
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);
|