summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorricea@chromium.org <ricea@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-07 14:59:21 +0000
committerricea@chromium.org <ricea@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-07 14:59:21 +0000
commit40e9c62fe01cb651eb50329b65d264a1fa7edd4e (patch)
tree98b00d9c8279a4ec38ec46a761af66cf92bf7b70
parent7a1f79852d930debcb32274adad623adb1fe1cef (diff)
downloadchromium_src-40e9c62fe01cb651eb50329b65d264a1fa7edd4e.zip
chromium_src-40e9c62fe01cb651eb50329b65d264a1fa7edd4e.tar.gz
chromium_src-40e9c62fe01cb651eb50329b65d264a1fa7edd4e.tar.bz2
Add missing status codes to WebSocketError enum.
Add the close status codes that were missing from net::WebSocketError, and also change the style of the enum from ALL_UPPER to kCamelCase. Also add a constructor to WebSocketFrameHeader to minimise boilerplate when it is used, and utility functions IsKnownDataOpCode() and IsKnownControlOpCode() which will be used by WebSocketCommon. Made WebSocketFrameHeader uncopyable and added a Clone() method for more style-guide compliance. BUG=237496 TEST=net_unittests --gtest_filter='WebSocket*' Review URL: https://chromiumcodereview.appspot.com/14850012 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@198725 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--net/websockets/websocket_errors.cc25
-rw-r--r--net/websockets/websocket_errors.h40
-rw-r--r--net/websockets/websocket_errors_unittest.cc14
-rw-r--r--net/websockets/websocket_frame.cc16
-rw-r--r--net/websockets/websocket_frame.h43
-rw-r--r--net/websockets/websocket_frame_parser.cc19
-rw-r--r--net/websockets/websocket_frame_parser.h4
-rw-r--r--net/websockets/websocket_frame_parser_unittest.cc51
-rw-r--r--net/websockets/websocket_frame_unittest.cc87
9 files changed, 225 insertions, 74 deletions
diff --git a/net/websockets/websocket_errors.cc b/net/websockets/websocket_errors.cc
index 0814dab..b7ca7bc 100644
--- a/net/websockets/websocket_errors.cc
+++ b/net/websockets/websocket_errors.cc
@@ -10,14 +10,31 @@ namespace net {
Error WebSocketErrorToNetError(WebSocketError error) {
switch (error) {
- case WEB_SOCKET_OK:
+ case kWebSocketNormalClosure:
return OK;
- case WEB_SOCKET_ERR_PROTOCOL_ERROR:
+
+ case kWebSocketErrorGoingAway: // TODO(ricea): More specific code?
+ case kWebSocketErrorProtocolError:
+ case kWebSocketErrorUnsupportedData:
+ case kWebSocketErrorInvalidFramePayloadData:
+ case kWebSocketErrorPolicyViolation:
+ case kWebSocketErrorMandatoryExtension:
+ case kWebSocketErrorInternalServerError:
return ERR_WS_PROTOCOL_ERROR;
- case WEB_SOCKET_ERR_MESSAGE_TOO_BIG:
+
+ case kWebSocketErrorNoStatusReceived:
+ case kWebSocketErrorAbnormalClosure:
+ return ERR_CONNECTION_CLOSED;
+
+ case kWebSocketErrorTlsHandshake:
+ // This error will probably be reported with more detail at a lower layer;
+ // this is the best we can do at this layer.
+ return ERR_SSL_PROTOCOL_ERROR;
+
+ case kWebSocketErrorMessageTooBig:
return ERR_MSG_TOO_BIG;
+
default:
- NOTREACHED();
return ERR_UNEXPECTED;
}
}
diff --git a/net/websockets/websocket_errors.h b/net/websockets/websocket_errors.h
index 35d2462..7d62cc0 100644
--- a/net/websockets/websocket_errors.h
+++ b/net/websockets/websocket_errors.h
@@ -9,12 +9,40 @@
namespace net {
-// Error values for WebSocket framing.
-// This values are compatible to RFC6455 defined status codes.
+// Reason codes used with close messages. NoStatusReceived,
+// AbnormalClosure and TlsHandshake are special in that they
+// should never be sent on the wire; they are only used within the
+// implementation.
enum WebSocketError {
- WEB_SOCKET_OK = 1000,
- WEB_SOCKET_ERR_PROTOCOL_ERROR = 1002,
- WEB_SOCKET_ERR_MESSAGE_TOO_BIG = 1009
+ // Status codes in the range 0 to 999 are not used.
+
+ // The following are defined by RFC6455.
+ kWebSocketNormalClosure = 1000,
+ kWebSocketErrorGoingAway = 1001,
+ kWebSocketErrorProtocolError = 1002,
+ kWebSocketErrorUnsupportedData = 1003,
+ kWebSocketErrorNoStatusReceived = 1005,
+ kWebSocketErrorAbnormalClosure = 1006,
+ kWebSocketErrorInvalidFramePayloadData = 1007,
+ kWebSocketErrorPolicyViolation = 1008,
+ kWebSocketErrorMessageTooBig = 1009,
+ kWebSocketErrorMandatoryExtension = 1010,
+ kWebSocketErrorInternalServerError = 1011,
+ kWebSocketErrorTlsHandshake = 1015,
+
+ // The range 1000-2999 is reserved by RFC6455 for use by the WebSocket
+ // protocol and public extensions.
+ kWebSocketErrorProtocolReservedMax = 2999,
+
+ // The range 3000-3999 is reserved by RFC6455 for registered use by libraries,
+ // frameworks and applications.
+ kWebSocketErrorRegisteredReservedMin = 3000,
+ kWebSocketErrorRegisteredReservedMax = 3999,
+
+ // The range 4000-4999 is reserved by RFC6455 for private use by prior
+ // agreement of the endpoints.
+ kWebSocketErrorPrivateReservedMin = 4000,
+ kWebSocketErrorPrivateReservedMax = 4999,
};
// Convert WebSocketError to net::Error defined in net/base/net_errors.h.
@@ -22,4 +50,4 @@ NET_EXPORT_PRIVATE Error WebSocketErrorToNetError(WebSocketError error);
} // namespace net
-#endif // NET_WEBSOCKETS_WEBSOCKET_FRAME_H_
+#endif // NET_WEBSOCKETS_WEBSOCKET_ERRORS_H_
diff --git a/net/websockets/websocket_errors_unittest.cc b/net/websockets/websocket_errors_unittest.cc
index f0e719d..1a4fca6 100644
--- a/net/websockets/websocket_errors_unittest.cc
+++ b/net/websockets/websocket_errors_unittest.cc
@@ -4,17 +4,25 @@
#include "net/websockets/websocket_errors.h"
+#include "net/base/net_errors.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
namespace {
+// Confirm that the principle classes of errors are converted correctly. We
+// don't exhaustively test every error code, as it would be long, repetitive,
+// and add little value.
TEST(WebSocketErrorToNetErrorTest, ResultsAreCorrect) {
- EXPECT_EQ(OK, WebSocketErrorToNetError(WEB_SOCKET_OK));
+ EXPECT_EQ(OK, WebSocketErrorToNetError(kWebSocketNormalClosure));
EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
- WebSocketErrorToNetError(WEB_SOCKET_ERR_PROTOCOL_ERROR));
+ WebSocketErrorToNetError(kWebSocketErrorProtocolError));
EXPECT_EQ(ERR_MSG_TOO_BIG,
- WebSocketErrorToNetError(WEB_SOCKET_ERR_MESSAGE_TOO_BIG));
+ WebSocketErrorToNetError(kWebSocketErrorMessageTooBig));
+ EXPECT_EQ(ERR_CONNECTION_CLOSED,
+ WebSocketErrorToNetError(kWebSocketErrorNoStatusReceived));
+ EXPECT_EQ(ERR_SSL_PROTOCOL_ERROR,
+ WebSocketErrorToNetError(kWebSocketErrorTlsHandshake));
}
} // namespace
diff --git a/net/websockets/websocket_frame.cc b/net/websockets/websocket_frame.cc
index 0824063f..7a8e22c 100644
--- a/net/websockets/websocket_frame.cc
+++ b/net/websockets/websocket_frame.cc
@@ -44,9 +44,25 @@ const WebSocketFrameHeader::OpCode WebSocketFrameHeader::kOpCodeContinuation =
0x0;
const WebSocketFrameHeader::OpCode WebSocketFrameHeader::kOpCodeText = 0x1;
const WebSocketFrameHeader::OpCode WebSocketFrameHeader::kOpCodeBinary = 0x2;
+const WebSocketFrameHeader::OpCode WebSocketFrameHeader::kOpCodeDataUnused =
+ 0x3;
const WebSocketFrameHeader::OpCode WebSocketFrameHeader::kOpCodeClose = 0x8;
const WebSocketFrameHeader::OpCode WebSocketFrameHeader::kOpCodePing = 0x9;
const WebSocketFrameHeader::OpCode WebSocketFrameHeader::kOpCodePong = 0xA;
+const WebSocketFrameHeader::OpCode WebSocketFrameHeader::kOpCodeControlUnused =
+ 0xB;
+
+scoped_ptr<WebSocketFrameHeader> WebSocketFrameHeader::Clone() {
+ scoped_ptr<WebSocketFrameHeader> ret(new WebSocketFrameHeader(opcode));
+ ret->final = final;
+ ret->reserved1 = reserved1;
+ ret->reserved2 = reserved2;
+ ret->reserved3 = reserved3;
+ ret->opcode = opcode;
+ ret->masked = masked;
+ ret->payload_length = payload_length;
+ return ret.Pass();
+}
WebSocketFrameChunk::WebSocketFrameChunk() : final_chunk(false) {
}
diff --git a/net/websockets/websocket_frame.h b/net/websockets/websocket_frame.h
index 46b011f..0f456a5 100644
--- a/net/websockets/websocket_frame.h
+++ b/net/websockets/websocket_frame.h
@@ -25,9 +25,23 @@ struct NET_EXPORT WebSocketFrameHeader {
static const OpCode kOpCodeContinuation;
static const OpCode kOpCodeText;
static const OpCode kOpCodeBinary;
+ static const OpCode kOpCodeDataUnused;
static const OpCode kOpCodeClose;
static const OpCode kOpCodePing;
static const OpCode kOpCodePong;
+ static const OpCode kOpCodeControlUnused;
+
+ // Efficiently determine whether a given opcode is one of the data opcodes
+ // known to this implementation.
+ static bool IsKnownDataOpCode(OpCode opCode) {
+ return (opCode & ~3) == 0 && opCode != 3;
+ }
+
+ // Efficiently determine whether a given opcode is one of the control opcodes
+ // known to this implementation.
+ static bool IsKnownControlOpCode(OpCode opCode) {
+ return (opCode & ~3) == 8 && opCode != 0x0B;
+ }
// These values must be a compile-time constant. "enum hack" is used here
// to make MSVC happy.
@@ -37,6 +51,32 @@ struct NET_EXPORT WebSocketFrameHeader {
kMaskingKeyLength = 4
};
+ // Constructor to avoid a lot of repetitive initialisation.
+ explicit WebSocketFrameHeader(OpCode opCode)
+ : final(false),
+ reserved1(false),
+ reserved2(false),
+ reserved3(false),
+ opcode(opCode),
+ masked(false),
+ payload_length(0) {}
+
+ // Backwards-compatible constructor to avoid breaking Chromedriver.
+ // The above constructor should be used in preference, as there is no good
+ // default value for "opcode".
+ // TODO(ricea): Remove this once Chromedriver have stopped using it.
+ WebSocketFrameHeader()
+ : final(false),
+ reserved1(false),
+ reserved2(false),
+ reserved3(false),
+ opcode(kOpCodeDataUnused),
+ masked(false),
+ payload_length(0) {}
+
+ // Create a clone of this object on the heap.
+ scoped_ptr<WebSocketFrameHeader> Clone();
+
// Members below correspond to each item in WebSocket frame header.
// See <http://tools.ietf.org/html/rfc6455#section-5.2> for details.
bool final;
@@ -46,6 +86,9 @@ struct NET_EXPORT WebSocketFrameHeader {
OpCode opcode;
bool masked;
uint64 payload_length;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WebSocketFrameHeader);
};
// Contains payload data of part of a WebSocket frame.
diff --git a/net/websockets/websocket_frame_parser.cc b/net/websockets/websocket_frame_parser.cc
index b16996d..37e50f0 100644
--- a/net/websockets/websocket_frame_parser.cc
+++ b/net/websockets/websocket_frame_parser.cc
@@ -36,7 +36,7 @@ namespace net {
WebSocketFrameParser::WebSocketFrameParser()
: current_read_pos_(0),
frame_offset_(0),
- websocket_error_(WEB_SOCKET_OK) {
+ websocket_error_(kWebSocketNormalClosure) {
std::fill(masking_key_.key,
masking_key_.key + WebSocketFrameHeader::kMaskingKeyLength,
'\0');
@@ -49,7 +49,7 @@ bool WebSocketFrameParser::Decode(
const char* data,
size_t length,
ScopedVector<WebSocketFrameChunk>* frame_chunks) {
- if (websocket_error_ != WEB_SOCKET_OK)
+ if (websocket_error_ != kWebSocketNormalClosure)
return false;
if (!length)
return true;
@@ -61,7 +61,7 @@ bool WebSocketFrameParser::Decode(
bool first_chunk = false;
if (!current_frame_header_.get()) {
DecodeFrameHeader();
- if (websocket_error_ != WEB_SOCKET_OK)
+ if (websocket_error_ != kWebSocketNormalClosure)
return false;
// If frame header is incomplete, then carry over the remaining
// data to the next round of Decode().
@@ -129,7 +129,7 @@ void WebSocketFrameParser::DecodeFrameHeader() {
current += 2;
payload_length = payload_length_16;
if (payload_length <= kMaxPayloadLengthWithoutExtendedLengthField)
- websocket_error_ = WEB_SOCKET_ERR_PROTOCOL_ERROR;
+ websocket_error_ = kWebSocketErrorProtocolError;
} else if (payload_length == kPayloadLengthWithEightByteExtendedLengthField) {
if (end - current < 8)
return;
@@ -137,12 +137,12 @@ void WebSocketFrameParser::DecodeFrameHeader() {
current += 8;
if (payload_length <= kuint16max ||
payload_length > static_cast<uint64>(kint64max)) {
- websocket_error_ = WEB_SOCKET_ERR_PROTOCOL_ERROR;
+ websocket_error_ = kWebSocketErrorProtocolError;
} else if (payload_length > static_cast<uint64>(kint32max)) {
- websocket_error_ = WEB_SOCKET_ERR_MESSAGE_TOO_BIG;
+ websocket_error_ = kWebSocketErrorMessageTooBig;
}
}
- if (websocket_error_ != WEB_SOCKET_OK) {
+ if (websocket_error_ != kWebSocketNormalClosure) {
buffer_.clear();
current_read_pos_ = 0;
current_frame_header_.reset();
@@ -159,12 +159,11 @@ void WebSocketFrameParser::DecodeFrameHeader() {
std::fill(masking_key_.key, masking_key_.key + kMaskingKeyLength, '\0');
}
- current_frame_header_.reset(new WebSocketFrameHeader);
+ current_frame_header_.reset(new WebSocketFrameHeader(opcode));
current_frame_header_->final = final;
current_frame_header_->reserved1 = reserved1;
current_frame_header_->reserved2 = reserved2;
current_frame_header_->reserved3 = reserved3;
- current_frame_header_->opcode = opcode;
current_frame_header_->masked = masked;
current_frame_header_->payload_length = payload_length;
current_read_pos_ += current - start;
@@ -184,7 +183,7 @@ scoped_ptr<WebSocketFrameChunk> WebSocketFrameParser::DecodeFramePayload(
scoped_ptr<WebSocketFrameChunk> frame_chunk(new WebSocketFrameChunk);
if (first_chunk) {
- frame_chunk->header.reset(new WebSocketFrameHeader(*current_frame_header_));
+ frame_chunk->header = current_frame_header_->Clone();
}
frame_chunk->final_chunk = false;
if (next_size) {
diff --git a/net/websockets/websocket_frame_parser.h b/net/websockets/websocket_frame_parser.h
index 0a4d2ae..52e6f85 100644
--- a/net/websockets/websocket_frame_parser.h
+++ b/net/websockets/websocket_frame_parser.h
@@ -40,8 +40,8 @@ class NET_EXPORT WebSocketFrameParser {
size_t length,
ScopedVector<WebSocketFrameChunk>* frame_chunks);
- // Returns WEB_SOCKET_OK if the parser has not failed to decode WebSocket
- // frames. Otherwise returns WebSocketError which is defined in
+ // Returns kWebSocketNormalClosure if the parser has not failed to decode
+ // WebSocket frames. Otherwise returns WebSocketError which is defined in
// websocket_errors.h. We can convert net::WebSocketError to net::Error by
// using WebSocketErrorToNetError().
WebSocketError websocket_error() const { return websocket_error_; }
diff --git a/net/websockets/websocket_frame_parser_unittest.cc b/net/websockets/websocket_frame_parser_unittest.cc
index 653f66984..d59f9fa 100644
--- a/net/websockets/websocket_frame_parser_unittest.cc
+++ b/net/websockets/websocket_frame_parser_unittest.cc
@@ -35,18 +35,18 @@ struct FrameHeaderTestCase {
};
const FrameHeaderTestCase kFrameHeaderTests[] = {
- { "\x81\x00", 2, GG_UINT64_C(0), WEB_SOCKET_OK },
- { "\x81\x7D", 2, GG_UINT64_C(125), WEB_SOCKET_OK },
- { "\x81\x7E\x00\x7E", 4, GG_UINT64_C(126), WEB_SOCKET_OK },
- { "\x81\x7E\xFF\xFF", 4, GG_UINT64_C(0xFFFF), WEB_SOCKET_OK },
+ { "\x81\x00", 2, GG_UINT64_C(0), kWebSocketNormalClosure },
+ { "\x81\x7D", 2, GG_UINT64_C(125), kWebSocketNormalClosure },
+ { "\x81\x7E\x00\x7E", 4, GG_UINT64_C(126), kWebSocketNormalClosure },
+ { "\x81\x7E\xFF\xFF", 4, GG_UINT64_C(0xFFFF), kWebSocketNormalClosure },
{ "\x81\x7F\x00\x00\x00\x00\x00\x01\x00\x00", 10, GG_UINT64_C(0x10000),
- WEB_SOCKET_OK },
+ kWebSocketNormalClosure },
{ "\x81\x7F\x00\x00\x00\x00\x7F\xFF\xFF\xFF", 10, GG_UINT64_C(0x7FFFFFFF),
- WEB_SOCKET_OK },
+ kWebSocketNormalClosure },
{ "\x81\x7F\x00\x00\x00\x00\x80\x00\x00\x00", 10, GG_UINT64_C(0x80000000),
- WEB_SOCKET_ERR_MESSAGE_TOO_BIG },
+ kWebSocketErrorMessageTooBig },
{ "\x81\x7F\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 10,
- GG_UINT64_C(0x7FFFFFFFFFFFFFFF), WEB_SOCKET_ERR_MESSAGE_TOO_BIG }
+ GG_UINT64_C(0x7FFFFFFFFFFFFFFF), kWebSocketErrorMessageTooBig }
};
const int kNumFrameHeaderTests = arraysize(kFrameHeaderTests);
@@ -55,7 +55,7 @@ TEST(WebSocketFrameParserTest, DecodeNormalFrame) {
ScopedVector<WebSocketFrameChunk> frames;
EXPECT_TRUE(parser.Decode(kHelloFrame, kHelloFrameLength, &frames));
- EXPECT_EQ(WEB_SOCKET_OK, parser.websocket_error());
+ EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
ASSERT_EQ(1u, frames.size());
WebSocketFrameChunk* frame = frames[0];
ASSERT_TRUE(frame != NULL);
@@ -82,7 +82,7 @@ TEST(WebSocketFrameParserTest, DecodeMaskedFrame) {
ScopedVector<WebSocketFrameChunk> frames;
EXPECT_TRUE(parser.Decode(kMaskedHelloFrame, kMaskedHelloFrameLength,
&frames));
- EXPECT_EQ(WEB_SOCKET_OK, parser.websocket_error());
+ EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
ASSERT_EQ(1u, frames.size());
WebSocketFrameChunk* frame = frames[0];
ASSERT_TRUE(frame != NULL);
@@ -140,7 +140,7 @@ TEST(WebSocketFrameParserTest, DecodeManyFrames) {
ScopedVector<WebSocketFrameChunk> frames;
EXPECT_TRUE(parser.Decode(&input.front(), input.size(), &frames));
- EXPECT_EQ(WEB_SOCKET_OK, parser.websocket_error());
+ EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
ASSERT_EQ(static_cast<size_t>(kNumInputs), frames.size());
for (int i = 0; i < kNumInputs; ++i) {
@@ -186,7 +186,7 @@ TEST(WebSocketFrameParserTest, DecodePartialFrame) {
ScopedVector<WebSocketFrameChunk> frames1;
EXPECT_TRUE(parser.Decode(&input1.front(), input1.size(), &frames1));
- EXPECT_EQ(WEB_SOCKET_OK, parser.websocket_error());
+ EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
EXPECT_EQ(1u, frames1.size());
if (frames1.size() != 1u)
continue;
@@ -217,7 +217,7 @@ TEST(WebSocketFrameParserTest, DecodePartialFrame) {
ScopedVector<WebSocketFrameChunk> frames2;
EXPECT_TRUE(parser.Decode(&input2.front(), input2.size(), &frames2));
- EXPECT_EQ(WEB_SOCKET_OK, parser.websocket_error());
+ EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
EXPECT_EQ(1u, frames2.size());
if (frames2.size() != 1u)
continue;
@@ -256,7 +256,7 @@ TEST(WebSocketFrameParserTest, DecodePartialMaskedFrame) {
ScopedVector<WebSocketFrameChunk> frames1;
EXPECT_TRUE(parser.Decode(&input1.front(), input1.size(), &frames1));
- EXPECT_EQ(WEB_SOCKET_OK, parser.websocket_error());
+ EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
EXPECT_EQ(1u, frames1.size());
if (frames1.size() != 1u)
continue;
@@ -287,7 +287,7 @@ TEST(WebSocketFrameParserTest, DecodePartialMaskedFrame) {
ScopedVector<WebSocketFrameChunk> frames2;
EXPECT_TRUE(parser.Decode(&input2.front(), input2.size(), &frames2));
- EXPECT_EQ(WEB_SOCKET_OK, parser.websocket_error());
+ EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
EXPECT_EQ(1u, frames2.size());
if (frames2.size() != 1u)
continue;
@@ -324,10 +324,10 @@ TEST(WebSocketFrameParserTest, DecodeFramesOfVariousLengths) {
WebSocketFrameParser parser;
ScopedVector<WebSocketFrameChunk> frames;
- EXPECT_EQ(kFrameHeaderTests[i].error_code == WEB_SOCKET_OK,
+ EXPECT_EQ(kFrameHeaderTests[i].error_code == kWebSocketNormalClosure,
parser.Decode(&input.front(), input.size(), &frames));
EXPECT_EQ(kFrameHeaderTests[i].error_code, parser.websocket_error());
- if (kFrameHeaderTests[i].error_code != WEB_SOCKET_OK) {
+ if (kFrameHeaderTests[i].error_code != kWebSocketNormalClosure) {
EXPECT_EQ(0u, frames.size());
} else {
EXPECT_EQ(1u, frames.size());
@@ -381,15 +381,16 @@ TEST(WebSocketFrameParserTest, DecodePartialHeader) {
// when it receives partial frame header.
size_t last_byte_offset = frame_header_length - 1;
for (size_t j = 0; j < frame_header_length; ++j) {
- bool failed = kFrameHeaderTests[i].error_code != WEB_SOCKET_OK &&
+ bool failed =
+ kFrameHeaderTests[i].error_code != kWebSocketNormalClosure &&
j == last_byte_offset;
EXPECT_EQ(!failed, parser.Decode(frame_header + j, 1, &frames));
if (failed) {
EXPECT_EQ(kFrameHeaderTests[i].error_code, parser.websocket_error());
} else {
- EXPECT_EQ(WEB_SOCKET_OK, parser.websocket_error());
+ EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
}
- if (kFrameHeaderTests[i].error_code == WEB_SOCKET_OK &&
+ if (kFrameHeaderTests[i].error_code == kWebSocketNormalClosure &&
j == last_byte_offset) {
EXPECT_EQ(1u, frames.size());
} else {
@@ -446,15 +447,15 @@ TEST(WebSocketFrameParserTest, InvalidLengthEncoding) {
WebSocketFrameParser parser;
ScopedVector<WebSocketFrameChunk> frames;
- EXPECT_EQ(WEB_SOCKET_OK, parser.websocket_error());
+ EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
EXPECT_FALSE(parser.Decode(frame_header, frame_header_length, &frames));
- EXPECT_EQ(WEB_SOCKET_ERR_PROTOCOL_ERROR, parser.websocket_error());
+ EXPECT_EQ(kWebSocketErrorProtocolError, parser.websocket_error());
EXPECT_EQ(0u, frames.size());
// Once the parser has failed, it no longer accepts any input (even if
// the input is empty).
EXPECT_FALSE(parser.Decode("", 0, &frames));
- EXPECT_EQ(WEB_SOCKET_ERR_PROTOCOL_ERROR, parser.websocket_error());
+ EXPECT_EQ(kWebSocketErrorProtocolError, parser.websocket_error());
EXPECT_EQ(0u, frames.size());
}
}
@@ -496,7 +497,7 @@ TEST(WebSocketFrameParserTest, FrameTypes) {
ScopedVector<WebSocketFrameChunk> frames;
EXPECT_TRUE(parser.Decode(frame_header, frame_header_length, &frames));
- EXPECT_EQ(WEB_SOCKET_OK, parser.websocket_error());
+ EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
EXPECT_EQ(1u, frames.size());
if (frames.size() != 1u)
continue;
@@ -552,7 +553,7 @@ TEST(WebSocketFrameParserTest, FinalBitAndReservedBits) {
ScopedVector<WebSocketFrameChunk> frames;
EXPECT_TRUE(parser.Decode(frame_header, frame_header_length, &frames));
- EXPECT_EQ(WEB_SOCKET_OK, parser.websocket_error());
+ EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error());
EXPECT_EQ(1u, frames.size());
if (frames.size() != 1u)
continue;
diff --git a/net/websockets/websocket_frame_unittest.cc b/net/websockets/websocket_frame_unittest.cc
index 59f4719..a790af8 100644
--- a/net/websockets/websocket_frame_unittest.cc
+++ b/net/websockets/websocket_frame_unittest.cc
@@ -45,13 +45,8 @@ TEST(WebSocketFrameHeaderTest, FrameLengths) {
static const int kNumTests = ARRAYSIZE_UNSAFE(kTests);
for (int i = 0; i < kNumTests; ++i) {
- WebSocketFrameHeader header;
+ WebSocketFrameHeader header(WebSocketFrameHeader::kOpCodeText);
header.final = true;
- header.reserved1 = false;
- header.reserved2 = false;
- header.reserved3 = false;
- header.opcode = WebSocketFrameHeader::kOpCodeText;
- header.masked = false;
header.payload_length = kTests[i].frame_length;
std::vector<char> expected_output(
@@ -93,12 +88,8 @@ TEST(WebSocketFrameHeaderTest, FrameLengthsWithMasking) {
masking_key.key);
for (int i = 0; i < kNumTests; ++i) {
- WebSocketFrameHeader header;
+ WebSocketFrameHeader header(WebSocketFrameHeader::kOpCodeText);
header.final = true;
- header.reserved1 = false;
- header.reserved2 = false;
- header.reserved3 = false;
- header.opcode = WebSocketFrameHeader::kOpCodeText;
header.masked = true;
header.payload_length = kTests[i].frame_length;
@@ -141,13 +132,8 @@ TEST(WebSocketFrameHeaderTest, FrameOpCodes) {
static const int kNumTests = ARRAYSIZE_UNSAFE(kTests);
for (int i = 0; i < kNumTests; ++i) {
- WebSocketFrameHeader header;
+ WebSocketFrameHeader header(kTests[i].opcode);
header.final = true;
- header.reserved1 = false;
- header.reserved2 = false;
- header.reserved3 = false;
- header.opcode = kTests[i].opcode;
- header.masked = false;
header.payload_length = 0;
std::vector<char> expected_output(
@@ -182,13 +168,11 @@ TEST(WebSocketFrameHeaderTest, FinalBitAndReservedBits) {
static const int kNumTests = ARRAYSIZE_UNSAFE(kTests);
for (int i = 0; i < kNumTests; ++i) {
- WebSocketFrameHeader header;
+ WebSocketFrameHeader header(WebSocketFrameHeader::kOpCodeText);
header.final = kTests[i].final;
header.reserved1 = kTests[i].reserved1;
header.reserved2 = kTests[i].reserved2;
header.reserved3 = kTests[i].reserved3;
- header.opcode = WebSocketFrameHeader::kOpCodeText;
- header.masked = false;
header.payload_length = 0;
std::vector<char> expected_output(
@@ -225,11 +209,8 @@ TEST(WebSocketFrameHeaderTest, InsufficientBufferSize) {
static const int kNumTests = ARRAYSIZE_UNSAFE(kTests);
for (int i = 0; i < kNumTests; ++i) {
- WebSocketFrameHeader header;
+ WebSocketFrameHeader header(WebSocketFrameHeader::kOpCodeText);
header.final = true;
- header.reserved1 = false;
- header.reserved2 = false;
- header.reserved3 = false;
header.opcode = WebSocketFrameHeader::kOpCodeText;
header.masked = kTests[i].masked;
header.payload_length = kTests[i].payload_length;
@@ -423,4 +404,62 @@ TEST_F(WebSocketFrameTestMaskBenchmark, BenchmarkMaskLongPayload) {
Benchmark(payload.get(), kLongPayloadSize);
}
+// "IsKnownDataOpCode" is implemented using bit-mangling for efficiency, so we
+// need to check that the results match the actual op-codes defined.
+TEST(WebSocketFrameHeaderTest, IsKnownDataOpCode) {
+ // Make the test less verbose.
+ typedef WebSocketFrameHeader Frame;
+
+ // Known opcode, is used for data frames
+ EXPECT_TRUE(Frame::IsKnownDataOpCode(Frame::kOpCodeContinuation));
+ EXPECT_TRUE(Frame::IsKnownDataOpCode(Frame::kOpCodeText));
+ EXPECT_TRUE(Frame::IsKnownDataOpCode(Frame::kOpCodeBinary));
+
+ // Known opcode, is used for control frames
+ EXPECT_FALSE(Frame::IsKnownDataOpCode(Frame::kOpCodeClose));
+ EXPECT_FALSE(Frame::IsKnownDataOpCode(Frame::kOpCodePing));
+ EXPECT_FALSE(Frame::IsKnownDataOpCode(Frame::kOpCodePong));
+
+ // Check that unused opcodes return false
+ EXPECT_FALSE(Frame::IsKnownDataOpCode(Frame::kOpCodeDataUnused));
+ EXPECT_FALSE(Frame::IsKnownDataOpCode(Frame::kOpCodeControlUnused));
+
+ // Check that opcodes with the 4 bit set return false
+ EXPECT_FALSE(Frame::IsKnownDataOpCode(0x6));
+ EXPECT_FALSE(Frame::IsKnownDataOpCode(0xF));
+
+ // Check that out-of-range opcodes return false
+ EXPECT_FALSE(Frame::IsKnownDataOpCode(-1));
+ EXPECT_FALSE(Frame::IsKnownDataOpCode(0xFF));
+}
+
+// "IsKnownControlOpCode" is implemented using bit-mangling as with
+// "IsKnownDataOpCode".
+TEST(WebSocketFrameHeaderTest, IsKnownControlOpCode) {
+ // Make the test less verbose.
+ typedef WebSocketFrameHeader Frame;
+
+ // Known opcode, is used for data frames
+ EXPECT_FALSE(Frame::IsKnownControlOpCode(Frame::kOpCodeContinuation));
+ EXPECT_FALSE(Frame::IsKnownControlOpCode(Frame::kOpCodeText));
+ EXPECT_FALSE(Frame::IsKnownControlOpCode(Frame::kOpCodeBinary));
+
+ // Known opcode, is used for control frames
+ EXPECT_TRUE(Frame::IsKnownControlOpCode(Frame::kOpCodeClose));
+ EXPECT_TRUE(Frame::IsKnownControlOpCode(Frame::kOpCodePing));
+ EXPECT_TRUE(Frame::IsKnownControlOpCode(Frame::kOpCodePong));
+
+ // Check that unused opcodes return false
+ EXPECT_FALSE(Frame::IsKnownControlOpCode(Frame::kOpCodeDataUnused));
+ EXPECT_FALSE(Frame::IsKnownControlOpCode(Frame::kOpCodeControlUnused));
+
+ // Check that opcodes with the 4 bit set return false
+ EXPECT_FALSE(Frame::IsKnownControlOpCode(0x6));
+ EXPECT_FALSE(Frame::IsKnownControlOpCode(0xF));
+
+ // Check that out-of-range opcodes return false
+ EXPECT_FALSE(Frame::IsKnownControlOpCode(-1));
+ EXPECT_FALSE(Frame::IsKnownControlOpCode(0xFF));
+}
+
} // namespace net