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);
 | |
| } |