diff --git a/Makefile.am b/Makefile.am index 006c5ba2..74e9d90e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -13,6 +13,7 @@ lms_SOURCES = \ $(top_srcdir)/av/FormatContext.cpp \ $(top_srcdir)/av/InputFormatContext.cpp \ $(top_srcdir)/av/Stream.cpp \ + $(top_srcdir)/config/ConfigReader.cpp \ $(top_srcdir)/cover/CoverArt.cpp \ $(top_srcdir)/cover/CoverArtGrabber.cpp \ $(top_srcdir)/database/Artist.cpp \ diff --git a/config/ConfigReader.cpp b/config/ConfigReader.cpp new file mode 100644 index 00000000..3cb092fa --- /dev/null +++ b/config/ConfigReader.cpp @@ -0,0 +1,26 @@ +#include "ConfigReader.hpp" + +ConfigReader::ConfigReader(boost::filesystem::path p) +{ + _config.readFile(p.string().c_str()); +} + +void +ConfigReader::getUserInterfaceConfig(Service::UserInterfaceService::Config& config) +{ + + config.enable = _config.lookup("ui.enable"); + if (!config.enable) + return; + + config.docRootPath = _config.lookup("ui.resources.docroot"); + config.appRootPath = _config.lookup("ui.resources.approot"); + config.httpsPort = static_cast(_config.lookup("ui.listen-endpoint.port")); + config.httpsAddress = boost::asio::ip::address::from_string((const char*)_config.lookup("ui.listen-endpoint.addr")); + config.sslCertificatePath = _config.lookup("ui.ssl-crypto.cert"); + config.sslPrivateKeyPath = _config.lookup("ui.ssl-crypto.key"); + config.sslTempDhPath = _config.lookup("ui.ssl-crypto.dh"); + + config.dbPath = _config.lookup("main.db"); +} + diff --git a/config/ConfigReader.hpp b/config/ConfigReader.hpp new file mode 100644 index 00000000..9b424dfd --- /dev/null +++ b/config/ConfigReader.hpp @@ -0,0 +1,23 @@ +#ifndef CONFIG_READER_HPP +#define CONFIG_READER_HPP + +#include +#include + +#include "service/UserInterfaceService.hpp" + +class ConfigReader +{ + public: + + ConfigReader(boost::filesystem::path p); + + void getUserInterfaceConfig(Service::UserInterfaceService::Config& config); + + + private: + + libconfig::Config _config; +}; + +#endif diff --git a/configure.ac b/configure.ac index 08235bca..3e307156 100644 --- a/configure.ac +++ b/configure.ac @@ -12,6 +12,11 @@ AC_CHECK_HEADERS([Wt/WApplication jpeglib.h], [], [AC_MSG_ERROR([Header not found or unusable !])]) +AC_CHECK_LIB([config++], + [main], + , + [AC_MSG_ERROR([config++ not found!])]) + AC_CHECK_LIB([jpeg], [jpeg_destroy], , diff --git a/etc/lms.conf.sample b/etc/lms.conf.sample new file mode 100644 index 00000000..91bcc974 --- /dev/null +++ b/etc/lms.conf.sample @@ -0,0 +1,44 @@ + +main = { + log-level = 1; + db = "/var/lms/lms.db"; +} + +ui = { + enable = true; + + resources = { + docroot = "/usr/share/Wt/" + approot = "/var/lms/approot" + } + + listen-endpoint = { + port = 5081; + addr = "0.0.0.0"; + } + + ssl-crypto = { + cert = "/var/lms/certs/certUI.pem"; + key = "/var/lms/private/privkeyUI.pem"; + dh = "/var/lms/dh/dh2048.pem"; + } + +} + +remote = { + enable = true; + + nb-threads = 1; + + listen-endpoint = { + port = 5080; + addr = "0.0.0.0"; + } + + ssl-crypto = { + cert = ""; + key = ""; + dh = ""; + } +} + diff --git a/main/main.cpp b/main/main.cpp index 9edaf2bb..233aeea6 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1,19 +1,14 @@ -#include -#include -#include -#include +#include +#include "config/ConfigReader.hpp" #include "transcode/AvConvTranscoder.hpp" #include "av/Common.hpp" -#include "database/DatabaseHandler.hpp" #include "service/ServiceManager.hpp" #include "service/DatabaseUpdateService.hpp" #include "service/UserInterfaceService.hpp" #include "service/RemoteServerService.hpp" -#include "ui/LmsApplication.hpp" - int main(int argc, char* argv[]) { @@ -21,7 +16,26 @@ int main(int argc, char* argv[]) try { - ServiceManager& serviceManager = ServiceManager::instance(); + // TODO generate a nice command line help with args + + // Open configuration file + boost::filesystem::path configFile("/etc/lms.conf"); + if (argc > 1) + configFile = boost::filesystem::path(argv[1]); + + if ( !boost::filesystem::exists(configFile) + || !boost::filesystem::is_regular(configFile)) + { + std::cerr << "Cannot open config file '" << configFile << "'" << std::endl; + return EXIT_FAILURE; + } + + ConfigReader configReader(configFile); + + Service::UserInterfaceService::Config uiConfig; + configReader.getUserInterfaceConfig(uiConfig); + + Service::ServiceManager& serviceManager = Service::ServiceManager::instance(); // TODO Retreive the database path in some config file const boost::filesystem::path dbPath("test.db"); @@ -34,9 +48,9 @@ int main(int argc, char* argv[]) std::cout << "Starting services..." << std::endl; - serviceManager.startService( std::make_shared( dbPath) ); - serviceManager.startService( std::make_shared( remoteListenEndpoint, dbPath) ); - serviceManager.startService( std::make_shared(argc, argv, dbPath) ); + serviceManager.startService( std::make_shared( dbPath) ); + serviceManager.startService( std::make_shared( remoteListenEndpoint, dbPath) ); + serviceManager.startService( std::make_shared(boost::filesystem::path(argv[0]), uiConfig)); std::cout << "Running..." << std::endl; @@ -45,10 +59,13 @@ int main(int argc, char* argv[]) res = EXIT_SUCCESS; } + catch( libconfig::ParseException& e) + { + std::cerr << "Caught libconfig::ParseException! error='" << e.getError() << "', file = '" << e.getFile() << "', line = " << e.getLine() << std::endl; + } catch( Wt::WServer::Exception& e) { std::cerr << "Caught WServer::Exception: " << e.what() << std::endl; - } catch( std::exception& e) { diff --git a/service/DatabaseUpdateService.cpp b/service/DatabaseUpdateService.cpp index 98772b79..d13765ce 100644 --- a/service/DatabaseUpdateService.cpp +++ b/service/DatabaseUpdateService.cpp @@ -2,6 +2,8 @@ #include "DatabaseUpdateService.hpp" +namespace Service { + DatabaseUpdateService::DatabaseUpdateService(const boost::filesystem::path& p) : _metadataParser(), _databaseUpdater( p, _metadataParser) @@ -30,3 +32,5 @@ DatabaseUpdateService::restart(void) start(); } +} // namespace Service + diff --git a/service/DatabaseUpdateService.hpp b/service/DatabaseUpdateService.hpp index 91efc8ca..c42d7533 100644 --- a/service/DatabaseUpdateService.hpp +++ b/service/DatabaseUpdateService.hpp @@ -9,6 +9,8 @@ #include "Service.hpp" +namespace Service { + class DatabaseUpdateService : public Service { public: @@ -28,5 +30,7 @@ class DatabaseUpdateService : public Service DatabaseUpdater::Updater _databaseUpdater; // Todo use handler }; +} // namespace Service + #endif diff --git a/service/RemoteServerService.cpp b/service/RemoteServerService.cpp index 6bb6618f..df597dba 100644 --- a/service/RemoteServerService.cpp +++ b/service/RemoteServerService.cpp @@ -1,6 +1,8 @@ #include "RemoteServerService.hpp" +namespace Service { + RemoteServerService::RemoteServerService(const Remote::Server::Server::endpoint_type& endpoint, boost::filesystem::path dbPath) : _server(endpoint, dbPath) { @@ -28,3 +30,5 @@ RemoteServerService::restart(void) { std::cout << "RemoteServerService::restart, not implemented!" << std::endl; } + +} // namespace Service diff --git a/service/RemoteServerService.hpp b/service/RemoteServerService.hpp index 60d78b57..f13346f5 100644 --- a/service/RemoteServerService.hpp +++ b/service/RemoteServerService.hpp @@ -7,6 +7,8 @@ #include "remote/server/Server.hpp" +namespace Service { + class RemoteServerService : public Service { public: @@ -22,4 +24,6 @@ class RemoteServerService : public Service Remote::Server::Server _server; }; +} // namespace Service + #endif diff --git a/service/Service.hpp b/service/Service.hpp index e70d4e9a..bb1fefad 100644 --- a/service/Service.hpp +++ b/service/Service.hpp @@ -5,6 +5,8 @@ #include #include +namespace Service { + // Interface class wrapper for running services class Service { @@ -24,5 +26,7 @@ class Service }; +} // namespace Service + #endif diff --git a/service/ServiceManager.cpp b/service/ServiceManager.cpp index 59a50e6e..9fd6c55a 100644 --- a/service/ServiceManager.cpp +++ b/service/ServiceManager.cpp @@ -1,11 +1,11 @@ -//#include - #include #include #include "ServiceManager.hpp" +namespace Service { + ServiceManager& ServiceManager::instance() { @@ -122,3 +122,5 @@ ServiceManager::handleSignal(boost::system::error_code /*ec*/, int signo) } } +} // namespace Service + diff --git a/service/ServiceManager.hpp b/service/ServiceManager.hpp index cc2d15a2..6f91452f 100644 --- a/service/ServiceManager.hpp +++ b/service/ServiceManager.hpp @@ -6,6 +6,8 @@ #include "Service.hpp" +namespace Service { + // Start/Stop/Reload Services class ServiceManager { @@ -63,5 +65,7 @@ ServiceManager::getService() return std::shared_ptr(); } +} // namespace Service + #endif diff --git a/service/UserInterfaceService.cpp b/service/UserInterfaceService.cpp index 66986725..6f94eb31 100644 --- a/service/UserInterfaceService.cpp +++ b/service/UserInterfaceService.cpp @@ -1,17 +1,43 @@ #include -#include #include "UserInterfaceService.hpp" #include "ui/LmsApplication.hpp" -UserInterfaceService::UserInterfaceService( int argc, char* argv[], boost::filesystem::path dbPath) -: _server(argv[0], "") +namespace Service { + +UserInterfaceService::UserInterfaceService( boost::filesystem::path runAppPath, const Config& config) +: _server(runAppPath.string()) { - // TODO configure server using another way (config file?) - _server.setServerConfiguration (argc, argv, WTHTTP_CONFIGURATION); + std::vector args; + + args.push_back(runAppPath.string()); + args.push_back("--docroot=" + config.docRootPath.string()); + args.push_back("--approot=" + config.appRootPath.string()); + { + std::ostringstream oss; oss << config.httpsPort; + args.push_back("--https-port=" + oss.str()); + } + args.push_back("--https-address=" + config.httpsAddress.to_string()); + args.push_back("--ssl-certificate=" + config.sslCertificatePath.string()); + args.push_back("--ssl-private-key=" + config.sslPrivateKeyPath.string()); + args.push_back("--ssl-tmp-dh=" + config.sslTempDhPath.string()); + + // Construct argc/argv + int argc = args.size(); + const char* argv[args.size()]; + for (int i = 0; i < argc; ++i) + argv[i] = args[i].c_str(); + + for(int i = 0; i < argc; ++i) + { + std::cout << "i = " << i << ", arg = '" << argv[i] << "'" << std::endl; + } + + _server.setServerConfiguration (argc, const_cast(argv)); // bind entry point - _server.addEntryPoint(Wt::Application, boost::bind(UserInterface::LmsApplication::create, _1, dbPath)); + _server.addEntryPoint(Wt::Application, boost::bind(UserInterface::LmsApplication::create, _1, config.dbPath)); + } void @@ -35,4 +61,5 @@ UserInterfaceService::restart(void) } +} // namespace Service diff --git a/service/UserInterfaceService.hpp b/service/UserInterfaceService.hpp index c9b78d6b..b50d22a2 100644 --- a/service/UserInterfaceService.hpp +++ b/service/UserInterfaceService.hpp @@ -2,15 +2,32 @@ #define WEB_SERVER_SERVICE_HPP #include +#include #include #include "Service.hpp" +namespace Service { + class UserInterfaceService : public Service { public: - UserInterfaceService( int argc, char* argv[], boost::filesystem::path dbPath); + + struct Config { + bool enable; + boost::filesystem::path docRootPath; + boost::filesystem::path appRootPath; + unsigned short httpsPort; + boost::asio::ip::address httpsAddress; + boost::filesystem::path sslCertificatePath; + boost::filesystem::path sslPrivateKeyPath; + boost::filesystem::path sslTempDhPath; + boost::filesystem::path dbPath; + }; + + UserInterfaceService(boost::filesystem::path runAppPath, + const Config& config); void start(void); void stop(void); @@ -22,5 +39,7 @@ class UserInterfaceService : public Service }; +} //namespace Service + #endif diff --git a/ui/settings/Settings.cpp b/ui/settings/Settings.cpp index a01c9da4..d06eaeef 100644 --- a/ui/settings/Settings.cpp +++ b/ui/settings/Settings.cpp @@ -81,9 +81,9 @@ void Settings::restartDatabaseUpdateService() { // Restarting the update service - boost::lock_guard serviceLock (ServiceManager::instance().mutex()); + boost::lock_guard serviceLock (Service::ServiceManager::instance().mutex()); - DatabaseUpdateService::pointer service = ServiceManager::instance().getService(); + Service::DatabaseUpdateService::pointer service = Service::ServiceManager::instance().getService(); if (service) service->restart(); }