File transfer server now respects the port and host settings set via the config.yml
This commit is contained in:
		
							parent
							
								
									ed7cbd38e8
								
							
						
					
					
						commit
						a23002ce66
					
				| @ -413,7 +413,7 @@ namespace ts::server::file { | |||||||
|             std::deque<std::shared_ptr<VirtualFileServer>> servers_{}; |             std::deque<std::shared_ptr<VirtualFileServer>> servers_{}; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     extern bool initialize(std::string& /* error */); |     extern bool initialize(std::string& /* error */, const std::string& /* host names */, uint16_t /* port */); | ||||||
|     extern void finalize(); |     extern void finalize(); | ||||||
| 
 | 
 | ||||||
|     extern std::shared_ptr<AbstractFileServer> server(); |     extern std::shared_ptr<AbstractFileServer> server(); | ||||||
|  | |||||||
| @ -3,6 +3,7 @@ | |||||||
| //
 | //
 | ||||||
| 
 | 
 | ||||||
| #include <netinet/in.h> | #include <netinet/in.h> | ||||||
|  | #include <log/LogUtils.h> | ||||||
| #include "LocalFileProvider.h" | #include "LocalFileProvider.h" | ||||||
| 
 | 
 | ||||||
| using namespace ts::server; | using namespace ts::server; | ||||||
| @ -10,13 +11,80 @@ using LocalFileServer = file::LocalFileProvider; | |||||||
| using LocalVirtualFileServer = file::LocalVirtualFileServer; | using LocalVirtualFileServer = file::LocalVirtualFileServer; | ||||||
| 
 | 
 | ||||||
| std::shared_ptr<LocalFileServer> server_instance{}; | std::shared_ptr<LocalFileServer> server_instance{}; | ||||||
| bool file::initialize(std::string &error) { | bool file::initialize(std::string &error, const std::string& hostnames, uint16_t port) { | ||||||
|     server_instance = std::make_shared<LocalFileProvider>(); |     server_instance = std::make_shared<LocalFileProvider>(); | ||||||
| 
 | 
 | ||||||
|     if(!server_instance->initialize(error)) { |     if(!server_instance->initialize(error)) { | ||||||
|         server_instance = nullptr; |         server_instance = nullptr; | ||||||
|         return false; |         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; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -32,28 +100,13 @@ std::shared_ptr<file::AbstractFileServer> file::server() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| LocalFileServer::LocalFileProvider() : file_system_{}, file_transfer_{this->file_system_} {} | LocalFileServer::LocalFileProvider() : file_system_{}, file_transfer_{this->file_system_} {} | ||||||
| LocalFileServer::~LocalFileProvider() {} | LocalFileServer::~LocalFileProvider() = default; | ||||||
| 
 | 
 | ||||||
| bool LocalFileServer::initialize(std::string &error) { | bool LocalFileServer::initialize(std::string &error) { | ||||||
|     if(!this->file_system_.initialize(error, "files/")) |     if(!this->file_system_.initialize(error, "files/")) | ||||||
|         return false; |         return false; | ||||||
| 
 | 
 | ||||||
| 
 |     if(!this->file_transfer_.start()) { | ||||||
|     std::deque<std::shared_ptr<transfer::NetworkBinding>> bindings{}; |  | ||||||
|     { |  | ||||||
|         auto binding = std::make_shared<transfer::NetworkBinding>(); |  | ||||||
| 
 |  | ||||||
|         binding->hostname = "0.0.0.0"; |  | ||||||
| 
 |  | ||||||
|         auto& iaddr = *(sockaddr_in*) &binding->address; |  | ||||||
|         iaddr.sin_family = AF_INET; |  | ||||||
|         iaddr.sin_port = htons(30303); |  | ||||||
|         iaddr.sin_addr.s_addr = INADDR_ANY; |  | ||||||
| 
 |  | ||||||
|         bindings.push_back(std::move(binding)); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if(!this->file_transfer_.start(bindings)) { |  | ||||||
|         error = "transfer server startup failed"; |         error = "transfer server startup failed"; | ||||||
|         this->file_system_.finalize(); |         this->file_system_.finalize(); | ||||||
|         return false; |         return false; | ||||||
|  | |||||||
| @ -11,6 +11,7 @@ | |||||||
| #include <misc/net.h> | #include <misc/net.h> | ||||||
| #include <misc/spin_mutex.h> | #include <misc/spin_mutex.h> | ||||||
| #include <random> | #include <random> | ||||||
|  | #include <misc/memtracker.h> | ||||||
| #include "./NetTools.h" | #include "./NetTools.h" | ||||||
| 
 | 
 | ||||||
| #define TRANSFER_MAX_CACHED_BYTES (1024 * 1024 * 1) // Buffer up to 1mb
 | #define TRANSFER_MAX_CACHED_BYTES (1024 * 1024 * 1) // Buffer up to 1mb
 | ||||||
| @ -243,7 +244,7 @@ namespace ts::server::file { | |||||||
|                 std::chrono::system_clock::time_point disconnecting{}; |                 std::chrono::system_clock::time_point disconnecting{}; | ||||||
|             } timings; |             } timings; | ||||||
| 
 | 
 | ||||||
|             explicit FileClient(LocalFileTransfer* handle) : handle{handle} {} |             explicit FileClient(LocalFileTransfer* handle) : handle{handle} { memtrack::allocated<FileClient>(this); } | ||||||
|             ~FileClient(); |             ~FileClient(); | ||||||
| 
 | 
 | ||||||
|             void add_network_write_event(bool /* ignore bandwidth limits */); |             void add_network_write_event(bool /* ignore bandwidth limits */); | ||||||
| @ -270,8 +271,24 @@ namespace ts::server::file { | |||||||
| 
 | 
 | ||||||
|         enum struct NetworkingStartResult { |         enum struct NetworkingStartResult { | ||||||
|             SUCCESS, |             SUCCESS, | ||||||
|  |             OUT_OF_MEMORY | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         enum struct NetworkingBindResult { | ||||||
|  |             SUCCESS, | ||||||
|  | 
 | ||||||
|  |             BINDING_ALREADY_EXISTS, | ||||||
|  |             NETWORKING_NOT_INITIALIZED, | ||||||
|  |             FAILED_TO_ALLOCATE_SOCKET, /* errno is set */ | ||||||
|  |             FAILED_TO_BIND, | ||||||
|  |             FAILED_TO_LISTEN, | ||||||
|  | 
 | ||||||
|             OUT_OF_MEMORY, |             OUT_OF_MEMORY, | ||||||
|             NO_BINDINGS |         }; | ||||||
|  | 
 | ||||||
|  |         enum struct NetworkingUnbindResult { | ||||||
|  |             SUCCESS, | ||||||
|  |             UNKNOWN_BINDING | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         enum struct ClientWorkerStartResult { |         enum struct ClientWorkerStartResult { | ||||||
| @ -364,7 +381,12 @@ namespace ts::server::file { | |||||||
|             /* UNKNOWN ERROR */ |             /* UNKNOWN ERROR */ | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         struct NetworkBinding : std::enable_shared_from_this<NetworkBinding> { |         struct NetworkBinding { | ||||||
|  |             std::string hostname{}; | ||||||
|  |             sockaddr_storage address{}; | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         struct ActiveNetworkBinding : std::enable_shared_from_this<ActiveNetworkBinding> { | ||||||
|             std::string hostname{}; |             std::string hostname{}; | ||||||
|             sockaddr_storage address{}; |             sockaddr_storage address{}; | ||||||
| 
 | 
 | ||||||
| @ -379,9 +401,13 @@ namespace ts::server::file { | |||||||
|                 explicit LocalFileTransfer(filesystem::LocalFileSystem&); |                 explicit LocalFileTransfer(filesystem::LocalFileSystem&); | ||||||
|                 ~LocalFileTransfer(); |                 ~LocalFileTransfer(); | ||||||
| 
 | 
 | ||||||
|                 [[nodiscard]] bool start(const std::deque<std::shared_ptr<NetworkBinding>>& /* bindings */); |                 [[nodiscard]] bool start(); | ||||||
|                 void stop(); |                 void stop(); | ||||||
| 
 | 
 | ||||||
|  |                 [[nodiscard]] NetworkingBindResult add_network_binding(const NetworkBinding& /* binding */); | ||||||
|  |                 [[nodiscard]] std::vector<NetworkBinding> active_network_bindings(); | ||||||
|  |                 [[nodiscard]] NetworkingUnbindResult remove_network_binding(const NetworkBinding& /* binding */); | ||||||
|  | 
 | ||||||
|                 std::shared_ptr<ExecuteResponse<TransferInitError, std::shared_ptr<Transfer>>> |                 std::shared_ptr<ExecuteResponse<TransferInitError, std::shared_ptr<Transfer>>> | ||||||
|                 initialize_channel_transfer(Transfer::Direction direction, const std::shared_ptr<VirtualFileServer>& server, ChannelId channelId, |                 initialize_channel_transfer(Transfer::Direction direction, const std::shared_ptr<VirtualFileServer>& server, ChannelId channelId, | ||||||
|                                             const TransferInfo &info) override; |                                             const TransferInfo &info) override; | ||||||
| @ -430,11 +456,13 @@ namespace ts::server::file { | |||||||
|                 } disconnect; |                 } disconnect; | ||||||
| 
 | 
 | ||||||
|                 struct { |                 struct { | ||||||
|  |                     std::mutex mutex; | ||||||
|  | 
 | ||||||
|                     bool active{false}; |                     bool active{false}; | ||||||
|                     std::thread dispatch_thread{}; |                     std::thread dispatch_thread{}; | ||||||
|                     struct event_base* event_base{nullptr}; |                     struct event_base* event_base{nullptr}; | ||||||
| 
 | 
 | ||||||
|                     std::deque<std::shared_ptr<NetworkBinding>> bindings{}; |                     std::deque<std::shared_ptr<ActiveNetworkBinding>> bindings{}; | ||||||
|                 } network{}; |                 } network{}; | ||||||
| 
 | 
 | ||||||
|                 struct { |                 struct { | ||||||
|  | |||||||
| @ -7,7 +7,6 @@ | |||||||
| #include <log/LogUtils.h> | #include <log/LogUtils.h> | ||||||
| #include <random> | #include <random> | ||||||
| #include "./LocalFileProvider.h" | #include "./LocalFileProvider.h" | ||||||
| #include "LocalFileProvider.h" |  | ||||||
| #include <experimental/filesystem> | #include <experimental/filesystem> | ||||||
| 
 | 
 | ||||||
| namespace fs = std::experimental::filesystem; | namespace fs = std::experimental::filesystem; | ||||||
| @ -42,12 +41,13 @@ FileClient::~FileClient() { | |||||||
|     assert(!this->networking.event_write); |     assert(!this->networking.event_write); | ||||||
| 
 | 
 | ||||||
|     assert(this->state == STATE_DISCONNECTED); |     assert(this->state == STATE_DISCONNECTED); | ||||||
|  |     memtrack::freed<FileClient>(this); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| LocalFileTransfer::LocalFileTransfer(filesystem::LocalFileSystem &fs) : file_system_{fs} {} | LocalFileTransfer::LocalFileTransfer(filesystem::LocalFileSystem &fs) : file_system_{fs} {} | ||||||
| LocalFileTransfer::~LocalFileTransfer() = default; | LocalFileTransfer::~LocalFileTransfer() = default; | ||||||
| 
 | 
 | ||||||
| bool LocalFileTransfer::start(const std::deque<std::shared_ptr<NetworkBinding>>& bindings) { | bool LocalFileTransfer::start() { | ||||||
|     (void) this->start_client_worker(); |     (void) this->start_client_worker(); | ||||||
| 
 | 
 | ||||||
|     { |     { | ||||||
| @ -66,17 +66,15 @@ bool LocalFileTransfer::start(const std::deque<std::shared_ptr<NetworkBinding>>& | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     { |     { | ||||||
|         this->network.bindings = bindings; |  | ||||||
|         auto start_result = this->start_networking(); |         auto start_result = this->start_networking(); | ||||||
|         switch (start_result) { |         switch (start_result) { | ||||||
|             case NetworkingStartResult::SUCCESS: |             case NetworkingStartResult::SUCCESS: | ||||||
|                 break; |                 break; | ||||||
|  | 
 | ||||||
|             case NetworkingStartResult::OUT_OF_MEMORY: |             case NetworkingStartResult::OUT_OF_MEMORY: | ||||||
|                 logError(LOG_FT, "Failed to start networking (Out of memory)"); |                 logError(LOG_FT, "Failed to start networking (Out of memory)"); | ||||||
|                 goto error_exit_network; |                 goto error_exit_network; | ||||||
|             case NetworkingStartResult::NO_BINDINGS: | 
 | ||||||
|                 logError(LOG_FT, "Failed to start networking (No address could be bound)"); |  | ||||||
|                 goto error_exit_network; |  | ||||||
|             default: |             default: | ||||||
|                 logError(LOG_FT, "Failed to start networking ({})", (int) start_result); |                 logError(LOG_FT, "Failed to start networking ({})", (int) start_result); | ||||||
|                 goto error_exit_network; |                 goto error_exit_network; | ||||||
|  | |||||||
| @ -168,95 +168,161 @@ void FileClient::flush_network_buffer() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| NetworkingStartResult LocalFileTransfer::start_networking() { | NetworkingStartResult LocalFileTransfer::start_networking() { | ||||||
|  |     std::lock_guard nlock{this->network.mutex}; | ||||||
|     assert(!this->network.active); |     assert(!this->network.active); | ||||||
| 
 | 
 | ||||||
|     this->network.active = true; |     this->network.active = true; | ||||||
|     this->network.event_base = event_base_new(); |     this->network.event_base = event_base_new(); | ||||||
|     if(!this->network.event_base) return NetworkingStartResult::OUT_OF_MEMORY; |     if(!this->network.event_base) return NetworkingStartResult::OUT_OF_MEMORY; | ||||||
| 
 | 
 | ||||||
|     bool bound{false}; |  | ||||||
|     for(auto& binding : this->network.bindings) { |  | ||||||
|         binding->file_descriptor = socket(binding->address.ss_family, SOCK_STREAM | SOCK_NONBLOCK, 0); |  | ||||||
|         if(!binding->file_descriptor) { |  | ||||||
|             logWarning(LOG_FT, "Failed to allocate socket for {}: {}/{}", binding->hostname, errno, strerror(errno)); |  | ||||||
|             continue; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|         int enable = 1, disabled = 0; |  | ||||||
| 
 |  | ||||||
|         if (setsockopt(binding->file_descriptor, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0) |  | ||||||
|             logWarning(LOG_FT, "Failed to activate SO_REUSEADDR for binding {} ({} | {})", binding->hostname, errno, strerror(errno)); |  | ||||||
| 
 |  | ||||||
|         if(setsockopt(binding->file_descriptor, IPPROTO_TCP, TCP_NOPUSH, &disabled, sizeof disabled) < 0) |  | ||||||
|             logWarning(LOG_FT, "Failed to deactivate TCP_NOPUSH for binding {} ({} | {})", binding->hostname, errno, strerror(errno)); |  | ||||||
| 
 |  | ||||||
|         if(binding->address.ss_family == AF_INET6) { |  | ||||||
|             if(setsockopt(binding->file_descriptor, IPPROTO_IPV6, IPV6_V6ONLY, &enable, sizeof(int)) < 0) |  | ||||||
|                 logWarning(LOG_FT, "Failed to activate IPV6_V6ONLY for IPv6 binding {} ({} | {})", binding->hostname, errno, strerror(errno)); |  | ||||||
|         } |  | ||||||
|         if(fcntl(binding->file_descriptor, F_SETFD, FD_CLOEXEC) < 0) |  | ||||||
|             logWarning(LOG_FT, "Failed to set flag FD_CLOEXEC for binding {} ({} | {})", binding->hostname, errno, strerror(errno)); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|         if (bind(binding->file_descriptor, (struct sockaddr *) &binding->address, sizeof(binding->address)) < 0) { |  | ||||||
|             logError(LOG_FT, "Failed to bind server to {}. (Failed to bind socket: {} | {})", binding->hostname, errno, strerror(errno)); |  | ||||||
|             goto reset_binding; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if (listen(binding->file_descriptor, 8) < 0) { |  | ||||||
|             logError(LOG_FT, "Failed to bind server to {}. (Failed to listen: {} | {})", binding->hostname, errno, strerror(errno)); |  | ||||||
|             goto reset_binding; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         binding->handle = this; |  | ||||||
|         binding->accept_event = event_new(this->network.event_base, binding->file_descriptor, (unsigned) EV_READ | (unsigned) EV_PERSIST, &LocalFileTransfer::callback_transfer_network_accept, &*binding); |  | ||||||
|         if(!binding->accept_event) |  | ||||||
|             goto reset_binding; |  | ||||||
| 
 |  | ||||||
|         event_add(binding->accept_event, nullptr); |  | ||||||
|         logMessage(LOG_FT, "Started to listen on {}:{}", binding->hostname, net::port(binding->address)); |  | ||||||
| 
 |  | ||||||
|         bound = true; |  | ||||||
|         continue; |  | ||||||
| 
 |  | ||||||
|         reset_binding: |  | ||||||
|         if(binding->accept_event) { |  | ||||||
|             event_free(binding->accept_event); |  | ||||||
|             binding->accept_event = nullptr; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if(binding->file_descriptor > 0) |  | ||||||
|             ::close(binding->file_descriptor); |  | ||||||
|         binding->file_descriptor = 0; |  | ||||||
| 
 |  | ||||||
|         binding->handle = nullptr; |  | ||||||
|     } |  | ||||||
|     if(!bound) { |  | ||||||
|         event_base_free(std::exchange(this->network.event_base, nullptr)); |  | ||||||
|         return NetworkingStartResult::NO_BINDINGS; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     this->network.dispatch_thread = std::thread(&LocalFileTransfer::dispatch_loop_network, this); |     this->network.dispatch_thread = std::thread(&LocalFileTransfer::dispatch_loop_network, this); | ||||||
|     return NetworkingStartResult::SUCCESS; |     return NetworkingStartResult::SUCCESS; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void LocalFileTransfer::shutdown_networking() { | NetworkingBindResult LocalFileTransfer::add_network_binding(const NetworkBinding &binding) { | ||||||
|     if(!this->network.active) return; |     std::lock_guard nlock{this->network.mutex}; | ||||||
|     this->network.active = false; |     if(!this->network.active) | ||||||
|  |         return NetworkingBindResult::NETWORKING_NOT_INITIALIZED; | ||||||
| 
 | 
 | ||||||
|     for(auto& binding : this->network.bindings) { |     for(const auto& abinding : this->network.bindings) { | ||||||
|         if(binding->accept_event) { |         if(net::address_equal(abinding->address, binding.address) && net::port(abinding->address) == net::port(binding.address)) | ||||||
|             event_del_block(binding->accept_event); |             return NetworkingBindResult::BINDING_ALREADY_EXISTS; | ||||||
|             event_free(binding->accept_event); |     } | ||||||
|             binding->accept_event = nullptr; | 
 | ||||||
|  |     NetworkingBindResult result{NetworkingBindResult::SUCCESS}; | ||||||
|  |     auto abinding = std::make_shared<ActiveNetworkBinding>(); | ||||||
|  |     abinding->handle = this; | ||||||
|  |     abinding->hostname = binding.hostname; | ||||||
|  |     memcpy(&abinding->address, &binding.address, sizeof(binding.address)); | ||||||
|  | 
 | ||||||
|  |     abinding->file_descriptor = socket(abinding->address.ss_family, SOCK_STREAM | SOCK_NONBLOCK, 0); | ||||||
|  |     if(!abinding->file_descriptor) { | ||||||
|  |         //logWarning(LOG_FT, "Failed to allocate socket for {}: {}/{}", abinding->hostname, errno, strerror(errno));
 | ||||||
|  |         return NetworkingBindResult::FAILED_TO_ALLOCATE_SOCKET; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     int enable = 1, disabled = 0; | ||||||
|  | 
 | ||||||
|  |     if (setsockopt(abinding->file_descriptor, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0) | ||||||
|  |         logWarning(LOG_FT, "Failed to activate SO_REUSEADDR for binding {} ({}/{})", abinding->hostname, errno, strerror(errno)); | ||||||
|  | 
 | ||||||
|  |     if(setsockopt(abinding->file_descriptor, IPPROTO_TCP, TCP_NOPUSH, &disabled, sizeof disabled) < 0) | ||||||
|  |         logWarning(LOG_FT, "Failed to deactivate TCP_NOPUSH for binding {} ({}/{})", abinding->hostname, errno, strerror(errno)); | ||||||
|  | 
 | ||||||
|  |     if(abinding->address.ss_family == AF_INET6) { | ||||||
|  |         if(setsockopt(abinding->file_descriptor, IPPROTO_IPV6, IPV6_V6ONLY, &enable, sizeof(int)) < 0) | ||||||
|  |             logWarning(LOG_FT, "Failed to activate IPV6_V6ONLY for IPv6 binding {} ({}/{})", abinding->hostname, errno, strerror(errno)); | ||||||
|  |     } | ||||||
|  |     if(fcntl(abinding->file_descriptor, F_SETFD, FD_CLOEXEC) < 0) | ||||||
|  |         logWarning(LOG_FT, "Failed to set flag FD_CLOEXEC for binding {} ({}/{})", abinding->hostname, errno, strerror(errno)); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     if (bind(abinding->file_descriptor, (struct sockaddr *) &abinding->address, sizeof(abinding->address)) < 0) { | ||||||
|  |         //logError(LOG_FT, "Failed to bind server to {}. (Failed to bind socket: {}/{})", binding->hostname, errno, strerror(errno));
 | ||||||
|  |         result = NetworkingBindResult::FAILED_TO_BIND; | ||||||
|  |         goto reset_binding; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (listen(abinding->file_descriptor, 8) < 0) { | ||||||
|  |         //logError(LOG_FT, "Failed to bind server to {}. (Failed to listen: {}/{})", binding->hostname, errno, strerror(errno));
 | ||||||
|  |         result = NetworkingBindResult::FAILED_TO_LISTEN; | ||||||
|  |         goto reset_binding; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     abinding->accept_event = event_new(this->network.event_base, abinding->file_descriptor, (unsigned) EV_READ | (unsigned) EV_PERSIST, &LocalFileTransfer::callback_transfer_network_accept, &*abinding); | ||||||
|  |     if(!abinding->accept_event) { | ||||||
|  |         result = NetworkingBindResult::OUT_OF_MEMORY; | ||||||
|  |         goto reset_binding; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     event_add(abinding->accept_event, nullptr); | ||||||
|  |     logMessage(LOG_FT, "Started to listen on {}:{}", abinding->hostname, net::port(abinding->address)); | ||||||
|  |     this->network.bindings.push_back(std::move(abinding)); | ||||||
|  | 
 | ||||||
|  |     return NetworkingBindResult::SUCCESS; | ||||||
|  | 
 | ||||||
|  |     reset_binding: | ||||||
|  |     if(abinding->accept_event) { | ||||||
|  |         event_free(abinding->accept_event); | ||||||
|  |         abinding->accept_event = nullptr; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if(abinding->file_descriptor > 0) | ||||||
|  |         ::close(abinding->file_descriptor); | ||||||
|  |     abinding->file_descriptor = 0; | ||||||
|  |     abinding->handle = nullptr; | ||||||
|  |     return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::vector<NetworkBinding> LocalFileTransfer::active_network_bindings() { | ||||||
|  |     std::lock_guard nlock{this->network.mutex}; | ||||||
|  |     std::vector<NetworkBinding> result{}; | ||||||
|  |     result.reserve(this->network.bindings.size()); | ||||||
|  | 
 | ||||||
|  |     for(const auto& binding : this->network.bindings) { | ||||||
|  |         auto& rbinding = result.emplace_back(); | ||||||
|  |         rbinding.hostname = binding->hostname; | ||||||
|  |         memcpy(&rbinding.address, &binding->address, sizeof(rbinding.address)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | NetworkingUnbindResult LocalFileTransfer::remove_network_binding(const NetworkBinding &binding) { | ||||||
|  |     std::lock_guard nlock{this->network.mutex}; | ||||||
|  |     std::shared_ptr<ActiveNetworkBinding> abinding{}; | ||||||
|  |     for(auto it = this->network.bindings.begin(); it != this->network.bindings.end(); it++) { | ||||||
|  |         abinding = *it; | ||||||
|  | 
 | ||||||
|  |         if(net::address_equal(abinding->address, binding.address) && net::port(abinding->address) == net::port(binding.address)) { | ||||||
|  |             this->network.bindings.erase(it); | ||||||
|  |             break; | ||||||
|         } |         } | ||||||
|  |         abinding = nullptr; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|         if(binding->file_descriptor > 0) |     if(!abinding) | ||||||
|             ::close(binding->file_descriptor); |         return NetworkingUnbindResult::UNKNOWN_BINDING; | ||||||
|         binding->file_descriptor = 0; |  | ||||||
| 
 | 
 | ||||||
|         binding->handle = nullptr; |     if(abinding->accept_event) { | ||||||
|  |         event_del_block(abinding->accept_event); | ||||||
|  |         event_free(abinding->accept_event); | ||||||
|  |         abinding->accept_event = nullptr; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if(abinding->file_descriptor > 0) | ||||||
|  |         ::close(abinding->file_descriptor); | ||||||
|  |     abinding->file_descriptor = 0; | ||||||
|  |     abinding->handle = nullptr; | ||||||
|  | 
 | ||||||
|  |     return NetworkingUnbindResult::SUCCESS; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void LocalFileTransfer::shutdown_networking() { | ||||||
|  |     event_base* ev_base; | ||||||
|  |     std::thread dispatch_thread{}; | ||||||
|  |     { | ||||||
|  |         std::lock_guard nlock{this->network.mutex}; | ||||||
|  |         if(!this->network.active) return; | ||||||
|  |         this->network.active = false; | ||||||
|  | 
 | ||||||
|  |         for(auto& binding : this->network.bindings) { | ||||||
|  |             if(binding->accept_event) { | ||||||
|  |                 event_del_block(binding->accept_event); | ||||||
|  |                 event_free(binding->accept_event); | ||||||
|  |                 binding->accept_event = nullptr; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if(binding->file_descriptor > 0) | ||||||
|  |                 ::close(binding->file_descriptor); | ||||||
|  |             binding->file_descriptor = 0; | ||||||
|  |             binding->handle = nullptr; | ||||||
|  |         } | ||||||
|  |         this->network.bindings.clear(); | ||||||
|  | 
 | ||||||
|  |         ev_base = std::exchange(this->network.event_base, nullptr); | ||||||
|  |         std::swap(this->network.dispatch_thread, dispatch_thread); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     { |     { | ||||||
| @ -269,12 +335,11 @@ void LocalFileTransfer::shutdown_networking() { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     auto ev_base = std::exchange(this->network.event_base, nullptr); |  | ||||||
|     if(ev_base) |     if(ev_base) | ||||||
|         event_base_loopbreak(ev_base); |         event_base_loopbreak(ev_base); | ||||||
| 
 | 
 | ||||||
|     if(this->network.dispatch_thread.joinable()) |     if(dispatch_thread.joinable()) | ||||||
|         this->network.dispatch_thread.join(); |         dispatch_thread.join(); | ||||||
| 
 | 
 | ||||||
|     if(ev_base) |     if(ev_base) | ||||||
|         event_base_free(ev_base); |         event_base_free(ev_base); | ||||||
| @ -428,7 +493,7 @@ void LocalFileTransfer::finalize_client_ssl(const std::shared_ptr<FileClient> &c | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void LocalFileTransfer::callback_transfer_network_accept(int fd, short, void *ptr_binding) { | void LocalFileTransfer::callback_transfer_network_accept(int fd, short, void *ptr_binding) { | ||||||
|     auto binding = reinterpret_cast<NetworkBinding*>(ptr_binding); |     auto binding = reinterpret_cast<ActiveNetworkBinding*>(ptr_binding); | ||||||
|     auto transfer = binding->handle; |     auto transfer = binding->handle; | ||||||
| 
 | 
 | ||||||
|     sockaddr_storage address{}; |     sockaddr_storage address{}; | ||||||
|  | |||||||
| @ -3,7 +3,6 @@ | |||||||
| //
 | //
 | ||||||
| 
 | 
 | ||||||
| #include <files/FileServer.h> | #include <files/FileServer.h> | ||||||
| #include <log/LogUtils.h> |  | ||||||
| #include <files/Config.h> | #include <files/Config.h> | ||||||
| 
 | 
 | ||||||
| #include "./client/ConnectedClient.h" | #include "./client/ConnectedClient.h" | ||||||
| @ -15,15 +14,10 @@ using namespace ts::server::file; | |||||||
| FileServerHandler::FileServerHandler(ts::server::InstanceHandler *instance) : instance_{instance} {} | FileServerHandler::FileServerHandler(ts::server::InstanceHandler *instance) : instance_{instance} {} | ||||||
| 
 | 
 | ||||||
| bool FileServerHandler::initialize(std::string &error) { | bool FileServerHandler::initialize(std::string &error) { | ||||||
|     /*
 |     if(!file::initialize(error, serverInstance->properties()[property::SERVERINSTANCE_FILETRANSFER_HOST].as<std::string>(), serverInstance->properties()[property::SERVERINSTANCE_FILETRANSFER_PORT].as<uint16_t>())) | ||||||
|       * FIXME: Ports etc! |  | ||||||
|       * |  | ||||||
|          auto bindings_string = this->properties()[property::SERVERINSTANCE_FILETRANSFER_HOST].as<string>(); |  | ||||||
|          auto port = this->properties()[property::SERVERINSTANCE_FILETRANSFER_PORT].as<uint16_t>(); |  | ||||||
|       */ |  | ||||||
|     if(!file::initialize(error)) |  | ||||||
|         return false; |         return false; | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|     file::config::ssl_option_supplier = [&]{ |     file::config::ssl_option_supplier = [&]{ | ||||||
|         return this->instance_->sslManager()->web_ssl_options(); |         return this->instance_->sslManager()->web_ssl_options(); | ||||||
|     }; |     }; | ||||||
|  | |||||||
| @ -58,7 +58,6 @@ namespace ts { | |||||||
|         class InstanceHandler; |         class InstanceHandler; | ||||||
|         class VoiceServer; |         class VoiceServer; | ||||||
|         class QueryServer; |         class QueryServer; | ||||||
|         class LocalFileServer; |  | ||||||
|         class SpeakingClient; |         class SpeakingClient; | ||||||
| 
 | 
 | ||||||
|         class WebControlServer; |         class WebControlServer; | ||||||
|  | |||||||
| @ -259,8 +259,8 @@ command_result ConnectedClient::handleCommandServerRequestConnectionInfo(Command | |||||||
|     first_bulk.put_unchecked(property::CONNECTION_FILETRANSFER_BANDWIDTH_SENT, minute_report.file_bytes_sent); |     first_bulk.put_unchecked(property::CONNECTION_FILETRANSFER_BANDWIDTH_SENT, minute_report.file_bytes_sent); | ||||||
|     first_bulk.put_unchecked(property::CONNECTION_FILETRANSFER_BANDWIDTH_RECEIVED, minute_report.file_bytes_received); |     first_bulk.put_unchecked(property::CONNECTION_FILETRANSFER_BANDWIDTH_RECEIVED, minute_report.file_bytes_received); | ||||||
| 
 | 
 | ||||||
|     first_bulk.put_unchecked(property::CONNECTION_FILETRANSFER_BYTES_SENT_TOTAL, minute_report.file_bytes_sent); |     first_bulk.put_unchecked(property::CONNECTION_FILETRANSFER_BYTES_SENT_TOTAL, this->server->properties()[property::VIRTUALSERVER_TOTAL_BYTES_DOWNLOADED].as<string>()); | ||||||
|     first_bulk.put_unchecked(property::CONNECTION_FILETRANSFER_BYTES_RECEIVED_TOTAL, minute_report.file_bytes_received); |     first_bulk.put_unchecked(property::CONNECTION_FILETRANSFER_BYTES_RECEIVED_TOTAL, this->server->properties()[property::VIRTUALSERVER_TOTAL_BYTES_UPLOADED].as<string>()); | ||||||
| 
 | 
 | ||||||
|     first_bulk.put_unchecked("connection_filetransfer_bytes_sent_month", this->server->properties()[property::VIRTUALSERVER_MONTH_BYTES_DOWNLOADED].as<string>()); |     first_bulk.put_unchecked("connection_filetransfer_bytes_sent_month", this->server->properties()[property::VIRTUALSERVER_MONTH_BYTES_DOWNLOADED].as<string>()); | ||||||
|     first_bulk.put_unchecked("connection_filetransfer_bytes_received_month", this->server->properties()[property::VIRTUALSERVER_MONTH_BYTES_UPLOADED].as<string>()); |     first_bulk.put_unchecked("connection_filetransfer_bytes_received_month", this->server->properties()[property::VIRTUALSERVER_MONTH_BYTES_UPLOADED].as<string>()); | ||||||
|  | |||||||
| @ -190,6 +190,8 @@ void VoiceBridge::handle_data_channel(const std::shared_ptr<rtc::DataChannel> &c | |||||||
| 
 | 
 | ||||||
|     weak_ptr<rtc::DataChannel> weak_channel = channel; |     weak_ptr<rtc::DataChannel> weak_channel = channel; | ||||||
|     channel->callback_binary = [&, weak_channel](const pipes::buffer_view& buffer) { |     channel->callback_binary = [&, weak_channel](const pipes::buffer_view& buffer) { | ||||||
|  |         if(buffer.length() < 2) | ||||||
|  |             return; | ||||||
|         this->callback_voice_data(buffer.view(2), buffer[0] == 1, buffer[1] == 1); /* buffer.substr(2), buffer[0] == 1, buffer[1] == 1 */ |         this->callback_voice_data(buffer.view(2), buffer[0] == 1, buffer[1] == 1); /* buffer.substr(2), buffer[0] == 1, buffer[1] == 1 */ | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -28,6 +28,8 @@ WebClient::WebClient(WebControlServer* server, int fd) : SpeakingClient(server-> | |||||||
|     assert(server->getTS()); |     assert(server->getTS()); | ||||||
|     this->state = ConnectionState::INIT_LOW; |     this->state = ConnectionState::INIT_LOW; | ||||||
|     this->file_descriptor = fd; |     this->file_descriptor = fd; | ||||||
|  | 
 | ||||||
|  |     debugMessage(this->server->getServerId(), " Creating WebClient instance at {}", (void*) this); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void WebClient::initialize() { | void WebClient::initialize() { | ||||||
| @ -120,6 +122,7 @@ void WebClient::initialize() { | |||||||
| 
 | 
 | ||||||
| WebClient::~WebClient() { | WebClient::~WebClient() { | ||||||
|     memtrack::freed<WebClient>(this); |     memtrack::freed<WebClient>(this); | ||||||
|  |     debugMessage(this->server->getServerId(), " Destroying WebClient instance at {}", (void*) this); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static Json::StreamWriterBuilder stream_write_builder = []{ | static Json::StreamWriterBuilder stream_write_builder = []{ | ||||||
|  | |||||||
| @ -11,8 +11,6 @@ | |||||||
| #include "../SignalHandler.h" | #include "../SignalHandler.h" | ||||||
| #include "../client/ConnectedClient.h" | #include "../client/ConnectedClient.h" | ||||||
| #include "../InstanceHandler.h" | #include "../InstanceHandler.h" | ||||||
| #include "../VirtualServerManager.h" |  | ||||||
| #include "../VirtualServer.h" |  | ||||||
| #include "../ShutdownHelper.h" | #include "../ShutdownHelper.h" | ||||||
| #include "../server/QueryServer.h" | #include "../server/QueryServer.h" | ||||||
| 
 | 
 | ||||||
| @ -385,6 +383,7 @@ namespace terminal { | |||||||
|             resident_set = rss * page_size_kb; |             resident_set = rss * page_size_kb; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         //meminfo track
 | ||||||
|         bool handleCommandMemInfo(TerminalCommand& cmd){ |         bool handleCommandMemInfo(TerminalCommand& cmd){ | ||||||
|             bool flag_base = false, flag_malloc = false, flag_track = false, flag_buffer = false; |             bool flag_base = false, flag_malloc = false, flag_track = false, flag_buffer = false; | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user