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