How to create a boost ssl iostream?

前端 未结 3 1575
无人共我
无人共我 2020-12-08 00:47

I\'m adding HTTPS support to code that does input and output using boost tcp::iostream (acting as an HTTP server).

I\'ve found examples (and have a working toy HTTPS

3条回答
  •  -上瘾入骨i
    2020-12-08 01:31

    ssl::stream could be wrapped with boost::iostreams / bidirectional to mimic similar behaviours as tcp::iostream. flushing output before further reading seems cannot be avoided.

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    namespace bios = boost::iostreams;
    namespace asio = boost::asio;
    namespace ssl = boost::asio::ssl;
    
    using std::string;
    using boost::asio::ip::tcp;
    using boost::system::system_error;
    using boost::system::error_code;
    
    int parse_url(const std::string &s,
        std::string& proto, std::string& host, std::string& path)
    {
        std::smatch m;
        bool found = regex_search(s, m, std::regex("^(http[s]?)://([^/]*)(.*)$"));
        if (m.size() != 4)
            return -1;
        proto = m[1].str();
        host = m[2].str();
        path = m[3].str();
        return 0;
    }
    
    void get_page(std::iostream& s, const string& host, const string& path)
    { 
        s << "GET " <<  path << " HTTP/1.0\r\n"
            << "Host: " << host << "\r\n"
            << "Accept: */*\r\n"
            << "Connection: close\r\n\r\n" << std::flush;
    
        std::cout << s.rdbuf() << std::endl;;
    }
    
    typedef ssl::stream ssl_socket;
    class ssl_wrapper : public bios::device
    {
        ssl_socket& sock;
    public:
        typedef char char_type;
    
        ssl_wrapper(ssl_socket& sock) : sock(sock) {}
    
        std::streamsize read(char_type* s, std::streamsize n) {
            error_code ec;          
            auto rc = asio::read(sock, asio::buffer(s,n), ec);
            return rc;
        }
        std::streamsize write(const char_type* s, std::streamsize n) {
            return asio::write(sock, asio::buffer(s,n));
        }
    };
    
    int main(int argc, char* argv[])
    {
        std::string proto, host, path;
        if (argc!= 2 || parse_url(argv[1], proto, host, path)!=0)
            return EXIT_FAILURE;
        try {
            if (proto != "https") {
                tcp::iostream s(host, proto);
                s.expires_from_now(boost::posix_time::seconds(60));
                get_page(s, host, path);
            } else {
                asio::io_service ios;
    
                tcp::resolver resolver(ios);
                tcp::resolver::query query(host, "https");
                tcp::resolver::iterator endpoint_iterator = 
                   resolver.resolve(query);
    
                ssl::context ctx(ssl::context::sslv23);
                ctx.set_default_verify_paths();
                ssl_socket socket(ios, ctx);
    
                asio::connect(socket.lowest_layer(), endpoint_iterator);
    
                socket.set_verify_mode(ssl::verify_none);
                socket.set_verify_callback(ssl::rfc2818_verification(host));
                socket.handshake(ssl_socket::client);
    
                bios::stream ss(socket);
                get_page(ss, host, path);
            }
        } catch (const std::exception& e) {
            std::cout << "Exception: " << e.what() << "\n";
        }
    }
    

提交回复
热议问题