diff options
-rw-r--r-- | doc/relnotes/1_11_6.rst | 3 | ||||
-rw-r--r-- | src/build-data/cc/gcc.txt | 2 | ||||
-rw-r--r-- | src/libstate/info.txt | 4 | ||||
-rw-r--r-- | src/utils/http_get/http_get.cpp | 95 | ||||
-rw-r--r-- | src/utils/http_get/http_get.h | 34 | ||||
-rw-r--r-- | src/utils/http_get/info.txt | 3 |
6 files changed, 139 insertions, 2 deletions
diff --git a/doc/relnotes/1_11_6.rst b/doc/relnotes/1_11_6.rst index a776411fd..84d081d5c 100644 --- a/doc/relnotes/1_11_6.rst +++ b/doc/relnotes/1_11_6.rst @@ -1,5 +1,6 @@ Version 1.11.6, Not Yet Released ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - * Add HKDF from :rfc:`5869` + * Botan now requires Boost, specifically the filesystem and asio libraries. + * Add HKDF from :rfc:`5869` diff --git a/src/build-data/cc/gcc.txt b/src/build-data/cc/gcc.txt index 3a12c64ed..ed425ca84 100644 --- a/src/build-data/cc/gcc.txt +++ b/src/build-data/cc/gcc.txt @@ -9,7 +9,7 @@ add_lib_dir_option -L add_lib_option -l lang_flags "-D_REENTRANT -std=c++11" -warning_flags "-Werror -Wno-error=old-style-cast -Wall -Wextra -Wstrict-aliasing -Wstrict-overflow=5 -Wcast-align -Wmissing-declarations -Wpointer-arith -Wcast-qual -Wold-style-cast -Wzero-as-null-pointer-constant" +warning_flags "-Werror -Wno-error=old-style-cast -Wno-error=zero-as-null-pointer-constant -Wall -Wextra -Wstrict-aliasing -Wstrict-overflow=5 -Wcast-align -Wmissing-declarations -Wpointer-arith -Wcast-qual -Wold-style-cast -Wzero-as-null-pointer-constant" lib_opt_flags "-O3" check_opt_flags "-O2" diff --git a/src/libstate/info.txt b/src/libstate/info.txt index 49a6d38ee..7e2bac6ee 100644 --- a/src/libstate/info.txt +++ b/src/libstate/info.txt @@ -19,3 +19,7 @@ pubkey rng stream </requires> + +<libs> +all -> boost_system,boost_filesystem +</libs> diff --git a/src/utils/http_get/http_get.cpp b/src/utils/http_get/http_get.cpp new file mode 100644 index 000000000..a6069c861 --- /dev/null +++ b/src/utils/http_get/http_get.cpp @@ -0,0 +1,95 @@ +/* +* HTTP GET function +* (C) 2013 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/http_get.h> +#include <botan/parsing.h> +#include <boost/asio.hpp> + +namespace Botan { + +http_response sync_http_get(const std::string& url, std::chrono::milliseconds timeout) + { + using namespace boost::asio::ip; + + const auto protocol_host_sep = url.find("://"); + const auto host_loc_sep = url.find('/', protocol_host_sep + 3); + + if(protocol_host_sep == std::string::npos || host_loc_sep == std::string::npos) + throw std::runtime_error("Invalid URL " + url); + + const std::string protocol = url.substr(0, protocol_host_sep); + const std::string hostname = url.substr(protocol_host_sep+3, host_loc_sep-protocol_host_sep-3); + const std::string loc = url.substr(host_loc_sep, std::string::npos); + + if(protocol != "http") + throw std::runtime_error("Unsupported protocol " + protocol); + + tcp::iostream sock; + + if(timeout.count()) + sock.expires_from_now(boost::posix_time::milliseconds(timeout.count())); + + sock.connect(hostname, protocol); + if(!sock) + throw std::runtime_error("Connection to " + hostname + " / " + protocol + " failed"); + + sock << "GET " << loc << " HTTP/1.0\r\n"; + sock << "Host: " << hostname << "\r\n"; + sock << "Accept: */*\r\n"; + sock << "Cache-Control: no-cache\r\n"; + sock << "Connection: close\r\n\r\n"; + sock.flush(); + + std::string line1; + std::getline(sock, line1); + if(!sock) + throw std::runtime_error("No response"); + + std::stringstream response_stream(line1); + std::string http_version; + unsigned int status_code; + std::string status_message; + + response_stream >> http_version >> status_code; + + std::getline(response_stream, status_message); + + if(!response_stream || http_version.substr(0,5) != "HTTP/") + throw std::runtime_error("Not an HTTP response"); + + std::map<std::string, std::string> headers; + std::string header_line; + while (std::getline(sock, header_line) && header_line != "\r") + { + auto sep = header_line.find(": "); + if(sep == std::string::npos || sep > header_line.size() - 2) + throw std::runtime_error("Invalid HTTP header " + header_line); + const std::string key = header_line.substr(0, sep); + const std::string val = header_line.substr(sep + 2, std::string::npos); + headers[key] = val; + } + + if(status_code == 301 && headers.count("Location")) + return sync_http_get(headers["Location"], timeout); + + std::vector<byte> body; + std::vector<byte> buf(4096); + while(sock.good()) + { + sock.read(reinterpret_cast<char*>(&buf[0]), buf.size()); + body.insert(body.end(), &buf[0], &buf[sock.gcount()]); + } + + return http_response { status_code, body, headers }; + } + +std::future<http_response> async_http_get(const std::string& url) + { + return std::async(std::launch::async, sync_http_get, url, std::chrono::seconds(3)); + } + +} diff --git a/src/utils/http_get/http_get.h b/src/utils/http_get/http_get.h new file mode 100644 index 000000000..68ee2f85c --- /dev/null +++ b/src/utils/http_get/http_get.h @@ -0,0 +1,34 @@ +/* +* HTTP GET function +* (C) 2013 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/types.h> +#include <future> +#include <vector> +#include <map> +#include <chrono> +#include <string> + +#ifndef BOTAN_UTILS_URLGET_H__ +#define BOTAN_UTILS_URLGET_H__ + +namespace Botan { + +struct http_response + { + unsigned int status_code; + std::vector<byte> body; + std::map<std::string, std::string> headers; + }; + +BOTAN_DLL http_response sync_http_get(const std::string& url, + std::chrono::milliseconds timeout); + +BOTAN_DLL std::future<http_response> BOTAN_DLL async_http_get(const std::string& url); + +} + +#endif diff --git a/src/utils/http_get/info.txt b/src/utils/http_get/info.txt new file mode 100644 index 000000000..ab36a6b95 --- /dev/null +++ b/src/utils/http_get/info.txt @@ -0,0 +1,3 @@ +define HTTP_GET + +load_on auto |