167 lines
5.8 KiB
C++
167 lines
5.8 KiB
C++
//
|
|
// Created by WolverinDEV on 28/04/2020.
|
|
//
|
|
|
|
#include <netinet/in.h>
|
|
#include <log/LogUtils.h>
|
|
#include "LocalFileProvider.h"
|
|
|
|
using namespace ts::server;
|
|
using LocalFileServer = file::LocalFileProvider;
|
|
using LocalVirtualFileServer = file::LocalVirtualFileServer;
|
|
|
|
std::shared_ptr<LocalFileServer> server_instance{};
|
|
bool file::initialize(std::string &error, const std::string& hostnames, uint16_t port) {
|
|
server_instance = std::make_shared<LocalFileProvider>();
|
|
|
|
if(!server_instance->initialize(error)) {
|
|
server_instance = nullptr;
|
|
return false;
|
|
}
|
|
|
|
bool any_bind{false};
|
|
for(const auto& binding : net::resolve_bindings(hostnames, port)) {
|
|
if(!get<2>(binding).empty()) {
|
|
logError(LOG_FT, "Failed to resolve binding for {}: {}", get<0>(binding), get<2>(binding));
|
|
continue;
|
|
}
|
|
|
|
auto result = dynamic_cast<transfer::LocalFileTransfer&>(server_instance->file_transfer()).add_network_binding({ get<0>(binding), get<1>(binding) });
|
|
switch (result) {
|
|
case transfer::NetworkingBindResult::SUCCESS:
|
|
any_bind = true;
|
|
break;
|
|
|
|
case transfer::NetworkingBindResult::OUT_OF_MEMORY:
|
|
logWarning(LOG_FT, "Failed to listen to address {}: Out of memory", get<0>(binding));
|
|
continue;
|
|
|
|
case transfer::NetworkingBindResult::FAILED_TO_LISTEN:
|
|
logWarning(LOG_FT, "Failed to listen on {}: {}/{}", get<0>(binding), errno, strerror(errno));
|
|
continue;
|
|
|
|
case transfer::NetworkingBindResult::FAILED_TO_BIND:
|
|
logWarning(LOG_FT, "Failed to bind on {}: {}/{}", get<0>(binding), errno, strerror(errno));
|
|
continue;
|
|
|
|
case transfer::NetworkingBindResult::BINDING_ALREADY_EXISTS:
|
|
logWarning(LOG_FT, "Failed to bind on {}: binding already exists", get<0>(binding));
|
|
continue;
|
|
|
|
case transfer::NetworkingBindResult::NETWORKING_NOT_INITIALIZED:
|
|
logWarning(LOG_FT, "Failed to bind on {}: networking not initialized", get<0>(binding));
|
|
continue;
|
|
|
|
case transfer::NetworkingBindResult::FAILED_TO_ALLOCATE_SOCKET:
|
|
logWarning(LOG_FT, "Failed to allocate a socket for {}: {}/{}", get<0>(binding), errno, strerror(errno));
|
|
continue;
|
|
}
|
|
}
|
|
#if 0
|
|
{
|
|
auto query_bindings_string = this->properties()[property::SERVERINSTANCE_QUERY_HOST].as<string>();
|
|
auto query_port = this->properties()[property::SERVERINSTANCE_QUERY_PORT].as<uint16_t>();
|
|
auto query_bindings = net::resolve_bindings(query_bindings_string, query_port);
|
|
deque<shared_ptr<QueryServer::Binding>> bindings;
|
|
|
|
for(auto& binding : query_bindings) {
|
|
if(!get<2>(binding).empty()) {
|
|
logError(LOG_QUERY, "Failed to resolve binding for {}: {}", get<0>(binding), get<2>(binding));
|
|
continue;
|
|
}
|
|
auto entry = make_shared<QueryServer::Binding>();
|
|
memcpy(&entry->address, &get<1>(binding), sizeof(sockaddr_storage));
|
|
|
|
entry->file_descriptor = -1;
|
|
entry->event_accept = nullptr;
|
|
bindings.push_back(entry);
|
|
}
|
|
|
|
logMessage(LOG_QUERY, "Starting server on {}:{}", query_bindings_string, query_port);
|
|
if(!queryServer->start(bindings, errorMessage)) {
|
|
logCritical(LOG_QUERY, "Failed to start query server: {}", errorMessage);
|
|
return false;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
void file::finalize() {
|
|
auto server = std::exchange(server_instance, nullptr);
|
|
if(!server) return;
|
|
|
|
server->finalize();
|
|
}
|
|
|
|
std::shared_ptr<file::AbstractFileServer> file::server() {
|
|
return server_instance;
|
|
}
|
|
|
|
LocalFileServer::LocalFileProvider() : file_system_{}, file_transfer_{this->file_system_} {}
|
|
LocalFileServer::~LocalFileProvider() = default;
|
|
|
|
bool LocalFileServer::initialize(std::string &error) {
|
|
if(!this->file_system_.initialize(error, "files/"))
|
|
return false;
|
|
|
|
if(!this->file_transfer_.start()) {
|
|
error = "transfer server startup failed";
|
|
this->file_system_.finalize();
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void LocalFileServer::finalize() {
|
|
this->file_transfer_.stop();
|
|
this->file_system_.finalize();
|
|
}
|
|
|
|
file::filesystem::AbstractProvider &LocalFileServer::file_system() {
|
|
return this->file_system_;
|
|
}
|
|
|
|
file::transfer::AbstractProvider &LocalFileServer::file_transfer() {
|
|
return this->file_transfer_;
|
|
}
|
|
|
|
std::string file::LocalFileProvider::file_base_path() const {
|
|
return this->file_system_.root_path();
|
|
}
|
|
|
|
std::shared_ptr<file::VirtualFileServer> LocalFileServer::register_server(ServerId server_id) {
|
|
auto server = this->find_virtual_server(server_id);
|
|
if(server) return server;
|
|
|
|
server = std::make_shared<file::LocalVirtualFileServer>(server_id, std::to_string(server_id));
|
|
{
|
|
std::lock_guard slock{this->servers_mutex};
|
|
this->servers_.push_back(server);
|
|
}
|
|
|
|
return server;
|
|
}
|
|
|
|
void LocalFileServer::unregister_server(ServerId server_id) {
|
|
auto server_unique_id = std::to_string(server_id);
|
|
|
|
std::lock_guard slock{this->servers_mutex};
|
|
auto it = std::find_if(this->servers_.begin(), this->servers_.end(), [&](const std::shared_ptr<VirtualFileServer>& server) {
|
|
return server->unique_id() == server_unique_id;
|
|
});
|
|
|
|
if(it == this->servers_.end()) return;
|
|
this->servers_.erase(it);
|
|
}
|
|
|
|
void LocalVirtualFileServer::max_networking_upload_bandwidth(int64_t value) {
|
|
VirtualFileServer::max_networking_upload_bandwidth(value);
|
|
this->upload_throttle.set_max_bandwidth(value);
|
|
}
|
|
|
|
void LocalVirtualFileServer::max_networking_download_bandwidth(int64_t value) {
|
|
VirtualFileServer::max_networking_download_bandwidth(value);
|
|
this->download_throttle.set_max_bandwidth(value);
|
|
} |