37#include <boost/version.hpp>
38#include <boost/asio/io_context.hpp>
39#include <boost/asio/ip/tcp.hpp>
40#include <boost/asio/post.hpp>
41#include <boost/asio/read.hpp>
42#include <boost/asio/ssl.hpp>
43#include <boost/asio/steady_timer.hpp>
44#include <boost/thread/future.hpp>
45#include <boost/lambda/bind.hpp>
46#include <boost/lambda/lambda.hpp>
47#include <boost/system/error_code.hpp>
48#include <boost/utility/string_ref.hpp>
50#ifdef BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR
51#include <boost/asio/posix/stream_descriptor.hpp>
61#undef MONERO_DEFAULT_LOG_CATEGORY
62#define MONERO_DEFAULT_LOG_CATEGORY "net"
65#define MAKE_IP( a1, a2, a3, a4 ) (a1|(a2<<8)|(a3<<16)|(a4<<24))
75 boost::unique_future<boost::asio::ip::tcp::socket>
76 operator()(
const std::string& addr,
const std::string& port, boost::asio::steady_timer&)
const;
102 std::size_t bytes_transferred
121#ifdef BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR
130#ifdef BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR
134 if (0 != ::pipe(fds))
135 throw std::runtime_error(
"failed to create shutdown wake pipe");
136 bool flags_set =
true;
137 for (
const int fd : fds)
139 if (-1 == ::fcntl(
fd, F_SETFL, O_NONBLOCK) || -1 == ::fcntl(
fd, F_SETFD, FD_CLOEXEC))
142 boost::system::error_code ec;
144 m_wake_reader.assign(fds[0], ec);
145 if (!flags_set || ec)
149 throw std::runtime_error(
"failed to set up shutdown wake pipe");
151 m_wake_writer = fds[1];
170 using connect_func = boost::unique_future<boost::asio::ip::tcp::socket>(
const std::string&,
const std::string&, boost::asio::steady_timer&);
178#ifdef BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR
179 if (m_wake_writer != -1)
180 ::close(m_wake_writer);
189 m_ctx = boost::asio::ssl::context(boost::asio::ssl::context::tlsv12);
194 bool connect(
const std::string& addr,
int port, std::chrono::milliseconds timeout)
196 return connect(addr, std::to_string(port), timeout);
202 const auto deadline = std::chrono::steady_clock::now() + timeout;
223 boost::system::error_code ignored_ec;
230 m_deadline.expires_at(std::chrono::steady_clock::time_point::max());
243 boost::system::error_code ignored_ec;
244 m_ssl_socket->next_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec);
251 MWARNING(
"Failed to establish SSL connection");
262 boost::system::error_code ignored_ec;
269 MWARNING(
"Some problems at connect, expected open socket");
276 bool connect(
const std::string& addr,
const std::string& port, std::chrono::milliseconds timeout)
299 MERROR(
"SSL handshake failed on an autodetect connection, reconnecting without SSL");
306 catch(
const boost::system::system_error& er)
308 MDEBUG(
"Some problems at connect, message: " << er.what());
313 MDEBUG(
"Some fatal problems.");
336 boost::system::error_code ignored_ec;
337 m_ssl_socket->next_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec);
342 catch(
const boost::system::system_error& )
357 bool send(
const boost::string_ref buff, std::chrono::milliseconds timeout)
368 boost::system::error_code ec = boost::asio::error::would_block;
385 if (ec == boost::asio::error::would_block)
387 boost::system::error_code ignored_ec;
389 while (ec == boost::asio::error::would_block)
398 LOG_PRINT_L3(
"Problems at write: " << ec.message());
403 m_deadline.expires_at(std::chrono::steady_clock::time_point::max());
408 catch(
const boost::system::system_error& er)
410 LOG_ERROR(
"Some problems at connect, message: " << er.what());
415 LOG_ERROR(
"Some fatal problems.");
449 boost::system::error_code ec;
455 LOG_PRINT_L3(
"Problems at write: " << ec.message());
460 m_deadline.expires_at(std::chrono::steady_clock::time_point::max());
465 catch(
const boost::system::system_error& er)
467 LOG_ERROR(
"Some problems at send, message: " << er.what());
473 LOG_ERROR(
"Some fatal problems.");
485 boost::system::error_code ec;
491 const auto pending = std::make_shared<pending_read>();
494 socket->async_read_some(boost::asio::buffer(&pending->byte, 1),
495 [socket, pending](
const boost::system::error_code& error,
size_t) {
496 pending->error = error;
497 if (pending->handler)
499 auto handler = std::move(pending->handler);
500 handler(error, pending->byte);
513 const bool non_blocking = socket.non_blocking();
514 socket.non_blocking(
true, ec);
518 socket.receive(boost::asio::buffer(&
byte, 1), boost::asio::ip::tcp::socket::message_peek, ec);
519 boost::system::error_code restore_error;
520 socket.non_blocking(non_blocking, restore_error);
528 if (ec && ec != boost::asio::error::would_block &&
529 ec != boost::asio::error::try_again && ec != boost::asio::error::interrupted)
531 MDEBUG(
"Peer closed idle connection, marking disconnected: " << ec.message());
542 bool recv(std::string& buff, std::chrono::milliseconds timeout)
563 boost::system::error_code ec = boost::asio::error::would_block;
564 size_t bytes_transfered = 0;
568 static const size_t max_size = 16384;
569 buff.resize(max_size);
571 async_read(&buff[0], max_size, boost::asio::transfer_at_least(1), hndlr);
582 if (ec == boost::asio::error::would_block)
584 boost::system::error_code ignored_ec;
586 while (ec == boost::asio::error::would_block)
596 MTRACE(
"READ ENDS: Connection err_code " << ec.value());
597 if(ec == boost::asio::error::eof)
599 MTRACE(
"Connection err_code eof.");
605 MDEBUG(
"Problems at read: " << ec.message());
609 MTRACE(
"READ ENDS: Success. bytes_tr: " << bytes_transfered);
610 m_deadline.expires_at(std::chrono::steady_clock::time_point::max());
617 buff.resize(bytes_transfered);
621 catch(
const boost::system::system_error& er)
623 LOG_ERROR(
"Some problems at read, message: " << er.what());
629 LOG_ERROR(
"Some fatal problems at read.");
639 inline bool recv_n(std::string& buff,
int64_t sz, std::chrono::milliseconds timeout)
661 buff.resize(
static_cast<size_t>(sz));
662 boost::system::error_code ec = boost::asio::error::would_block;
663 size_t bytes_transfered = 0;
667 async_read((
char*)buff.data(), buff.size(), boost::asio::transfer_at_least(buff.size()), hndlr);
677 if (ec == boost::asio::error::would_block)
679 boost::system::error_code ignored_ec;
681 while (ec == boost::asio::error::would_block)
690 LOG_PRINT_L3(
"Problems at read: " << ec.message());
695 m_deadline.expires_at(std::chrono::steady_clock::time_point::max());
699 if(bytes_transfered != buff.size())
701 LOG_ERROR(
"Transferred mismatch with transfer_at_least value: m_bytes_transferred=" << bytes_transfered <<
" at_least value=" << buff.size());
708 catch(
const boost::system::system_error& er)
710 LOG_ERROR(
"Some problems at read, message: " << er.what());
716 LOG_ERROR(
"Some fatal problems at read.");
731#ifdef BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR
733 const int saved_errno = errno;
735 while (
::write(m_wake_writer, &wake, 1) == -1 && errno == EINTR) {}
769 boost::system::error_code
error = boost::asio::error::would_block;
770 std::function<void(
const boost::system::error_code&,
char)>
handler;
778#ifdef BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR
782 m_wake_reader.async_read_some(boost::asio::buffer(m_wake_buf),
783 [
this] (
const boost::system::error_code& ec, std::size_t) {
if (!ec) wait_wake(); });
792 if (
m_deadline.expiry() <= std::chrono::steady_clock::now())
797 LOG_PRINT_L3(
"Timed out socket");
803 m_deadline.expires_at(std::chrono::steady_clock::time_point::max());
812 boost::system::error_code ec = boost::asio::error::would_block;
813 m_deadline.expires_after(std::chrono::milliseconds(2000));
814 m_ssl_socket->async_shutdown(boost::lambda::var(ec) = boost::lambda::_1);
815 while (ec == boost::asio::error::would_block)
821 if (ec.category() == boost::asio::error::get_ssl_category() &&
823#
if BOOST_VERSION >= 106200
824 boost::asio::ssl::error::stream_truncated
826 ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ)
829 MDEBUG(
"Problems at ssl shutdown: " << ec.message());
833 bool write(
const void*
data,
size_t sz, boost::system::error_code& ec)
846 boost::asio::async_write(*
m_ssl_socket, boost::asio::buffer(
data, sz), boost::lambda::var(ec) = boost::lambda::_1);
848 boost::asio::async_write(
m_ssl_socket->next_layer(), boost::asio::buffer(
data, sz), boost::lambda::var(ec) = boost::lambda::_1);
851 void async_read(
char* buff,
size_t sz, boost::asio::detail::transfer_at_least_t transfer_at_least,
handler_obj& hndlr)
857 auto on_read = [socket =
m_ssl_socket, buff, sz, transfer_at_least, hndlr]
858 (
const boost::system::error_code& error,
char byte)
mutable {
865 if (!transfer_at_least(error, 1) || sz == 1)
868 boost::asio::async_read(*socket, boost::asio::buffer(buff + 1, sz - 1),
869 [transfer_at_least](
const boost::system::error_code& ec,
size_t bytes)
mutable {
870 return transfer_at_least(ec, bytes + 1);
872 [hndlr](
const boost::system::error_code& ec,
size_t bytes)
mutable { hndlr(ec, bytes + 1); });
874 if (pending->error == boost::asio::error::would_block)
875 pending->handler = std::move(on_read);
877 if (pending->error != boost::asio::error::would_block)
878 on_read(pending->error, pending->byte);
882 boost::asio::async_read(
m_ssl_socket->next_layer(), boost::asio::buffer(buff, sz), transfer_at_least, hndlr);
884 boost::asio::async_read(*
m_ssl_socket, boost::asio::buffer(buff, sz), transfer_at_least, hndlr);
891 std::shared_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>
m_ssl_socket;
898#ifdef BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR
900 boost::asio::posix::stream_descriptor m_wake_reader;
#define fd(x)
Definition aesb.c:127
bool shutdown_requested() const
Definition net_helper.h:773
uint64_t get_bytes_received() const
Definition net_helper.h:759
boost::asio::steady_timer m_deadline
Definition net_helper.h:897
boost::unique_future< boost::asio::ip::tcp::socket >(const std::string &, const std::string &, boost::asio::steady_timer &) connect_func
Definition net_helper.h:170
void async_read(char *buff, size_t sz, boost::asio::detail::transfer_at_least_t transfer_at_least, handler_obj &hndlr)
Definition net_helper.h:851
uint64_t get_bytes_sent() const
Definition net_helper.h:754
bool shutdown()
Definition net_helper.h:725
bool connect(const std::string &addr, const std::string &port, std::chrono::milliseconds timeout)
Definition net_helper.h:276
bool write(const void *data, size_t sz, boost::system::error_code &ec)
Definition net_helper.h:833
try_connect_result_t try_connect(const std::string &addr, const std::string &port, std::chrono::milliseconds timeout)
Definition net_helper.h:200
void set_connector(std::function< connect_func > connector)
Change the connection routine (proxy, etc.).
Definition net_helper.h:320
bool recv(std::string &buff, std::chrono::milliseconds timeout)
Definition net_helper.h:542
void shutdown_ssl()
Definition net_helper.h:810
bool recv_n(std::string &buff, int64_t sz, std::chrono::milliseconds timeout)
Definition net_helper.h:639
void async_write(const void *data, size_t sz, boost::system::error_code &ec)
Definition net_helper.h:843
std::shared_ptr< pending_read > m_pending_read
Definition net_helper.h:892
void check_deadline()
Definition net_helper.h:787
~blocked_mode_client()
Definition net_helper.h:173
std::atomic< uint64_t > m_bytes_received
Definition net_helper.h:907
try_connect_result_t
Definition net_helper.h:83
@ CONNECT_FAILURE
Definition net_helper.h:85
@ CONNECT_NO_SSL
Definition net_helper.h:86
@ CONNECT_SUCCESS
Definition net_helper.h:84
blocked_mode_client()
Definition net_helper.h:112
std::atomic< bool > m_aborted
Definition net_helper.h:905
boost::asio::io_context & get_io_service()
Definition net_helper.h:744
std::function< connect_func > m_connector
Definition net_helper.h:893
bool send(const void *data, size_t sz)
Definition net_helper.h:423
bool connect(const std::string &addr, int port, std::chrono::milliseconds timeout)
Definition net_helper.h:194
boost::asio::io_context m_io_service
Definition net_helper.h:889
bool disconnect()
Definition net_helper.h:326
boost::asio::ip::tcp::socket & get_socket()
Definition net_helper.h:749
bool is_connected(bool *ssl=NULL)
Definition net_helper.h:480
void set_ssl(ssl_options_t ssl_options)
Definition net_helper.h:184
std::atomic< uint64_t > m_bytes_sent
Definition net_helper.h:906
bool send(const boost::string_ref buff, std::chrono::milliseconds timeout)
Definition net_helper.h:357
boost::asio::ssl::context m_ctx
Definition net_helper.h:890
ssl_options_t m_ssl_options
Definition net_helper.h:894
std::shared_ptr< boost::asio::ssl::stream< boost::asio::ip::tcp::socket > > m_ssl_socket
Definition net_helper.h:891
std::atomic< bool > m_connected
Definition net_helper.h:896
bool m_initialized
Definition net_helper.h:895
Represents a single connection from a client.
Definition abstract_tcp_server2.h:100
ssl_support_t support
Definition net_ssl.h:85
boost::asio::ssl::context create_context() const
Definition net_ssl.cpp:303
bool handshake(boost::asio::io_context &io_context, boost::asio::ssl::stream< boost::asio::ip::tcp::socket > &socket, boost::asio::ssl::stream_base::handshake_type type, boost::asio::const_buffer buffer={}, const std::string &host={}, std::chrono::milliseconds timeout=std::chrono::seconds(15), const std::function< bool()> &abort_requested=nullptr) const
Definition net_ssl.cpp:553
bool success
Definition cold-transaction.cpp:57
Definition portable_binary_archive.hpp:29
Definition abstract_http_client.h:36
ssl_support_t
Definition net_ssl.h:50
@ e_ssl_support_disabled
Definition net_ssl.h:51
@ e_ssl_support_autodetect
Definition net_ssl.h:53
@ e_ssl_support_enabled
Definition net_ssl.h:52
TODO: (mj-xmr) This will be reduced in an another PR.
Definition byte_slice.h:40
signed __int64 int64_t
Definition stdint.h:135
unsigned __int64 uint64_t
Definition stdint.h:136
Definition net_helper.h:92
handler_obj(const handler_obj &other_obj)
Definition net_helper.h:95
void operator()(const boost::system::error_code &error, std::size_t bytes_transferred)
Definition net_helper.h:101
boost::system::error_code & ref_error
Definition net_helper.h:98
handler_obj(boost::system::error_code &error, size_t &bytes_transferred)
Definition net_helper.h:93
size_t & ref_bytes_transferred
Definition net_helper.h:99
Definition net_helper.h:767
boost::system::error_code error
Definition net_helper.h:769
std::function< void(const boost::system::error_code &, char)> handler
Definition net_helper.h:770
Definition net_helper.h:74
boost::unique_future< boost::asio::ip::tcp::socket > operator()(const std::string &addr, const std::string &port, boost::asio::steady_timer &) const
Definition net_helper.cpp:22
std::string data
Definition base58.cpp:37