diff options
Diffstat (limited to 'src/net')
-rw-r--r-- | src/net/CMakeLists.txt | 4 | ||||
-rw-r--r-- | src/net/http.cpp | 70 | ||||
-rw-r--r-- | src/net/http.h | 51 | ||||
-rw-r--r-- | src/net/parse.cpp | 35 | ||||
-rw-r--r-- | src/net/parse.h | 3 | ||||
-rw-r--r-- | src/net/zmq.cpp | 14 | ||||
-rw-r--r-- | src/net/zmq.h | 22 |
7 files changed, 183 insertions, 16 deletions
diff --git a/src/net/CMakeLists.txt b/src/net/CMakeLists.txt index 1ce7118ad..afcd42ef7 100644 --- a/src/net/CMakeLists.txt +++ b/src/net/CMakeLists.txt @@ -26,9 +26,9 @@ # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -set(net_sources dandelionpp.cpp error.cpp i2p_address.cpp parse.cpp socks.cpp +set(net_sources dandelionpp.cpp error.cpp http.cpp i2p_address.cpp parse.cpp socks.cpp socks_connect.cpp tor_address.cpp zmq.cpp) -set(net_headers dandelionpp.h error.h i2p_address.h parse.h socks.h socks_connect.h +set(net_headers dandelionpp.h error.h http.cpp i2p_address.h parse.h socks.h socks_connect.h tor_address.h zmq.h) monero_add_library(net ${net_sources} ${net_headers}) diff --git a/src/net/http.cpp b/src/net/http.cpp new file mode 100644 index 000000000..f54b65c29 --- /dev/null +++ b/src/net/http.cpp @@ -0,0 +1,70 @@ +// Copyright (c) 2020, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "http.h" + +#include "parse.h" +#include "socks_connect.h" + +namespace net +{ +namespace http +{ + +bool client::set_proxy(const std::string &address) +{ + if (address.empty()) + { + set_connector(epee::net_utils::direct_connect{}); + } + else + { + const auto endpoint = get_tcp_endpoint(address); + if (!endpoint) + { + auto always_fail = net::socks::connector{boost::asio::ip::tcp::endpoint()}; + set_connector(always_fail); + } + else + { + set_connector(net::socks::connector{*endpoint}); + } + } + + disconnect(); + + return true; +} + +std::unique_ptr<epee::net_utils::http::abstract_http_client> client_factory::create() +{ + return std::unique_ptr<epee::net_utils::http::abstract_http_client>(new client()); +} + +} // namespace http +} // namespace net diff --git a/src/net/http.h b/src/net/http.h new file mode 100644 index 000000000..91a345851 --- /dev/null +++ b/src/net/http.h @@ -0,0 +1,51 @@ +// Copyright (c) 2020, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#pragma once + +#include "net/http_client.h" + +namespace net +{ +namespace http +{ + +class client : public epee::net_utils::http::http_simple_client +{ +public: + bool set_proxy(const std::string &address) override; +}; + +class client_factory : public epee::net_utils::http::http_client_factory +{ +public: + std::unique_ptr<epee::net_utils::http::abstract_http_client> create() override; +}; + +} // namespace http +} // namespace net diff --git a/src/net/parse.cpp b/src/net/parse.cpp index ce580afe7..95b22cd44 100644 --- a/src/net/parse.cpp +++ b/src/net/parse.cpp @@ -122,4 +122,39 @@ namespace net return {epee::net_utils::ipv4_network_subnet{ip, (uint8_t)mask}}; } + + expect<boost::asio::ip::tcp::endpoint> get_tcp_endpoint(const boost::string_ref address) + { + uint16_t port = 0; + expect<epee::net_utils::network_address> parsed = get_network_address(address, port); + if (!parsed) + { + return parsed.error(); + } + + boost::asio::ip::tcp::endpoint result; + switch (parsed->get_type_id()) + { + case epee::net_utils::ipv4_network_address::get_type_id(): + { + const auto &ipv4 = parsed->as<epee::net_utils::ipv4_network_address>(); + result = boost::asio::ip::tcp::endpoint(boost::asio::ip::address_v4(ipv4.ip()), ipv4.port()); + break; + } + case epee::net_utils::ipv6_network_address::get_type_id(): + { + const auto &ipv6 = parsed->as<epee::net_utils::ipv6_network_address>(); + result = boost::asio::ip::tcp::endpoint(ipv6.ip(), ipv6.port()); + break; + } + default: + return make_error_code(net::error::unsupported_address); + } + if (result.port() == 0) + { + return make_error_code(net::error::invalid_port); + } + + return result; + } } diff --git a/src/net/parse.h b/src/net/parse.h index 0d8fda711..4d5efe161 100644 --- a/src/net/parse.h +++ b/src/net/parse.h @@ -28,6 +28,7 @@ #pragma once +#include <boost/asio/ip/tcp.hpp> #include <boost/utility/string_ref.hpp> #include <cstdint> @@ -65,5 +66,7 @@ namespace net */ expect<epee::net_utils::ipv4_network_subnet> get_ipv4_subnet_address(boost::string_ref address, bool allow_implicit_32 = false); + + expect<boost::asio::ip::tcp::endpoint> get_tcp_endpoint(const boost::string_ref address); } diff --git a/src/net/zmq.cpp b/src/net/zmq.cpp index 1a0edb4b9..15560ca7e 100644 --- a/src/net/zmq.cpp +++ b/src/net/zmq.cpp @@ -158,20 +158,6 @@ namespace zmq return unsigned(max_out) < added ? max_out : int(added); } }; - - template<typename F, typename... T> - expect<void> retry_op(F op, T&&... args) noexcept(noexcept(op(args...))) - { - for (;;) - { - if (0 <= op(args...)) - return success(); - - const int error = zmq_errno(); - if (error != EINTR) - return make_error_code(error); - } - } } // anonymous expect<std::string> receive(void* const socket, const int flags) diff --git a/src/net/zmq.h b/src/net/zmq.h index 8c587ed7c..fa4ef2fc9 100644 --- a/src/net/zmq.h +++ b/src/net/zmq.h @@ -26,6 +26,8 @@ // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#pragma once + #include <memory> #include <string> #include <system_error> @@ -105,6 +107,26 @@ namespace zmq //! Unique ZMQ socket handle, calls `zmq_close` on destruction. using socket = std::unique_ptr<void, close>; + /*! Retry a ZMQ function on `EINTR` errors. `F` must return an int with + values less than 0 on error. + + \param op The ZMQ function to execute + retry + \param args Forwarded to `op`. Must be resuable in case of retry. + \return All errors except for `EINTR`. */ + template<typename F, typename... T> + expect<void> retry_op(F op, T&&... args) noexcept(noexcept(op(args...))) + { + for (;;) + { + if (0 <= op(args...)) + return success(); + + const int error = zmq_errno(); + if (error != EINTR) + return make_error_code(error); + } + } + /*! Read all parts of the next message on `socket`. Blocks until the entire next message (all parts) are read, or until `zmq_term` is called on the `zmq_context` associated with `socket`. If the context is terminated, |