added check version support to remote mounts
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
|
||||
### Changes from v2.0.7-release
|
||||
|
||||
* Added check version support to remote mounts
|
||||
* Fixed handling of `FALLOC_FL_KEEP_SIZE` on Linux
|
||||
* Fixed intermittent client hang on remote mount server disconnect
|
||||
|
||||
|
@@ -68,7 +68,8 @@ private:
|
||||
|
||||
[[nodiscard]] auto get_client() -> std::shared_ptr<client>;
|
||||
|
||||
[[nodiscard]] auto handshake(client &cli) const -> bool;
|
||||
[[nodiscard]] auto handshake(client &cli, std::uint32_t &min_version) const
|
||||
-> bool;
|
||||
|
||||
void put_client(std::shared_ptr<client> &cli);
|
||||
|
||||
@@ -78,6 +79,9 @@ private:
|
||||
void resolve();
|
||||
|
||||
public:
|
||||
[[nodiscard]] auto check_version(std::uint32_t client_version,
|
||||
std::uint32_t &min_version) -> api_error;
|
||||
|
||||
[[nodiscard]] auto send(std::string_view method, std::uint32_t &service_flags)
|
||||
-> packet::error_type;
|
||||
|
||||
|
@@ -41,6 +41,9 @@ create_rocksdb(const app_config &cfg, const std::string &name,
|
||||
[[nodiscard]] auto create_volume_label(provider_type prov) -> std::string;
|
||||
|
||||
[[nodiscard]] auto get_attributes_from_meta(const api_meta_map &meta) -> DWORD;
|
||||
|
||||
[[nodiscard]] auto get_version_number(std::string_view version)
|
||||
-> std::uint32_t;
|
||||
} // namespace utils
|
||||
} // namespace repertory
|
||||
|
||||
|
@@ -27,7 +27,6 @@
|
||||
#include "utils/collection.hpp"
|
||||
#include "utils/common.hpp"
|
||||
#include "utils/error_utils.hpp"
|
||||
#include "version.hpp"
|
||||
|
||||
using namespace repertory::comm;
|
||||
|
||||
@@ -58,7 +57,8 @@ void packet_client::close(client &cli) {
|
||||
|
||||
boost::system::error_code err;
|
||||
[[maybe_unused]] auto res = cli.socket.close(err);
|
||||
} catch (...) {
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_error(function_name, e, "connection handshake failed");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,6 +76,39 @@ void packet_client::close_all() {
|
||||
unique_id_ = utils::create_uuid_string();
|
||||
}
|
||||
|
||||
auto packet_client::check_version(std::uint32_t client_version,
|
||||
std::uint32_t &min_version) -> api_error {
|
||||
try {
|
||||
min_version = 0U;
|
||||
|
||||
boost::asio::io_context ctx{};
|
||||
auto resolve_results = tcp::resolver(ctx).resolve(
|
||||
cfg_.host_name_or_ip, std::to_string(cfg_.api_port));
|
||||
|
||||
client cli(ctx);
|
||||
connect_with_deadline(ctx, cli.socket, resolve_results,
|
||||
std::chrono::milliseconds(cfg_.conn_timeout_ms));
|
||||
|
||||
cli.socket.set_option(boost::asio::ip::tcp::no_delay(true));
|
||||
cli.socket.set_option(boost::asio::socket_base::linger(false, 0));
|
||||
cli.socket.set_option(boost::asio::socket_base::keep_alive(true));
|
||||
|
||||
if (not handshake(cli, min_version)) {
|
||||
return api_error::comm_error;
|
||||
}
|
||||
|
||||
if (client_version < min_version) {
|
||||
return api_error::incompatible_version;
|
||||
}
|
||||
|
||||
return api_error::success;
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_error(function_name, e, "connection handshake failed");
|
||||
}
|
||||
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
void packet_client::connect(client &cli) {
|
||||
try {
|
||||
resolve();
|
||||
@@ -87,7 +120,8 @@ void packet_client::connect(client &cli) {
|
||||
cli.socket.set_option(boost::asio::socket_base::linger(false, 0));
|
||||
cli.socket.set_option(boost::asio::socket_base::keep_alive(true));
|
||||
|
||||
if (not handshake(cli)) {
|
||||
std::uint32_t min_version{};
|
||||
if (not handshake(cli, min_version)) {
|
||||
close(cli);
|
||||
return;
|
||||
}
|
||||
@@ -131,14 +165,18 @@ auto packet_client::get_client() -> std::shared_ptr<packet_client::client> {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto packet_client::handshake(client &cli) const -> bool {
|
||||
auto packet_client::handshake(client &cli, std::uint32_t &min_version) const
|
||||
-> bool {
|
||||
REPERTORY_USES_FUNCTION_NAME();
|
||||
|
||||
try {
|
||||
min_version = 0U;
|
||||
|
||||
data_buffer buffer;
|
||||
{
|
||||
packet tmp;
|
||||
tmp.encode_top(utils::generate_random_string(packet_nonce_size));
|
||||
tmp.encode(utils::get_version_number(REPERTORY_MIN_REMOTE_VERSION));
|
||||
tmp.encode(utils::generate_random_string(packet_nonce_size));
|
||||
tmp.to_buffer(buffer);
|
||||
}
|
||||
|
||||
@@ -146,6 +184,7 @@ auto packet_client::handshake(client &cli) const -> bool {
|
||||
boost::asio::buffer(buffer),
|
||||
std::chrono::milliseconds(cfg_.recv_timeout_ms));
|
||||
packet response(buffer);
|
||||
response.decode(min_version);
|
||||
response.encrypt(cfg_.encryption_token, false);
|
||||
response.to_buffer(buffer);
|
||||
|
||||
@@ -154,7 +193,7 @@ auto packet_client::handshake(client &cli) const -> bool {
|
||||
std::chrono::milliseconds(cfg_.send_timeout_ms));
|
||||
return true;
|
||||
} catch (const std::exception &e) {
|
||||
repertory::utils::error::raise_error(function_name, e, "handlshake failed");
|
||||
utils::error::raise_error(function_name, e, "handlshake failed");
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@@ -32,12 +32,12 @@
|
||||
#include "types/repertory.hpp"
|
||||
#include "utils/error_utils.hpp"
|
||||
#include "utils/timeout.hpp"
|
||||
#include "utils/utils.hpp"
|
||||
|
||||
using namespace repertory::comm;
|
||||
using std::thread;
|
||||
|
||||
namespace repertory {
|
||||
|
||||
packet_server::packet_server(std::uint16_t port, std::string token,
|
||||
std::uint8_t pool_size, closed_callback closed,
|
||||
message_handler_callback message_handler)
|
||||
@@ -91,7 +91,8 @@ auto packet_server::handshake(std::shared_ptr<connection> conn) const -> bool {
|
||||
|
||||
data_buffer buffer;
|
||||
packet request;
|
||||
request.encode_top(conn->nonce);
|
||||
request.encode(utils::get_version_number(REPERTORY_MIN_REMOTE_VERSION));
|
||||
request.encode(conn->nonce);
|
||||
request.to_buffer(buffer);
|
||||
auto to_read{buffer.size() + utils::encryption::encryption_header_size};
|
||||
|
||||
|
@@ -19,8 +19,6 @@
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#include "rocksdb/table.h"
|
||||
|
||||
#include "utils/utils.hpp"
|
||||
|
||||
#include "app_config.hpp"
|
||||
@@ -90,4 +88,13 @@ auto create_volume_label(provider_type prov) -> std::string {
|
||||
auto get_attributes_from_meta(const api_meta_map &meta) -> DWORD {
|
||||
return static_cast<DWORD>(utils::string::to_uint32(meta.at(META_ATTRIBUTES)));
|
||||
}
|
||||
|
||||
auto get_repertory_version_number(std::string_view version) -> std::uint32_t {
|
||||
auto parts = utils::string::split(version, '-', false);
|
||||
parts = utils::string::split(parts.at(0U), '.', false);
|
||||
|
||||
return (utils::string::to_uint32(parts.at(0U)) << 24U) |
|
||||
(utils::string::to_uint32(parts.at(1U)) << 16U) |
|
||||
(utils::string::to_uint32(parts.at(2U)) << 8U);
|
||||
}
|
||||
} // namespace repertory::utils
|
||||
|
@@ -23,17 +23,41 @@
|
||||
#define REPERTORY_INCLUDE_CLI_CHECK_VERSION_HPP_
|
||||
|
||||
#include "cli/common.hpp"
|
||||
#include "comm/packet/packet_client.hpp"
|
||||
#include "utils/utils.hpp"
|
||||
#include "version.cpp"
|
||||
|
||||
namespace repertory::cli::actions {
|
||||
[[nodiscard]] inline auto check_version(std::vector<const char *> /* args */,
|
||||
const std::string &data_directory,
|
||||
provider_type prov,
|
||||
const std::string & /*unique_id*/,
|
||||
std::string /*user*/,
|
||||
std::string /*password*/) -> exit_code {
|
||||
[[nodiscard]] inline auto
|
||||
check_version(const std::string &data_directory, provider_type prov,
|
||||
const std::string &remote_host, std::uint16_t remote_port)
|
||||
-> exit_code {
|
||||
if (prov == provider_type::remote) {
|
||||
app_config config(prov, data_directory);
|
||||
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);
|
||||
packet_client client(config.get_remote_config());
|
||||
|
||||
std::uint32_t min_version{};
|
||||
auto client_version = utils::get_version_number(project_get_version());
|
||||
auto ret = client.check_version(client_version, min_version);
|
||||
if (ret == api_error::success) {
|
||||
fmt::println("0\nSuccess:\n\tRequired: {}\n\tActual: {}", min_version,
|
||||
client_version);
|
||||
} else {
|
||||
fmt::println("1\nFailed:\n\tRequired: {}\n\tActual: {}", min_version,
|
||||
client_version);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (prov != provider_type::sia) {
|
||||
fmt::println("Success:\n\tNo specific version is required for {} providers",
|
||||
app_config::get_provider_display_name(prov));
|
||||
fmt::println(
|
||||
"0\nSuccess:\n\tNo specific version is required for {} providers",
|
||||
app_config::get_provider_display_name(prov));
|
||||
return exit_code::success;
|
||||
}
|
||||
|
||||
|
@@ -113,6 +113,7 @@ auto main(int argc, char **argv) -> int {
|
||||
'_'),
|
||||
})
|
||||
: utils::path::absolute(data_directory);
|
||||
|
||||
} catch (const std::exception &e) {
|
||||
std::cerr << (e.what() == nullptr ? "Unable to parse port"
|
||||
: e.what())
|
||||
@@ -145,32 +146,38 @@ auto main(int argc, char **argv) -> int {
|
||||
}
|
||||
}
|
||||
|
||||
int mount_result{};
|
||||
if (res == exit_code::success) {
|
||||
res = exit_code::option_not_found;
|
||||
for (std::size_t idx = 0U;
|
||||
(res == exit_code::option_not_found) &&
|
||||
(idx < utils::cli::options::option_list.size());
|
||||
idx++) {
|
||||
try {
|
||||
res = cli::actions::perform_action(
|
||||
utils::cli::options::option_list[idx], args, data_directory, prov,
|
||||
unique_id, user, password);
|
||||
} catch (const std::exception &ex) {
|
||||
res = exit_code::exception;
|
||||
} catch (...) {
|
||||
res = exit_code::exception;
|
||||
if (utils::cli::has_option(args,
|
||||
utils::cli::options::check_version_option)) {
|
||||
ret = static_cast<std::int32_t>(utils::cli::check_version(
|
||||
data_directory, prov, remote_host, remote_port));
|
||||
} else {
|
||||
int mount_result{};
|
||||
if (res == exit_code::success) {
|
||||
res = exit_code::option_not_found;
|
||||
for (std::size_t idx = 0U;
|
||||
(res == exit_code::option_not_found) &&
|
||||
(idx < utils::cli::options::option_list.size());
|
||||
idx++) {
|
||||
try {
|
||||
res = cli::actions::perform_action(
|
||||
utils::cli::options::option_list[idx], args, data_directory,
|
||||
prov, unique_id, user, password);
|
||||
} catch (const std::exception &ex) {
|
||||
res = exit_code::exception;
|
||||
} catch (...) {
|
||||
res = exit_code::exception;
|
||||
}
|
||||
}
|
||||
|
||||
if (res == exit_code::option_not_found) {
|
||||
res = cli::actions::mount(args, data_directory, mount_result, prov,
|
||||
remote_host, remote_port, unique_id);
|
||||
}
|
||||
}
|
||||
|
||||
if (res == exit_code::option_not_found) {
|
||||
res = cli::actions::mount(args, data_directory, mount_result, prov,
|
||||
remote_host, remote_port, unique_id);
|
||||
}
|
||||
ret = ((res == exit_code::mount_result) ? mount_result
|
||||
: static_cast<std::int32_t>(res));
|
||||
}
|
||||
|
||||
ret = ((res == exit_code::mount_result) ? mount_result
|
||||
: static_cast<std::int32_t>(res));
|
||||
}
|
||||
|
||||
repertory::project_cleanup();
|
||||
|
Reference in New Issue
Block a user