8#define RESIPROCATE_SUBSYSTEM Subsystem::TRANSPORT
11const int WsFrameExtractor::mMaxHeaderLen = 14;
12const size_t WsFrameExtractor::mMaxFrames = 1024;
25 : mMaxMessage(maxMessage),
32 mOpcode(OpContinuation),
37 memset(mWsMaskKey, 0,
sizeof(mWsMaskKey));
41 mWsHeader =
new uint8_t[mMaxHeaderLen];
50 delete [] (
char*)mPayload;
52 while(!mFrames.empty())
54 delete [] mFrames.front()->data();
55 delete mFrames.front();
59 while(!mMessages.empty())
61 delete [] mMessages.front()->data();
62 delete mMessages.front();
71 std::unique_ptr<Data> ret;
72 dropConnection =
false;
74 if(mClosed && input != 0 && len > 0)
77 StackLog(<<
"discarding " << len <<
" bytes received after a WebSocket Close");
80 while(input != 0 && pos < len)
84 StackLog(<<
"Need a header, parsing bytes...");
90 int needed = parseHeader();
98 if((mHeaderLen + needed) > mMaxHeaderLen)
101 dropConnection =
true;
104 for( ; needed > 0 && pos < len; needed-- )
106 mWsHeader[mHeaderLen++] = input[pos++];
110 StackLog(<<
"Not enough bytes available to form a full header");
116 StackLog(<<
"have header, parsing payload data...");
117 const bool control = isControlFrame();
121 WarningLog(<<
"WS frame with reserved opcode " << (
int)mOpcode <<
", dropping connection");
122 dropConnection =
true;
132 WarningLog(<<
"WS control frame (opcode " << (
int)mOpcode <<
") is fragmented or longer than "
134 dropConnection =
true;
144 else if(mPayloadLength > mMaxMessage ||
145 mMessageSize > mMaxMessage - mPayloadLength)
147 WarningLog(<<
"WS frame header describes a payload size bigger than messageSizeMax, max = " << mMaxMessage
148 <<
", dropping connection");
149 dropConnection =
true;
158 StackLog(<<
"starting new frame buffer");
160 mPayload = (
uint8_t*)
new char[payloadLength + 1];
165 if(takeBytes > payloadLength - mPayloadPos)
167 takeBytes = payloadLength - mPayloadPos;
173 for( ; mPayloadPos < endOffset; mPayloadPos++)
175 mPayload[mPayloadPos] = (input[pos++] ^ mWsMaskKey[(mPayloadPos & 3)]);
180 memmove(&mPayload[mPayloadPos], &input[pos], takeBytes);
182 mPayloadPos += takeBytes;
185 if(mPayloadPos == payloadLength && control)
187 StackLog(<<
"Got a whole control frame, opcode " << (
int)mOpcode);
190 frame.
payload =
Data((
const char*)mPayload, payloadLength);
191 mControlFrames.push(frame);
192 delete [] (
char*)mPayload;
201 StackLog(<<
"discarding " << (len - pos) <<
" bytes received after a WebSocket Close");
206 else if(mPayloadPos == payloadLength)
208 StackLog(<<
"Got a whole frame, queueing it");
209 mMessageSize += payloadLength;
211 mFrames.push(mFrame);
219 else if(mFrames.size() >= mMaxFrames)
224 WarningLog(<<
"WS message fragmented into more than " << mMaxFrames
225 <<
" frames, dropping connection");
226 dropConnection =
true;
232 if(mMessages.empty())
234 StackLog(<<
"no full messages available in queue");
237 ret = std::unique_ptr<Data>(mMessages.front());
239 StackLog(<<
"returning a message, size = " << ret->size());
244WsFrameExtractor::parseHeader()
248 StackLog(<<
"Too short to contain ws data [0]");
249 return (2 - mHeaderLen);
254 mFinalFrame = (mWsHeader[0] >> 7) != 0;
255 mOpcode = mWsHeader[0] & 0x0F;
256 mMasked = (mWsHeader[1] >> 7) != 0;
258 if(mWsHeader[0] & 0x40 || mWsHeader[0] & 0x20 || mWsHeader[0] & 0x10)
260 WarningLog(<<
"Unknown extension: " << ((mWsHeader[0] >> 4) & 0x07));
264 mPayloadLength = mWsHeader[1] & 0x7F;
265 if(mPayloadLength == 126)
269 StackLog(<<
"Too short to contain ws data [1]");
270 return (4 - mHeaderLen) + (mMasked ? 4 : 0);
272 mPayloadLength = (mWsHeader[hdrPos] << 8 | mWsHeader[hdrPos + 1]);
275 else if(mPayloadLength == 127)
281 StackLog(<<
"Too short to contain ws data [2]");
282 return (10 - mHeaderLen) + (mMasked ? 4 : 0);
284 mPayloadLength = (((
uint64_t)mWsHeader[hdrPos]) << 56 | ((
uint64_t)mWsHeader[hdrPos + 1]) << 48 | ((
uint64_t)mWsHeader[hdrPos + 2]) << 40 | ((
uint64_t)mWsHeader[hdrPos + 3]) << 32 | ((
uint64_t)mWsHeader[hdrPos + 4]) << 24 | ((
uint64_t)mWsHeader[hdrPos + 5]) << 16 | ((
uint64_t)mWsHeader[hdrPos + 6]) << 8 | ((
uint64_t)mWsHeader[hdrPos + 7]));
290 if((mHeaderLen - hdrPos) < 4)
292 StackLog(<<
"Too short to contain ws data [3]");
293 return (
int)((hdrPos + 4) - mHeaderLen);
295 mWsMaskKey[0] = mWsHeader[hdrPos];
296 mWsMaskKey[1] = mWsHeader[hdrPos + 1];
297 mWsMaskKey[2] = mWsHeader[hdrPos + 2];
298 mWsMaskKey[3] = mWsHeader[hdrPos + 3];
302 StackLog(<<
"successfully processed a WebSocket frame header, opcode = " << (
int)mOpcode
303 <<
", payload length = " << mPayloadLength
304 <<
", masked = "<< mMasked <<
", final frame = "<< mFinalFrame);
312WsFrameExtractor::isControlFrame()
const
315 return (mOpcode & 0x08) != 0;
321 if(mControlFrames.empty())
325 frame = mControlFrames.front();
326 mControlFrames.pop();
331WsFrameExtractor::joinFrames()
333 StackLog(<<
"trying to join frames");
336 ErrLog(<<
"No frames to join!");
340 Data *msg = mFrames.front();
347 char *_msg = (
char *)msg->
data();
351 char *newBuf =
new char [mMessageSize + 1];
352 memcpy(newBuf, _msg, frameSize);
359 while(!mFrames.empty())
361 Data *mFrame = mFrames.front();
364 delete [] mFrame->
data();
369 char *_msg = (
char *)msg->
data();
371 _msg[mMessageSize] = 0;
#define WarningLog(args_)
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
@ Borrow
The Data instance is borrowing the memory from the passed in buffer.
Data & append(const char *str, size_type len)
Appends the specified number of bytes to the end of this Data.
size_type size() const noexcept
Returns the number of bytes in this Data.
const char * data() const noexcept
Returns a pointer to the contents of this Data.
dcm! – add UnusedChecking(_enum) below;
unsigned long long uint64_t
unsigned __int64 uint64_t