/* Copyright © 2015 Gluzskiy Alexandr (sss) This file is part of Unknown Download Manager (UDM). UDM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. UDM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with UDM. If not, see . */ #include #include #include #include #include #include #include "api_module_metadata_storage.h" #include "modules_handler.h" #include "utilities.h" #include "server.h" #include "main.h" #include "config.h" #include "client.h" #include "download_internal.h" core_api *module_api = nullptr; modules_handler *modules = nullptr; namespace bpo = boost::program_options; std::map clients; //auth token used for key runtime_config_s runtime_config; std::map downloads; server *serv = nullptr; //TODO: "core" config section architecture, define base settings void on_exit() { serv->terminate(); bpt::write_info(runtime_config.config_file_path, runtime_config.config_file); //save config on sigint for(auto m : modules->get_downloader_modules()) delete m; for(auto m : modules->get_metadata_modules()) delete m; } void sig_handler(int sig) { switch(sig) { default: { on_exit(); exit(0); } break; } } extern "C" int main(int argc, char *argv[]) { //handle signals signal(SIGINT, sig_handler); signal(SIGTERM, sig_handler); signal(SIGABRT, sig_handler); //this will not work signal(SIGKILL, sig_handler); signal(SIGSTOP, sig_handler); bpo::options_description desc("Available commands and options"); desc.add_options() ("help,h", "this message") ("daemon,d", "fork to background (must be combined with \"--run\", does nothing alone)") ("config,c", bpo::value(), "use specified config file instead of \"~/.config/udm/udm.conf\"") ("list-modules", "list all installed modules (you can set verbosity level, accepted values from 0 to 1, default = 0)") ("verbosity,v", bpo::value()->default_value(0), "set global verbosity level") ("run", "start UDM server") ; bool daemon = false, run = false; std::string config_path = "~/.config/udm/udm.conf", parsed_config_path; try{ bpo::variables_map vm; bpo::store(bpo::command_line_parser(argc, argv).options(desc).style(bpo::command_line_style::unix_style | bpo::command_line_style::allow_long_disguise).run(), vm); bpo::notify(vm); //load config first, as it may be needed for other commands if(vm.count("config")) config_path = vm["config"].as(); { parsed_config_path = replace_home_var(config_path); if(boost::filesystem::exists(parsed_config_path) && boost::filesystem::is_regular(parsed_config_path)) bpt::read_info(parsed_config_path, runtime_config.config_file); //TODO: finish this else std::cerr<<"failed to load config: \"" + config_path + "\", file does not exists or is not regular file\n"; runtime_config.config_file_path = parsed_config_path; } { auto server_pt = runtime_config.config_file.find("server"); if(server_pt == runtime_config.config_file.not_found()) { runtime_config.config_file.put("server", ""); server_pt = runtime_config.config_file.find("server"); } auto it = server_pt->second.find("port"); if(it == server_pt->second.not_found()) server_pt->second.put("port", 6613); it = server_pt->second.find("password"); if(it == server_pt->second.not_found()) server_pt->second.put("password", ""); it = server_pt->second.find("default_download_directory"); if(it == server_pt->second.not_found()) server_pt->second.put("default_download_directory", "~/udm/downloads"); it = server_pt->second.find("default_metadata_module"); if(it == server_pt->second.not_found()) server_pt->second.put("default_metadata_module", "flat_files_metadata"); it = server_pt->second.find("daemon"); if(it == server_pt->second.not_found()) server_pt->second.put("daemon", false); it = server_pt->second.find("verbosity"); if(it == server_pt->second.not_found()) server_pt->second.put("verbosity", 0); it = server_pt->second.find("enable_encryption"); if(it == server_pt->second.not_found()) server_pt->second.put("enable_encryption", false); it = server_pt->second.find("ssl_certificate"); if(it == server_pt->second.not_found()) server_pt->second.put("ssl_certificate", "~/config/udm/cert.crt"); it = server_pt->second.find("ssl_key"); if(it == server_pt->second.not_found()) server_pt->second.put("ssl_key", "~/config/udm/cert.key"); it = server_pt->second.find("ssl_ca"); if(it == server_pt->second.not_found()) server_pt->second.put("ssl_ca", "~/config/udm/ca.crt"); it = server_pt->second.find("ssl_dh"); if(it == server_pt->second.not_found()) server_pt->second.put("ssl_dh", "~/config/udm/dh.pem"); } //load all config variables here runtime_config.settings.verbosity = runtime_config.config_file.get("server.verbosity", 0); daemon = runtime_config.config_file.get("server.daemon", false); //override config from command line here if(vm.count("verbosity")) { runtime_config.settings.verbosity = vm["verbosity"].as(); } if(vm.count("help")) { std::cout<load_modules(); } std::cout<list_modules(); bpt::write_info(parsed_config_path, runtime_config.config_file); //save config on exit return 0; } if(vm.count("run")) { run = true; } } catch(std::exception &e) { std::cerr<<"error: "<load_modules(); } std::string default_metadata_module_name = runtime_config.config_file.get("server.default_metadata_module", ""); if(default_metadata_module_name == "") { if(!modules->get_metadata_modules().empty()) runtime_config.default_metadata_storage = static_cast(*(modules->get_metadata_modules().begin())); else std::cerr<<"Error: Metadata storage modules not installed'n"; } else { for(auto i = modules->get_metadata_modules().begin(), end = modules->get_metadata_modules().end(); i != end; ++i) { if((*i)->get_module_info().name == default_metadata_module_name) runtime_config.default_metadata_storage = static_cast(*i); } if(!runtime_config.default_metadata_storage) { std::cerr<<"Error: Failed to load metadata storage module named \""<on_modules_loaded(); //call second initialization stage in modules modules->sync_downloads(downloads); if(daemon) { //TODO: fork here } boost::asio::io_service io_service_server; try{ //TODO: server options ip address, interface name serv = new server(io_service_server, runtime_config, clients, downloads, runtime_config.config_file.get("server.port", 6613)); } catch(std::exception &e) { //TODO: } catch(...) { //TODO: } //TODO: run in separate thread ? boost::system::error_code ec; io_service_server.run(ec); if(ec) { //TODO: } //TODO: run here return 0; //stub for now } std::cerr<<"error: no command specified"<