1 // Copyright (c) 2012 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 #ifndef NET_WEBSOCKETS_WEBSOCKET_FRAME_H_ 6 #define NET_WEBSOCKETS_WEBSOCKET_FRAME_H_ 7 8 #include <vector> 9 10 #include "base/basictypes.h" 11 #include "base/memory/ref_counted.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "net/base/net_export.h" 14 15 namespace net { 16 17 class IOBufferWithSize; 18 19 // Represents a WebSocket frame header. 20 // 21 // Members of this class correspond to each element in WebSocket frame header 22 // (see http://tools.ietf.org/html/rfc6455#section-5.2). 23 struct NET_EXPORT WebSocketFrameHeader { 24 typedef int OpCode; 25 26 // Originally these constants were static const int, but to make it possible 27 // to use them in a switch statement they were changed to an enum. 28 enum OpCodeEnum { 29 kOpCodeContinuation = 0x0, 30 kOpCodeText = 0x1, 31 kOpCodeBinary = 0x2, 32 kOpCodeDataUnused = 0x3, 33 kOpCodeClose = 0x8, 34 kOpCodePing = 0x9, 35 kOpCodePong = 0xA, 36 kOpCodeControlUnused = 0xB, 37 }; 38 39 // Return true if |opcode| is one of the data opcodes known to this 40 // implementation. 41 static bool IsKnownDataOpCode(OpCode opcode) { 42 return opcode == kOpCodeContinuation || opcode == kOpCodeText || 43 opcode == kOpCodeBinary; 44 } 45 46 // Return true if |opcode| is one of the control opcodes known to this 47 // implementation. 48 static bool IsKnownControlOpCode(OpCode opcode) { 49 return opcode == kOpCodeClose || opcode == kOpCodePing || 50 opcode == kOpCodePong; 51 } 52 53 // These values must be a compile-time constant. "enum hack" is used here 54 // to make MSVC happy. 55 enum { 56 kBaseHeaderSize = 2, 57 kMaximumExtendedLengthSize = 8, 58 kMaskingKeyLength = 4 59 }; 60 61 // Constructor to avoid a lot of repetitive initialisation. 62 explicit WebSocketFrameHeader(OpCode opCode) 63 : final(false), 64 reserved1(false), 65 reserved2(false), 66 reserved3(false), 67 opcode(opCode), 68 masked(false), 69 payload_length(0) {} 70 71 // Create a clone of this object on the heap. 72 scoped_ptr<WebSocketFrameHeader> Clone(); 73 74 // Members below correspond to each item in WebSocket frame header. 75 // See <http://tools.ietf.org/html/rfc6455#section-5.2> for details. 76 bool final; 77 bool reserved1; 78 bool reserved2; 79 bool reserved3; 80 OpCode opcode; 81 bool masked; 82 uint64 payload_length; 83 84 private: 85 DISALLOW_COPY_AND_ASSIGN(WebSocketFrameHeader); 86 }; 87 88 // Contains payload data of part of a WebSocket frame. 89 // 90 // Payload of a WebSocket frame may be divided into multiple chunks. 91 // You need to look at |final_chunk| member variable to detect the end of a 92 // series of chunk objects of a WebSocket frame. 93 // 94 // Frame dissection is necessary to handle WebSocket frame stream containing 95 // abritrarily large frames in the browser process. Because the server may send 96 // a huge frame that doesn't fit in the memory, we cannot store the entire 97 // payload data in the memory. 98 // 99 // Users of this struct should treat WebSocket frames as a data stream; it's 100 // important to keep the frame data flowing, especially in the browser process. 101 // Users should not let the data stuck somewhere in the pipeline. 102 // 103 // This struct is used for reading WebSocket frame data (created by 104 // WebSocketFrameParser). To construct WebSocket frames, use functions below. 105 struct NET_EXPORT WebSocketFrameChunk { 106 WebSocketFrameChunk(); 107 ~WebSocketFrameChunk(); 108 109 // Non-null |header| is provided only if this chunk is the first part of 110 // a series of chunks. 111 scoped_ptr<WebSocketFrameHeader> header; 112 113 // Indicates this part is the last chunk of a frame. 114 bool final_chunk; 115 116 // |data| is always unmasked even if the frame is masked. |data| might be 117 // null in the first chunk. 118 scoped_refptr<IOBufferWithSize> data; 119 }; 120 121 // Contains four-byte data representing "masking key" of WebSocket frames. 122 struct WebSocketMaskingKey { 123 char key[WebSocketFrameHeader::kMaskingKeyLength]; 124 }; 125 126 // Returns the size of WebSocket frame header. The size of WebSocket frame 127 // header varies from 2 bytes to 14 bytes depending on the payload length 128 // and maskedness. 129 NET_EXPORT int GetWebSocketFrameHeaderSize(const WebSocketFrameHeader& header); 130 131 // Writes wire format of a WebSocket frame header into |output|, and returns 132 // the number of bytes written. 133 // 134 // WebSocket frame format is defined at: 135 // <http://tools.ietf.org/html/rfc6455#section-5.2>. This function writes 136 // everything but payload data in a WebSocket frame to |buffer|. 137 // 138 // If |header->masked| is true, |masking_key| must point to a valid 139 // WebSocketMaskingKey object containing the masking key for that frame 140 // (possibly generated by GenerateWebSocketMaskingKey() function below). 141 // Otherwise, |masking_key| must be NULL. 142 // 143 // |buffer| should have enough size to contain the frame header. 144 // GetWebSocketFrameHeaderSize() can be used to know the size of header 145 // beforehand. If the size of |buffer| is insufficient, this function returns 146 // ERR_INVALID_ARGUMENT and does not write any data to |buffer|. 147 NET_EXPORT int WriteWebSocketFrameHeader(const WebSocketFrameHeader& header, 148 const WebSocketMaskingKey* masking_key, 149 char* buffer, 150 int buffer_size); 151 152 // Generates a masking key suitable for use in a new WebSocket frame. 153 NET_EXPORT WebSocketMaskingKey GenerateWebSocketMaskingKey(); 154 155 // Masks WebSocket frame payload. 156 // 157 // A client must mask every WebSocket frame by XOR'ing the frame payload 158 // with four-byte random data (masking key). This function applies the masking 159 // to the given payload data. 160 // 161 // This function masks |data| with |masking_key|, assuming |data| is partial 162 // data starting from |frame_offset| bytes from the beginning of the payload 163 // data. 164 // 165 // Since frame masking is a reversible operation, this function can also be 166 // used for unmasking a WebSocket frame. 167 NET_EXPORT void MaskWebSocketFramePayload( 168 const WebSocketMaskingKey& masking_key, 169 uint64 frame_offset, 170 char* data, 171 int data_size); 172 173 } // namespace net 174 175 #endif // NET_WEBSOCKETS_WEBSOCKET_FRAME_H_ 176