Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / ot-br-posix / repo / third_party / Simple-web-server / repo / client_https.hpp
1 #ifndef CLIENT_HTTPS_HPP
2 #define CLIENT_HTTPS_HPP
3
4 #include "client_http.hpp"
5 #include <boost/asio/ssl.hpp>
6
7 namespace SimpleWeb {
8     typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> HTTPS;
9     
10     template<>
11     class Client<HTTPS> : public ClientBase<HTTPS> {
12     public:
13         Client(const std::string& server_port_path, bool verify_certificate=true, 
14                 const std::string& cert_file=std::string(), const std::string& private_key_file=std::string(), 
15                 const std::string& verify_file=std::string()) : 
16                 ClientBase<HTTPS>::ClientBase(server_port_path, 443), context(boost::asio::ssl::context::tlsv12) {
17             if(cert_file.size()>0 && private_key_file.size()>0) {
18                 context.use_certificate_chain_file(cert_file);
19                 context.use_private_key_file(private_key_file, boost::asio::ssl::context::pem);
20             }
21             
22             if(verify_certificate)
23                 context.set_verify_callback(boost::asio::ssl::rfc2818_verification(host));
24             
25             if(verify_file.size()>0)
26                 context.load_verify_file(verify_file);
27             else
28                 context.set_default_verify_paths();
29             
30             if(verify_file.size()>0 || verify_certificate)
31                 context.set_verify_mode(boost::asio::ssl::verify_peer);
32             else
33                 context.set_verify_mode(boost::asio::ssl::verify_none);
34         }
35
36     protected:
37         boost::asio::ssl::context context;
38         
39         void connect() {
40             if(!socket || !socket->lowest_layer().is_open()) {
41                 std::unique_ptr<boost::asio::ip::tcp::resolver::query> query;
42                 if(config.proxy_server.empty())
43                     query=std::unique_ptr<boost::asio::ip::tcp::resolver::query>(new boost::asio::ip::tcp::resolver::query(host, std::to_string(port)));
44                 else {
45                     auto proxy_host_port=parse_host_port(config.proxy_server, 8080);
46                     query=std::unique_ptr<boost::asio::ip::tcp::resolver::query>(new boost::asio::ip::tcp::resolver::query(proxy_host_port.first, std::to_string(proxy_host_port.second)));
47                 }
48                 resolver.async_resolve(*query, [this]
49                                        (const boost::system::error_code &ec, boost::asio::ip::tcp::resolver::iterator it){
50                     if(!ec) {
51                         {
52                             std::lock_guard<std::mutex> lock(socket_mutex);
53                             socket=std::unique_ptr<HTTPS>(new HTTPS(io_service, context));
54                         }
55                         
56                         auto timer=get_timeout_timer(config.timeout_connect);
57                         boost::asio::async_connect(socket->lowest_layer(), it, [this, timer]
58                                                    (const boost::system::error_code &ec, boost::asio::ip::tcp::resolver::iterator /*it*/){
59                             if(timer)
60                                 timer->cancel();
61                             if(!ec) {
62                                 boost::asio::ip::tcp::no_delay option(true);
63                                 this->socket->lowest_layer().set_option(option);
64                             }
65                             else {
66                                 std::lock_guard<std::mutex> lock(socket_mutex);
67                                 this->socket=nullptr;
68                                 throw boost::system::system_error(ec);
69                             }
70                         });
71                     }
72                     else {
73                         std::lock_guard<std::mutex> lock(socket_mutex);
74                         socket=nullptr;
75                         throw boost::system::system_error(ec);
76                     }
77                 });
78                 io_service.reset();
79                 io_service.run();
80                 
81                 if(!config.proxy_server.empty()) {
82                     boost::asio::streambuf write_buffer;
83                     std::ostream write_stream(&write_buffer);
84                     auto host_port=host+':'+std::to_string(port);
85                     write_stream << "CONNECT "+host_port+" HTTP/1.1\r\n" << "Host: " << host_port << "\r\n\r\n";
86                     auto timer=get_timeout_timer();
87                     boost::asio::async_write(socket->next_layer(), write_buffer,
88                                              [this, timer](const boost::system::error_code &ec, size_t /*bytes_transferred*/) {
89                         if(timer)
90                             timer->cancel();
91                         if(ec) {
92                             std::lock_guard<std::mutex> lock(socket_mutex);
93                             socket=nullptr;
94                             throw boost::system::system_error(ec);
95                         }
96                     });
97                     io_service.reset();
98                     io_service.run();
99                     
100                     std::shared_ptr<Response> response(new Response());
101                     timer=get_timeout_timer();
102                     boost::asio::async_read_until(socket->next_layer(), response->content_buffer, "\r\n\r\n",
103                                                   [this, timer](const boost::system::error_code& ec, size_t /*bytes_transferred*/) {
104                         if(timer)
105                             timer->cancel();
106                         if(ec) {
107                             std::lock_guard<std::mutex> lock(socket_mutex);
108                             socket=nullptr;
109                             throw boost::system::system_error(ec);
110                         }
111                     });
112                     io_service.reset();
113                     io_service.run();
114                     parse_response_header(response);
115                     if (response->status_code.empty() || response->status_code.compare(0, 3, "200") != 0) {
116                         std::lock_guard<std::mutex> lock(socket_mutex);
117                         socket=nullptr;
118                         throw boost::system::system_error(boost::system::error_code(boost::system::errc::permission_denied, boost::system::generic_category()));
119                     }
120                 }
121                 
122                 auto timer=get_timeout_timer();
123                 this->socket->async_handshake(boost::asio::ssl::stream_base::client,
124                                               [this, timer](const boost::system::error_code& ec) {
125                     if(timer)
126                         timer->cancel();
127                     if(ec) {
128                         std::lock_guard<std::mutex> lock(socket_mutex);
129                         socket=nullptr;
130                         throw boost::system::system_error(ec);
131                     }
132                 });
133                 io_service.reset();
134                 io_service.run();
135             }
136         }
137     };
138 }
139
140 #endif  /* CLIENT_HTTPS_HPP */