proxygen
CodecProtocol.cpp
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  */
13 #include <boost/algorithm/string/trim.hpp>
14 
15 #include <glog/logging.h>
16 
17 namespace proxygen {
18 
19 namespace {
20 static const std::string http_1_1 = "http/1.1";
21 static const std::string spdy_3 = "spdy/3";
22 static const std::string spdy_3_1 = "spdy/3.1";
23 static const std::string http_2 = "http/2";
24 static const std::string hq = "hq";
25 static const std::string empty = "";
26 
28  if (protocolStr == http_1_1) {
30  } else if (protocolStr == spdy_3) {
31  return CodecProtocol::SPDY_3;
32  } else if (protocolStr == spdy_3_1) {
34  } else if (protocolStr == http_2 || protocolStr == http2::kProtocolString ||
35  protocolStr == http2::kProtocolCleartextString) {
36  return CodecProtocol::HTTP_2;
37  } else if (protocolStr.find(hq) == 0) {
38  return CodecProtocol::HQ;
39  } else {
40  // return default protocol
42  }
43 }
44 
45 }
46 
48  switch (proto) {
49  case CodecProtocol::HTTP_1_1: return http_1_1;
50  case CodecProtocol::SPDY_3: return spdy_3;
51  case CodecProtocol::SPDY_3_1: return spdy_3_1;
52  case CodecProtocol::HTTP_2: return http_2;
53  case CodecProtocol::HQ: return hq;
54  }
55  LOG(FATAL) << "Unreachable";
56  return empty;
57 }
58 
59 extern bool isValidCodecProtocolStr(const std::string& protocolStr) {
60  return protocolStr == http_1_1 ||
61  protocolStr == spdy_3 ||
62  protocolStr == spdy_3_1 ||
63  protocolStr == http2::kProtocolString ||
64  protocolStr == http2::kProtocolCleartextString ||
65  protocolStr == http_2 ||
66  protocolStr == hq;
67 }
68 
70  return getCodecProtocolFromStr(folly::StringPiece(protocolStr));
71 }
72 
73 extern bool isSpdyCodecProtocol(CodecProtocol protocol) {
74  return protocol == CodecProtocol::SPDY_3 ||
75  protocol == CodecProtocol::SPDY_3_1;
76 }
77 
78 extern bool isHTTP2CodecProtocol(CodecProtocol protocol) {
79  return protocol == CodecProtocol::HTTP_2;
80 }
81 
82 extern bool isHQCodecProtocol(CodecProtocol protocol) {
83  return protocol == CodecProtocol::HQ;
84 }
85 
86 extern bool isParallelCodecProtocol(CodecProtocol protocol) {
87  return isSpdyCodecProtocol(protocol) || isHTTP2CodecProtocol(protocol);
88 }
89 
91 checkForProtocolUpgrade(const std::string& clientUpgrade,
92  const std::string& serverUpgrade,
93  bool serverMode) {
94  CodecProtocol protocol;
95  if (clientUpgrade.empty() || serverUpgrade.empty()) {
96  return folly::none;
97  }
98 
99  // Should be a comma separated list of protocols, like NPN
100  std::vector<folly::StringPiece> clientProtocols;
101  folly::split(",", clientUpgrade, clientProtocols, true /* ignore empty */);
102  for (auto& clientProtocol: clientProtocols) {
103  boost::algorithm::trim(clientProtocol);
104  }
105 
106  // List of server chosen protocols in layer-ascending order. We can
107  // only support one layer right now. We just skip anything that
108  // isn't an HTTP transport protocol
109  std::vector<folly::StringPiece> serverProtocols;
110  folly::split(",", serverUpgrade, serverProtocols, true /* ignore empty */);
111 
112  for (auto& testProtocol: serverProtocols) {
113  // Get rid of leading/trailing LWS
114  boost::algorithm::trim(testProtocol);
115  if (std::find(clientProtocols.begin(), clientProtocols.end(),
116  testProtocol) == clientProtocols.end()) {
117  if (serverMode) {
118  // client didn't offer this, try the next
119  continue;
120  } else {
121  // The server returned a protocol the client didn't ask for
122  return folly::none;
123  }
124  }
125  protocol = getCodecProtocolFromStr(testProtocol);
126  // Non-native upgrades get returned as HTTP_1_1/<actual protocol>
127  return std::make_pair(protocol, testProtocol.str());
128  }
129  return folly::none;
130 }
131 
133  folly::none;
135  folly::none;
137 
138 }
static const folly::Optional< uint8_t > NoPadding
Definition: HTTPCodec.h:53
const std::string kProtocolCleartextString
const std::string kProtocolString
size_type find(const_range_type str) const
Definition: Range.h:721
void split(const Delim &delimiter, const String &input, std::vector< OutputType > &out, bool ignoreEmpty)
Definition: String-inl.h:382
bool isHQCodecProtocol(CodecProtocol protocol)
constexpr auto empty(C const &c) -> decltype(c.empty())
Definition: Access.h:55
folly::Optional< std::pair< CodecProtocol, std::string > > checkForProtocolUpgrade(const std::string &clientUpgrade, const std::string &serverUpgrade, bool serverMode)
const std::string & getCodecProtocolString(CodecProtocol proto)
bool isSpdyCodecProtocol(CodecProtocol protocol)
bool isParallelCodecProtocol(CodecProtocol protocol)
const char * string
Definition: Conv.cpp:212
static const folly::Optional< StreamID > NoStream
Definition: HTTPCodec.h:51
bool isHTTP2CodecProtocol(CodecProtocol protocol)
CodecProtocol getCodecProtocolFromStr(const std::string &protocolStr)
bool isValidCodecProtocolStr(const std::string &protocolStr)
constexpr None none
Definition: Optional.h:87
static const folly::Optional< ExAttributes > NoExAttributes
Definition: HTTPCodec.h:66