// // sync_client.cpp // ~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #include #include #include #include #include #include using boost::asio::ip::tcp; namespace ssl = boost::asio::ssl; int main(int argc, char* argv[]) { try { if (argc != 3) { std::cout << "Usage: sync_client \n"; std::cout << "Example:\n"; std::cout << " sync_client www.boost.org /LICENSE_1_0.txt\n"; return 1; } boost::asio::io_service io_service; // Get a list of endpoints corresponding to the server name. tcp::resolver resolver(io_service); tcp::resolver::query query(argv[1], "https"); // <-- HTTPS tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); tcp::resolver::iterator end; // Try each endpoint until we successfully establish a connection. tcp::socket socket(io_service); boost::system::error_code error = boost::asio::error::host_not_found; while (error && endpoint_iterator != end) { socket.close(); socket.connect(*endpoint_iterator++, error); } if (error) throw boost::system::system_error(error); ssl::context ctx(io_service, ssl::context::sslv23_client); // <-- setup an ssl context ctx.set_verify_mode(ssl::context::verify_none); // <-- do not verify anything (for non-cdertified ssl keys) ssl::stream ssl_sock(socket, ctx); // <-- setup an ssl socket stream based on the socket we already have connected ssl_sock.handshake(ssl::stream_base::client, error); // <-- This is left out in the documentation (Overview/SSL): do not forget the handshake if (error) throw boost::system::system_error(error); // Form the request. We specify the "Connection: close" header so that the // server will close the socket after transmitting the response. This will // allow us to treat all data up until the EOF as the content. boost::asio::streambuf request; std::ostream request_stream(&request); request_stream << "GET " << argv[2] << " HTTP/1.0\r\n"; request_stream << "Host: " << argv[1] << "\r\n"; request_stream << "Accept: */*\r\n"; request_stream << "Connection: close\r\n\r\n"; // Send the request. boost::asio::write(ssl_sock, request); // <-- write to the ssl stream // Read the response status line. boost::asio::streambuf response; boost::asio::read_until(ssl_sock, response, "\r\n"); // <-- read from the ssl stream // Check that response is OK. std::istream response_stream(&response); std::string http_version; response_stream >> http_version; unsigned int status_code; response_stream >> status_code; std::string status_message; std::getline(response_stream, status_message); if (!response_stream || http_version.substr(0, 5) != "HTTP/") { std::cout << "Invalid response\n"; return 1; } if (false && status_code != 200) // <-- show content of other codes, too, e.g. 302 { std::cout << "Response returned with status code " << status_code << "\n"; return 1; } // Read the response headers, which are terminated by a blank line. boost::asio::read_until(ssl_sock, response, "\r\n\r\n"); // <-- read from the ssl stream // Process the response headers. std::string header; while (std::getline(response_stream, header) && header != "\r") std::cout << header << "\n"; std::cout << "\n"; // Write whatever content we already have to output. if (response.size() > 0) std::cout << &response; // Read until EOF, writing data to output as we go. while (boost::asio::read(ssl_sock, response, // <<-- read from the ssl stream boost::asio::transfer_at_least(1), error)) std::cout << &response; if (error != boost::asio::error::eof && error != boost::asio::error::shut_down) // <-- instead of eof, we probably stumble over shutdown by the server throw boost::system::system_error(error); } catch (std::exception& e) { std::cout << "Exception: " << e.what() << "\n"; } return 0; }