| Index: Source/modules/websockets/WebSocketFrame.cpp
|
| diff --git a/Source/modules/websockets/WebSocketFrame.cpp b/Source/modules/websockets/WebSocketFrame.cpp
|
| index 30f7acaebf309ba3bf229fb022c83f6b532866bf..6f7856630c18b7a8b6467133e5499f476f109cc2 100644
|
| --- a/Source/modules/websockets/WebSocketFrame.cpp
|
| +++ b/Source/modules/websockets/WebSocketFrame.cpp
|
| @@ -24,165 +24,8 @@
|
|
|
| #include "modules/websockets/WebSocketFrame.h"
|
|
|
| -#include "wtf/CryptographicallyRandomNumber.h"
|
| -#include "wtf/MathExtras.h"
|
| -
|
| namespace blink {
|
|
|
| -// Constants for hybi-10 frame format.
|
| -// These are bitmasks for frame composition / decomposition.
|
| -// Do not mistake these constants for the flags given to the WebSocketFrame constructor.
|
| -const unsigned char finalBit = 0x80;
|
| -const unsigned char compressBit = 0x40;
|
| -const unsigned char reserved2Bit = 0x20;
|
| -const unsigned char reserved3Bit = 0x10;
|
| -const unsigned char opCodeMask = 0xF;
|
| -const unsigned char maskBit = 0x80;
|
| -const unsigned char payloadLengthMask = 0x7F;
|
| -const size_t maxPayloadLengthWithoutExtendedLengthField = 125;
|
| -const size_t payloadLengthWithTwoByteExtendedLengthField = 126;
|
| -const size_t payloadLengthWithEightByteExtendedLengthField = 127;
|
| -const size_t maskingKeyWidthInBytes = 4;
|
| -
|
| -bool WebSocketFrame::needsExtendedLengthField(size_t payloadLength)
|
| -{
|
| - return payloadLength > maxPayloadLengthWithoutExtendedLengthField;
|
| -}
|
| -
|
| -WebSocketFrame::ParseFrameResult WebSocketFrame::parseFrame(char* data, size_t dataLength, WebSocketFrame& frame, const char*& frameEnd, String& errorString)
|
| -{
|
| - char* p = data;
|
| - const char* bufferEnd = data + dataLength;
|
| -
|
| - if (dataLength < 2)
|
| - return FrameIncomplete;
|
| -
|
| - unsigned char firstByte = *p++;
|
| - unsigned char secondByte = *p++;
|
| -
|
| - bool final = firstByte & finalBit;
|
| - bool compress = firstByte & compressBit;
|
| - bool reserved2 = firstByte & reserved2Bit;
|
| - bool reserved3 = firstByte & reserved3Bit;
|
| - unsigned char opCode = firstByte & opCodeMask;
|
| -
|
| - bool masked = secondByte & maskBit;
|
| - uint64_t payloadLength64 = secondByte & payloadLengthMask;
|
| - if (payloadLength64 > maxPayloadLengthWithoutExtendedLengthField) {
|
| - int extendedPayloadLengthSize;
|
| - if (payloadLength64 == payloadLengthWithTwoByteExtendedLengthField)
|
| - extendedPayloadLengthSize = 2;
|
| - else {
|
| - ASSERT(payloadLength64 == payloadLengthWithEightByteExtendedLengthField);
|
| - extendedPayloadLengthSize = 8;
|
| - }
|
| - if (bufferEnd - p < extendedPayloadLengthSize)
|
| - return FrameIncomplete;
|
| - payloadLength64 = 0;
|
| - for (int i = 0; i < extendedPayloadLengthSize; ++i) {
|
| - payloadLength64 <<= 8;
|
| - payloadLength64 |= static_cast<unsigned char>(*p++);
|
| - }
|
| - if (extendedPayloadLengthSize == 2 && payloadLength64 <= maxPayloadLengthWithoutExtendedLengthField) {
|
| - errorString = "The minimal number of bytes MUST be used to encode the length";
|
| - return FrameError;
|
| - }
|
| - if (extendedPayloadLengthSize == 8 && payloadLength64 <= 0xFFFF) {
|
| - errorString = "The minimal number of bytes MUST be used to encode the length";
|
| - return FrameError;
|
| - }
|
| - }
|
| -
|
| - static const uint64_t maxPayloadLength = UINT64_C(0x7FFFFFFFFFFFFFFF);
|
| - size_t maskingKeyLength = masked ? maskingKeyWidthInBytes : 0;
|
| - if (payloadLength64 > maxPayloadLength || payloadLength64 + maskingKeyLength > std::numeric_limits<size_t>::max()) {
|
| - errorString = "WebSocket frame length too large: " + String::number(payloadLength64) + " bytes";
|
| - return FrameError;
|
| - }
|
| - size_t payloadLength = static_cast<size_t>(payloadLength64);
|
| -
|
| - if (static_cast<size_t>(bufferEnd - p) < maskingKeyLength + payloadLength)
|
| - return FrameIncomplete;
|
| -
|
| - if (masked) {
|
| - const char* maskingKey = p;
|
| - char* payload = p + maskingKeyWidthInBytes;
|
| - for (size_t i = 0; i < payloadLength; ++i)
|
| - payload[i] ^= maskingKey[i % maskingKeyWidthInBytes]; // Unmask the payload.
|
| - }
|
| -
|
| - frame.opCode = static_cast<WebSocketFrame::OpCode>(opCode);
|
| - frame.final = final;
|
| - frame.compress = compress;
|
| - frame.reserved2 = reserved2;
|
| - frame.reserved3 = reserved3;
|
| - frame.masked = masked;
|
| - frame.payload = p + maskingKeyLength;
|
| - frame.payloadLength = payloadLength;
|
| - frameEnd = p + maskingKeyLength + payloadLength;
|
| - return FrameOK;
|
| -}
|
| -
|
| -static void appendFramePayload(const WebSocketFrame& frame, Vector<char>& frameData)
|
| -{
|
| - size_t maskingKeyStart = 0;
|
| - if (frame.masked) {
|
| - maskingKeyStart = frameData.size();
|
| - frameData.grow(frameData.size() + maskingKeyWidthInBytes); // Add placeholder for masking key. Will be overwritten.
|
| - }
|
| -
|
| - size_t payloadStart = frameData.size();
|
| - frameData.append(frame.payload, frame.payloadLength);
|
| -
|
| - if (frame.masked) {
|
| - cryptographicallyRandomValues(frameData.data() + maskingKeyStart, maskingKeyWidthInBytes);
|
| - for (size_t i = 0; i < frame.payloadLength; ++i)
|
| - frameData[payloadStart + i] ^= frameData[maskingKeyStart + i % maskingKeyWidthInBytes];
|
| - }
|
| -}
|
| -
|
| -void WebSocketFrame::makeFrameData(Vector<char>& frameData)
|
| -{
|
| - ASSERT(!(opCode & ~opCodeMask)); // Checks whether "opCode" fits in the range of opCodes.
|
| -
|
| - frameData.resize(2);
|
| - frameData.at(0) = (final ? finalBit : 0) | (compress ? compressBit : 0) | opCode;
|
| - frameData.at(1) = masked ? maskBit : 0;
|
| -
|
| - if (payloadLength <= maxPayloadLengthWithoutExtendedLengthField)
|
| - frameData.at(1) |= payloadLength;
|
| - else if (payloadLength <= 0xFFFF) {
|
| - frameData.at(1) |= payloadLengthWithTwoByteExtendedLengthField;
|
| - frameData.append((payloadLength & 0xFF00) >> 8);
|
| - frameData.append(payloadLength & 0xFF);
|
| - } else {
|
| - frameData.at(1) |= payloadLengthWithEightByteExtendedLengthField;
|
| - char extendedPayloadLength[8];
|
| - size_t remaining = payloadLength;
|
| - // Fill the length into extendedPayloadLength in the network byte order.
|
| - for (int i = 0; i < 8; ++i) {
|
| - extendedPayloadLength[7 - i] = remaining & 0xFF;
|
| - remaining >>= 8;
|
| - }
|
| - ASSERT(!remaining);
|
| - frameData.append(extendedPayloadLength, 8);
|
| - }
|
| -
|
| - appendFramePayload(*this, frameData);
|
| -}
|
| -
|
| -WebSocketFrame::WebSocketFrame()
|
| - : opCode(OpCodeInvalid)
|
| - , final(false)
|
| - , compress(false)
|
| - , reserved2(false)
|
| - , reserved3(false)
|
| - , masked(false)
|
| - , payload(0)
|
| - , payloadLength(0)
|
| -{
|
| -}
|
| -
|
| WebSocketFrame::WebSocketFrame(OpCode opCode, const char* payload, size_t payloadLength, Flags flags)
|
| : opCode(opCode)
|
| , final(flags & Final)
|
|
|