15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NET_WEBSOCKETS_WEBSOCKET_FRAME_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NET_WEBSOCKETS_WEBSOCKET_FRAME_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_export.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)class IOBuffer; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class IOBufferWithSize; 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Represents a WebSocket frame header. 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Members of this class correspond to each element in WebSocket frame header 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (see http://tools.ietf.org/html/rfc6455#section-5.2). 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct NET_EXPORT WebSocketFrameHeader { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef int OpCode; 2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Originally these constants were static const int, but to make it possible 2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // to use them in a switch statement they were changed to an enum. 2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) enum OpCodeEnum { 3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) kOpCodeContinuation = 0x0, 3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) kOpCodeText = 0x1, 3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) kOpCodeBinary = 0x2, 3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) kOpCodeDataUnused = 0x3, 3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) kOpCodeClose = 0x8, 3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) kOpCodePing = 0x9, 3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) kOpCodePong = 0xA, 3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) kOpCodeControlUnused = 0xB, 3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) }; 3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Return true if |opcode| is one of the data opcodes known to this 4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // implementation. 4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) static bool IsKnownDataOpCode(OpCode opcode) { 4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return opcode == kOpCodeContinuation || opcode == kOpCodeText || 4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) opcode == kOpCodeBinary; 45b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 46b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Return true if |opcode| is one of the control opcodes known to this 4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // implementation. 4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) static bool IsKnownControlOpCode(OpCode opcode) { 5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return opcode == kOpCodeClose || opcode == kOpCodePing || 5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) opcode == kOpCodePong; 52b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // These values must be a compile-time constant. "enum hack" is used here 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to make MSVC happy. 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kBaseHeaderSize = 2, 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kMaximumExtendedLengthSize = 8, 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kMaskingKeyLength = 4 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 62b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Constructor to avoid a lot of repetitive initialisation. 63b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) explicit WebSocketFrameHeader(OpCode opCode) 6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) : final(false), 6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) reserved1(false), 6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) reserved2(false), 6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) reserved3(false), 6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) opcode(opCode), 6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) masked(false), 7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) payload_length(0) {} 71b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 72b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Create a clone of this object on the heap. 734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) scoped_ptr<WebSocketFrameHeader> Clone() const; 744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Overwrite this object with the fields from |source|. 764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) void CopyFrom(const WebSocketFrameHeader& source); 77b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Members below correspond to each item in WebSocket frame header. 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See <http://tools.ietf.org/html/rfc6455#section-5.2> for details. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool final; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool reserved1; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool reserved2; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool reserved3; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OpCode opcode; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool masked; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 payload_length; 87b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 88b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) private: 89b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(WebSocketFrameHeader); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Contains an entire WebSocket frame including payload. This is used by APIs 934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// that are not concerned about retaining the original frame boundaries (because 944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// frames may need to be split in order for the data to fit in memory). 954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)struct NET_EXPORT_PRIVATE WebSocketFrame { 964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // A frame must always have an opcode, so this parameter is compulsory. 974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) explicit WebSocketFrame(WebSocketFrameHeader::OpCode opcode); 984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ~WebSocketFrame(); 994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // |header| is always present. 1014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) WebSocketFrameHeader header; 1024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // |data| is always unmasked even if the frame is masked. The size of |data| 1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // is given by |header.payload_length|. 1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) scoped_refptr<IOBuffer> data; 1064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}; 1074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Structure describing one chunk of a WebSocket frame. 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// The payload of a WebSocket frame may be divided into multiple chunks. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// You need to look at |final_chunk| member variable to detect the end of a 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// series of chunk objects of a WebSocket frame. 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Frame dissection is necessary to handle frames that are too large to store in 1154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// the browser memory without losing information about the frame boundaries. In 1164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// practice, most code does not need to worry about the original frame 1174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// boundaries and can use the WebSocketFrame type declared above. 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Users of this struct should treat WebSocket frames as a data stream; it's 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// important to keep the frame data flowing, especially in the browser process. 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Users should not let the data stuck somewhere in the pipeline. 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This struct is used for reading WebSocket frame data (created by 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WebSocketFrameParser). To construct WebSocket frames, use functions below. 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct NET_EXPORT WebSocketFrameChunk { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebSocketFrameChunk(); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~WebSocketFrameChunk(); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Non-null |header| is provided only if this chunk is the first part of 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a series of chunks. 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<WebSocketFrameHeader> header; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Indicates this part is the last chunk of a frame. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool final_chunk; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |data| is always unmasked even if the frame is masked. |data| might be 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // null in the first chunk. 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<IOBufferWithSize> data; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Contains four-byte data representing "masking key" of WebSocket frames. 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct WebSocketMaskingKey { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char key[WebSocketFrameHeader::kMaskingKeyLength]; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the size of WebSocket frame header. The size of WebSocket frame 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// header varies from 2 bytes to 14 bytes depending on the payload length 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and maskedness. 14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)NET_EXPORT int GetWebSocketFrameHeaderSize(const WebSocketFrameHeader& header); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Writes wire format of a WebSocket frame header into |output|, and returns 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the number of bytes written. 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WebSocket frame format is defined at: 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// <http://tools.ietf.org/html/rfc6455#section-5.2>. This function writes 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// everything but payload data in a WebSocket frame to |buffer|. 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If |header->masked| is true, |masking_key| must point to a valid 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WebSocketMaskingKey object containing the masking key for that frame 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (possibly generated by GenerateWebSocketMaskingKey() function below). 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Otherwise, |masking_key| must be NULL. 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |buffer| should have enough size to contain the frame header. 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// GetWebSocketFrameHeaderSize() can be used to know the size of header 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// beforehand. If the size of |buffer| is insufficient, this function returns 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ERR_INVALID_ARGUMENT and does not write any data to |buffer|. 16790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)NET_EXPORT int WriteWebSocketFrameHeader(const WebSocketFrameHeader& header, 16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const WebSocketMaskingKey* masking_key, 16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) char* buffer, 17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int buffer_size); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Generates a masking key suitable for use in a new WebSocket frame. 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)NET_EXPORT WebSocketMaskingKey GenerateWebSocketMaskingKey(); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Masks WebSocket frame payload. 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A client must mask every WebSocket frame by XOR'ing the frame payload 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// with four-byte random data (masking key). This function applies the masking 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to the given payload data. 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function masks |data| with |masking_key|, assuming |data| is partial 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// data starting from |frame_offset| bytes from the beginning of the payload 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// data. 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Since frame masking is a reversible operation, this function can also be 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// used for unmasking a WebSocket frame. 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)NET_EXPORT void MaskWebSocketFramePayload( 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebSocketMaskingKey& masking_key, 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 frame_offset, 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* data, 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int data_size); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // NET_WEBSOCKETS_WEBSOCKET_FRAME_H_ 196