websocket_frame.h 7.8 KB

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