// // Created by WolverinDEV on 28/04/2020. // #include #include "LocalFileProvider.h" using namespace ts::server; using LocalFileServer = file::LocalFileProvider; using LocalVirtualFileServer = file::LocalVirtualFileServer; EVP_PKEY* ssl_generate_key() { auto key = std::unique_ptr(EVP_PKEY_new(), ::EVP_PKEY_free); auto rsa = RSA_new(); auto e = std::unique_ptr(BN_new(), ::BN_free); BN_set_word(e.get(), RSA_F4); if(!RSA_generate_key_ex(rsa, 2048, e.get(), nullptr)) return nullptr; EVP_PKEY_assign_RSA(key.get(), rsa); return key.release(); } X509* ssl_generate_certificate(EVP_PKEY* key) { auto cert = X509_new(); X509_set_pubkey(cert, key); ASN1_INTEGER_set(X509_get_serialNumber(cert), 3); X509_gmtime_adj(X509_get_notBefore(cert), 0); X509_gmtime_adj(X509_get_notAfter(cert), 31536000L); X509_NAME* name = nullptr; name = X509_get_subject_name(cert); //for(const auto& subject : this->subjects) // X509_NAME_add_entry_by_txt(name, subject.first.c_str(), MBSTRING_ASC, (unsigned char *) subject.second.c_str(), subject.second.length(), -1, 0); X509_set_subject_name(cert, name); name = X509_get_issuer_name(cert); //for(const auto& subject : this->issues) // X509_NAME_add_entry_by_txt(name, subject.first.c_str(), MBSTRING_ASC, (unsigned char *) subject.second.c_str(), subject.second.length(), -1, 0); X509_set_issuer_name(cert, name); X509_sign(cert, key, EVP_sha512()); return cert; } std::shared_ptr server_instance{}; bool file::initialize(std::string &error) { server_instance = std::make_shared(); auto options = std::make_shared(); options->verbose_io = true; options->context_method = SSLv23_method(); options->free_unused_keypairs = false; { std::shared_ptr pkey{ssl_generate_key(), ::EVP_PKEY_free}; std::shared_ptr cert{ssl_generate_certificate(&*pkey), ::X509_free}; options->default_keypair({pkey, cert}); } if(!server_instance->initialize(error, options)) { server_instance = nullptr; return false; } return true; } void file::finalize() { auto server = std::exchange(server_instance, nullptr); if(!server) return; server->finalize(); } std::shared_ptr file::server() { return server_instance; } LocalFileServer::LocalFileProvider() : file_system_{}, file_transfer_{this->file_system_} {} LocalFileServer::~LocalFileProvider() {} bool LocalFileServer::initialize(std::string &error, const std::shared_ptr& ssl_options) { if(!this->file_system_.initialize(error, "files/")) return false; std::deque> bindings{}; { auto binding = std::make_shared(); binding->hostname = "0.0.0.0"; auto& iaddr = *(sockaddr_in*) &binding->address; iaddr.sin_family = AF_INET; iaddr.sin_port = htons(1112); iaddr.sin_addr.s_addr = INADDR_ANY; bindings.push_back(std::move(binding)); } if(!this->file_transfer_.start(bindings, ssl_options)) { 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 LocalFileServer::register_server(ServerId server_id) { auto server = this->find_virtual_server(server_id); if(server) return server; server = std::make_shared(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& 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); }