| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "net/server/web_socket_frame.h" |
| 6 |
| 7 #include "base/rand_util.h" |
| 8 #include "base/logging.h" |
| 9 |
| 10 #include <limits> |
| 11 |
| 12 namespace net { |
| 13 |
| 14 // Constants for hybi-10 frame format. |
| 15 const WebSocketFrame::OpCode WebSocketFrame::kOpCodeContinuation = 0x0; |
| 16 const WebSocketFrame::OpCode WebSocketFrame::kOpCodeText = 0x1; |
| 17 const WebSocketFrame::OpCode WebSocketFrame::kOpCodeBinary = 0x2; |
| 18 const WebSocketFrame::OpCode WebSocketFrame::kOpCodeClose = 0x8; |
| 19 const WebSocketFrame::OpCode WebSocketFrame::kOpCodePing = 0x9; |
| 20 const WebSocketFrame::OpCode WebSocketFrame::kOpCodePong = 0xA; |
| 21 |
| 22 const unsigned char WebSocketFrame::kFinalBit = 0x80; |
| 23 const unsigned char WebSocketFrame::kReserved1Bit = 0x40; |
| 24 const unsigned char WebSocketFrame::kReserved2Bit = 0x20; |
| 25 const unsigned char WebSocketFrame::kReserved3Bit = 0x10; |
| 26 const unsigned char WebSocketFrame::kOpCodeMask = 0xF; |
| 27 const unsigned char WebSocketFrame::kMaskBit = 0x80; |
| 28 const unsigned char WebSocketFrame::kPayloadLengthMask = 0x7F; |
| 29 |
| 30 const size_t WebSocketFrame::kMaxSingleBytePayloadLength = 125; |
| 31 const size_t WebSocketFrame::kTwoBytePayloadLengthField = 126; |
| 32 const size_t WebSocketFrame::kEightBytePayloadLengthField = 127; |
| 33 const size_t WebSocketFrame::kMaskingKeyWidthInBytes = 4; |
| 34 |
| 35 WebSocketFrame::ParseResult WebSocketFrame::DecodeFrame( |
| 36 const char* data, size_t data_length) { |
| 37 const char* p = data; |
| 38 const char* buffer_end = data + data_length; |
| 39 |
| 40 if (data_length < 2) |
| 41 return FrameIncomplete; |
| 42 |
| 43 unsigned char first_byte = *p++; |
| 44 unsigned char second_byte = *p++; |
| 45 |
| 46 final_ = first_byte & kFinalBit; |
| 47 reserved1_ = first_byte & kReserved1Bit; |
| 48 reserved2_ = first_byte & kReserved2Bit; |
| 49 reserved3_ = first_byte & kReserved3Bit; |
| 50 op_code_ = first_byte & kOpCodeMask; |
| 51 masked_ = second_byte & kMaskBit; |
| 52 |
| 53 uint64_t payload_length64 = second_byte & kPayloadLengthMask; |
| 54 if (payload_length64 > kMaxSingleBytePayloadLength) { |
| 55 int extended_payload_length_size; |
| 56 if (payload_length64 == kTwoBytePayloadLengthField) |
| 57 extended_payload_length_size = 2; |
| 58 else { |
| 59 DCHECK(payload_length64 == kEightBytePayloadLengthField); |
| 60 extended_payload_length_size = 8; |
| 61 } |
| 62 if (buffer_end - p < extended_payload_length_size) |
| 63 return FrameIncomplete; |
| 64 payload_length64 = 0; |
| 65 for (int i = 0; i < extended_payload_length_size; ++i) { |
| 66 payload_length64 <<= 8; |
| 67 payload_length64 |= static_cast<unsigned char>(*p++); |
| 68 } |
| 69 } |
| 70 |
| 71 static const uint64_t max_payload_ength = 0x7FFFFFFFFFFFFFFFull; |
| 72 size_t masking_key_length = masked_ ? kMaskingKeyWidthInBytes : 0; |
| 73 static size_t max_length = std::numeric_limits<size_t>::max(); |
| 74 if (payload_length64 > max_payload_ength || |
| 75 payload_length64 + masking_key_length > max_length) { |
| 76 // WebSocket frame length too large. |
| 77 return FrameError; |
| 78 } |
| 79 payload_length_ = static_cast<size_t>(payload_length64); |
| 80 |
| 81 size_t total_length = masking_key_length + payload_length_; |
| 82 if (static_cast<size_t>(buffer_end - p) < total_length) |
| 83 return FrameIncomplete; |
| 84 |
| 85 if (masked_) { |
| 86 const char* masking_key = p; |
| 87 char* payload = const_cast<char*>(p + kMaskingKeyWidthInBytes); |
| 88 for (size_t i = 0; i < payload_length_; ++i) // Unmask the payload. |
| 89 payload[i] ^= masking_key[i % kMaskingKeyWidthInBytes]; |
| 90 } |
| 91 |
| 92 payload_ = p + masking_key_length; |
| 93 frame_end_ = p + masking_key_length + payload_length_; |
| 94 return FrameOK; |
| 95 } |
| 96 |
| 97 std::vector<char> WebSocketFrame::EncodeFrame( |
| 98 OpCode op_code, const char* data, size_t data_length) { |
| 99 std::vector<char> frame; |
| 100 |
| 101 // Checks whether "op_code" fits in the range of opCodes. |
| 102 DCHECK(!(op_code & ~kOpCodeMask)); |
| 103 frame.push_back(kFinalBit | op_code); |
| 104 if (data_length <= kMaxSingleBytePayloadLength) |
| 105 frame.push_back(kMaskBit | data_length); |
| 106 else if (data_length <= 0xFFFF) { |
| 107 frame.push_back(kMaskBit | kTwoBytePayloadLengthField); |
| 108 frame.push_back((data_length & 0xFF00) >> 8); |
| 109 frame.push_back(data_length & 0xFF); |
| 110 } else { |
| 111 frame.push_back(kMaskBit | kEightBytePayloadLengthField); |
| 112 char extended_payload_length[8]; |
| 113 size_t remaining = data_length; |
| 114 // Fill the length into extended_payload_length in the network byte order. |
| 115 for (int i = 0; i < 8; ++i) { |
| 116 extended_payload_length[7 - i] = remaining & 0xFF; |
| 117 remaining >>= 8; |
| 118 } |
| 119 frame.insert(frame.end(), |
| 120 extended_payload_length, |
| 121 extended_payload_length + 8); |
| 122 CHECK(!remaining); |
| 123 } |
| 124 |
| 125 // Mask the frame. |
| 126 size_t masking_key_start = frame.size(); |
| 127 // Add placeholder for masking key. Will be overwritten. |
| 128 frame.resize(frame.size() + kMaskingKeyWidthInBytes); |
| 129 size_t payload_start = frame.size(); |
| 130 frame.insert(frame.end(), data, data + data_length); |
| 131 |
| 132 base::RandBytes(&frame[0] + masking_key_start, |
| 133 kMaskingKeyWidthInBytes); |
| 134 for (size_t i = 0; i < data_length; ++i) { |
| 135 frame[payload_start + i] ^= |
| 136 frame[masking_key_start + i % kMaskingKeyWidthInBytes]; |
| 137 } |
| 138 |
| 139 return frame; |
| 140 } |
| 141 |
| 142 |
| 143 } // namespace net |
| OLD | NEW |