Compare commits
12 Commits
e3d036fcb8
...
0e8e56ad90
Author | SHA1 | Date | |
---|---|---|---|
0e8e56ad90 | |||
e53acf799a | |||
c2eaa92f4a | |||
13eab49207 | |||
616dca89ca | |||
9626f383d3 | |||
a262a79eb2 | |||
f9ec02bf3f | |||
e6793f0d6c | |||
0d972b0b75 | |||
60f0e3dbc1 | |||
630c3463d8 |
@ -12,6 +12,7 @@
|
|||||||
### Changes from v2.0.4-rc
|
### Changes from v2.0.4-rc
|
||||||
|
|
||||||
* Continue documentation updates
|
* Continue documentation updates
|
||||||
|
* Prevent overlapping `repertory` `ApiPort`'s
|
||||||
* Removed passwords and secret key values from API calls
|
* Removed passwords and secret key values from API calls
|
||||||
* Renamed setting `ApiAuth` to `ApiPassword`
|
* Renamed setting `ApiAuth` to `ApiPassword`
|
||||||
* Require `--name,-na` option for encryption provider
|
* Require `--name,-na` option for encryption provider
|
||||||
|
@ -43,8 +43,7 @@ public:
|
|||||||
[[nodiscard]] static auto default_remote_api_port(const provider_type &prov)
|
[[nodiscard]] static auto default_remote_api_port(const provider_type &prov)
|
||||||
-> std::uint16_t;
|
-> std::uint16_t;
|
||||||
|
|
||||||
[[nodiscard]] static auto default_rpc_port(const provider_type &prov)
|
[[nodiscard]] static auto default_rpc_port() -> std::uint16_t;
|
||||||
-> std::uint16_t;
|
|
||||||
|
|
||||||
[[nodiscard]] static auto get_provider_display_name(const provider_type &prov)
|
[[nodiscard]] static auto get_provider_display_name(const provider_type &prov)
|
||||||
-> std::string;
|
-> std::string;
|
||||||
|
@ -67,7 +67,7 @@ app_config::app_config(const provider_type &prov,
|
|||||||
std::string_view data_directory)
|
std::string_view data_directory)
|
||||||
: prov_(prov),
|
: prov_(prov),
|
||||||
api_password_(utils::generate_random_string(default_api_password_size)),
|
api_password_(utils::generate_random_string(default_api_password_size)),
|
||||||
api_port_(default_rpc_port(prov)),
|
api_port_(default_rpc_port()),
|
||||||
api_user_(std::string{REPERTORY}),
|
api_user_(std::string{REPERTORY}),
|
||||||
config_changed_(false),
|
config_changed_(false),
|
||||||
download_timeout_secs_(default_download_timeout_secs),
|
download_timeout_secs_(default_download_timeout_secs),
|
||||||
@ -743,17 +743,7 @@ auto app_config::default_remote_api_port(const provider_type &prov)
|
|||||||
return PROVIDER_REMOTE_PORTS.at(static_cast<std::size_t>(prov));
|
return PROVIDER_REMOTE_PORTS.at(static_cast<std::size_t>(prov));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto app_config::default_rpc_port(const provider_type &prov) -> std::uint16_t {
|
auto app_config::default_rpc_port() -> std::uint16_t { return 10000U; }
|
||||||
static const std::array<std::uint16_t,
|
|
||||||
static_cast<std::size_t>(provider_type::unknown)>
|
|
||||||
PROVIDER_RPC_PORTS = {
|
|
||||||
10000U,
|
|
||||||
10010U,
|
|
||||||
10100U,
|
|
||||||
10002U,
|
|
||||||
};
|
|
||||||
return PROVIDER_RPC_PORTS.at(static_cast<std::size_t>(prov));
|
|
||||||
}
|
|
||||||
|
|
||||||
auto app_config::get_api_password() const -> std::string {
|
auto app_config::get_api_password() const -> std::string {
|
||||||
return api_password_;
|
return api_password_;
|
||||||
@ -943,24 +933,18 @@ auto app_config::get_preferred_download_type() const -> download_type {
|
|||||||
auto app_config::get_provider_display_name(const provider_type &prov)
|
auto app_config::get_provider_display_name(const provider_type &prov)
|
||||||
-> std::string {
|
-> std::string {
|
||||||
static const std::array<std::string,
|
static const std::array<std::string,
|
||||||
static_cast<std::size_t>(provider_type::unknown)>
|
static_cast<std::size_t>(provider_type::unknown) + 1U>
|
||||||
PROVIDER_DISPLAY_NAMES = {
|
PROVIDER_DISPLAY_NAMES = {
|
||||||
"Sia",
|
"Sia", "Remote", "S3", "Encrypt", "Unknown",
|
||||||
"Remote",
|
|
||||||
"S3",
|
|
||||||
"Encrypt",
|
|
||||||
};
|
};
|
||||||
return PROVIDER_DISPLAY_NAMES.at(static_cast<std::size_t>(prov));
|
return PROVIDER_DISPLAY_NAMES.at(static_cast<std::size_t>(prov));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto app_config::get_provider_name(const provider_type &prov) -> std::string {
|
auto app_config::get_provider_name(const provider_type &prov) -> std::string {
|
||||||
static const std::array<std::string,
|
static const std::array<std::string,
|
||||||
static_cast<std::size_t>(provider_type::unknown)>
|
static_cast<std::size_t>(provider_type::unknown) + 1U>
|
||||||
PROVIDER_NAMES = {
|
PROVIDER_NAMES = {
|
||||||
"sia",
|
"sia", "remote", "s3", "encrypt", "unknown",
|
||||||
"remote",
|
|
||||||
"s3",
|
|
||||||
"encrypt",
|
|
||||||
};
|
};
|
||||||
return PROVIDER_NAMES.at(static_cast<std::size_t>(prov));
|
return PROVIDER_NAMES.at(static_cast<std::size_t>(prov));
|
||||||
}
|
}
|
||||||
|
@ -143,8 +143,17 @@ void server::start() {
|
|||||||
|
|
||||||
initialize(*server_);
|
initialize(*server_);
|
||||||
|
|
||||||
server_thread_ = std::make_unique<std::thread>(
|
server_thread_ = std::make_unique<std::thread>([this]() {
|
||||||
[this]() { server_->listen("127.0.0.1", config_.get_api_port()); });
|
#ifdef _WIN32
|
||||||
|
server_->set_socket_options([](auto &&sock) {
|
||||||
|
int enable = 1;
|
||||||
|
setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
|
||||||
|
reinterpret_cast<const char *>(&enable), sizeof(enable));
|
||||||
|
});
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
|
server_->listen("127.0.0.1", config_.get_api_port());
|
||||||
|
});
|
||||||
event_system::instance().raise<service_start_end>(function_name, "server");
|
event_system::instance().raise<service_start_end>(function_name, "server");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,8 +29,7 @@
|
|||||||
#include "types/repertory.hpp"
|
#include "types/repertory.hpp"
|
||||||
#include "utils/cli_utils.hpp"
|
#include "utils/cli_utils.hpp"
|
||||||
#include "utils/com_init_wrapper.hpp"
|
#include "utils/com_init_wrapper.hpp"
|
||||||
#include "utils/file_utils.hpp"
|
#include "utils/file.hpp"
|
||||||
#include "utils/string.hpp"
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#include "drives/winfsp/remotewinfsp/remote_client.hpp"
|
#include "drives/winfsp/remotewinfsp/remote_client.hpp"
|
||||||
@ -57,130 +56,141 @@ namespace repertory::cli::actions {
|
|||||||
mount(std::vector<const char *> args, std::string data_directory,
|
mount(std::vector<const char *> args, std::string data_directory,
|
||||||
int &mount_result, provider_type prov, const std::string &remote_host,
|
int &mount_result, provider_type prov, const std::string &remote_host,
|
||||||
std::uint16_t remote_port, const std::string &unique_id) -> exit_code {
|
std::uint16_t remote_port, const std::string &unique_id) -> exit_code {
|
||||||
auto ret = exit_code::success;
|
|
||||||
|
|
||||||
lock_data lock(prov, unique_id);
|
lock_data lock(prov, unique_id);
|
||||||
const auto res = lock.grab_lock();
|
auto lock_result = lock.grab_lock();
|
||||||
if (res == lock_result::locked) {
|
if (lock_result == lock_result::locked) {
|
||||||
ret = exit_code::mount_active;
|
|
||||||
std::cerr << app_config::get_provider_display_name(prov)
|
std::cerr << app_config::get_provider_display_name(prov)
|
||||||
<< " mount is already active" << std::endl;
|
<< " mount is already active" << std::endl;
|
||||||
} else if (res == lock_result::success) {
|
return exit_code::mount_active;
|
||||||
const auto generate_config = utils::cli::has_option(
|
|
||||||
args, utils::cli::options::generate_config_option);
|
|
||||||
if (generate_config) {
|
|
||||||
app_config config(prov, data_directory);
|
|
||||||
if (prov == provider_type::remote) {
|
|
||||||
auto cfg = config.get_remote_config();
|
|
||||||
cfg.host_name_or_ip = remote_host;
|
|
||||||
cfg.api_port = remote_port;
|
|
||||||
config.set_remote_config(cfg);
|
|
||||||
} else if (prov == provider_type::sia &&
|
|
||||||
config.get_sia_config().bucket.empty()) {
|
|
||||||
[[maybe_unused]] auto bucket =
|
|
||||||
config.set_value_by_name("SiaConfig.Bucket", unique_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "Generated " << app_config::get_provider_display_name(prov)
|
|
||||||
<< " Configuration" << std::endl;
|
|
||||||
std::cout << config.get_config_file_path() << std::endl;
|
|
||||||
ret = utils::file::file(config.get_config_file_path()).exists()
|
|
||||||
? exit_code::success
|
|
||||||
: exit_code::file_creation_failed;
|
|
||||||
} else {
|
|
||||||
#if defined(_WIN32)
|
|
||||||
if (utils::cli::has_option(args, utils::cli::options::hidden_option)) {
|
|
||||||
::ShowWindow(::GetConsoleWindow(), SW_HIDE);
|
|
||||||
}
|
|
||||||
#endif // defined(_WIN32)
|
|
||||||
auto drive_args =
|
|
||||||
utils::cli::parse_drive_options(args, prov, data_directory);
|
|
||||||
app_config config(prov, data_directory);
|
|
||||||
#if defined(_WIN32)
|
|
||||||
if (config.get_enable_mount_manager() &&
|
|
||||||
not utils::is_process_elevated()) {
|
|
||||||
utils::com_init_wrapper cw;
|
|
||||||
if (not lock.set_mount_state(true, "elevating", -1)) {
|
|
||||||
std::cerr << "failed to set mount state" << std::endl;
|
|
||||||
}
|
|
||||||
lock.release();
|
|
||||||
|
|
||||||
mount_result = utils::run_process_elevated(args);
|
|
||||||
lock_data lock2(prov, unique_id);
|
|
||||||
if (lock2.grab_lock() == lock_result::success) {
|
|
||||||
if (not lock2.set_mount_state(false, "", -1)) {
|
|
||||||
std::cerr << "failed to set mount state" << std::endl;
|
|
||||||
}
|
|
||||||
lock2.release();
|
|
||||||
}
|
|
||||||
|
|
||||||
return exit_code::mount_result;
|
|
||||||
}
|
|
||||||
#endif // defined(_WIN32)
|
|
||||||
std::cout << "Initializing "
|
|
||||||
<< app_config::get_provider_display_name(prov)
|
|
||||||
<< (unique_id.empty() ? ""
|
|
||||||
: (prov == provider_type::remote)
|
|
||||||
? " [" + remote_host + ':' +
|
|
||||||
std::to_string(remote_port) + ']'
|
|
||||||
: " [" + unique_id + ']')
|
|
||||||
<< " Drive" << std::endl;
|
|
||||||
if (prov == provider_type::remote) {
|
|
||||||
std::uint16_t port{0U};
|
|
||||||
if (utils::get_next_available_port(config.get_api_port(), port)) {
|
|
||||||
auto cfg = config.get_remote_config();
|
|
||||||
cfg.host_name_or_ip = remote_host;
|
|
||||||
cfg.api_port = remote_port;
|
|
||||||
config.set_remote_config(cfg);
|
|
||||||
config.set_api_port(port);
|
|
||||||
|
|
||||||
try {
|
|
||||||
remote_drive drive(
|
|
||||||
config,
|
|
||||||
[&config]() -> std::unique_ptr<remote_instance> {
|
|
||||||
return std::unique_ptr<remote_instance>(
|
|
||||||
new remote_client(config));
|
|
||||||
},
|
|
||||||
lock);
|
|
||||||
if (not lock.set_mount_state(true, "", -1)) {
|
|
||||||
std::cerr << "failed to set mount state" << std::endl;
|
|
||||||
}
|
|
||||||
mount_result = drive.mount(drive_args);
|
|
||||||
ret = exit_code::mount_result;
|
|
||||||
} catch (const std::exception &e) {
|
|
||||||
std::cerr << "FATAL: " << e.what() << std::endl;
|
|
||||||
ret = exit_code::startup_exception;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
std::cerr << "FATAL: Unable to get available port" << std::endl;
|
|
||||||
ret = exit_code::startup_exception;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (prov == provider_type::sia &&
|
|
||||||
config.get_sia_config().bucket.empty()) {
|
|
||||||
[[maybe_unused]] auto bucket =
|
|
||||||
config.set_value_by_name("SiaConfig.Bucket", unique_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
auto provider = create_provider(prov, config);
|
|
||||||
repertory_drive drive(config, lock, *provider);
|
|
||||||
if (not lock.set_mount_state(true, "", -1)) {
|
|
||||||
std::cerr << "failed to set mount state" << std::endl;
|
|
||||||
}
|
|
||||||
mount_result = drive.mount(drive_args);
|
|
||||||
ret = exit_code::mount_result;
|
|
||||||
} catch (const std::exception &e) {
|
|
||||||
std::cerr << "FATAL: " << e.what() << std::endl;
|
|
||||||
ret = exit_code::startup_exception;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ret = exit_code::lock_failed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
if (lock_result != lock_result::success) {
|
||||||
|
std::cerr << "FATAL: Unable to get provider lock" << std::endl;
|
||||||
|
return exit_code::lock_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (utils::cli::has_option(args,
|
||||||
|
utils::cli::options::generate_config_option)) {
|
||||||
|
app_config config(prov, data_directory);
|
||||||
|
if (prov == provider_type::remote) {
|
||||||
|
auto remote_config = config.get_remote_config();
|
||||||
|
remote_config.host_name_or_ip = remote_host;
|
||||||
|
remote_config.api_port = remote_port;
|
||||||
|
config.set_remote_config(remote_config);
|
||||||
|
} else if (prov == provider_type::sia &&
|
||||||
|
config.get_sia_config().bucket.empty()) {
|
||||||
|
[[maybe_unused]] auto bucket =
|
||||||
|
config.set_value_by_name("SiaConfig.Bucket", unique_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Generated " << app_config::get_provider_display_name(prov)
|
||||||
|
<< " Configuration" << std::endl;
|
||||||
|
std::cout << config.get_config_file_path() << std::endl;
|
||||||
|
return utils::file::file(config.get_config_file_path()).exists()
|
||||||
|
? exit_code::success
|
||||||
|
: exit_code::file_creation_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
if (utils::cli::has_option(args, utils::cli::options::hidden_option)) {
|
||||||
|
::ShowWindow(::GetConsoleWindow(), SW_HIDE);
|
||||||
|
}
|
||||||
|
#endif // defined(_WIN32)
|
||||||
|
|
||||||
|
lock_data global_lock(provider_type::unknown, "global");
|
||||||
|
lock_result = global_lock.grab_lock(100U);
|
||||||
|
if (lock_result != lock_result::success) {
|
||||||
|
std::cerr << "FATAL: Unable to get global lock" << std::endl;
|
||||||
|
return exit_code::lock_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto drive_args = utils::cli::parse_drive_options(args, prov, data_directory);
|
||||||
|
app_config config(prov, data_directory);
|
||||||
|
{
|
||||||
|
std::uint16_t port{};
|
||||||
|
if (not utils::get_next_available_port(config.get_api_port(), port)) {
|
||||||
|
std::cerr << "FATAL: Unable to get available port" << std::endl;
|
||||||
|
return exit_code::startup_exception;
|
||||||
|
}
|
||||||
|
config.set_api_port(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
if (config.get_enable_mount_manager() && not utils::is_process_elevated()) {
|
||||||
|
utils::com_init_wrapper wrapper;
|
||||||
|
if (not lock.set_mount_state(true, "elevating", -1)) {
|
||||||
|
std::cerr << "failed to set mount state" << std::endl;
|
||||||
|
}
|
||||||
|
lock.release();
|
||||||
|
global_lock.release();
|
||||||
|
|
||||||
|
mount_result = utils::run_process_elevated(args);
|
||||||
|
lock_data prov_lock(prov, unique_id);
|
||||||
|
if (prov_lock.grab_lock() == lock_result::success) {
|
||||||
|
if (not prov_lock.set_mount_state(false, "", -1)) {
|
||||||
|
std::cerr << "failed to set mount state" << std::endl;
|
||||||
|
}
|
||||||
|
prov_lock.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
return exit_code::mount_result;
|
||||||
|
}
|
||||||
|
#endif // defined(_WIN32)
|
||||||
|
|
||||||
|
std::cout << "Initializing " << app_config::get_provider_display_name(prov)
|
||||||
|
<< (unique_id.empty() ? ""
|
||||||
|
: (prov == provider_type::remote)
|
||||||
|
? " [" + remote_host + ':' + std::to_string(remote_port) +
|
||||||
|
']'
|
||||||
|
: " [" + unique_id + ']')
|
||||||
|
<< " Drive" << std::endl;
|
||||||
|
if (prov == provider_type::remote) {
|
||||||
|
try {
|
||||||
|
auto remote_cfg = config.get_remote_config();
|
||||||
|
remote_cfg.host_name_or_ip = remote_host;
|
||||||
|
remote_cfg.api_port = remote_port;
|
||||||
|
config.set_remote_config(remote_cfg);
|
||||||
|
|
||||||
|
remote_drive drive(
|
||||||
|
config,
|
||||||
|
[&config]() -> std::unique_ptr<remote_instance> {
|
||||||
|
return std::unique_ptr<remote_instance>(new remote_client(config));
|
||||||
|
},
|
||||||
|
lock);
|
||||||
|
if (not lock.set_mount_state(true, "", -1)) {
|
||||||
|
std::cerr << "failed to set mount state" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
global_lock.release();
|
||||||
|
mount_result = drive.mount(drive_args);
|
||||||
|
return exit_code::mount_result;
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
std::cerr << "FATAL: " << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return exit_code::startup_exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (prov == provider_type::sia && config.get_sia_config().bucket.empty()) {
|
||||||
|
[[maybe_unused]] auto bucket =
|
||||||
|
config.set_value_by_name("SiaConfig.Bucket", unique_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto provider = create_provider(prov, config);
|
||||||
|
repertory_drive drive(config, lock, *provider);
|
||||||
|
if (not lock.set_mount_state(true, "", -1)) {
|
||||||
|
std::cerr << "failed to set mount state" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
global_lock.release();
|
||||||
|
mount_result = drive.mount(drive_args);
|
||||||
|
return exit_code::mount_result;
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
std::cerr << "FATAL: " << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return exit_code::startup_exception;
|
||||||
}
|
}
|
||||||
} // namespace repertory::cli::actions
|
} // namespace repertory::cli::actions
|
||||||
|
|
||||||
|
@ -109,6 +109,14 @@ handlers::handlers(mgmt_app_config *config, httplib::Server *server)
|
|||||||
server_(server) {
|
server_(server) {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
server_->set_socket_options([](auto &&sock) {
|
||||||
|
int enable = 1;
|
||||||
|
setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
|
||||||
|
reinterpret_cast<const char *>(&enable), sizeof(enable));
|
||||||
|
});
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
server_->set_pre_routing_handler(
|
server_->set_pre_routing_handler(
|
||||||
[this](const httplib::Request &req,
|
[this](const httplib::Request &req,
|
||||||
auto &&res) -> httplib::Server::HandlerResponse {
|
auto &&res) -> httplib::Server::HandlerResponse {
|
||||||
@ -505,8 +513,13 @@ void handlers::handle_post_mount(const httplib::Request &req,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::mutex mount_mtx;
|
||||||
|
mutex_lock lock(mount_mtx);
|
||||||
|
|
||||||
launch_process(prov, name, {location}, true);
|
launch_process(prov, name, {location}, true);
|
||||||
config_->set_mount_location(prov, name, location);
|
config_->set_mount_location(prov, name, location);
|
||||||
|
|
||||||
|
launch_process(prov, name, {"-status"});
|
||||||
}
|
}
|
||||||
|
|
||||||
res.status = http_error_codes::ok;
|
res.status = http_error_codes::ok;
|
||||||
|
@ -128,7 +128,7 @@ std::atomic<std::uint64_t> app_config_test::idx{0U};
|
|||||||
|
|
||||||
static void defaults_tests(const json &json_data, provider_type prov) {
|
static void defaults_tests(const json &json_data, provider_type prov) {
|
||||||
json json_defaults = {
|
json json_defaults = {
|
||||||
{JSON_API_PORT, app_config::default_rpc_port(prov)},
|
{JSON_API_PORT, app_config::default_rpc_port()},
|
||||||
{JSON_API_USER, std::string{REPERTORY}},
|
{JSON_API_USER, std::string{REPERTORY}},
|
||||||
{JSON_DOWNLOAD_TIMEOUT_SECS, default_download_timeout_secs},
|
{JSON_DOWNLOAD_TIMEOUT_SECS, default_download_timeout_secs},
|
||||||
{JSON_DATABASE_TYPE, database_type::rocksdb},
|
{JSON_DATABASE_TYPE, database_type::rocksdb},
|
||||||
|
@ -25,8 +25,8 @@
|
|||||||
#include "utils/string.hpp"
|
#include "utils/string.hpp"
|
||||||
|
|
||||||
namespace repertory::utils {
|
namespace repertory::utils {
|
||||||
auto compare_version_strings(std::string version1,
|
auto compare_version_strings(std::string version1, std::string version2)
|
||||||
std::string version2) -> std::int32_t {
|
-> std::int32_t {
|
||||||
|
|
||||||
if (utils::string::contains(version1, "-")) {
|
if (utils::string::contains(version1, "-")) {
|
||||||
version1 = utils::string::split(version1, '-', true)[0U];
|
version1 = utils::string::split(version1, '-', true)[0U];
|
||||||
@ -131,23 +131,46 @@ auto get_next_available_port(std::uint16_t first_port,
|
|||||||
using ip::tcp;
|
using ip::tcp;
|
||||||
|
|
||||||
boost::system::error_code error_code{};
|
boost::system::error_code error_code{};
|
||||||
while (first_port != 0U) {
|
|
||||||
io_context ctx{};
|
std::uint32_t check_port{first_port};
|
||||||
tcp::acceptor acceptor(ctx);
|
while (check_port <= 65535U) {
|
||||||
acceptor.open(tcp::v4(), error_code) ||
|
{
|
||||||
acceptor.bind({tcp::v4(), first_port}, error_code);
|
io_context ctx{};
|
||||||
if (not error_code) {
|
tcp::socket socket(ctx);
|
||||||
break;
|
socket.connect(
|
||||||
|
{
|
||||||
|
tcp::endpoint(ip::address_v4::loopback(),
|
||||||
|
static_cast<std::uint16_t>(check_port)),
|
||||||
|
},
|
||||||
|
error_code);
|
||||||
|
if (not error_code) {
|
||||||
|
++check_port;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
++first_port;
|
{
|
||||||
|
io_context ctx{};
|
||||||
|
tcp::acceptor acceptor(ctx);
|
||||||
|
acceptor.open(tcp::v4(), error_code);
|
||||||
|
if (error_code) {
|
||||||
|
++check_port;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
acceptor.bind({tcp::v4(), static_cast<std::uint16_t>(check_port)},
|
||||||
|
error_code);
|
||||||
|
if (error_code) {
|
||||||
|
++check_port;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
available_port = static_cast<std::uint16_t>(check_port);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not error_code) {
|
return false;
|
||||||
available_port = first_port;
|
|
||||||
}
|
|
||||||
|
|
||||||
return not error_code;
|
|
||||||
}
|
}
|
||||||
#endif // defined(PROJECT_ENABLE_BOOST)
|
#endif // defined(PROJECT_ENABLE_BOOST)
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
@ -111,10 +112,19 @@ class MountList with ChangeNotifier {
|
|||||||
Future<bool> add(
|
Future<bool> add(
|
||||||
String type,
|
String type,
|
||||||
String name,
|
String name,
|
||||||
Map<String, dynamic> mountConfig,
|
Map<String, dynamic> settings,
|
||||||
) async {
|
) async {
|
||||||
var ret = false;
|
var ret = false;
|
||||||
|
|
||||||
|
var apiPort = settings['ApiPort'] ?? 10000;
|
||||||
|
for (var mount in _mountList) {
|
||||||
|
var port = mount.mountConfig.settings['ApiPort'] as int?;
|
||||||
|
if (port != null) {
|
||||||
|
apiPort = max(apiPort, port + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
settings["ApiPort"] = apiPort;
|
||||||
|
|
||||||
displayError() {
|
displayError() {
|
||||||
if (constants.navigatorKey.currentContext == null) {
|
if (constants.navigatorKey.currentContext == null) {
|
||||||
return;
|
return;
|
||||||
@ -129,7 +139,7 @@ class MountList with ChangeNotifier {
|
|||||||
try {
|
try {
|
||||||
final auth = await _auth.createAuth();
|
final auth = await _auth.createAuth();
|
||||||
final map = await convertAllToString(
|
final map = await convertAllToString(
|
||||||
jsonDecode(jsonEncode(mountConfig)),
|
jsonDecode(jsonEncode(settings)),
|
||||||
_auth.key,
|
_auth.key,
|
||||||
);
|
);
|
||||||
final response = await http.post(
|
final response = await http.post(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user