proxygen
SPDYCodec.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015-present, Facebook, Inc.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * LICENSE file in the root directory of this source tree. An additional grant
7  * of patent rights can be found in the PATENTS file in the same directory.
8  *
9  */
10 #pragma once
11 
12 #include <bitset>
13 #include <folly/Optional.h>
14 #include <deque>
23 #include <zlib.h>
24 
25 namespace folly { namespace io {
26 class Cursor;
27 }}
28 
29 namespace proxygen {
30 
37 public:
38  static const StreamID NoStream = 0;
39 
40  explicit SPDYCodec(TransportDirection direction,
42  int spdyCompressionLevel = Z_NO_COMPRESSION);
43  ~SPDYCodec() override;
44 
45  static const SPDYVersionSettings& getVersionSettings(SPDYVersion version);
46 
47  // HTTPCodec API
48  CodecProtocol getProtocol() const override;
49  const std::string& getUserAgent() const override;
50  bool supportsStreamFlowControl() const override;
51  bool supportsSessionFlowControl() const override;
52  size_t onIngress(const folly::IOBuf& buf) override;
53  bool supportsPushTransactions() const override { return true; }
54  void generateHeader(folly::IOBufQueue& writeBuf,
56  const HTTPMessage& msg,
57  bool eom = false,
58  HTTPHeaderSize* size = nullptr) override;
59  void generatePushPromise(folly::IOBufQueue& writeBuf,
60  StreamID stream,
61  const HTTPMessage& msg,
62  StreamID assocstream,
63  bool eom = false,
64  HTTPHeaderSize* size = nullptr) override;
65  size_t generateBody(folly::IOBufQueue& writeBuf,
66  StreamID stream,
67  std::unique_ptr<folly::IOBuf> chain,
69  bool eom) override;
70  size_t generateChunkHeader(folly::IOBufQueue& writeBuf,
71  StreamID stream,
72  size_t length) override;
73  size_t generateChunkTerminator(folly::IOBufQueue& writeBuf,
74  StreamID stream) override;
75  size_t generateTrailers(folly::IOBufQueue& writeBuf,
76  StreamID stream,
77  const HTTPHeaders& trailers) override;
78  size_t generateEOM(folly::IOBufQueue& writeBuf,
79  StreamID stream) override;
80  size_t generateRstStream(folly::IOBufQueue& writeBuf,
81  StreamID txn,
82  ErrorCode statusCode) override;
83  size_t generateGoaway(
84  folly::IOBufQueue& writeBuf,
85  StreamID lastStream,
86  ErrorCode statusCode,
87  std::unique_ptr<folly::IOBuf> debugData = nullptr) override;
88  size_t generatePingRequest(folly::IOBufQueue& writeBuf) override;
89  size_t generatePingReply(folly::IOBufQueue& writeBuf,
90  uint64_t uniqueID) override;
91  size_t generateSettings(folly::IOBufQueue& writeBuf) override;
92  size_t generateWindowUpdate(folly::IOBufQueue& writeBuf,
93  StreamID stream,
94  uint32_t delta) override;
95 
101  const HTTPSettings* getIngressSettings() const override {
102  return &ingressSettings_;
103  }
107  HTTPSettings* getEgressSettings() override { return &egressSettings_; }
108  uint32_t getDefaultWindowSize() const override {
109  return spdy::kInitialWindow;
110  }
111 
112  uint8_t getVersion() const;
113 
114  uint8_t getMinorVersion() const;
115 
116  void setMaxFrameLength(uint32_t maxFrameLength);
117 
121  void setMaxUncompressedHeaders(uint32_t maxUncompressed);
122 
123  void setHeaderCodecStats(HeaderCodec::Stats* stats) override {
124  headerCodec_.setStats(stats);
125  }
126 
127  size_t addPriorityNodes(
128  PriorityQueue& queue,
129  folly::IOBufQueue& writeBuf,
130  uint8_t maxLevel) override;
131 
132  StreamID mapPriorityToDependency(uint8_t priority) const override {
133  return MAX_STREAM_ID + priority;
134  }
135 
137  if (parent >= MAX_STREAM_ID) {
138  return parent - MAX_STREAM_ID;
139  }
140  return -1;
141  }
142 
143  struct SettingData {
144  SettingData(uint8_t inFlags, uint32_t inId, uint32_t inValue)
145  : flags(inFlags),
146  id(inId),
147  value(inValue) {}
151  };
152 
153  using SettingList = std::vector<SettingData>;
154 
158  static folly::Optional<SPDYVersion> getVersion(const std::string& protocol);
159 
160  private:
161 
165  void generateSynStream(StreamID stream,
166  StreamID assocStream,
167  folly::IOBufQueue& writeBuf,
168  const HTTPMessage& msg,
169  bool eom,
174  void generateSynReply(StreamID stream,
175  folly::IOBufQueue& writeBuf,
176  const HTTPMessage& msg,
177  bool eom,
179 
183  size_t generatePingCommon(folly::IOBufQueue& writeBuf,
184  uint64_t uniqueID);
188  size_t parseIngress(const folly::IOBuf& buf);
189 
194  void onSynStream(uint32_t assocStream,
195  uint8_t pri, uint8_t slot,
196  const compress::HeaderPieceList& headers,
197  const HTTPHeaderSize& size);
202  void onSynReply(const compress::HeaderPieceList& headers,
203  const HTTPHeaderSize& size);
207  void onRstStream(uint32_t statusCode) noexcept;
212  void onSettings(const SettingList& settings);
213 
214  void onPing(uint32_t uniqueID) noexcept;
215 
216  void onGoaway(uint32_t lastGoodStream,
217  uint32_t statusCode) noexcept;
223  void onHeaders(const compress::HeaderPieceList& headers) noexcept;
224 
225  void onWindowUpdate(uint32_t delta) noexcept;
226 
227  // Helpers
228 
233  std::unique_ptr<HTTPMessage> parseHeaders(
235  StreamID assocStreamID, const compress::HeaderPieceList& headers);
236 
241  void onControlFrame(folly::io::Cursor& cursor);
242 
252  void onSynCommon(StreamID streamID,
253  StreamID assocStreamID,
254  const compress::HeaderPieceList& headers,
255  int8_t pri,
256  const HTTPHeaderSize& size);
257 
258  void deliverOnMessageBegin(StreamID streamID, StreamID assocStreamID,
259  HTTPMessage* msg);
260 
270  size_t generateDataFrame(folly::IOBufQueue& writeBuf,
272  uint8_t flags,
273  uint32_t length,
274  std::unique_ptr<folly::IOBuf> payload);
275 
285  std::unique_ptr<folly::IOBuf> serializeRequestHeaders(
286  const HTTPMessage& msg,
287  bool isPushed,
288  uint32_t headroom = 0,
289  HTTPHeaderSize* size = nullptr);
290 
299  std::unique_ptr<folly::IOBuf> serializeResponseHeaders(
300  const HTTPMessage& msg,
301  uint32_t headroom = 0,
302  HTTPHeaderSize* size = nullptr);
303 
314  std::unique_ptr<folly::IOBuf> encodeHeaders(
315  const HTTPMessage& msg, std::vector<compress::Header>& headers,
316  uint32_t headroom = 0,
317  HTTPHeaderSize* size = nullptr);
318 
319  void failStream(bool newTxn, StreamID streamID, uint32_t code,
320  std::string excStr = empty_string);
321 
322  void failSession(uint32_t statusCode);
323 
327  HeaderDecodeResult decodeHeaders(folly::io::Cursor& cursor);
328 
329  void checkLength(uint32_t expectedLength, const std::string& msg);
330 
331  void checkMinLength(uint32_t minLength, const std::string& msg);
332 
333  bool isSPDYReserved(const std::string& name);
334 
339  bool rstStatusSupported(int statusCode) const;
340 
343 
344  HTTPSettings ingressSettings_{
345  {SettingsId::MAX_CONCURRENT_STREAMS, spdy::kMaxConcurrentStreams},
346  {SettingsId::INITIAL_WINDOW_SIZE, spdy::kInitialWindow}
347  };
348  HTTPSettings egressSettings_{
349  {SettingsId::MAX_CONCURRENT_STREAMS, spdy::kMaxConcurrentStreams},
350  {SettingsId::INITIAL_WINDOW_SIZE, spdy::kInitialWindow}
351  };
352 
353  std::unique_ptr<HTTPMessage> partialMsg_;
355  const folly::IOBuf* currentIngressBuf_{nullptr};
356 
358  // StreamID's are 31 bit unsigned integers, so all received goaways will
359  // be lower than this.
360 
361  uint32_t maxFrameLength_{spdy::kMaxFrameLength};
362  uint32_t streamId_{0};
364  uint16_t version_{0};
365  uint16_t type_{0xffff};
366  uint8_t flags_{0};
367 
368  // SPDY Frame parsing state
369  enum FrameState {
370  FRAME_HEADER = 0,
371  CTRL_FRAME_DATA = 1,
372  DATA_FRAME_DATA = 2,
373  } frameState_:2;
374 
375  bool ctrl_:1;
376 
378 };
379 
380 } // proxygen
const HTTPSettings * getIngressSettings() const override
Definition: SPDYCodec.h:101
int64_t length_
Definition: JSONSchema.cpp:233
const uint32_t kInitialWindow
const uint32_t kMaxFrameLength
flags
Definition: http_parser.h:127
spdy::GoawayStatusCode statusCode
Definition: SPDYCodec.cpp:110
std::unique_ptr< HTTPMessage > partialMsg_
Definition: SPDYCodec.h:353
std::vector< SettingData > SettingList
Definition: SPDYCodec.h:153
std::string userAgent_
Definition: SPDYCodec.h:354
static http_parser_settings settings
Definition: test.c:1529
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
bool supportsPushTransactions() const override
Definition: SPDYCodec.h:53
requires E e noexcept(noexcept(s.error(std::move(e))))
ProtocolVersion version
const char * name
Definition: http_parser.c:437
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
void writeBuf(const Buf &buf, folly::io::Appender &out)
std::deque< HeaderPiece > HeaderPieceList
Definition: HeaderPiece.h:59
Type type_
Definition: JSONSchema.cpp:208
HTTPSettings * getEgressSettings() override
Definition: SPDYCodec.h:107
SettingData(uint8_t inFlags, uint32_t inId, uint32_t inValue)
Definition: SPDYCodec.h:144
StreamID mapPriorityToDependency(uint8_t priority) const override
Definition: SPDYCodec.h:132
StreamID nextEgressPingID_
Definition: SPDYCodec.h:357
ErrorCode parseHeaders(Cursor &cursor, const FrameHeader &header, folly::Optional< PriorityUpdate > &outPriority, std::unique_ptr< IOBuf > &outBuf) noexcept
const std::string empty_string
Definition: HTTPHeaders.cpp:23
const char * string
Definition: Conv.cpp:212
void setHeaderCodecStats(HeaderCodec::Stats *stats) override
Definition: SPDYCodec.h:123
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
uint64_t StreamID
Definition: HTTPCodec.h:49
GzipHeaderCodec headerCodec_
Definition: SPDYCodec.h:377
uint32_t getDefaultWindowSize() const override
Definition: SPDYCodec.h:108
const uint32_t kMaxConcurrentStreams
const SPDYVersionSettings & versionSettings_
Definition: SPDYCodec.h:342
uint32_t streamID
Definition: SPDYCodec.cpp:131
folly::fbvector< StreamID > closedStreams_
Definition: SPDYCodec.h:341
int8_t mapDependencyToPriority(StreamID parent) const override
Definition: SPDYCodec.h:136
folly::Function< void()> parent
Definition: AtFork.cpp:34