| 
									
										
										
										
											2020-06-16 19:40:32 +02:00
										 |  |  | #include <dlfcn.h>
 | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  | #include <client/linux/handler/exception_handler.h>
 | 
					
						
							|  |  |  | #include <iostream>
 | 
					
						
							| 
									
										
										
										
											2019-09-14 12:06:48 +02:00
										 |  |  | #include <misc/strobf.h>
 | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  | #include <CXXTerminal/QuickTerminal.h>
 | 
					
						
							|  |  |  | #include <event2/thread.h>
 | 
					
						
							|  |  |  | #include <log/LogUtils.h>
 | 
					
						
							|  |  |  | #include <ThreadPool/Timer.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "src/Configuration.h"
 | 
					
						
							| 
									
										
										
										
											2020-01-26 18:04:38 +01:00
										 |  |  | #include "src/VirtualServer.h"
 | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  | #include "src/InstanceHandler.h"
 | 
					
						
							|  |  |  | #include "src/server/QueryServer.h"
 | 
					
						
							|  |  |  | #include "src/terminal/CommandHandler.h"
 | 
					
						
							|  |  |  | #include "src/client/InternalClient.h"
 | 
					
						
							|  |  |  | #include "src/SignalHandler.h"
 | 
					
						
							|  |  |  | #include "src/build.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using namespace std; | 
					
						
							|  |  |  | using namespace std::chrono; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define BUILD_CREATE_TABLE(tblName, types) "CREATE TABLE IF NOT EXISTS `" tblName "` (" types ")"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define CREATE_TABLE(table, types)   \
 | 
					
						
							|  |  |  | result = sql::command(sqlData, BUILD_CREATE_TABLE(table, types)).execute();\ | 
					
						
							|  |  |  | if(!result){\ | 
					
						
							|  |  |  |     logger::logger(0)->critical("Could not setup sql tables. Command '{}' returns {}", BUILD_CREATE_TABLE(table, types), result.fmtStr());\ | 
					
						
							|  |  |  |     goto stopApp;\ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool mainThreadActive = true; | 
					
						
							|  |  |  | bool mainThreadDone = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ts::server::InstanceHandler* serverInstance = nullptr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern void testTomMath(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef FUCK_CLION
 | 
					
						
							|  |  |  |     #define DB_NAME_BEG "TeaData"
 | 
					
						
							|  |  |  |     #define DB_NAME_END ".sqlite"
 | 
					
						
							|  |  |  |     #define DB_NAME DB_NAME_BEG DB_NAME_END
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |     #define DB_NAME "TeaData.sqlite"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <codecvt>
 | 
					
						
							|  |  |  | #include "src/client/music/internal_provider/channel_replay/ChannelProvider.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-09 16:55:15 +02:00
										 |  |  | class CLIParser { | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  |     public: | 
					
						
							|  |  |  |         CLIParser (int &argc, char **argv){ | 
					
						
							|  |  |  |             for (int i = 1; i < argc; i++) | 
					
						
							|  |  |  |                 this->tokens.emplace_back(argv[i]); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-24 02:57:58 +01:00
										 |  |  |         std::deque<std::string> getCmdOptions(const std::string &option) const { | 
					
						
							|  |  |  |             std::deque<std::string> result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             auto itr = this->tokens.begin(); | 
					
						
							|  |  |  |             while(true) { | 
					
						
							|  |  |  |                 itr = std::find(itr, this->tokens.end(), option); | 
					
						
							|  |  |  |                 if (itr != this->tokens.end() && ++itr != this->tokens.end()){ | 
					
						
							|  |  |  |                     result.push_back(*itr); | 
					
						
							|  |  |  |                     itr++; | 
					
						
							|  |  |  |                 } else break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return result; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         std::deque<std::string> getCmdOptionsBegins(const std::string &option) const { | 
					
						
							|  |  |  |             std::deque<std::string> result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for(const auto& token : this->tokens) | 
					
						
							|  |  |  |                 if(token.find(option) == 0) | 
					
						
							|  |  |  |                     result.push_back(token); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return result; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         const std::string& get_option(const std::string &option) const { | 
					
						
							|  |  |  |             auto itr =  std::find(this->tokens.begin(), this->tokens.end(), option); | 
					
						
							|  |  |  |             if (itr != this->tokens.end() && ++itr != this->tokens.end()){ | 
					
						
							|  |  |  |                 return *itr; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             static const std::string empty_string; | 
					
						
							|  |  |  |             return empty_string; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         bool cmdOptionExists(const std::string &option) const{ | 
					
						
							|  |  |  |             return std::find(this->tokens.begin(), this->tokens.end(), option) != this->tokens.end(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     private: | 
					
						
							|  |  |  |         std::vector <std::string> tokens; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* addr is where the exception identifier is stored
 | 
					
						
							|  |  |  |    id is the exception identifier.  */ | 
					
						
							|  |  |  | void __raise_exception (void **addr, void *id); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define T(address) \
 | 
					
						
							|  |  |  | std::cout << "Testing: " << address << " => "; \ | 
					
						
							|  |  |  | {\ | 
					
						
							| 
									
										
										
										
											2020-01-24 02:57:58 +01:00
										 |  |  |     sockaddr_storage storage;\ | 
					
						
							|  |  |  |     net::resolve_address(address, storage);\ | 
					
						
							|  |  |  |     std::cout << manager.contains(storage) << std::endl;\ | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define CONFIG_NAME "config.yml"
 | 
					
						
							|  |  |  | const char *malloc_conf = ""; //retain:false"; //,dirty_decay_ms:0";
 | 
					
						
							|  |  |  | int main(int argc, char** argv) { | 
					
						
							|  |  |  | #ifdef HAVE_JEMALLOC
 | 
					
						
							| 
									
										
										
										
											2020-01-24 02:57:58 +01:00
										 |  |  |     (void*) malloc_conf; | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     CLIParser arguments(argc, argv); | 
					
						
							|  |  |  |     SSL_load_error_strings(); | 
					
						
							|  |  |  |     OpenSSL_add_ssl_algorithms(); | 
					
						
							| 
									
										
										
										
											2020-01-24 02:57:58 +01:00
										 |  |  |     ts::permission::setup_permission_resolve(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         auto evthread_use_pthreads_result = evthread_use_pthreads(); | 
					
						
							|  |  |  |         assert(evthread_use_pthreads_result == 0); | 
					
						
							|  |  |  |         (void) evthread_use_pthreads_result; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-02-28 11:24:07 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if(!arguments.cmdOptionExists("--no-terminal")) { | 
					
						
							|  |  |  |         terminal::install(); | 
					
						
							|  |  |  |         if(!terminal::active()){ cerr << "could not setup terminal!" << endl; return -1; } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if(arguments.cmdOptionExists("--help") || arguments.cmdOptionExists("-h")) { | 
					
						
							|  |  |  |         #define HELP_FMT "  {} {} | {}"
 | 
					
						
							|  |  |  |         logMessageFmt(true, LOG_GENERAL, "Available command line parameters:"); | 
					
						
							|  |  |  |         logMessageFmt(true, LOG_GENERAL, HELP_FMT, "-h", "--help", "Shows this page"); | 
					
						
							|  |  |  |         logMessageFmt(true, LOG_GENERAL, HELP_FMT, "-q", "--set_query_password", "Changed the server admin query password"); | 
					
						
							| 
									
										
										
										
											2020-01-24 02:57:58 +01:00
										 |  |  |         logMessageFmt(true, LOG_GENERAL, HELP_FMT, "-P<property>=<value>", "--property:<property>=<value>", "Override a config value manual"); | 
					
						
							|  |  |  |         logMessageFmt(true, LOG_GENERAL, HELP_FMT, "-l", "--property-list", "List all available properties"); | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  |         terminal::uninstall(); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-01-24 02:57:58 +01:00
										 |  |  |     if(arguments.cmdOptionExists("--property-list") || arguments.cmdOptionExists("-l")) { | 
					
						
							|  |  |  |         logMessageFmt(true, LOG_GENERAL, "Available properties:"); | 
					
						
							|  |  |  |         auto properties = ts::config::create_bindings(); | 
					
						
							|  |  |  |         for(const auto& property : properties) { | 
					
						
							|  |  |  |             logMessageFmt(true, LOG_GENERAL, "  " + property->key); | 
					
						
							|  |  |  |             for(const auto& entry : property->description) { | 
					
						
							|  |  |  |                 if(entry.first.empty()) { | 
					
						
							|  |  |  |                     for(const auto& line : entry.second) | 
					
						
							|  |  |  |                         logMessageFmt(true, LOG_GENERAL, "    " + line); | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     logMessageFmt(true, LOG_GENERAL, "    " + entry.first + ":"); | 
					
						
							|  |  |  |                     for(const auto& line : entry.second) | 
					
						
							|  |  |  |                         logMessageFmt(true, LOG_GENERAL, "      " + line); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             logMessageFmt(true, LOG_GENERAL, "    " + property->value_description()); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if(!arguments.cmdOptionExists("--valgrind")) { | 
					
						
							|  |  |  |         ts::syssignal::setup(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     ts::syssignal::setup_threads(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     map<string, string> override_settings; | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         auto short_override = arguments.getCmdOptionsBegins("-P"); | 
					
						
							|  |  |  |         for(const auto& entry : short_override) { | 
					
						
							|  |  |  |             if(entry.length() < 2) continue; | 
					
						
							|  |  |  |             auto ei = entry.find('='); | 
					
						
							|  |  |  |             if(ei == string::npos || ei == 2) { | 
					
						
							|  |  |  |                 logErrorFmt(true, LOG_GENERAL, "Invalid command line parameter. (\"" + entry + "\")"); | 
					
						
							|  |  |  |                 return 1; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             auto key = entry.substr(2, ei - 2); | 
					
						
							|  |  |  |             auto value = entry.substr(ei + 1); | 
					
						
							|  |  |  |             override_settings[key] = value; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         auto short_override = arguments.getCmdOptionsBegins("--property:"); | 
					
						
							|  |  |  |         for(const auto& entry : short_override) { | 
					
						
							|  |  |  |             if(entry.length() < 11) continue; | 
					
						
							|  |  |  |             auto ei = entry.find('='); | 
					
						
							|  |  |  |             if(ei == string::npos || ei == 11) { | 
					
						
							|  |  |  |                 logErrorFmt(true, LOG_GENERAL, "Invalid command line parameter. (\"" + entry + "\")"); | 
					
						
							|  |  |  |                 return 1; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             auto key = entry.substr(11, ei - 11); | 
					
						
							|  |  |  |             auto value = entry.substr(ei + 1); | 
					
						
							|  |  |  |             override_settings[key] = value; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         auto bindings = ts::config::create_bindings(); | 
					
						
							|  |  |  |         for(const auto& setting : bindings) { | 
					
						
							|  |  |  |             for(auto it = override_settings.begin(); it != override_settings.end(); it++) { | 
					
						
							|  |  |  |                 if(it->first == setting->key) { | 
					
						
							|  |  |  |                     try { | 
					
						
							|  |  |  |                         setting->read_argument(it->second); | 
					
						
							|  |  |  |                     } catch(const std::exception& ex) { | 
					
						
							|  |  |  |                         logErrorFmt(true, LOG_GENERAL, "Failed to apply value for given property '" + it->first + "': " + ex.what()); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     override_settings.erase(it); | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         for(const auto& entry : override_settings) { | 
					
						
							|  |  |  |             logMessageFmt(true, LOG_GENERAL, "Missing property " + entry.first + ". Value unused!"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  |     /*
 | 
					
						
							|  |  |  |     std::string error; | 
					
						
							|  |  |  |     if(!interaction::waitForAttach(error)){ | 
					
						
							|  |  |  |         cerr << "Rsult: " << error << endl; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while(interaction::memoryInfo()){ | 
					
						
							|  |  |  |         usleep(1 * 1000 * 1000); | 
					
						
							|  |  |  |         logMessage("Current instances: " + to_string(interaction::memoryInfo()->instanceCount) + "/" + to_string(interaction::memoryInfo()->maxInstances)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     interaction::removeMemoryHook(); | 
					
						
							|  |  |  |      if(true) return 0; | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         //http://git.mcgalaxy.de/WolverinDEV/tomcrypt/blob/develop/src/misc/crypt/crypt_inits.c#L40-86
 | 
					
						
							|  |  |  |         std::string descriptors = "LTGE"; | 
					
						
							|  |  |  |         bool crypt_init = false; | 
					
						
							|  |  |  |         for(const auto& c : descriptors) | 
					
						
							| 
									
										
										
										
											2019-09-14 12:06:48 +02:00
										 |  |  |             if((crypt_init |= crypt_mp_init(&c))) | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  |                 break; | 
					
						
							|  |  |  |         if(!crypt_init) { | 
					
						
							|  |  |  |             logCritical(LOG_GENERAL, "Could not initialise libtomcrypt mp descriptors!"); | 
					
						
							|  |  |  |             return 1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if(register_prng(&sprng_desc) == -1) { | 
					
						
							| 
									
										
										
										
											2020-01-24 02:57:58 +01:00
										 |  |  |             logCritical(LOG_GENERAL, "could not setup prng"); | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  |             return EXIT_FAILURE; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (register_cipher(&rijndael_desc) == -1) { | 
					
						
							| 
									
										
										
										
											2020-01-24 02:57:58 +01:00
										 |  |  |             logCritical(LOG_GENERAL, "could not setup rijndael"); | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  |             return EXIT_FAILURE; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         testTomMath(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-24 02:57:58 +01:00
										 |  |  |     ts::server::SqlDataManager* sql = nullptr; | 
					
						
							|  |  |  |     std::string errorMessage; | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  |     shared_ptr<logger::LoggerConfig> logConfig = nullptr; | 
					
						
							| 
									
										
										
										
											2020-01-24 02:57:58 +01:00
										 |  |  |     std::string line; | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-14 12:06:48 +02:00
										 |  |  |     logMessageFmt(true, LOG_GENERAL, "Loading configuration"); | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  |     auto cfgErrors = ts::config::parseConfig(CONFIG_NAME); | 
					
						
							|  |  |  |     if(!cfgErrors.empty()){ | 
					
						
							| 
									
										
										
										
											2019-09-14 12:06:48 +02:00
										 |  |  |         logErrorFmt(true, LOG_GENERAL, "Could not load configuration. Errors: (" + to_string(cfgErrors.size()) + ")"); | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  |         for(const auto& entry : cfgErrors) | 
					
						
							| 
									
										
										
										
											2020-04-19 18:40:40 +02:00
										 |  |  |             logErrorFmt(true, LOG_GENERAL, " - {}", entry); | 
					
						
							| 
									
										
										
										
											2019-09-14 12:06:48 +02:00
										 |  |  |         logErrorFmt(true, LOG_GENERAL, "Stopping server..."); | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  |         goto stopApp; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-14 12:06:48 +02:00
										 |  |  |     logMessage(LOG_GENERAL, "Setting up logging"); | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  |     logConfig = make_shared<logger::LoggerConfig>(); | 
					
						
							|  |  |  |     logConfig->logfileLevel = (spdlog::level::level_enum) ts::config::log::logfileLevel; | 
					
						
							|  |  |  |     logConfig->terminalLevel = (spdlog::level::level_enum) ts::config::log::terminalLevel; | 
					
						
							|  |  |  |     logConfig->file_colored = ts::config::log::logfileColored; | 
					
						
							|  |  |  |     logConfig->logPath = ts::config::log::path; | 
					
						
							|  |  |  |     logConfig->vs_group_size = ts::config::log::vs_size; | 
					
						
							| 
									
										
										
										
											2020-02-28 11:24:07 +01:00
										 |  |  |     logConfig->sync = !terminal::instance(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  |     logger::setup(logConfig); | 
					
						
							| 
									
										
										
										
											2020-01-24 02:57:58 +01:00
										 |  |  |     threads::timer::function_log = [](const std::string& message, bool debug) { | 
					
						
							| 
									
										
										
										
											2020-02-15 14:03:46 +01:00
										 |  |  |         auto msg = message.find('\n') == std::string::npos ? message : message.substr(0, message.find('\n')); | 
					
						
							| 
									
										
										
										
											2020-01-24 02:57:58 +01:00
										 |  |  |         if(debug) | 
					
						
							| 
									
										
										
										
											2020-02-15 14:03:46 +01:00
										 |  |  |             debugMessage(LOG_GENERAL, msg); | 
					
						
							| 
									
										
										
										
											2020-01-24 02:57:58 +01:00
										 |  |  |         else | 
					
						
							| 
									
										
										
										
											2020-02-15 14:03:46 +01:00
										 |  |  |             logWarning(LOG_GENERAL, msg); | 
					
						
							| 
									
										
										
										
											2020-01-24 02:57:58 +01:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     logger::updateLogLevels(); | 
					
						
							| 
									
										
										
										
											2020-01-24 02:57:58 +01:00
										 |  |  |     if(ts::config::license_original && ts::config::license_original->data.type != license::LicenseType::DEMO){ | 
					
						
							|  |  |  |         logMessageFmt(true, LOG_GENERAL, strobf("[]---------------------------------------------------------[]").string()); | 
					
						
							|  |  |  |         logMessageFmt(true, LOG_GENERAL, strobf("  §aThank you for buying the TeaSpeak-§lPremium-§aSoftware!  ").string()); | 
					
						
							|  |  |  |         logMessageFmt(true, LOG_GENERAL, strobf("  §aLicense information:").string()); | 
					
						
							|  |  |  |         logMessageFmt(true, LOG_GENERAL, strobf("     §aLicense owner  : §e").string() + ts::config::license_original->owner()); | 
					
						
							|  |  |  |         logMessageFmt(true, LOG_GENERAL, strobf("     §aLicense type   : §e").string() + license::LicenseTypeNames[ts::config::license_original->data.type]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if(ts::config::license_original->end().time_since_epoch().count() == 0){ | 
					
						
							|  |  |  |             logMessageFmt(true, LOG_GENERAL, strobf("     §aLicense expires: §enever").string()); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             char timeBuffer[32]; | 
					
						
							|  |  |  |             time_t t = duration_cast<seconds>(ts::config::license_original->end().time_since_epoch()).count(); | 
					
						
							|  |  |  |             tm* stime = localtime(&t); | 
					
						
							|  |  |  |             strftime(timeBuffer, 32, "%c", stime); | 
					
						
							|  |  |  |             logMessageFmt(true, LOG_GENERAL, strobf("     §aLicense expires: §e").string() + string(timeBuffer)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         logMessageFmt(true, LOG_GENERAL, string() + strobf("     §aLicense valid  : ").string() + (ts::config::license_original->isValid() ? strobf("§ayes").string() : strobf("§cno").string())); | 
					
						
							|  |  |  |         logMessageFmt(true, LOG_GENERAL, strobf("[]---------------------------------------------------------[]").string()); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-25 20:36:44 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |         rlimit rlimit{0, 0}; | 
					
						
							|  |  |  |         //forum.teaspeak.de/index.php?threads/2570/
 | 
					
						
							|  |  |  |         constexpr auto seek_help_message = "Fore more help visit the forum and read this thread (https://forum.teaspeak.de/index.php?threads/2570/)."; | 
					
						
							|  |  |  |         if(getrlimit(RLIMIT_NOFILE, &rlimit) != 0) { | 
					
						
							|  |  |  |             //prlimit -n4096 -p pid_of_process
 | 
					
						
							|  |  |  |             logWarningFmt(true, LOG_INSTANCE, "Failed to get open file rlimit ({}). Please ensure its over 16384.", strerror(errno)); | 
					
						
							|  |  |  |             logWarningFmt(true, LOG_INSTANCE, seek_help_message); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             const auto original = rlimit.rlim_cur; | 
					
						
							|  |  |  |             rlimit.rlim_cur = std::max(rlimit.rlim_cur, std::min(rlimit.rlim_max, (rlim_t) 16384)); | 
					
						
							|  |  |  |             if(original != rlimit.rlim_cur) { | 
					
						
							|  |  |  |                 if(setrlimit(RLIMIT_NOFILE, &rlimit) != 0) { | 
					
						
							|  |  |  |                     logErrorFmt(true, LOG_INSTANCE, "Failed to set open file rlimit to {} ({}). Please ensure its over 16384.", rlimit.rlim_cur, strerror(errno)); | 
					
						
							|  |  |  |                     logWarningFmt(true, LOG_INSTANCE, seek_help_message); | 
					
						
							|  |  |  |                     goto rlimit_updates; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if(rlimit.rlim_cur < 16384) { | 
					
						
							|  |  |  |                 logWarningFmt(true, LOG_INSTANCE, "Open file rlimit is bellow 16384 ({}). Please increase the system file descriptor limits.", rlimit.rlim_cur); | 
					
						
							|  |  |  |                 logWarningFmt(true, LOG_INSTANCE, seek_help_message); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         rlimit_updates:; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  |     logMessage(LOG_GENERAL, "Starting TeaSpeak-Server v{}", build::version()->string(true)); | 
					
						
							| 
									
										
										
										
											2020-01-24 02:57:58 +01:00
										 |  |  |     logMessage(LOG_GENERAL, "Starting music providers"); | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-28 11:24:07 +01:00
										 |  |  |     if(terminal::instance()) terminal::instance()->setPrompt("§aStarting server. §7[§aloading music§7]"); | 
					
						
							| 
									
										
										
										
											2020-01-24 02:57:58 +01:00
										 |  |  |     if(ts::config::music::enabled && !arguments.cmdOptionExists("--no-providers")) { | 
					
						
							|  |  |  |         ::music::manager::loadProviders("providers"); | 
					
						
							|  |  |  |         ::music::manager::register_provider(::music::provider::ChannelProvider::create_provider()); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-28 11:24:07 +01:00
										 |  |  |     if(terminal::instance()) terminal::instance()->setPrompt("§aStarting server. §7[§aloading geoloc§7]"); | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if(!ts::config::geo::staticFlag) { | 
					
						
							|  |  |  |         if(ts::config::geo::type == geoloc::PROVIDER_SOFTWARE77) | 
					
						
							|  |  |  |             geoloc::provider = new geoloc::Software77Provider(ts::config::geo::mappingFile); | 
					
						
							|  |  |  |         else if(ts::config::geo::type == geoloc::PROVIDER_IP2LOCATION) | 
					
						
							|  |  |  |             geoloc::provider = new geoloc::IP2LocationProvider(ts::config::geo::mappingFile); | 
					
						
							|  |  |  |         else { | 
					
						
							| 
									
										
										
										
											2019-11-23 21:16:55 +01:00
										 |  |  |             logCritical(LOG_GENERAL,"Invalid geo resolver type!"); | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         if(geoloc::provider && !geoloc::provider->load(errorMessage)) { | 
					
						
							| 
									
										
										
										
											2019-11-23 21:16:55 +01:00
										 |  |  |             logCritical(LOG_GENERAL,"Could not setup geoloc! Fallback to default flag!"); | 
					
						
							|  |  |  |             logCritical(LOG_GENERAL,"Message: {}", errorMessage); | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  |             geoloc::provider = nullptr; | 
					
						
							| 
									
										
										
										
											2020-01-24 02:57:58 +01:00
										 |  |  |             errorMessage = ""; | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if(ts::config::geo::vpn_block) { | 
					
						
							|  |  |  |         geoloc::provider_vpn = new geoloc::IPCatBlocker(ts::config::geo::vpn_file); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if(geoloc::provider_vpn && !geoloc::provider_vpn->load(errorMessage)) { | 
					
						
							| 
									
										
										
										
											2019-11-23 21:16:55 +01:00
										 |  |  |             logCritical(LOG_GENERAL,"Could not setup vpn detector!"); | 
					
						
							| 
									
										
										
										
											2020-01-24 02:57:58 +01:00
										 |  |  |             logCritical(LOG_GENERAL,"Message: {}", errorMessage); | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  |             geoloc::provider_vpn = nullptr; | 
					
						
							|  |  |  |             errorMessage = ""; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-02-28 11:24:07 +01:00
										 |  |  |     if(terminal::instance()) terminal::instance()->setPrompt("§aStarting server. §7[§aloading sql§7]"); | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-24 02:57:58 +01:00
										 |  |  |     sql = new ts::server::SqlDataManager(); | 
					
						
							|  |  |  |     if(!sql->initialize(errorMessage)) { | 
					
						
							|  |  |  |         logCriticalFmt(true, LOG_GENERAL, "Could not initialize SQL!"); | 
					
						
							|  |  |  |         if(errorMessage.find("database is locked") != string::npos) { | 
					
						
							|  |  |  |             logCriticalFmt(true, LOG_GENERAL, "----------------------------[ ATTENTION ]----------------------------"); | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  |             logCriticalFmt(true, LOG_GENERAL, "{:^69}", "You're database is already in use!"); | 
					
						
							| 
									
										
										
										
											2020-01-24 02:57:58 +01:00
										 |  |  |             logCriticalFmt(true, LOG_GENERAL, "{:^69}", "Stop the other instance first!"); | 
					
						
							|  |  |  |             logCriticalFmt(true, LOG_GENERAL, "----------------------------[ ATTENTION ]----------------------------"); | 
					
						
							|  |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  |             logCriticalFmt(true, LOG_GENERAL, errorMessage); | 
					
						
							| 
									
										
										
										
											2020-01-24 02:57:58 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |         goto stopApp; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-28 11:24:07 +01:00
										 |  |  |     if(terminal::instance()) terminal::instance()->setPrompt("§aStarting server. §7[§astarting instance§7]"); | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     serverInstance = new ts::server::InstanceHandler(sql); //if error than mainThreadActive = false
 | 
					
						
							|  |  |  |     if(!mainThreadActive || !serverInstance->startInstance()) | 
					
						
							|  |  |  |         goto stopApp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if(arguments.cmdOptionExists("-q") || arguments.cmdOptionExists("--set_query_password")) { | 
					
						
							| 
									
										
										
										
											2020-01-24 02:57:58 +01:00
										 |  |  |         auto password = arguments.cmdOptionExists("-q") ? arguments.get_option("-q") : arguments.get_option("--set_query_password"); | 
					
						
							|  |  |  |         if(!password.empty()) { | 
					
						
							|  |  |  |             logMessageFmt(true, LOG_GENERAL, "Updating server admin query password to \"{}\"", password); | 
					
						
							| 
									
										
										
										
											2020-03-11 10:33:39 +01:00
										 |  |  |             auto account = serverInstance->getQueryServer()->find_query_account_by_name("serveradmin"); | 
					
						
							|  |  |  |             if(!account) { | 
					
						
							|  |  |  |                 logErrorFmt(true, LOG_GENERAL, "Failed to update server admin query password! Login does not exists!"); | 
					
						
							|  |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2020-01-24 02:57:58 +01:00
										 |  |  |                 if(!serverInstance->getQueryServer()->change_query_password(account, password)) { | 
					
						
							|  |  |  |                     logErrorFmt(true, LOG_GENERAL, "Failed to update server admin query password! (Internal error)"); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-28 11:24:07 +01:00
										 |  |  |     if(terminal::instance()) terminal::instance()->setPrompt("§7> §f"); | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  |     while(mainThreadActive) { | 
					
						
							|  |  |  |         usleep(5 * 1000); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-28 11:24:07 +01:00
										 |  |  |         if(terminal::instance()) { | 
					
						
							|  |  |  |             if(terminal::instance()->linesAvailable() > 0){ | 
					
						
							|  |  |  |                 while(!(line = terminal::instance()->readLine("§7> §f")).empty()) | 
					
						
							|  |  |  |                     threads::Thread(THREAD_DETACHED, [line](){ terminal::chandler::handleCommand(line); }); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     stopApp: | 
					
						
							| 
									
										
										
										
											2019-09-14 12:06:48 +02:00
										 |  |  |     logMessageFmt(true, LOG_GENERAL, "Stopping application"); | 
					
						
							| 
									
										
										
										
											2020-01-24 02:57:58 +01:00
										 |  |  |     ::music::manager::finalizeProviders(); | 
					
						
							| 
									
										
										
										
											2019-11-22 20:51:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  |     if(serverInstance) | 
					
						
							|  |  |  |         serverInstance->stopInstance(); | 
					
						
							|  |  |  |     delete serverInstance; | 
					
						
							| 
									
										
										
										
											2020-01-24 02:57:58 +01:00
										 |  |  |     serverInstance = nullptr; | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-24 02:57:58 +01:00
										 |  |  |     ts::music::MusicBotManager::shutdown(); | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  |     if(sql) | 
					
						
							| 
									
										
										
										
											2020-01-24 02:57:58 +01:00
										 |  |  |         sql->finalize(); | 
					
						
							|  |  |  |     delete sql; | 
					
						
							|  |  |  |     logMessageFmt(true, LOG_GENERAL, "Application suspend successful!"); | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     logger::uninstall(); | 
					
						
							| 
									
										
										
										
											2020-02-28 11:24:07 +01:00
										 |  |  |     if(terminal::active()) | 
					
						
							|  |  |  |         terminal::uninstall(); | 
					
						
							| 
									
										
										
										
											2020-01-24 02:57:58 +01:00
										 |  |  |     mainThreadDone = true; | 
					
						
							| 
									
										
										
										
											2019-07-17 19:37:18 +02:00
										 |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2020-06-16 19:40:32 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Fix for Virtuzzo 7 where sometimes the pthread create fails! */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef int (*pthread_create_t)(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); | 
					
						
							|  |  |  | pthread_create_t original_pthread_create{nullptr}; | 
					
						
							|  |  |  | int	pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg) { | 
					
						
							|  |  |  |     if(!original_pthread_create) { | 
					
						
							|  |  |  |         original_pthread_create = (pthread_create_t) dlsym(RTLD_NEXT, "pthread_create"); | 
					
						
							|  |  |  |         if(!original_pthread_create) { | 
					
						
							|  |  |  |             std::cerr << "[CRITICAL] Missing original pthread_create function. Aborting execution!" << std::endl; | 
					
						
							|  |  |  |             std::abort(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-16 19:51:06 +02:00
										 |  |  |     int result, attempt{0}, sleep{5}; | 
					
						
							| 
									
										
										
										
											2020-06-16 19:40:32 +02:00
										 |  |  |     while((result = original_pthread_create(thread, attr, start_routine, arg)) != 0 && errno == EAGAIN) { | 
					
						
							| 
									
										
										
										
											2020-06-16 19:59:44 +02:00
										 |  |  |         if(attempt > 55) { | 
					
						
							|  |  |  |             std::cerr << "[CRITICAL] pthread_create(...) cause EAGAIN for the last 50 attempts (~4.7seconds)! Aborting application execution!" << std::endl; | 
					
						
							| 
									
										
										
										
											2020-06-16 19:40:32 +02:00
										 |  |  |             std::abort(); | 
					
						
							|  |  |  |         } else if(attempt > 5) { | 
					
						
							|  |  |  |             /* let some other threads do work */ | 
					
						
							|  |  |  |             pthread_yield(); | 
					
						
							| 
									
										
										
										
											2020-06-16 19:59:44 +02:00
										 |  |  |         } else if(attempt == 0) { | 
					
						
							|  |  |  |             std::string message{"[CRITICAL] Failed to spawn thread (Resource temporarily unavailable). Trying to recover."}; | 
					
						
							|  |  |  |             std::cerr << message << std::endl; | 
					
						
							| 
									
										
										
										
											2020-06-16 19:40:32 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-06-16 19:51:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-16 19:59:44 +02:00
										 |  |  |         //std::string message{"[CRITICAL] pthread_create(...) cause EAGAIN! Trying again in " + std::to_string(sleep) + "usec (Attempt: " + std::to_string(attempt) + ")"};
 | 
					
						
							|  |  |  |         //std::cerr << message << std::endl;
 | 
					
						
							| 
									
										
										
										
											2020-06-16 19:51:06 +02:00
										 |  |  |         usleep(sleep); | 
					
						
							| 
									
										
										
										
											2020-06-16 19:40:32 +02:00
										 |  |  |         attempt++; | 
					
						
							| 
									
										
										
										
											2020-06-16 19:51:06 +02:00
										 |  |  |         sleep = (int) (sleep * 1.25); | 
					
						
							| 
									
										
										
										
											2020-06-16 19:40:32 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-06-16 19:59:44 +02:00
										 |  |  |     if(attempt > 0) { | 
					
						
							|  |  |  |         std::string message{"[CRITICAL] Successfully recovered from pthread_create() EAGAIN error. Took " + std::to_string(attempt) + " attempts."}; | 
					
						
							|  |  |  |         std::cerr << message << std::endl; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-06-16 19:40:32 +02:00
										 |  |  |     return result; | 
					
						
							| 
									
										
										
										
											2019-11-22 20:51:00 +01:00
										 |  |  | } |