diff options
author | ricea@chromium.org <ricea@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-07 14:59:21 +0000 |
---|---|---|
committer | ricea@chromium.org <ricea@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-07 14:59:21 +0000 |
commit | 40e9c62fe01cb651eb50329b65d264a1fa7edd4e (patch) | |
tree | 98b00d9c8279a4ec38ec46a761af66cf92bf7b70 | |
parent | 7a1f79852d930debcb32274adad623adb1fe1cef (diff) | |
download | chromium_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.cc | 25 | ||||
-rw-r--r-- | net/websockets/websocket_errors.h | 40 | ||||
-rw-r--r-- | net/websockets/websocket_errors_unittest.cc | 14 | ||||
-rw-r--r-- | net/websockets/websocket_frame.cc | 16 | ||||
-rw-r--r-- | net/websockets/websocket_frame.h | 43 | ||||
-rw-r--r-- | net/websockets/websocket_frame_parser.cc | 19 | ||||
-rw-r--r-- | net/websockets/websocket_frame_parser.h | 4 | ||||
-rw-r--r-- | net/websockets/websocket_frame_parser_unittest.cc | 51 | ||||
-rw-r--r-- | net/websockets/websocket_frame_unittest.cc | 87 |
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 |