prevent overlapping api ports
This commit is contained in:
parent
e3d036fcb8
commit
630c3463d8
@ -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_;
|
||||||
|
@ -29,8 +29,6 @@
|
|||||||
#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/string.hpp"
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#include "drives/winfsp/remotewinfsp/remote_client.hpp"
|
#include "drives/winfsp/remotewinfsp/remote_client.hpp"
|
||||||
@ -62,125 +60,112 @@ mount(std::vector<const char *> args, std::string data_directory,
|
|||||||
lock_data lock(prov, unique_id);
|
lock_data lock(prov, unique_id);
|
||||||
const auto res = lock.grab_lock();
|
const auto res = lock.grab_lock();
|
||||||
if (res == lock_result::locked) {
|
if (res == 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)
|
if (res != lock_result::success) {
|
||||||
<< " 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;
|
ret = exit_code::lock_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
#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);
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
|
||||||
|
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) {
|
||||||
|
std::uint16_t port{};
|
||||||
|
if (not utils::get_next_available_port(config.get_remote_config().api_port,
|
||||||
|
port)) {
|
||||||
|
std::cerr << "FATAL: Unable to get available port" << std::endl;
|
||||||
|
return exit_code::startup_exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
return exit_code::mount_result;
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
std::cerr << "FATAL: " << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return exit_code::startup_exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
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
|
||||||
|
|
||||||
|
@ -505,6 +505,9 @@ 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);
|
||||||
}
|
}
|
||||||
|
@ -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},
|
||||||
|
@ -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