Diff
Modified: trunk/Source/WebCore/ChangeLog (108239 => 108240)
--- trunk/Source/WebCore/ChangeLog 2012-02-20 14:53:08 UTC (rev 108239)
+++ trunk/Source/WebCore/ChangeLog 2012-02-20 14:54:49 UTC (rev 108240)
@@ -1,3 +1,44 @@
+2012-02-20 Kenichi Ishibashi <[email protected]>
+
+ [WebSocket] Move WebSocketChannel::FrameData into a separate header file
+ https://bugs.webkit.org/show_bug.cgi?id=78682
+
+ Extract WebSocketChannel::FrameData as WebSocketFrame. This brings
+ flexibility to add classes which want to do something for
+ incoming/outgoing frames (e.g. compression/decompression).
+
+ Reviewed by Kent Tamura.
+
+ No new tests. No behavior change.
+
+ * GNUmakefile.list.am: AddedWebSocketFrame.h
+ * Target.pri: Ditto.
+ * WebCore.gypi: Ditto.
+ * WebCore.vcproj/WebCore.vcproj: Ditto.
+ * WebCore.xcodeproj/project.pbxproj: Ditto.
+ * websockets/WebSocketChannel.cpp: Modified to use WebSocketFrame instead of FrameData
+ (WebCore):
+ (WebCore::WebSocketChannel::send):
+ (WebCore::WebSocketChannel::startClosingHandshake):
+ (WebCore::WebSocketChannel::parseFrame):
+ (WebCore::WebSocketChannel::processFrame):
+ (WebCore::WebSocketChannel::enqueueTextFrame):
+ (WebCore::WebSocketChannel::enqueueRawFrame):
+ (WebCore::WebSocketChannel::enqueueBlobFrame):
+ (WebCore::appendMaskedFramePayload): Added.
+ (WebCore::makeFrameData): Added.
+ (WebCore::WebSocketChannel::sendFrame):
+ * websockets/WebSocketChannel.h: Removed FrameData.
+ (WebSocketChannel):
+ (QueuedFrame):
+ * websockets/WebSocketFrame.h: Added.
+ (WebCore):
+ (WebSocketFrame):
+ (WebCore::WebSocketFrame::isNonControlOpCode):
+ (WebCore::WebSocketFrame::isControlOpCode):
+ (WebCore::WebSocketFrame::isReservedOpCode):
+ (WebCore::WebSocketFrame::WebSocketFrame):
+
2012-02-20 Adam Roben <[email protected]>
32-bit build fix
Modified: trunk/Source/WebCore/GNUmakefile.list.am (108239 => 108240)
--- trunk/Source/WebCore/GNUmakefile.list.am 2012-02-20 14:53:08 UTC (rev 108239)
+++ trunk/Source/WebCore/GNUmakefile.list.am 2012-02-20 14:54:49 UTC (rev 108240)
@@ -4337,6 +4337,7 @@
Source/WebCore/websockets/WebSocketExtensionDispatcher.cpp \
Source/WebCore/websockets/WebSocketExtensionDispatcher.h \
Source/WebCore/websockets/WebSocketExtensionProcessor.h \
+ Source/WebCore/websockets/WebSocketFrame.h \
Source/WebCore/websockets/WebSocketHandshake.cpp \
Source/WebCore/websockets/WebSocketHandshake.h \
Source/WebCore/websockets/WebSocketHandshakeRequest.cpp \
Modified: trunk/Source/WebCore/Target.pri (108239 => 108240)
--- trunk/Source/WebCore/Target.pri 2012-02-20 14:53:08 UTC (rev 108239)
+++ trunk/Source/WebCore/Target.pri 2012-02-20 14:54:49 UTC (rev 108240)
@@ -3668,6 +3668,7 @@
websockets/WebSocketChannelClient.h \
websockets/WebSocketExtensionDispatcher.h \
websockets/WebSocketExtensionProcessor.h \
+ websockets/WebSocketFrame.h \
websockets/WebSocketHandshake.h \
websockets/WebSocketHandshakeRequest.h \
websockets/WebSocketHandshakeResponse.h \
Modified: trunk/Source/WebCore/WebCore.gypi (108239 => 108240)
--- trunk/Source/WebCore/WebCore.gypi 2012-02-20 14:53:08 UTC (rev 108239)
+++ trunk/Source/WebCore/WebCore.gypi 2012-02-20 14:54:49 UTC (rev 108240)
@@ -4816,6 +4816,7 @@
'websockets/WebSocketExtensionDispatcher.cpp',
'websockets/WebSocketExtensionDispatcher.h',
'websockets/WebSocketExtensionProcessor.h',
+ 'websockets/WebSocketFrame.h',
'websockets/WebSocketHandshake.cpp',
'websockets/WebSocketHandshake.h',
'websockets/WebSocketHandshakeRequest.cpp',
Modified: trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj (108239 => 108240)
--- trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj 2012-02-20 14:53:08 UTC (rev 108239)
+++ trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj 2012-02-20 14:54:49 UTC (rev 108240)
@@ -73458,6 +73458,10 @@
>
</File>
<File
+ RelativePath="..\websockets\WebSocketFrame.h"
+ >
+ </File>
+ <File
RelativePath="..\websockets\WebSocketHandshake.cpp"
>
</File>
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (108239 => 108240)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2012-02-20 14:53:08 UTC (rev 108239)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2012-02-20 14:54:49 UTC (rev 108240)
@@ -1365,6 +1365,7 @@
4A1E719614E101F900626F9D /* JSHTMLShadowElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A1E719414E101F900626F9D /* JSHTMLShadowElement.h */; };
4A1E71A514E106AC00626F9D /* JSShadowRoot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A1E71A314E106AC00626F9D /* JSShadowRoot.cpp */; };
4A1E71A614E106AC00626F9D /* JSShadowRoot.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A1E71A414E106AC00626F9D /* JSShadowRoot.h */; };
+ 4A4A234614F1E1440046FBF1 /* WebSocketFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A4A234514F1E1440046FBF1 /* WebSocketFrame.h */; };
4A6E9FC313C17D1D0046A7F8 /* FontFeatureValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A6E9FC113C17D1D0046A7F8 /* FontFeatureValue.cpp */; };
4A6E9FC413C17D1D0046A7F8 /* FontFeatureValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A6E9FC213C17D1D0046A7F8 /* FontFeatureValue.h */; settings = {ATTRIBUTES = (Private, ); }; };
4A6E9FC713C17D570046A7F8 /* FontFeatureSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A6E9FC513C17D570046A7F8 /* FontFeatureSettings.cpp */; };
@@ -8228,6 +8229,7 @@
4A1E719414E101F900626F9D /* JSHTMLShadowElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSHTMLShadowElement.h; sourceTree = "<group>"; };
4A1E71A314E106AC00626F9D /* JSShadowRoot.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSShadowRoot.cpp; sourceTree = "<group>"; };
4A1E71A414E106AC00626F9D /* JSShadowRoot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSShadowRoot.h; sourceTree = "<group>"; };
+ 4A4A234514F1E1440046FBF1 /* WebSocketFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSocketFrame.h; sourceTree = "<group>"; };
4A6E9FC113C17D1D0046A7F8 /* FontFeatureValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FontFeatureValue.cpp; sourceTree = "<group>"; };
4A6E9FC213C17D1D0046A7F8 /* FontFeatureValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FontFeatureValue.h; sourceTree = "<group>"; };
4A6E9FC513C17D570046A7F8 /* FontFeatureSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FontFeatureSettings.cpp; sourceTree = "<group>"; };
@@ -14847,6 +14849,7 @@
4A957F0314E241100049DBFB /* WebSocketExtensionDispatcher.cpp */,
4A957F0414E241100049DBFB /* WebSocketExtensionDispatcher.h */,
4ADE25F914E3BB4C004C2213 /* WebSocketExtensionProcessor.h */,
+ 4A4A234514F1E1440046FBF1 /* WebSocketFrame.h */,
51ABAE421043AB4A008C5260 /* WebSocketHandshake.cpp */,
51ABAE431043AB4A008C5260 /* WebSocketHandshake.h */,
7637C540112E7B74003D6CDC /* WebSocketHandshakeRequest.cpp */,
@@ -24212,6 +24215,7 @@
4AE02ABE14E8A9D200BC3BA7 /* WebSocketDeflater.h in Headers */,
4A957F0714E241300049DBFB /* WebSocketExtensionDispatcher.h in Headers */,
4ADE25FA14E3BB4C004C2213 /* WebSocketExtensionProcessor.h in Headers */,
+ 4A4A234614F1E1440046FBF1 /* WebSocketFrame.h in Headers */,
51ABAE451043AB4A008C5260 /* WebSocketHandshake.h in Headers */,
7637C543112E7B7E003D6CDC /* WebSocketHandshakeRequest.h in Headers */,
767F99C011A119560080C51D /* WebSocketHandshakeResponse.h in Headers */,
Modified: trunk/Source/WebCore/websockets/WebSocketChannel.cpp (108239 => 108240)
--- trunk/Source/WebCore/websockets/WebSocketChannel.cpp 2012-02-20 14:53:08 UTC (rev 108239)
+++ trunk/Source/WebCore/websockets/WebSocketChannel.cpp 2012-02-20 14:54:49 UTC (rev 108240)
@@ -81,13 +81,6 @@
const size_t payloadLengthWithEightByteExtendedLengthField = 127;
const size_t maskingKeyWidthInBytes = 4;
-const WebSocketChannel::OpCode WebSocketChannel::OpCodeContinuation = 0x0;
-const WebSocketChannel::OpCode WebSocketChannel::OpCodeText = 0x1;
-const WebSocketChannel::OpCode WebSocketChannel::OpCodeBinary = 0x2;
-const WebSocketChannel::OpCode WebSocketChannel::OpCodeClose = 0x8;
-const WebSocketChannel::OpCode WebSocketChannel::OpCodePing = 0x9;
-const WebSocketChannel::OpCode WebSocketChannel::OpCodePong = 0xA;
-
WebSocketChannel::WebSocketChannel(Document* document, WebSocketChannelClient* client)
: m_document(document)
, m_client(client)
@@ -183,7 +176,7 @@
{
LOG(Network, "WebSocketChannel %p send arraybuffer %p", this, &binaryData);
ASSERT(!m_useHixie76Protocol);
- enqueueRawFrame(OpCodeBinary, static_cast<const char*>(binaryData.data()), binaryData.byteLength());
+ enqueueRawFrame(WebSocketFrame::OpCodeBinary, static_cast<const char*>(binaryData.data()), binaryData.byteLength());
return true;
}
@@ -191,7 +184,7 @@
{
LOG(Network, "WebSocketChannel %p send blob %s", this, binaryData.url().string().utf8().data());
ASSERT(!m_useHixie76Protocol);
- enqueueBlobFrame(OpCodeBinary, binaryData);
+ enqueueBlobFrame(WebSocketFrame::OpCodeBinary, binaryData);
return true;
}
@@ -199,7 +192,7 @@
{
LOG(Network, "WebSocketChannel %p send binary %p (%dB)", this, data, length);
ASSERT(!m_useHixie76Protocol);
- enqueueRawFrame(OpCodeBinary, data, length);
+ enqueueRawFrame(WebSocketFrame::OpCodeBinary, data, length);
return true;
}
@@ -527,7 +520,7 @@
buf.append(static_cast<char>(lowByte));
buf.append(reason.utf8().data(), reason.utf8().length());
}
- enqueueRawFrame(OpCodeClose, buf.data(), buf.size());
+ enqueueRawFrame(WebSocketFrame::OpCodeClose, buf.data(), buf.size());
}
m_closing = true;
if (m_client)
@@ -542,7 +535,7 @@
m_handle->disconnect();
}
-WebSocketChannel::ParseFrameResult WebSocketChannel::parseFrame(FrameData& frame)
+WebSocketChannel::ParseFrameResult WebSocketChannel::parseFrame(WebSocketFrame& frame, const char*& frameEnd)
{
const char* p = m_buffer;
const char* bufferEnd = m_buffer + m_bufferSize;
@@ -557,7 +550,7 @@
bool reserved1 = firstByte & reserved1Bit;
bool reserved2 = firstByte & reserved2Bit;
bool reserved3 = firstByte & reserved3Bit;
- OpCode opCode = firstByte & opCodeMask;
+ unsigned char opCode = firstByte & opCodeMask;
bool masked = secondByte & maskBit;
uint64_t payloadLength64 = secondByte & payloadLengthMask;
@@ -601,7 +594,7 @@
payload[i] ^= maskingKey[i % maskingKeyWidthInBytes]; // Unmask the payload.
}
- frame.opCode = opCode;
+ frame.opCode = static_cast<WebSocketFrame::OpCode>(opCode);
frame.final = final;
frame.reserved1 = reserved1;
frame.reserved2 = reserved2;
@@ -609,7 +602,7 @@
frame.masked = masked;
frame.payload = p + maskingKeyLength;
frame.payloadLength = payloadLength;
- frame.frameEnd = p + maskingKeyLength + payloadLength;
+ frameEnd = p + maskingKeyLength + payloadLength;
return FrameOK;
}
@@ -617,12 +610,16 @@
{
ASSERT(m_buffer);
- FrameData frame;
- if (parseFrame(frame) != FrameOK)
+ WebSocketFrame frame;
+ const char* frameEnd;
+ if (parseFrame(frame, frameEnd) != FrameOK)
return false;
+ ASSERT(m_buffer < frameEnd);
+ ASSERT(frameEnd <= m_buffer + m_bufferSize);
+
// Validate the frame data.
- if (isReservedOpCode(frame.opCode)) {
+ if (WebSocketFrame::isReservedOpCode(frame.opCode)) {
fail("Unrecognized frame opcode: " + String::number(frame.opCode));
return false;
}
@@ -633,34 +630,34 @@
}
// All control frames must not be fragmented.
- if (isControlOpCode(frame.opCode) && !frame.final) {
+ if (WebSocketFrame::isControlOpCode(frame.opCode) && !frame.final) {
fail("Received fragmented control frame: opcode = " + String::number(frame.opCode));
return false;
}
// All control frames must have a payload of 125 bytes or less, which means the frame must not contain
// the "extended payload length" field.
- if (isControlOpCode(frame.opCode) && frame.payloadLength > maxPayloadLengthWithoutExtendedLengthField) {
+ if (WebSocketFrame::isControlOpCode(frame.opCode) && frame.payloadLength > maxPayloadLengthWithoutExtendedLengthField) {
fail("Received control frame having too long payload: " + String::number(frame.payloadLength) + " bytes");
return false;
}
// A new data frame is received before the previous continuous frame finishes.
// Note that control frames are allowed to come in the middle of continuous frames.
- if (m_hasContinuousFrame && frame.opCode != OpCodeContinuation && !isControlOpCode(frame.opCode)) {
+ if (m_hasContinuousFrame && frame.opCode != WebSocketFrame::OpCodeContinuation && !WebSocketFrame::isControlOpCode(frame.opCode)) {
fail("Received new data frame but previous continuous frame is unfinished.");
return false;
}
switch (frame.opCode) {
- case OpCodeContinuation:
+ case WebSocketFrame::OpCodeContinuation:
// An unexpected continuation frame is received without any leading frame.
if (!m_hasContinuousFrame) {
fail("Received unexpected continuation frame.");
return false;
}
m_continuousFrameData.append(frame.payload, frame.payloadLength);
- skipBuffer(frame.frameEnd - m_buffer);
+ skipBuffer(frameEnd - m_buffer);
if (frame.final) {
// onmessage handler may eventually call the other methods of this channel,
// so we should pretend that we have finished to read this frame and
@@ -670,7 +667,7 @@
OwnPtr<Vector<char> > continuousFrameData = adoptPtr(new Vector<char>);
m_continuousFrameData.swap(*continuousFrameData);
m_hasContinuousFrame = false;
- if (m_continuousFrameOpCode == OpCodeText) {
+ if (m_continuousFrameOpCode == WebSocketFrame::OpCodeText) {
String message;
if (continuousFrameData->size())
message = String::fromUTF8(continuousFrameData->data(), continuousFrameData->size());
@@ -680,48 +677,48 @@
fail("Could not decode a text frame as UTF-8.");
else
m_client->didReceiveMessage(message);
- } else if (m_continuousFrameOpCode == OpCodeBinary)
+ } else if (m_continuousFrameOpCode == WebSocketFrame::OpCodeBinary)
m_client->didReceiveBinaryData(continuousFrameData.release());
}
break;
- case OpCodeText:
+ case WebSocketFrame::OpCodeText:
if (frame.final) {
String message;
if (frame.payloadLength)
message = String::fromUTF8(frame.payload, frame.payloadLength);
else
message = "";
- skipBuffer(frame.frameEnd - m_buffer);
+ skipBuffer(frameEnd - m_buffer);
if (message.isNull())
fail("Could not decode a text frame as UTF-8.");
else
m_client->didReceiveMessage(message);
} else {
m_hasContinuousFrame = true;
- m_continuousFrameOpCode = OpCodeText;
+ m_continuousFrameOpCode = WebSocketFrame::OpCodeText;
ASSERT(m_continuousFrameData.isEmpty());
m_continuousFrameData.append(frame.payload, frame.payloadLength);
- skipBuffer(frame.frameEnd - m_buffer);
+ skipBuffer(frameEnd - m_buffer);
}
break;
- case OpCodeBinary:
+ case WebSocketFrame::OpCodeBinary:
if (frame.final) {
OwnPtr<Vector<char> > binaryData = adoptPtr(new Vector<char>(frame.payloadLength));
memcpy(binaryData->data(), frame.payload, frame.payloadLength);
- skipBuffer(frame.frameEnd - m_buffer);
+ skipBuffer(frameEnd - m_buffer);
m_client->didReceiveBinaryData(binaryData.release());
} else {
m_hasContinuousFrame = true;
- m_continuousFrameOpCode = OpCodeBinary;
+ m_continuousFrameOpCode = WebSocketFrame::OpCodeBinary;
ASSERT(m_continuousFrameData.isEmpty());
m_continuousFrameData.append(frame.payload, frame.payloadLength);
- skipBuffer(frame.frameEnd - m_buffer);
+ skipBuffer(frameEnd - m_buffer);
}
break;
- case OpCodeClose:
+ case WebSocketFrame::OpCodeClose:
if (frame.payloadLength >= 2) {
unsigned char highByte = static_cast<unsigned char>(frame.payload[0]);
unsigned char lowByte = static_cast<unsigned char>(frame.payload[1]);
@@ -732,7 +729,7 @@
m_closeEventReason = String::fromUTF8(&frame.payload[2], frame.payloadLength - 2);
else
m_closeEventReason = "";
- skipBuffer(frame.frameEnd - m_buffer);
+ skipBuffer(frameEnd - m_buffer);
m_receivedClosingHandshake = true;
startClosingHandshake(m_closeEventCode, m_closeEventReason);
if (m_closing) {
@@ -741,20 +738,20 @@
}
break;
- case OpCodePing:
- enqueueRawFrame(OpCodePong, frame.payload, frame.payloadLength);
- skipBuffer(frame.frameEnd - m_buffer);
+ case WebSocketFrame::OpCodePing:
+ enqueueRawFrame(WebSocketFrame::OpCodePong, frame.payload, frame.payloadLength);
+ skipBuffer(frameEnd - m_buffer);
break;
- case OpCodePong:
+ case WebSocketFrame::OpCodePong:
// A server may send a pong in response to our ping, or an unsolicited pong which is not associated with
// any specific ping. Either way, there's nothing to do on receipt of pong.
- skipBuffer(frame.frameEnd - m_buffer);
+ skipBuffer(frameEnd - m_buffer);
break;
default:
ASSERT_NOT_REACHED();
- skipBuffer(frame.frameEnd - m_buffer);
+ skipBuffer(frameEnd - m_buffer);
break;
}
@@ -855,14 +852,14 @@
ASSERT(!m_useHixie76Protocol);
ASSERT(m_outgoingFrameQueueStatus == OutgoingFrameQueueOpen);
OwnPtr<QueuedFrame> frame = adoptPtr(new QueuedFrame);
- frame->opCode = OpCodeText;
+ frame->opCode = WebSocketFrame::OpCodeText;
frame->frameType = QueuedFrameTypeString;
frame->stringData = string;
m_outgoingFrameQueue.append(frame.release());
processOutgoingFrameQueue();
}
-void WebSocketChannel::enqueueRawFrame(OpCode opCode, const char* data, size_t dataLength)
+void WebSocketChannel::enqueueRawFrame(WebSocketFrame::OpCode opCode, const char* data, size_t dataLength)
{
ASSERT(!m_useHixie76Protocol);
ASSERT(m_outgoingFrameQueueStatus == OutgoingFrameQueueOpen);
@@ -876,7 +873,7 @@
processOutgoingFrameQueue();
}
-void WebSocketChannel::enqueueBlobFrame(OpCode opCode, const Blob& blob)
+void WebSocketChannel::enqueueBlobFrame(WebSocketFrame::OpCode opCode, const Blob& blob)
{
ASSERT(!m_useHixie76Protocol);
ASSERT(m_outgoingFrameQueueStatus == OutgoingFrameQueueOpen);
@@ -967,44 +964,55 @@
#endif
}
-bool WebSocketChannel::sendFrame(OpCode opCode, const char* data, size_t dataLength)
+static void appendMaskedFramePayload(const WebSocketFrame& frame, Vector<char>& frameData)
{
- ASSERT(m_handle);
- ASSERT(!m_suspended);
+ size_t 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);
- Vector<char> frame;
- ASSERT(!(opCode & ~opCodeMask)); // Checks whether "opCode" fits in the range of opCodes.
- frame.append(finalBit | opCode);
- if (dataLength <= maxPayloadLengthWithoutExtendedLengthField)
- frame.append(maskBit | dataLength);
- else if (dataLength <= 0xFFFF) {
- frame.append(maskBit | payloadLengthWithTwoByteExtendedLengthField);
- frame.append((dataLength & 0xFF00) >> 8);
- frame.append(dataLength & 0xFF);
+ cryptographicallyRandomValues(frameData.data() + maskingKeyStart, maskingKeyWidthInBytes);
+ for (size_t i = 0; i < frame.payloadLength; ++i)
+ frameData[payloadStart + i] ^= frameData[maskingKeyStart + i % maskingKeyWidthInBytes];
+}
+
+static void makeFrameData(const WebSocketFrame& frame, Vector<char>& frameData)
+{
+ unsigned char firstByte = (frame.final ? finalBit : 0) | frame.opCode;
+ frameData.append(firstByte);
+ if (frame.payloadLength <= maxPayloadLengthWithoutExtendedLengthField)
+ frameData.append(maskBit | frame.payloadLength);
+ else if (frame.payloadLength <= 0xFFFF) {
+ frameData.append(maskBit | payloadLengthWithTwoByteExtendedLengthField);
+ frameData.append((frame.payloadLength & 0xFF00) >> 8);
+ frameData.append(frame.payloadLength & 0xFF);
} else {
- frame.append(maskBit | payloadLengthWithEightByteExtendedLengthField);
+ frameData.append(maskBit | payloadLengthWithEightByteExtendedLengthField);
char extendedPayloadLength[8];
- size_t remaining = dataLength;
+ size_t remaining = frame.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);
- frame.append(extendedPayloadLength, 8);
+ frameData.append(extendedPayloadLength, 8);
}
- // Mask the frame.
- size_t maskingKeyStart = frame.size();
- frame.grow(frame.size() + maskingKeyWidthInBytes); // Add placeholder for masking key. Will be overwritten.
- size_t payloadStart = frame.size();
- frame.append(data, dataLength);
+ appendMaskedFramePayload(frame, frameData);
+}
- cryptographicallyRandomValues(frame.data() + maskingKeyStart, maskingKeyWidthInBytes);
- for (size_t i = 0; i < dataLength; ++i)
- frame[payloadStart + i] ^= frame[maskingKeyStart + i % maskingKeyWidthInBytes];
+bool WebSocketChannel::sendFrame(WebSocketFrame::OpCode opCode, const char* data, size_t dataLength)
+{
+ ASSERT(m_handle);
+ ASSERT(!m_suspended);
- return m_handle->send(frame.data(), frame.size());
+ ASSERT(!(opCode & ~opCodeMask)); // Checks whether "opCode" fits in the range of opCodes.
+ WebSocketFrame frame(opCode, true, true, data, dataLength);
+ Vector<char> frameData;
+ makeFrameData(frame, frameData);
+
+ return m_handle->send(frameData.data(), frameData.size());
}
bool WebSocketChannel::sendFrameHixie76(const char* data, size_t dataLength)
Modified: trunk/Source/WebCore/websockets/WebSocketChannel.h (108239 => 108240)
--- trunk/Source/WebCore/websockets/WebSocketChannel.h 2012-02-20 14:53:08 UTC (rev 108239)
+++ trunk/Source/WebCore/websockets/WebSocketChannel.h 2012-02-20 14:54:49 UTC (rev 108240)
@@ -37,6 +37,7 @@
#include "SocketStreamHandleClient.h"
#include "ThreadableWebSocketChannel.h"
#include "Timer.h"
+#include "WebSocketFrame.h"
#include "WebSocketHandshake.h"
#include <wtf/Deque.h>
#include <wtf/Forward.h>
@@ -128,39 +129,14 @@
void startClosingHandshake(int code, const String& reason);
void closingTimerFired(Timer<WebSocketChannel>*);
- // Hybi-10 opcodes.
- typedef unsigned int OpCode;
- static const OpCode OpCodeContinuation;
- static const OpCode OpCodeText;
- static const OpCode OpCodeBinary;
- static const OpCode OpCodeClose;
- static const OpCode OpCodePing;
- static const OpCode OpCodePong;
-
- static bool isNonControlOpCode(OpCode opCode) { return opCode == OpCodeContinuation || opCode == OpCodeText || opCode == OpCodeBinary; }
- static bool isControlOpCode(OpCode opCode) { return opCode == OpCodeClose || opCode == OpCodePing || opCode == OpCodePong; }
- static bool isReservedOpCode(OpCode opCode) { return !isNonControlOpCode(opCode) && !isControlOpCode(opCode); }
-
enum ParseFrameResult {
FrameOK,
FrameIncomplete,
FrameError
};
- struct FrameData {
- OpCode opCode;
- bool final;
- bool reserved1;
- bool reserved2;
- bool reserved3;
- bool masked;
- const char* payload;
- size_t payloadLength;
- const char* frameEnd;
- };
+ ParseFrameResult parseFrame(WebSocketFrame&, const char*& frameEnd); // May modify part of m_buffer to unmask the frame.
- ParseFrameResult parseFrame(FrameData&); // May modify part of m_buffer to unmask the frame.
-
bool processFrame();
bool processFrameHixie76();
@@ -180,7 +156,7 @@
QueuedFrameTypeBlob
};
struct QueuedFrame {
- OpCode opCode;
+ WebSocketFrame::OpCode opCode;
QueuedFrameType frameType;
// Only one of the following items is used, according to the value of frameType.
String stringData;
@@ -188,8 +164,8 @@
RefPtr<Blob> blobData;
};
void enqueueTextFrame(const String&);
- void enqueueRawFrame(OpCode, const char* data, size_t dataLength);
- void enqueueBlobFrame(OpCode, const Blob&);
+ void enqueueRawFrame(WebSocketFrame::OpCode, const char* data, size_t dataLength);
+ void enqueueBlobFrame(WebSocketFrame::OpCode, const Blob&);
void processOutgoingFrameQueue();
void abortOutgoingFrameQueue();
@@ -208,7 +184,7 @@
// If you are going to send a hybi-10 frame, you need to use the outgoing frame queue
// instead of call sendFrame() directly.
- bool sendFrame(OpCode, const char* data, size_t dataLength);
+ bool sendFrame(WebSocketFrame::OpCode, const char* data, size_t dataLength);
bool sendFrameHixie76(const char* data, size_t dataLength);
#if ENABLE(BLOB)
@@ -242,7 +218,7 @@
// Private members only for hybi-10 protocol.
bool m_hasContinuousFrame;
- OpCode m_continuousFrameOpCode;
+ WebSocketFrame::OpCode m_continuousFrameOpCode;
Vector<char> m_continuousFrameData;
unsigned short m_closeEventCode;
String m_closeEventReason;
Added: trunk/Source/WebCore/websockets/WebSocketFrame.h (0 => 108240)
--- trunk/Source/WebCore/websockets/WebSocketFrame.h (rev 0)
+++ trunk/Source/WebCore/websockets/WebSocketFrame.h 2012-02-20 14:54:49 UTC (rev 108240)
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WebSocketFrame_h
+#define WebSocketFrame_h
+
+#if ENABLE(WEB_SOCKETS)
+
+namespace WebCore {
+
+struct WebSocketFrame {
+ // RFC6455 opcodes.
+ enum OpCode {
+ OpCodeContinuation = 0x0,
+ OpCodeText = 0x1,
+ OpCodeBinary = 0x2,
+ OpCodeClose = 0x8,
+ OpCodePing = 0x9,
+ OpCodePong = 0xA,
+ OpCodeInvalid = 0x10
+ };
+
+ static bool isNonControlOpCode(OpCode opCode) { return opCode == OpCodeContinuation || opCode == OpCodeText || opCode == OpCodeBinary; }
+ static bool isControlOpCode(OpCode opCode) { return opCode == OpCodeClose || opCode == OpCodePing || opCode == OpCodePong; }
+ static bool isReservedOpCode(OpCode opCode) { return !isNonControlOpCode(opCode) && !isControlOpCode(opCode); }
+
+ WebSocketFrame(OpCode opCode = OpCodeInvalid, bool final = false, bool masked = false, const char* payload = 0, size_t payloadLength = 0)
+ : opCode(opCode)
+ , final(final)
+ , reserved1(false)
+ , reserved2(false)
+ , reserved3(false)
+ , masked(masked)
+ , payload(payload)
+ , payloadLength(payloadLength)
+ {
+ }
+
+ OpCode opCode;
+ bool final;
+ bool reserved1;
+ bool reserved2;
+ bool reserved3;
+ bool masked;
+ const char* payload;
+ size_t payloadLength;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_SOCKETS)
+
+#endif // WebSocketFrame_h