59 FETPAPI_DLL_IMPORT_OR_EXPORT SslClientSession(
60#
if USE_WINTLS_INSTEAD_OF_OPENSSL
61 wintls::context&& ctx,
65 InitializationParameters const* initializationParams,
const std::string& target,
const std::string& authorization,
const std::string& proxyAuthorization =
"",
66 const std::map<std::string, std::string>& additionalHandshakeHeaderFields = {}, std::size_t frameSize = 4096);
68 virtual ~SslClientSession() {}
71#if USE_WINTLS_INSTEAD_OF_OPENSSL
72 FETPAPI_DLL_IMPORT_OR_EXPORT std::unique_ptr<websocket::stream<wintls::stream<beast::tcp_stream>>>& ws() {
return ws_; }
73#elif BOOST_VERSION < 107000
74 FETPAPI_DLL_IMPORT_OR_EXPORT std::unique_ptr<websocket::stream<beast::ssl_stream<tcp::socket>>>& ws() {
return ws_; }
75#elif BOOST_VERSION < 108600
76 FETPAPI_DLL_IMPORT_OR_EXPORT std::unique_ptr<websocket::stream<beast::ssl_stream<beast::tcp_stream>>>& ws() {
return ws_; }
78 FETPAPI_DLL_IMPORT_OR_EXPORT std::unique_ptr< websocket::stream<ssl::stream<beast::tcp_stream>>>& ws() {
return ws_; }
81 bool isTls()
const final {
return true; }
83 void asyncConnect(
const tcp::resolver::results_type& results)
85#if USE_WINTLS_INSTEAD_OF_OPENSSL
86 ws_.reset(
new websocket::stream<wintls::stream<beast::tcp_stream>>(ioc, sslContext_));
87#elif BOOST_VERSION < 107000
88 ws_.reset(
new websocket::stream<beast::ssl_stream<tcp::socket>>(ioc, sslContext_));
89#elif BOOST_VERSION < 108600
90 ws_.reset(
new websocket::stream<beast::ssl_stream<beast::tcp_stream>>(ioc, sslContext_));
92 ws_.reset(
new websocket::stream<ssl::stream<beast::tcp_stream>>(ioc, sslContext_));
96#if BOOST_VERSION < 107000
97 ws_->write_buffer_size(frameSize_);
99 ws_->write_buffer_bytes(frameSize_);
102#if USE_WINTLS_INSTEAD_OF_OPENSSL
104 ws_->next_layer().set_server_hostname(etpServerHost);
107 ws_->next_layer().set_certificate_revocation_check(
true);
110 if (!SSL_set_tlsext_host_name(ws_->next_layer().native_handle(), etpServerHost.data()))
112 boost::system::error_code ecSNI{
static_cast<int>(::ERR_get_error()), boost::asio::error::get_ssl_category() };
113 std::cerr <<
"Websocket on connect (SNI): " << ecSNI.message() << std::endl;
118#if BOOST_VERSION < 107300
119 ws_->next_layer().set_verify_callback(ssl::rfc2818_verification(etpServerHost));
121 ws_->next_layer().set_verify_callback(ssl::host_name_verification(etpServerHost));
126 std::vector<tcp::endpoint> endpoints = std::vector<tcp::endpoint>(results.begin(), results.end());
127 std::stable_partition(endpoints.begin(), endpoints.end(), [](
auto entry) {return entry.protocol() == tcp::v4(); });
130#if BOOST_VERSION < 107000
131 boost::asio::async_connect(
132 ws_->next_layer().next_layer(),
136 &SslClientSession::on_ssl_connect,
137 std::static_pointer_cast<SslClientSession>(shared_from_this()),
138 std::placeholders::_1));
140 beast::get_lowest_layer(*ws_).async_connect(
142 beast::bind_front_handler(
143 &SslClientSession::on_ssl_connect,
144 std::static_pointer_cast<SslClientSession>(shared_from_this())));
148#if BOOST_VERSION < 107000
149 void on_ssl_connect(boost::system::error_code ec)
151 void on_ssl_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type)
155 std::cerr <<
"on_ssl_connect : " << ec.message() << std::endl;
158 if (!proxyHost.empty()) {
159 proxyHandshake.version(11);
160 proxyHandshake.method(http::verb::connect);
161 proxyHandshake.target(etpServerHost +
':' + etpServerPort);
162 proxyHandshake.set(http::field::host, etpServerHost +
':' + etpServerPort);
163 if (!etpServerAuthorization.empty()) {
164 proxyHandshake.set(http::field::authorization, etpServerAuthorization);
166 if (!proxyAuthorization.empty()) {
167 proxyHandshake.set(http::field::proxy_authorization, proxyAuthorization);
171 http::async_write(ws_->next_layer().next_layer(), proxyHandshake,
174 std::static_pointer_cast<SslClientSession>(shared_from_this()),
175 std::placeholders::_1,
176 std::placeholders::_2));
180 ws_->next_layer().async_handshake(
181#
if USE_WINTLS_INSTEAD_OF_OPENSSL
182 wintls::handshake_type::client,
184 ssl::stream_base::client,
187 &AbstractClientSessionCRTP::on_ssl_handshake,
188 std::static_pointer_cast<AbstractClientSessionCRTP>(shared_from_this()),
189 std::placeholders::_1));
195 boost::system::error_code ec,
196 std::size_t bytes_transferred)
198 boost::ignore_unused(bytes_transferred);
201 std::cerr <<
"Proxy handshake write : " << ec.message() << std::endl;
217 http_proxy_handshake_parser.skip(
true);
220 http::async_read(ws_->next_layer().next_layer(), receivedBuffer, http_proxy_handshake_parser,
222 &SslClientSession::on_proxy_handshake_read,
223 std::static_pointer_cast<SslClientSession>(shared_from_this()),
224 std::placeholders::_1,
225 std::placeholders::_2));
229 on_proxy_handshake_read(
230 boost::system::error_code ec,
231 std::size_t bytes_transferred)
233 boost::ignore_unused(bytes_transferred);
235 std::cerr <<
"read : " << ec.message() << std::endl;
240 ws_->next_layer().async_handshake(
241#
if USE_WINTLS_INSTEAD_OF_OPENSSL
242 wintls::handshake_type::client,
244 ssl::stream_base::client,
247 &AbstractClientSessionCRTP::on_ssl_handshake,
248 std::static_pointer_cast<AbstractClientSessionCRTP>(shared_from_this()),
249 std::placeholders::_1));
253#if USE_WINTLS_INSTEAD_OF_OPENSSL
254 wintls::context sslContext_;
256 ssl::context sslContext_;
258#if USE_WINTLS_INSTEAD_OF_OPENSSL
259 std::unique_ptr<websocket::stream<wintls::stream<beast::tcp_stream>>> ws_;
260#elif BOOST_VERSION < 107000
261 std::unique_ptr<websocket::stream<beast::ssl_stream<tcp::socket>>> ws_;
262#elif BOOST_VERSION < 108600
263 std::unique_ptr<websocket::stream<beast::ssl_stream<beast::tcp_stream>>> ws_;
265 std::unique_ptr<websocket::stream<ssl::stream<beast::tcp_stream>>> ws_;
267 http::request<http::empty_body> proxyHandshake;
268 http::response<http::empty_body> proxyHandshakeResponse;
271 http::response_parser<http::empty_body> http_proxy_handshake_parser;
272 std::size_t frameSize_;