rippled
HTTPStream.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2020 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/net/HTTPStream.h>
21 
22 namespace ripple {
23 
25  Config const& config,
26  boost::asio::io_service::strand& strand,
28  : ssl_ctx_(config, j, boost::asio::ssl::context::tlsv12_client)
29  , strand_(strand)
30 {
31 }
32 
33 boost::asio::ip::tcp::socket&
35 {
36  assert(stream_);
37  return stream_->next_layer();
38 }
39 
40 bool
42  std::string& errorOut,
43  std::string const& host,
44  std::string const& port,
45  boost::asio::yield_context& yield)
46 {
47  using namespace boost::asio;
48  using namespace boost::beast;
49 
50  boost::system::error_code ec;
51 
52  auto fail = [&errorOut, &ec](
53  std::string const& errorIn,
54  std::string const& message = "") {
55  errorOut = errorIn + ": " + (message.empty() ? ec.message() : message);
56  return false;
57  };
58 
59  ip::tcp::resolver resolver{strand_.context()};
60  auto const endpoints = resolver.async_resolve(host, port, yield[ec]);
61  if (ec)
62  return fail("async_resolve");
63 
64  try
65  {
66  stream_.emplace(strand_.context(), ssl_ctx_.context());
67  }
68  catch (std::exception const& e)
69  {
70  return fail("exception", e.what());
71  }
72 
73  ec = ssl_ctx_.preConnectVerify(*stream_, host);
74  if (ec)
75  return fail("preConnectVerify");
76 
77  boost::asio::async_connect(
78  stream_->next_layer(), endpoints.begin(), endpoints.end(), yield[ec]);
79  if (ec)
80  return fail("async_connect");
81 
82  ec = ssl_ctx_.postConnectVerify(*stream_, host);
83  if (ec)
84  return fail("postConnectVerify");
85 
86  stream_->async_handshake(ssl::stream_base::client, yield[ec]);
87  if (ec)
88  return fail("async_handshake");
89 
90  return true;
91 }
92 
93 void
95  request& req,
96  boost::asio::yield_context& yield,
97  boost::system::error_code& ec)
98 {
99  boost::beast::http::async_write(*stream_, req, yield[ec]);
100 }
101 
102 void
104  boost::beast::flat_buffer& buf,
105  parser& p,
106  boost::asio::yield_context& yield,
107  boost::system::error_code& ec)
108 {
109  boost::beast::http::async_read(*stream_, buf, p, yield[ec]);
110 }
111 
112 void
114  boost::beast::flat_buffer& buf,
115  parser& p,
116  boost::asio::yield_context& yield,
117  boost::system::error_code& ec)
118 {
119  boost::beast::http::async_read_some(*stream_, buf, p, yield[ec]);
120 }
121 
122 RawStream::RawStream(boost::asio::io_service::strand& strand) : strand_(strand)
123 {
124 }
125 
126 boost::asio::ip::tcp::socket&
128 {
129  assert(stream_);
130  return *stream_;
131 }
132 
133 bool
135  std::string& errorOut,
136  std::string const& host,
137  std::string const& port,
138  boost::asio::yield_context& yield)
139 {
140  using namespace boost::asio;
141  using namespace boost::beast;
142 
143  boost::system::error_code ec;
144 
145  auto fail = [&errorOut, &ec](
146  std::string const& errorIn,
147  std::string const& message = "") {
148  errorOut = errorIn + ": " + (message.empty() ? ec.message() : message);
149  return false;
150  };
151 
152  ip::tcp::resolver resolver{strand_.context()};
153  auto const endpoints = resolver.async_resolve(host, port, yield[ec]);
154  if (ec)
155  return fail("async_resolve");
156 
157  try
158  {
159  stream_.emplace(strand_.context());
160  }
161  catch (std::exception const& e)
162  {
163  return fail("exception", e.what());
164  }
165 
166  boost::asio::async_connect(
167  *stream_, endpoints.begin(), endpoints.end(), yield[ec]);
168  if (ec)
169  return fail("async_connect");
170 
171  return true;
172 }
173 
174 void
176  request& req,
177  boost::asio::yield_context& yield,
178  boost::system::error_code& ec)
179 {
180  boost::beast::http::async_write(*stream_, req, yield[ec]);
181 }
182 
183 void
185  boost::beast::flat_buffer& buf,
186  parser& p,
187  boost::asio::yield_context& yield,
188  boost::system::error_code& ec)
189 {
190  boost::beast::http::async_read(*stream_, buf, p, yield[ec]);
191 }
192 
193 void
195  boost::beast::flat_buffer& buf,
196  parser& p,
197  boost::asio::yield_context& yield,
198  boost::system::error_code& ec)
199 {
200  boost::beast::http::async_read_some(*stream_, buf, p, yield[ec]);
201 }
202 
203 } // namespace ripple
ripple::RawStream::asyncRead
void asyncRead(boost::beast::flat_buffer &buf, parser &p, boost::asio::yield_context &yield, boost::system::error_code &ec) override
Definition: HTTPStream.cpp:184
ripple::RawStream::stream_
std::optional< boost::asio::ip::tcp::socket > stream_
Definition: HTTPStream.h:159
ripple::SSLStream::asyncReadSome
void asyncReadSome(boost::beast::flat_buffer &buf, parser &p, boost::asio::yield_context &yield, boost::system::error_code &ec) override
Definition: HTTPStream.cpp:113
std::string
STL class.
std::exception
STL class.
ripple::RawStream::asyncWrite
void asyncWrite(request &req, boost::asio::yield_context &yield, boost::system::error_code &ec) override
Definition: HTTPStream.cpp:175
ripple::RawStream::RawStream
RawStream(boost::asio::io_service::strand &strand)
Definition: HTTPStream.cpp:122
ripple::SSLStream::getStream
boost::asio::ip::tcp::socket & getStream() override
Definition: HTTPStream.cpp:34
ripple::HTTPClientSSLContext::context
boost::asio::ssl::context & context()
Definition: HTTPClientSSLContext.h:72
ripple::HTTPStream::parser
boost::beast::http::basic_parser< false > parser
Definition: HTTPStream.h:39
std::optional::emplace
T emplace(T... args)
ripple::HTTPClientSSLContext::preConnectVerify
boost::system::error_code preConnectVerify(T &strm, std::string const &host)
invoked before connect/async_connect on an ssl stream to setup name verification.
Definition: HTTPClientSSLContext.h:107
boost
Definition: IPAddress.h:103
ripple::RawStream::getStream
boost::asio::ip::tcp::socket & getStream() override
Definition: HTTPStream.cpp:127
ripple::SSLStream::asyncWrite
void asyncWrite(request &req, boost::asio::yield_context &yield, boost::system::error_code &ec) override
Definition: HTTPStream.cpp:94
ripple::Config
Definition: Config.h:89
boost::asio
Definition: Overlay.h:41
ripple::HTTPClientSSLContext::postConnectVerify
boost::system::error_code postConnectVerify(T &strm, std::string const &host)
invoked after connect/async_connect but before sending data on an ssl stream - to setup name verifica...
Definition: HTTPClientSSLContext.h:142
ripple::RawStream::strand_
boost::asio::io_service::strand & strand_
Definition: HTTPStream.h:160
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
ripple::SSLStream::strand_
boost::asio::io_service::strand & strand_
Definition: HTTPStream.h:118
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::SSLStream::SSLStream
SSLStream(Config const &config, boost::asio::io_service::strand &strand, beast::Journal j)
Definition: HTTPStream.cpp:24
ripple::SSLStream::asyncRead
void asyncRead(boost::beast::flat_buffer &buf, parser &p, boost::asio::yield_context &yield, boost::system::error_code &ec) override
Definition: HTTPStream.cpp:103
ripple::RawStream::asyncReadSome
void asyncReadSome(boost::beast::flat_buffer &buf, parser &p, boost::asio::yield_context &yield, boost::system::error_code &ec) override
Definition: HTTPStream.cpp:194
ripple::RawStream::connect
bool connect(std::string &errorOut, std::string const &host, std::string const &port, boost::asio::yield_context &yield) override
Definition: HTTPStream.cpp:134
ripple::SSLStream::ssl_ctx_
HTTPClientSSLContext ssl_ctx_
Definition: HTTPStream.h:115
ripple::SSLStream::connect
bool connect(std::string &errorOut, std::string const &host, std::string const &port, boost::asio::yield_context &yield) override
Definition: HTTPStream.cpp:41
ripple::SSLStream::stream_
std::optional< boost::asio::ssl::stream< boost::asio::ip::tcp::socket > > stream_
Definition: HTTPStream.h:117
ripple::HTTPStream::request
boost::beast::http::request< boost::beast::http::empty_body > request
Definition: HTTPStream.h:38
std::exception::what
T what(T... args)