41 SocketClient(
const std::string &server_port_path,
bool verify_certificate =
true,
42 const std::string &certification_file = std::string(),
const std::string &private_key_file = std::string(),
43 const std::string &verify_file = std::string())
44 : SocketClientBase<
WSS>::SocketClientBase(server_port_path, 443),
45# if defined(ASIO_STANDALONE) && (ASIO_VERSION >= 101300 || BOOST_ASIO_VERSION >= 101300)
48 context.set_options(asio::ssl::context::no_tlsv1);
49 context.set_options(asio::ssl::context::no_tlsv1_1);
51 context(asio::ssl::context::tlsv12) {
54 if(certification_file.size() > 0 && private_key_file.size() > 0) {
55 context.use_certificate_chain_file(certification_file);
56 context.use_private_key_file(private_key_file, asio::ssl::context::pem);
59 if(verify_certificate) {
60# if defined(ASIO_STANDALONE) && (ASIO_VERSION >= 101300 || BOOST_ASIO_VERSION >= 101300)
61 context.set_verify_callback(asio::ssl::host_name_verification(host));
63 context.set_verify_callback(asio::ssl::rfc2818_verification(host));
67 if(verify_file.size() > 0) {
68 context.load_verify_file(verify_file);
74 if(verify_certificate) {
75 context.set_verify_mode(asio::ssl::verify_peer);
77 context.set_verify_mode(asio::ssl::verify_none);
88 X509_STORE* store = ::SSL_CTX_get_cert_store(
context.native_handle());
89 HCERTSTORE hCertStore = CertOpenSystemStore(0LL,
"ROOT");
94 PCCERT_CONTEXT certContext =
nullptr;
96 certContext = CertEnumCertificatesInStore(hCertStore, certContext);
100 X509* x509 = d2i_X509(
nullptr, (
const unsigned char**)&certContext->pbCertEncoded,
101 certContext->cbCertEncoded);
103 X509_STORE_add_cert(store, x509);
107 CertFreeCertificateContext(certContext);
108 CertCloseStore(hCertStore, 0);
120 LockGuard connection_lock(connection_mutex);
121 auto connection = this->connection = std::shared_ptr<Connection>(
new Connection(handler_runner, config.timeout_idle, *io_service,
context));
122 connection_lock.unlock();
124 std::pair<std::string, std::string> host_port;
125 if(config.proxy_server.empty())
126 host_port = {host, std::to_string(port)};
128 auto proxy_host_port = parse_host_port(config.proxy_server, 8080);
129 host_port = {proxy_host_port.first, std::to_string(proxy_host_port.second)};
132 auto resolver = std::make_shared<asio::ip::tcp::resolver>(*io_service);
133 connection->set_timeout(config.timeout_request);
134 async_resolve(*resolver, host_port, [
this, connection, resolver](
const error_code &ec, resolver_results results) {
135 connection->cancel_timeout();
136 auto lock = connection->handler_runner->continue_lock();
140 connection->set_timeout(this->config.timeout_request);
141 asio::async_connect(connection->socket->lowest_layer(), results, [
this, connection, resolver](
const error_code &ec, async_connect_endpoint ) {
142 connection->cancel_timeout();
143 auto lock = connection->handler_runner->continue_lock();
147 asio::ip::tcp::no_delay option(true);
149 connection->socket->lowest_layer().set_option(option, ec);
151 if(!this->config.proxy_server.empty()) {
152 auto streambuf = std::make_shared<asio::streambuf>();
153 std::ostream ostream(streambuf.get());
154 auto host_port = this->host +
':' + std::to_string(this->port);
155 ostream <<
"CONNECT " + host_port +
" HTTP/1.1\r\n"
156 <<
"Host: " << host_port <<
"\r\n";
157 if(!this->config.proxy_auth.empty())
158 ostream <<
"Proxy-Authorization: Basic " << Crypto::Base64::encode(this->config.proxy_auth) <<
"\r\n";
160 connection->set_timeout(this->config.timeout_request);
161 asio::async_write(connection->socket->next_layer(), *streambuf, [this, connection, streambuf](const error_code &ec, std::size_t ) {
162 connection->cancel_timeout();
163 auto lock = connection->handler_runner->continue_lock();
167 connection->set_timeout(this->config.timeout_request);
168 connection->in_message = std::shared_ptr<InMessage>(new InMessage());
169 asio::async_read_until(connection->socket->next_layer(), connection->in_message->streambuf,
"\r\n\r\n", [this, connection](const error_code &ec, std::size_t ) {
170 connection->cancel_timeout();
171 auto lock = connection->handler_runner->continue_lock();
175 if(!ResponseMessage::parse(*connection->in_message, connection->http_version, connection->status_code, connection->header))
176 this->connection_error(connection, make_error_code::make_error_code(errc::protocol_error));
178 if(connection->status_code.compare(0, 3,
"200") != 0)
179 this->connection_error(connection, make_error_code::make_error_code(errc::permission_denied));
181 this->handshake(connection);
184 this->connection_error(connection, ec);
187 this->connection_error(connection, ec);
190 this->handshake(connection);
192 this->connection_error(connection, ec);
195 this->connection_error(connection, ec);