#include "config.h" #include <unistd.h>#include <sys/stat.h>#include <torrent/data/file_manager.h>#include <torrent/runtime/client_config.h>#include <torrent/runtime/memory_manager.h>#include <torrent/runtime/socket_manager.h>#include <torrent/runtime/runtime.h>#include <torrent/utils/chrono.h>#include <torrent/utils/option_strings.h> #include "command_helpers.h"#include "control.h"#include "globals.h"#include "core/manager.h"#include "session/session_manager.h"#include "utils/file_status_cache.h" torrent::Objectsystem_env(const torrent::Object::string_type& arg) { if (arg.empty()) throw torrent::input_error("system.env: Missing variable name."); char* val = getenv(arg.c_str()); return std::string(val ? val : "");} torrent::Objectsystem_hostname() { char buffer[1024]; if (gethostname(buffer, 1023) == -1) throw torrent::input_error("Unable to read hostname."); // if (shorten)// *std::find(buffer, buffer + 1023, '.') = '\0'; return std::string(buffer);} torrent::Objectsystem_get_cwd() { char* buffer = getcwd(NULL, 0); if (buffer == NULL) throw torrent::input_error("Unable to read cwd."); torrent::Object result = torrent::Object(std::string(buffer)); free(buffer); return result;} torrent::Objectsystem_set_cwd(const torrent::Object::string_type& rawArgs) { if (::chdir(rawArgs.c_str()) != 0) throw torrent::input_error("Could not change current working directory."); return torrent::Object();} uint32_tchecked_socket_value(int64_t value, const char* label) { if (value < 0 || value > std::numeric_limits<uint32_t>::max()) throw torrent::input_error(std::string("Invalid ") + label + " value."); return static_cast<uint32_t>(value);} voidinitialize_command_system() { CMD_ANY ("system.hostname", std::bind(&system_hostname)); CMD_ANY ("system.pid", std::bind(&getpid)); CMD_VAR_C_STRING("system.api_version", (int64_t)API_VERSION); CMD_VAR_C_STRING("system.client_version", PACKAGE_VERSION); CMD_VAR_C_STRING("system.library_version", torrent::runtime::version()); CMD_ANY ("system.torrent_name.use_sanitized", [](auto, auto) { return torrent::runtime::client_config()->torrent_name_use_sanitized(); }); CMD_ANY_VALUE_V ("system.torrent_name.use_sanitized.set", [](auto, auto& value) { return torrent::runtime::client_config()->set_torrent_name_use_sanitized(value); }); CMD_VAR_VALUE ("system.file.allocate", 0); CMD_VAR_VALUE ("system.file.max_size", (int64_t)512 << 30); CMD_VAR_VALUE ("system.file.split_size", -1); CMD_VAR_STRING ("system.file.split_suffix", ".part"); CMD_ANY ("system.file_name.replace_slash", [](auto, auto) { return torrent::runtime::client_config()->file_name_replace_slash(); }); CMD_ANY_STRING_V("system.file_name.replace_slash.set", [](auto, auto& str) { return torrent::runtime::client_config()->set_file_name_replace_slash(str); }); CMD_ANY ("system.file_status_cache.size", [](auto, auto) { return control->core()->file_status_cache()->size(); }); CMD_ANY_V ("system.file_status_cache.prune", [](auto, auto) { return control->core()->file_status_cache()->prune(); }); CMD_VAR_BOOL ("file.prioritize_toc", 0); CMD_VAR_LIST ("file.prioritize_toc.first"); CMD_VAR_LIST ("file.prioritize_toc.last"); CMD_ANY ("system.files.advise_random", [](auto, auto) { return torrent::file_manager()->advise_random(); }); CMD_ANY_VALUE_V ("system.files.advise_random.set", [](auto, auto& value) { return torrent::file_manager()->set_advise_random(value); }); CMD_ANY ("system.files.advise_random.hashing", [](auto, auto) { return torrent::file_manager()->advise_random_hashing(); }); CMD_ANY_VALUE_V ("system.files.advise_random.hashing.set", [](auto, auto& value) { return torrent::file_manager()->set_advise_random_hashing(value); }); CMD_ANY ("system.files.session.fdatasync", [](auto, auto) { return session_thread::manager()->use_fsyncdisk(); }); CMD_ANY_VALUE_V ("system.files.session.fdatasync.set", [](auto, auto& value) { return session_thread::manager()->set_use_fsyncdisk(value); }); CMD_ANY ("system.files.close_idle", [](auto, auto) { return torrent::file_manager()->close_idle_timeout().count(); }); CMD_ANY_VALUE_V ("system.files.close_idle.set", [](auto, auto& value) { return torrent::file_manager()->set_close_idle_timeout(value * 1s); }); CMD_ANY ("system.files.opened_counter", [](auto, auto) { return torrent::file_manager()->files_opened_counter(); }); CMD_ANY ("system.files.closed_counter", [](auto, auto) { return torrent::file_manager()->files_closed_counter(); }); CMD_ANY ("system.files.failed_counter", [](auto, auto) { return torrent::file_manager()->files_failed_counter(); }); CMD_ANY_STRING ("system.env", [](auto, auto& str) { return system_env(str); }); CMD_ANY ("system.time", [](auto, auto) { return torrent::this_thread::cached_seconds().count(); }); CMD_ANY ("system.time_seconds", [](auto, auto) { return torrent::utils::cast_seconds(torrent::utils::time_since_epoch()).count(); }); CMD_ANY ("system.time_usec", [](auto, auto) { return torrent::utils::time_since_epoch().count(); }); CMD_ANY_VALUE_V ("system.umask.set", [](auto, auto& value) { return ::umask(value); }); CMD_VAR_BOOL ("system.daemon", false); CMD_ANY_V ("system.shutdown.normal", [](auto, auto) { control->receive_normal_shutdown(); }); CMD_ANY_V ("system.shutdown.quick", [](auto, auto) { control->receive_quick_shutdown(); }); CMD_REDIRECT_NO_EXPORT("system.shutdown", "system.shutdown.normal"); CMD_ANY ("system.cwd", [](auto, auto) { return system_get_cwd(); }); CMD_ANY_STRING ("system.cwd.set", [](auto, auto& str) { return system_set_cwd(str); }); CMD_ANY ("system.sockets.size", [](auto, auto) { return torrent::runtime::socket_manager()->size(); }); CMD_ANY ("system.sockets.max_size", [](auto, auto) { return torrent::runtime::socket_manager()->max_size(); }); CMD_ANY_VALUE_V ("system.sockets.max_size.set", [](auto, auto& value) { return torrent::runtime::socket_manager()->set_max_size_and_adjust(checked_socket_value(value, "socket max size")); }); CMD_ANY_V ("system.sockets.adjust_alloc", [](auto, auto) { torrent::runtime::socket_manager()->adjust_allocation(); }); CMD_ANY ("system.sockets.reserved_alloc", [](auto, auto) { return torrent::runtime::socket_manager()->reserved_allocation(); }); CMD_ANY ("system.sockets.available_alloc", [](auto, auto) { return torrent::runtime::socket_manager()->available_allocation(); }); for (uint32_t i = 0; i < torrent::runtime::SocketManager::category_count; ++i) { auto category = static_cast<torrent::runtime::socket_manager_category_t>(i); auto category_name = "system.sockets." + torrent::option_to_str_or_throw(torrent::OPTION_SOCKET_CATEGORY, i); CMD_ANY (category_name + ".size", [category](auto, auto) { return torrent::runtime::socket_manager()->category_managed_size(category); }); CMD_ANY (category_name + ".max_size", [category](auto, auto) { return torrent::runtime::socket_manager()->category_max_size(category); }); if (i == 0) { CMD_ANY (category_name + ".min_alloc", [](auto, auto) { return torrent::runtime::socket_manager()->generic_min_allocation(); }); continue; } CMD_ANY (category_name + ".max_alloc.limit", [category](auto, auto) { return torrent::runtime::socket_manager()->category_alloc_limit(category); }); CMD_ANY (category_name + ".min_alloc.limit", [category](auto, auto) { return torrent::runtime::socket_manager()->category_alloc_minimum(category); }); CMD_ANY (category_name + ".min_alloc", [category](auto, auto) { return torrent::runtime::socket_manager()->category_min_allocation(category); }); CMD_ANY (category_name + ".max_alloc", [category](auto, auto) { return torrent::runtime::socket_manager()->category_max_allocation(category); }); CMD_ANY_VALUE_V(category_name + ".min_alloc.set", [category](auto, auto& value) { torrent::runtime::socket_manager()->set_category_min_allocation(category, checked_socket_value(value, "socket min alloc")); }); CMD_ANY_VALUE_V(category_name + ".max_alloc.set", [category](auto, auto& value) { torrent::runtime::socket_manager()->set_category_max_allocation(category, checked_socket_value(value, "socket max alloc")); }); } rpc::rpc.mark_safe("system.api_version"); rpc::rpc.mark_safe("system.client_version"); rpc::rpc.mark_safe("system.library_version"); rpc::rpc.mark_safe("system.time"); rpc::rpc.mark_safe("system.time_seconds"); rpc::rpc.mark_safe("system.time_usec"); rpc::rpc.mark_safe("system.file.allocate"); rpc::rpc.mark_safe("system.file.max_size"); rpc::rpc.mark_safe("system.file.split_size"); rpc::rpc.mark_safe("system.file.split_suffix"); rpc::rpc.mark_safe("system.sockets.size"); rpc::rpc.mark_safe("system.sockets.max_size"); rpc::rpc.mark_safe("system.sockets.reserved_alloc"); rpc::rpc.mark_safe("system.sockets.available_alloc"); for (uint32_t i = 0; i < torrent::runtime::SocketManager::category_count; ++i) { auto category_name = "system.sockets." + torrent::option_to_str_or_throw(torrent::OPTION_SOCKET_CATEGORY, i); rpc::rpc.mark_safe(category_name + ".size"); rpc::rpc.mark_safe(category_name + ".max_size"); if (i == 0) { rpc::rpc.mark_safe(category_name + ".min_alloc"); continue; } rpc::rpc.mark_safe(category_name + ".max_alloc.limit"); rpc::rpc.mark_safe(category_name + ".min_alloc.limit"); rpc::rpc.mark_safe(category_name + ".min_alloc"); rpc::rpc.mark_safe(category_name + ".max_alloc"); }}
#include "config.h"
#include <unistd.h>
#include <sys/stat.h>
#include <torrent/data/file_manager.h>
#include <torrent/runtime/client_config.h>
#include <torrent/runtime/memory_manager.h>
#include <torrent/runtime/socket_manager.h>
#include <torrent/runtime/runtime.h>
#include <torrent/utils/chrono.h>
#include <torrent/utils/option_strings.h>
#include "command_helpers.h"
#include "control.h"
#include "globals.h"
#include "core/manager.h"
#include "session/session_manager.h"
#include "utils/file_status_cache.h"
torrent::Object
system_env(const torrent::Object::string_type& arg) {
if (arg.empty())
throw torrent::input_error("system.env: Missing variable name.");
char* val = getenv(arg.c_str());
return std::string(val ? val : "");
}
torrent::Object
system_hostname() {
char buffer[1024];
if (gethostname(buffer, 1023) == -1)
throw torrent::input_error("Unable to read hostname.");
// if (shorten)
// *std::find(buffer, buffer + 1023, '.') = '\0';
return std::string(buffer);
}
torrent::Object
system_get_cwd() {
char* buffer = getcwd(NULL, 0);
if (buffer == NULL)
throw torrent::input_error("Unable to read cwd.");
torrent::Object result = torrent::Object(std::string(buffer));
free(buffer);
return result;
}
torrent::Object
system_set_cwd(const torrent::Object::string_type& rawArgs) {
if (::chdir(rawArgs.c_str()) != 0)
throw torrent::input_error("Could not change current working directory.");
return torrent::Object();
}
uint32_t
checked_socket_value(int64_t value, const char* label) {
if (value < 0 || value > std::numeric_limits<uint32_t>::max())
throw torrent::input_error(std::string("Invalid ") + label + " value.");
return static_cast<uint32_t>(value);
}
void
initialize_command_system() {
CMD_ANY ("system.hostname", std::bind(&system_hostname));
CMD_ANY ("system.pid", std::bind(&getpid));
CMD_VAR_C_STRING("system.api_version", (int64_t)API_VERSION);
CMD_VAR_C_STRING("system.client_version", PACKAGE_VERSION);
CMD_VAR_C_STRING("system.library_version", torrent::runtime::version());
CMD_ANY ("system.torrent_name.use_sanitized", [](auto, auto) { return torrent::runtime::client_config()->torrent_name_use_sanitized(); });
CMD_ANY_VALUE_V ("system.torrent_name.use_sanitized.set", [](auto, auto& value) { return torrent::runtime::client_config()->set_torrent_name_use_sanitized(value); });
CMD_VAR_VALUE ("system.file.allocate", 0);
CMD_VAR_VALUE ("system.file.max_size", (int64_t)512 << 30);
CMD_VAR_VALUE ("system.file.split_size", -1);
CMD_VAR_STRING ("system.file.split_suffix", ".part");
CMD_ANY ("system.file_name.replace_slash", [](auto, auto) { return torrent::runtime::client_config()->file_name_replace_slash(); });
CMD_ANY_STRING_V("system.file_name.replace_slash.set", [](auto, auto& str) { return torrent::runtime::client_config()->set_file_name_replace_slash(str); });
CMD_ANY ("system.file_status_cache.size", [](auto, auto) { return control->core()->file_status_cache()->size(); });
CMD_ANY_V ("system.file_status_cache.prune", [](auto, auto) { return control->core()->file_status_cache()->prune(); });
CMD_VAR_BOOL ("file.prioritize_toc", 0);
CMD_VAR_LIST ("file.prioritize_toc.first");
CMD_VAR_LIST ("file.prioritize_toc.last");
CMD_ANY ("system.files.advise_random", [](auto, auto) { return torrent::file_manager()->advise_random(); });
CMD_ANY_VALUE_V ("system.files.advise_random.set", [](auto, auto& value) { return torrent::file_manager()->set_advise_random(value); });
CMD_ANY ("system.files.advise_random.hashing", [](auto, auto) { return torrent::file_manager()->advise_random_hashing(); });
CMD_ANY_VALUE_V ("system.files.advise_random.hashing.set", [](auto, auto& value) { return torrent::file_manager()->set_advise_random_hashing(value); });
CMD_ANY ("system.files.session.fdatasync", [](auto, auto) { return session_thread::manager()->use_fsyncdisk(); });
CMD_ANY_VALUE_V ("system.files.session.fdatasync.set", [](auto, auto& value) { return session_thread::manager()->set_use_fsyncdisk(value); });
CMD_ANY ("system.files.close_idle", [](auto, auto) { return torrent::file_manager()->close_idle_timeout().count(); });
CMD_ANY_VALUE_V ("system.files.close_idle.set", [](auto, auto& value) { return torrent::file_manager()->set_close_idle_timeout(value * 1s); });
CMD_ANY ("system.files.opened_counter", [](auto, auto) { return torrent::file_manager()->files_opened_counter(); });
CMD_ANY ("system.files.closed_counter", [](auto, auto) { return torrent::file_manager()->files_closed_counter(); });
CMD_ANY ("system.files.failed_counter", [](auto, auto) { return torrent::file_manager()->files_failed_counter(); });
CMD_ANY_STRING ("system.env", [](auto, auto& str) { return system_env(str); });
CMD_ANY ("system.time", [](auto, auto) { return torrent::this_thread::cached_seconds().count(); });
CMD_ANY ("system.time_seconds", [](auto, auto) { return torrent::utils::cast_seconds(torrent::utils::time_since_epoch()).count(); });
CMD_ANY ("system.time_usec", [](auto, auto) { return torrent::utils::time_since_epoch().count(); });
CMD_ANY_VALUE_V ("system.umask.set", [](auto, auto& value) { return ::umask(value); });
CMD_VAR_BOOL ("system.daemon", false);
CMD_ANY_V ("system.shutdown.normal", [](auto, auto) { control->receive_normal_shutdown(); });
CMD_ANY_V ("system.shutdown.quick", [](auto, auto) { control->receive_quick_shutdown(); });
CMD_REDIRECT_NO_EXPORT("system.shutdown", "system.shutdown.normal");
CMD_ANY ("system.cwd", [](auto, auto) { return system_get_cwd(); });
CMD_ANY_STRING ("system.cwd.set", [](auto, auto& str) { return system_set_cwd(str); });
CMD_ANY ("system.sockets.size", [](auto, auto) { return torrent::runtime::socket_manager()->size(); });
CMD_ANY ("system.sockets.max_size", [](auto, auto) { return torrent::runtime::socket_manager()->max_size(); });
CMD_ANY_VALUE_V ("system.sockets.max_size.set", [](auto, auto& value) {
return torrent::runtime::socket_manager()->set_max_size_and_adjust(checked_socket_value(value, "socket max size"));
});
CMD_ANY_V ("system.sockets.adjust_alloc", [](auto, auto) { torrent::runtime::socket_manager()->adjust_allocation(); });
CMD_ANY ("system.sockets.reserved_alloc", [](auto, auto) { return torrent::runtime::socket_manager()->reserved_allocation(); });
CMD_ANY ("system.sockets.available_alloc", [](auto, auto) { return torrent::runtime::socket_manager()->available_allocation(); });
for (uint32_t i = 0; i < torrent::runtime::SocketManager::category_count; ++i) {
auto category = static_cast<torrent::runtime::socket_manager_category_t>(i);
auto category_name = "system.sockets." + torrent::option_to_str_or_throw(torrent::OPTION_SOCKET_CATEGORY, i);
CMD_ANY (category_name + ".size", [category](auto, auto) { return torrent::runtime::socket_manager()->category_managed_size(category); });
CMD_ANY (category_name + ".max_size", [category](auto, auto) { return torrent::runtime::socket_manager()->category_max_size(category); });
if (i == 0) {
CMD_ANY (category_name + ".min_alloc", [](auto, auto) { return torrent::runtime::socket_manager()->generic_min_allocation(); });
continue;
}
CMD_ANY (category_name + ".max_alloc.limit", [category](auto, auto) { return torrent::runtime::socket_manager()->category_alloc_limit(category); });
CMD_ANY (category_name + ".min_alloc.limit", [category](auto, auto) { return torrent::runtime::socket_manager()->category_alloc_minimum(category); });
CMD_ANY (category_name + ".min_alloc", [category](auto, auto) { return torrent::runtime::socket_manager()->category_min_allocation(category); });
CMD_ANY (category_name + ".max_alloc", [category](auto, auto) { return torrent::runtime::socket_manager()->category_max_allocation(category); });
CMD_ANY_VALUE_V(category_name + ".min_alloc.set", [category](auto, auto& value) {
torrent::runtime::socket_manager()->set_category_min_allocation(category, checked_socket_value(value, "socket min alloc"));
});
CMD_ANY_VALUE_V(category_name + ".max_alloc.set", [category](auto, auto& value) {
torrent::runtime::socket_manager()->set_category_max_allocation(category, checked_socket_value(value, "socket max alloc"));
});
}
rpc::rpc.mark_safe("system.api_version");
rpc::rpc.mark_safe("system.client_version");
rpc::rpc.mark_safe("system.library_version");
rpc::rpc.mark_safe("system.time");
rpc::rpc.mark_safe("system.time_seconds");
rpc::rpc.mark_safe("system.time_usec");
rpc::rpc.mark_safe("system.file.allocate");
rpc::rpc.mark_safe("system.file.max_size");
rpc::rpc.mark_safe("system.file.split_size");
rpc::rpc.mark_safe("system.file.split_suffix");
rpc::rpc.mark_safe("system.sockets.size");
rpc::rpc.mark_safe("system.sockets.max_size");
rpc::rpc.mark_safe("system.sockets.reserved_alloc");
rpc::rpc.mark_safe("system.sockets.available_alloc");
for (uint32_t i = 0; i < torrent::runtime::SocketManager::category_count; ++i) {
auto category_name = "system.sockets." + torrent::option_to_str_or_throw(torrent::OPTION_SOCKET_CATEGORY, i);
rpc::rpc.mark_safe(category_name + ".size");
rpc::rpc.mark_safe(category_name + ".max_size");
if (i == 0) {
rpc::rpc.mark_safe(category_name + ".min_alloc");
continue;
}
rpc::rpc.mark_safe(category_name + ".max_alloc.limit");
rpc::rpc.mark_safe(category_name + ".min_alloc.limit");
rpc::rpc.mark_safe(category_name + ".min_alloc");
rpc::rpc.mark_safe(category_name + ".max_alloc");
}
}