From 71ac256cb5f0b4dc007413aa95a9137b3fbbc735 Mon Sep 17 00:00:00 2001 From: Jari Sundell Date: Sat, 9 May 2026 19:11:35 +0200 Subject: [PATCH] Moved socket counter to runtime::SocketManager. --- src/command_network.cc | 14 ++--- src/display/utils.cc | 6 +- src/rpc/scgi.cc | 101 ++++++++++++++++------------------ test/helpers/mock_function.cc | 20 +++---- 4 files changed, 64 insertions(+), 77 deletions(-) diff --git a/src/command_network.cc b/src/command_network.cc index b4b3dcd0..e32b501c 100644 --- a/src/command_network.cc +++ b/src/command_network.cc @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -215,10 +216,9 @@ apply_xmlrpc_dialect(const std::string& arg) { void initialize_command_network() { - auto cm = torrent::connection_manager(); - auto file_manager = torrent::file_manager(); - auto http_stack = torrent::net_thread::http_stack(); - auto nw_config = torrent::runtime::network_config(); + auto file_manager = torrent::file_manager(); + auto http_stack = torrent::net_thread::http_stack(); + auto nw_config = torrent::runtime::network_config(); CMD2_ANY_STRING ("encoding.add", std::bind(&apply_encoding_list, std::placeholders::_2)); @@ -289,9 +289,9 @@ initialize_command_network() { CMD2_ANY ("network.max_open_files", [file_manager](auto, auto) { return file_manager->max_open_files(); }); CMD2_ANY_VALUE_V ("network.max_open_files.set", [file_manager](auto, auto& value) { return file_manager->set_max_open_files(value); }); CMD2_ANY ("network.total_handshakes", [](auto, auto) { return torrent::total_handshakes(); }); - CMD2_ANY ("network.open_sockets", [cm](auto, auto) { return cm->size(); }); - CMD2_ANY ("network.max_open_sockets", [cm](auto, auto) { return cm->max_size(); }); - CMD2_ANY_VALUE_V ("network.max_open_sockets.set", [cm](auto, auto& value) { return cm->set_max_size(value); }); + CMD2_ANY ("network.open_sockets", [](auto, auto) { return torrent::runtime::socket_manager()->size(); }); + CMD2_ANY ("network.max_open_sockets", [](auto, auto) { return torrent::runtime::socket_manager()->max_size(); }); + CMD2_ANY_VALUE_V ("network.max_open_sockets.set", [](auto, auto& value) { return torrent::runtime::socket_manager()->set_max_size(value); }); CMD2_ANY_STRING ("network.scgi.open_port", std::bind(&apply_scgi, std::placeholders::_2, 1)); CMD2_ANY_STRING ("network.scgi.open_local", std::bind(&apply_scgi, std::placeholders::_2, 2)); diff --git a/src/display/utils.cc b/src/display/utils.cc index d1b40184..0ab25913 100644 --- a/src/display/utils.cc +++ b/src/display/utils.cc @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -19,6 +18,7 @@ #include #include #include +#include #include "control.h" #include "globals.h" @@ -427,8 +427,8 @@ print_status_extra(char* first, char* last) { first = print_buffer(first, last, " [S %i/%i/%i]", torrent::total_handshakes(), - torrent::connection_manager()->size(), - torrent::connection_manager()->max_size()); + torrent::runtime::socket_manager()->size(), + torrent::runtime::socket_manager()->max_size()); first = print_buffer(first, last, " [F %i/%i]", torrent::file_manager()->open_files(), diff --git a/src/rpc/scgi.cc b/src/rpc/scgi.cc index 833c65c2..fb55bf70 100644 --- a/src/rpc/scgi.cc +++ b/src/rpc/scgi.cc @@ -5,7 +5,6 @@ #include #include #include -#include #include #include #include @@ -34,24 +33,22 @@ SCgi::~SCgi() { void SCgi::open_port(sockaddr* sa, unsigned int length, bool dont_route) { - torrent::runtime::socket_manager()->open_event_or_throw(this, [&]() { - int fd = torrent::fd_open_family(torrent::fd_flag_stream | torrent::fd_flag_nonblock | torrent::fd_flag_reuse_address, - sa->sa_family); + int fd = torrent::fd_open_family(torrent::fd_flag_stream | torrent::fd_flag_nonblock | torrent::fd_flag_reuse_address, + sa->sa_family); - if (fd == -1) - throw torrent::resource_error("Could not open socket for listening: " + std::string(std::strerror(errno))); + if (fd == -1) + throw torrent::resource_error("Could not open socket for listening: " + std::string(std::strerror(errno))); - if (dont_route && !torrent::fd_set_dont_route(fd, true)) { - torrent::fd_close(fd); - throw torrent::resource_error("Could not set socket option IP_DONTROUTE: " + std::string(std::strerror(errno))); - } + if (dont_route && !torrent::fd_set_dont_route(fd, true)) { + torrent::fd_close(fd); + throw torrent::resource_error("Could not set socket option IP_DONTROUTE: " + std::string(std::strerror(errno))); + } - set_file_descriptor(fd); + set_file_descriptor(fd); - open(reinterpret_cast(sa), length); - }); + open(reinterpret_cast(sa), length); - torrent::connection_manager()->inc_socket_count(); + torrent::runtime::socket_manager()->register_event_or_throw(this, []() {}); } void @@ -63,35 +60,33 @@ SCgi::open_named(const std::string& filename) { sockaddr_un* sa = reinterpret_cast(buffer.get()); sa->sun_family = AF_LOCAL; + std::memcpy(sa->sun_path, filename.c_str(), filename.size() + 1); - torrent::runtime::socket_manager()->open_event_or_throw(this, [&]() { - int fd = torrent::fd_open_local(torrent::fd_flag_stream | torrent::fd_flag_nonblock | torrent::fd_flag_reuse_address); + int fd = torrent::fd_open_local(torrent::fd_flag_stream | torrent::fd_flag_nonblock | torrent::fd_flag_reuse_address); - if (fd == -1) - throw torrent::resource_error("Could not open socket for listening: " + std::string(std::strerror(errno))); + if (fd == -1) + throw torrent::resource_error("Could not open socket for listening: " + std::string(std::strerror(errno))); - set_file_descriptor(fd); + set_file_descriptor(fd); - open(reinterpret_cast(sa), offsetof(struct sockaddr_un, sun_path) + filename.size() + 1); - }); + open(reinterpret_cast(sa), offsetof(struct sockaddr_un, sun_path) + filename.size() + 1); - torrent::connection_manager()->inc_socket_count(); + torrent::runtime::socket_manager()->register_event_or_throw(this, []() {}); m_path = filename; } void SCgi::open_fd(int fd) { - torrent::runtime::socket_manager()->open_event_or_throw(this, [&]() { - if (!torrent::fd_set_nonblock(fd)) - throw torrent::resource_error("Could not set non-blocking on systemd fd: " + - std::string(std::strerror(errno))); - set_file_descriptor(fd); - // fd is already bound and listening; no bind()/listen() needed. - }); + if (!torrent::fd_set_nonblock(fd)) + throw torrent::resource_error("Could not set non-blocking on systemd fd: " + + std::string(std::strerror(errno))); + set_file_descriptor(fd); - torrent::connection_manager()->inc_socket_count(); + // fd is already bound and listening; no bind()/listen() needed. + + torrent::runtime::socket_manager()->register_event_or_throw(this, []() {}); } void @@ -132,15 +127,13 @@ SCgi::stop() { itr->close(); } - torrent::runtime::socket_manager()->close_event_or_throw(this, [this]() { + torrent::runtime::socket_manager()->unregister_event_or_throw(this, [this]() { torrent::this_thread::poll()->remove_and_close(this); torrent::fd_close(file_descriptor()); set_file_descriptor(-1); }); - torrent::connection_manager()->dec_socket_count(); - if (!m_path.empty()) ::unlink(m_path.c_str()); } @@ -159,34 +152,34 @@ SCgi::event_read() { if (m_current == m_tasks.end()) m_current = std::find_if(m_tasks.begin(), prev, [](const auto& task) { return !task->is_open(); }); + int fd = torrent::fd_accept(file_descriptor()); + + if (fd == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) + return; + + // Force a new event_read() call just to be sure we don't enter an infinite loop. + if (errno == ECONNABORTED) + return; + + throw torrent::resource_error("Listener port accept() failed: " + std::string(std::strerror(errno))); + } + if (m_current == prev) { - // TODO: Currently just close, although we should remove ourselves from read. - int fd = torrent::fd_accept(file_descriptor()); - - if (fd != -1) - torrent::fd_close(fd); - + torrent::fd_close(fd); continue; } - auto open_func = [this, task = m_current->get()]() { - int fd = torrent::fd_accept(file_descriptor()); - - if (fd == -1) { - if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) - return; - - // Force a new event_read() call just to be sure we don't enter an infinite loop. - if (errno == ECONNABORTED) - return; - - throw torrent::resource_error("Listener port accept() failed: " + std::string(std::strerror(errno))); - } - + auto open_func = [this, fd, task = m_current->get()]() { task->open(this, fd); }; - auto cleanup_func = [task = m_current->get()]() { + auto cleanup_func = [fd, task = m_current->get()](bool opened) { + if (!opened) { + torrent::fd_close(fd); + return; + } + task->cancel_open(); }; diff --git a/test/helpers/mock_function.cc b/test/helpers/mock_function.cc index 929f10b3..9c384246 100644 --- a/test/helpers/mock_function.cc +++ b/test/helpers/mock_function.cc @@ -17,6 +17,7 @@ #define MOCK_LOG(log_fmt, ...) \ lt_log_print(torrent::LOG_MOCK_CALLS, "%s: " log_fmt, __func__, __VA_ARGS__); +namespace { void mock_clear(bool ignore_assert) { MOCK_CLEANUP_MAP(torrent::fd__accept); @@ -28,23 +29,12 @@ mock_clear(bool ignore_assert) { MOCK_CLEANUP_MAP(torrent::fd__setsockopt_int); MOCK_CLEANUP_MAP(torrent::fd__socket); - MOCK_CLEANUP_MAP(torrent::this_thread::event_open); - MOCK_CLEANUP_MAP(torrent::this_thread::event_open_and_count); - MOCK_CLEANUP_MAP(torrent::this_thread::event_close_and_count); - MOCK_CLEANUP_MAP(torrent::this_thread::event_closed_and_count); - MOCK_CLEANUP_MAP(torrent::this_thread::event_insert_read); - MOCK_CLEANUP_MAP(torrent::this_thread::event_insert_write); - MOCK_CLEANUP_MAP(torrent::this_thread::event_insert_error); - MOCK_CLEANUP_MAP(torrent::this_thread::event_remove_read); - MOCK_CLEANUP_MAP(torrent::this_thread::event_remove_write); - MOCK_CLEANUP_MAP(torrent::this_thread::event_remove_error); - MOCK_CLEANUP_MAP(torrent::this_thread::event_remove_and_close); - MOCK_CLEANUP_MAP(torrent::random_uniform_uint16); MOCK_CLEANUP_MAP(torrent::random_uniform_uint32); mock_compare_map::values.clear(); -}; +} +} // namespace void mock_init() { @@ -59,6 +49,10 @@ mock_cleanup() { void mock_redirect_defaults([[maybe_unused]] mock_redirect_flags flags) { + mock_redirect(torrent::fd__bind, std::function([](int socket, const sockaddr *address, socklen_t address_len) { + return ::bind(socket, address, address_len); + })); + mock_redirect(torrent::fd__close, std::function([](int fildes) { return ::close(fildes); })); mock_redirect(torrent::fd__fcntl_int, std::function([](int fildes, int cmd, int arg) { return ::fcntl(fildes, cmd, arg); })); mock_redirect(torrent::fd__setsockopt_int, std::function([](int socket, int level, int option_name, int option_value) { return ::setsockopt(socket, level, option_name, &option_value, sizeof(int)); }));