diff --git a/.travis.yml b/.travis.yml index fc646c25..484be1ee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,28 +6,17 @@ before_install: - sudo apt-get update - sudo apt-get install -y software-properties-common - sudo apt-get update - - sudo apt-get install gcc-4.9 g++-4.9 gcc-4.9-multilib g++-4.9-multilib - - sudo apt-get install libboost-dev libboost-all-dev libmysqlclient-dev + - sudo apt-get install gcc-4.9 g++-4.9 gcc-4.9-multilib g++-4.9-multilib cmake3 -y + - sudo apt-get install libboost-dev libboost-all-dev libmysqlclient-dev -y compiler: - gcc -install: - - DEPS_DIR="${TRAVIS_BUILD_DIR}/deps" - - mkdir ${DEPS_DIR} && cd ${DEPS_DIR} - - - | - if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then - CMAKE_URL="http://www.cmake.org/files/v3.3/cmake-3.3.2-Linux-x86_64.tar.gz" - mkdir cmake && travis_retry wget --no-check-certificate --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake - export PATH=${DEPS_DIR}/cmake/bin:${PATH} - fi - - # Go to the Root directory - - cd .. - + # Build steps script: - mkdir build - cd build - - ${DEPS_DIR}/cmake/bin/cmake .. -DSAPPHIRE_BOOST_VER="1.54.0" -DCMAKE_CXX_COMPILER=g++-4.9 -DCMAKE_C_COMPILER=gcc-4.9 && make \ No newline at end of file + - cmake .. -DSAPPHIRE_BOOST_VER="1.54.0" -DCMAKE_CXX_COMPILER=g++-4.9 -DCMAKE_C_COMPILER=gcc-4.9 && make -j 3 + - cd .. + - bash sql_import.sh \ No newline at end of file diff --git a/README.md b/README.md index e8ff2cc7..4fa10544 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Sapphire - FINAL FANTASY XIV Server Emulator [![Discord Server](https://img.shields.io/badge/discord-Sapphire-7289DA.svg)](https://discord.gg/KfrZCkx) - +[![Build Status](https://travis-ci.org/SapphireMordred/Sapphire.svg?branch=master)](https://travis-ci.org/SapphireMordred/Sapphire) ![FFXIV Sapphire](http://i.imgur.com/I4bj1tR.png) Sapphire is a FINAL FANTASY XIV 4.0+ Server Emulator currently in development. diff --git a/sql_import.sh b/sql_import.sh new file mode 100644 index 00000000..a49e7f12 --- /dev/null +++ b/sql_import.sh @@ -0,0 +1,14 @@ +#!/bin/bash +cd sql +mysql -u root -e 'create database sapphire;' +for f in *.sql + do + [ "$f" = "update.sql" ] && continue; + echo -n "importing $f into the database..." + mysql sapphire -u root < $f && echo "Success" + CODE=$? + if [ $CODE -ne 0 ]; then exit $CODE; fi +done +#mysql sapphire -u root < update.sql -f +echo 'todo: test update sql' +cd .. diff --git a/src/servers/Server_REST/main.cpp b/src/servers/Server_REST/main.cpp index a1279231..72e59ca4 100644 --- a/src/servers/Server_REST/main.cpp +++ b/src/servers/Server_REST/main.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -43,35 +44,100 @@ typedef SimpleWeb::Client HttpClient; void default_resource_send( const HttpServer &server, const shared_ptr &response, const shared_ptr &ifs ); + +auto m_pConfig = boost::make_shared(); +HttpServer server; +std::string configPath("config/settings_rest.xml"); + +void reloadConfig() +{ + m_pConfig = boost::make_shared(); + + if (!m_pConfig->loadConfig(configPath)) + throw "Error loading config "; +} + void print_request_info( shared_ptr request ) { g_log.info( "Request from " + request->remote_endpoint_address + " (" + request->path + ")" ); } - -int main() +bool loadSettings( int argc, char* argv[] ) { - g_log.setLogPath( "log\\SapphireAPI" ); - g_log.init(); + g_log.info( "Loading config " + configPath ); - g_log.info( "===========================================================" ); - g_log.info( "Sapphire API Server " ); - g_log.info( "Version: 0.0.1" ); - g_log.info( "Compiled: " __DATE__ " " __TIME__ ); - g_log.info( "===========================================================" ); - - auto m_pConfig = new Core::XMLConfig(); - - g_log.info( "Loading config settings_rest.xml" ); - - if( !m_pConfig->loadConfig( "config/settings_rest.xml" ) ) + if( !m_pConfig->loadConfig( configPath ) ) { - g_log.fatal( "Error loading config settings_rest.xml" ); - return 1; + g_log.fatal( "Error loading config " + configPath ); + return false; } - if( !g_exdData.init( m_pConfig->getValue< std::string >( "Settings.General.DataPath" ) ) ) + std::vector args( argv + 1, argv + argc ); + for( auto i = 0; i + 1 < args.size(); i += 2 ) + { + std::string arg( "" ); + std::string val( "" ); + + try + { + arg = boost::to_lower_copy( std::string( args[i] ) ); + val = std::string( args[i + 1] ); + + // trim '-' from start of arg + arg = arg.erase( 0, arg.find_first_not_of( '-' ) ); + + if( arg == "ip" ) + { + // todo: ip addr in config + m_pConfig->setValue< std::string >( "Settings.General.ListenIP", val ); + } + else if( arg == "p" || arg == "port" ) + { + m_pConfig->setValue< std::string >( "Settings.General.ListenPort", val ); + } + else if( arg == "exdpath" || arg == "datapath" ) + { + m_pConfig->setValue< std::string >( "Settings.General.DataPath", val ); + } + else if( arg == "h" || arg == "dbhost" ) + { + m_pConfig->setValue< std::string >( "Settings.General.Mysql.Host", val ); + } + else if( arg == "dbport" ) + { + m_pConfig->setValue< std::string >( "Settings.General.Mysql.Port", val ); + } + else if( arg == "u" || arg == "user" || arg == "dbuser" ) + { + m_pConfig->setValue< std::string >( "Settings.General.Mysql.Username", val ); + } + else if( arg == "pass" || arg == "dbpass" ) + { + m_pConfig->setValue< std::string >( "Settings.General.Mysql.Pass", val ); + } + else if( arg == "d" || arg == "db" || arg == "database" ) + { + m_pConfig->setValue< std::string >( "Settings.General.Mysql.Database", val ); + } + else if ( arg == "lobbyip" || arg == "lobbyhost" ) + { + m_pConfig->setValue< std::string >( "Settings.General.LobbyHost", val ); + } + else if ( arg == "lobbyport" ) + { + m_pConfig->setValue< std::string >( "Settings.General.LobbyPort", val ); + } + } + catch( ... ) + { + g_log.error( "Error parsing argument: " + arg + " " + "value: " + val + "\n" ); + g_log.error( "Usage: \n" ); + } + } + + g_log.info( "Setting up EXD data" ); + if( !g_exdData.init( m_pConfig->getValue< std::string >( "Settings.General.DataPath", "" ) ) ) { g_log.fatal( "Error setting up EXD data " ); - return 1; + return false; } Core::Db::DatabaseParams params; @@ -83,21 +149,42 @@ int main() params.port = m_pConfig->getValue< uint16_t >( "Settings.General.Mysql.Port", 3306 ); params.username = m_pConfig->getValue< std::string >( "Settings.General.Mysql.Username", "root" ); + server.config.port = std::stoul( m_pConfig->getValue( "Settings.General.HttpPort", "80" ) ); + if( !g_database.initialize( params ) ) { std::this_thread::sleep_for( std::chrono::milliseconds( 5000 ) ); - return -1; + return false; + } + + g_log.info("Database: Connected to " + params.hostname + ":" + std::to_string(params.port)); + + return true; +} + +int main(int argc, char* argv[]) +{ + g_log.setLogPath( "log\\SapphireAPI" ); + g_log.init(); + + g_log.info( "===========================================================" ); + g_log.info( "Sapphire API Server " ); + g_log.info( "Version: 0.0.1" ); + g_log.info( "Compiled: " __DATE__ " " __TIME__ ); + g_log.info( "===========================================================" ); + + if (!loadSettings(argc, argv)) + { + throw std::exception(); } - g_log.info( "Database: Connected to " + params.hostname + ":" + std::to_string( params.port ) ); g_exdData.loadZoneInfo(); g_exdData.loadClassJobInfo(); - HttpServer server; server.config.port = stoi( m_pConfig->getValue< std::string >( "Settings.General.HttpPort", "80" ) ); g_log.info( "Starting REST server at port " + m_pConfig->getValue< std::string >( "Settings.General.HttpPort", "80" ) + "..." ); - server.resource["^/ZoneName/([0-9]+)$"]["GET"] = [&server]( shared_ptr response, shared_ptr request ) { + server.resource["^/ZoneName/([0-9]+)$"]["GET"] = [&]( shared_ptr response, shared_ptr request ) { string number = request->path_match[1]; auto it = g_exdData.m_zoneInfoMap.find( atoi( number.c_str() ) ); std::string responseStr = "Not found!"; @@ -110,7 +197,7 @@ int main() /* Create account */ - server.resource["^/sapphire-api/lobby/createAccount"]["POST"] = [&server]( shared_ptr response, shared_ptr request ) { + server.resource["^/sapphire-api/lobby/createAccount"]["POST"] = [&]( shared_ptr response, shared_ptr request ) { print_request_info( request ); std::string responseStr = "HTTP/1.1 400\r\n\r\n"; @@ -124,19 +211,11 @@ int main() std::string pass = pt.get( "pass" ); std::string user = pt.get( "username" ); + // reloadConfig(); + std::string sId; if( g_sapphireAPI.createAccount( user, pass, sId ) ) { - auto m_pConfig = new Core::XMLConfig(); - - g_log.info( "Loading config settings_rest.xml" ); - - if( !m_pConfig->loadConfig( "config/settings_rest.xml" ) ) - { - g_log.fatal( "Error loading config settings_rest.xml" ); - return 1; - } - std::string json_string = "{\"sId\":\"" + sId + "\", \"lobbyHost\":\"" + m_pConfig->getValue< std::string >( "Settings.General.LobbyHost" ) + "\", \"frontierHost\":\"" + m_pConfig->getValue< std::string >( "Settings.General.FrontierHost" ) + "\"}"; *response << "HTTP/1.1 200 OK\r\n " << "Content-Type: application/json\r\n" @@ -155,7 +234,7 @@ int main() }; - server.resource["^/sapphire-api/lobby/login"]["POST"] = [&server]( shared_ptr response, shared_ptr request ) { + server.resource["^/sapphire-api/lobby/login"]["POST"] = [&]( shared_ptr response, shared_ptr request ) { print_request_info( request ); try @@ -169,16 +248,10 @@ int main() std::string sId; + // reloadConfig(); + if( g_sapphireAPI.login( user, pass, sId ) ) { - auto m_pConfig = new Core::XMLConfig(); - - if( !m_pConfig->loadConfig( "config/settings_rest.xml" ) ) - { - g_log.fatal( "Error loading config settings_rest.xml" ); - return 1; - } - std::string json_string = "{\"sId\":\"" + sId + "\", \"lobbyHost\":\"" + m_pConfig->getValue< std::string >("Settings.General.LobbyHost") + "\", \"frontierHost\":\"" + m_pConfig->getValue< std::string >( "Settings.General.FrontierHost" ) + "\"}"; *response << "HTTP/1.1 200\r\nContent-Length: " << json_string.length() << "\r\n\r\n" << json_string; } @@ -194,7 +267,7 @@ int main() }; - server.resource["^/sapphire-api/lobby/deleteCharacter"]["POST"] = [&server]( shared_ptr response, shared_ptr request ) { + server.resource["^/sapphire-api/lobby/deleteCharacter"]["POST"] = [&]( shared_ptr response, shared_ptr request ) { print_request_info( request ); try @@ -206,16 +279,10 @@ int main() std::string sId = pt.get( "sId" ); std::string secret = pt.get( "secret" ); std::string name = pt.get( "name" ); + + // reloadConfig(); int accountId = g_sapphireAPI.checkSession( sId ); - - auto m_pConfig = new Core::XMLConfig(); - - if( !m_pConfig->loadConfig( "config/settings_rest.xml" ) ) - { - g_log.fatal( "Error loading config settings_rest.xml" ); - return 1; - } if( m_pConfig->getValue< std::string >( "Settings.General.ServerSecret" ) != secret ) { std::string json_string = "{\"result\":\"invalid_secret\"}"; @@ -236,7 +303,7 @@ int main() }; - server.resource["^/sapphire-api/lobby/createCharacter"]["POST"] = [&server]( shared_ptr response, shared_ptr request ) { + server.resource["^/sapphire-api/lobby/createCharacter"]["POST"] = [&]( shared_ptr response, shared_ptr request ) { print_request_info( request ); try @@ -252,18 +319,12 @@ int main() std::string finalJson = Core::Util::base64_decode( infoJson ); + // reloadConfig(); + int result = g_sapphireAPI.checkSession( sId ); if( result != -1 ) { - auto m_pConfig = new Core::XMLConfig(); - - if( !m_pConfig->loadConfig( "config/settings_rest.xml" ) ) - { - g_log.fatal( "Error loading config settings_rest.xml" ); - return 1; - } - if( m_pConfig->getValue< std::string >( "Settings.General.ServerSecret" ) != secret ) { std::string json_string = "{\"result\":\"invalid_secret\"}"; *response << "HTTP/1.1 403\r\nContent-Length: " << json_string.length() << "\r\n\r\n" << json_string; @@ -290,7 +351,7 @@ int main() }; - server.resource["^/sapphire-api/lobby/insertSession"]["POST"] = [&server]( shared_ptr response, shared_ptr request ) { + server.resource["^/sapphire-api/lobby/insertSession"]["POST"] = [&]( shared_ptr response, shared_ptr request ) { print_request_info( request ); try @@ -303,13 +364,7 @@ int main() uint32_t accountId = pt.get( "accountId" ); std::string secret = pt.get( "secret" ); - auto m_pConfig = new Core::XMLConfig(); - - if( !m_pConfig->loadConfig( "config/settings_rest.xml" ) ) - { - g_log.fatal( "Error loading config settings_rest.xml" ); - return 1; - } + // reloadConfig(); if( m_pConfig->getValue< std::string >( "Settings.General.ServerSecret" ) != secret ) { std::string json_string = "{\"result\":\"invalid_secret\"}"; @@ -330,7 +385,7 @@ int main() }; - server.resource["^/sapphire-api/lobby/checkNameTaken"]["POST"] = [&server]( shared_ptr response, shared_ptr request ) { + server.resource["^/sapphire-api/lobby/checkNameTaken"]["POST"] = [&]( shared_ptr response, shared_ptr request ) { print_request_info( request ); try @@ -342,13 +397,7 @@ int main() std::string name = pt.get( "name" ); std::string secret = pt.get( "secret" ); - auto m_pConfig = new Core::XMLConfig(); - - if( !m_pConfig->loadConfig( "config/settings_rest.xml" ) ) - { - g_log.fatal( "Error loading config settings_rest.xml" ); - return 1; - } + // reloadConfig(); if( m_pConfig->getValue< std::string >( "Settings.General.ServerSecret" ) != secret ) { std::string json_string = "{\"result\":\"invalid_secret\"}"; @@ -373,7 +422,7 @@ int main() }; - server.resource["^/sapphire-api/lobby/checkSession"]["POST"] = [&server]( shared_ptr response, shared_ptr request ) { + server.resource["^/sapphire-api/lobby/checkSession"]["POST"] = [&]( shared_ptr response, shared_ptr request ) { print_request_info( request ); try @@ -387,16 +436,10 @@ int main() int result = g_sapphireAPI.checkSession( sId ); + // reloadConfig(); + if( result != -1 ) { - auto m_pConfig = new Core::XMLConfig(); - - if( !m_pConfig->loadConfig( "config/settings_rest.xml" ) ) - { - g_log.fatal( "Error loading config settings_rest.xml" ); - return 1; - } - if( m_pConfig->getValue< std::string >( "Settings.General.ServerSecret" ) != secret ) { std::string json_string = "{\"result\":\"invalid_secret\"}"; *response << "HTTP/1.1 403\r\nContent-Length: " << json_string.length() << "\r\n\r\n" << json_string; @@ -421,7 +464,7 @@ int main() }; - server.resource["^/sapphire-api/lobby/getNextCharId"]["POST"] = [&server]( shared_ptr response, shared_ptr request ) { + server.resource["^/sapphire-api/lobby/getNextCharId"]["POST"] = [&]( shared_ptr response, shared_ptr request ) { print_request_info( request ); try @@ -432,13 +475,7 @@ int main() std::string secret = pt.get( "secret" ); - auto m_pConfig = new Core::XMLConfig(); - - if( !m_pConfig->loadConfig( "config/settings_rest.xml" ) ) - { - g_log.fatal( "Error loading config settings_rest.xml" ); - return 1; - } + // reloadConfig(); if( m_pConfig->getValue< std::string >( "Settings.General.ServerSecret" ) != secret ) { std::string json_string = "{\"result\":\"invalid_secret\"}"; @@ -458,7 +495,7 @@ int main() }; - server.resource["^/sapphire-api/lobby/getNextContentId"]["POST"] = [&server]( shared_ptr response, shared_ptr request ) { + server.resource["^/sapphire-api/lobby/getNextContentId"]["POST"] = [&]( shared_ptr response, shared_ptr request ) { print_request_info( request ); try @@ -469,13 +506,7 @@ int main() std::string secret = pt.get( "secret" ); - auto m_pConfig = new Core::XMLConfig(); - - if( !m_pConfig->loadConfig( "config/settings_rest.xml" ) ) - { - g_log.fatal( "Error loading config settings_rest.xml" ); - return 1; - } + // reloadConfig(); if( m_pConfig->getValue< std::string >( "Settings.General.ServerSecret" ) != secret ) { std::string json_string = "{\"result\":\"invalid_secret\"}"; @@ -495,7 +526,7 @@ int main() }; - server.resource["^/sapphire-api/lobby/getCharacterList"]["POST"] = [&server]( shared_ptr response, shared_ptr request ) { + server.resource["^/sapphire-api/lobby/getCharacterList"]["POST"] = [&]( shared_ptr response, shared_ptr request ) { print_request_info( request ); try @@ -507,17 +538,12 @@ int main() std::string sId = pt.get( "sId" ); std::string secret = pt.get( "secret" ); + // reloadConfig(); + int result = g_sapphireAPI.checkSession( sId ); if( result != -1 ) { - auto m_pConfig = new Core::XMLConfig(); - - if( !m_pConfig->loadConfig( "config/settings_rest.xml" ) ) - { - g_log.fatal( "Error loading config settings_rest.xml" ); - return 1; - } if( m_pConfig->getValue< std::string >( "Settings.General.ServerSecret" ) != secret ) { std::string json_string = "{\"result\":\"invalid_secret\"}"; @@ -562,7 +588,7 @@ int main() }; - server.resource["^(/frontier-api/ffxivsupport/view/get_init)(.*)"]["GET"] = [&server]( shared_ptr response, shared_ptr request ) { + server.resource["^(/frontier-api/ffxivsupport/view/get_init)(.*)"]["GET"] = [&]( shared_ptr response, shared_ptr request ) { print_request_info( request ); try @@ -603,7 +629,7 @@ int main() }; - server.resource["^(/frontier-api/ffxivsupport/information/get_headline_all)(.*)"]["GET"] = [&server]( shared_ptr response, shared_ptr request ) { + server.resource["^(/frontier-api/ffxivsupport/information/get_headline_all)(.*)"]["GET"] = [&]( shared_ptr response, shared_ptr request ) { print_request_info( request ); try @@ -648,7 +674,7 @@ int main() //Will respond with content in the web/-directory, and its subdirectories. //Default file: index.html //Can for instance be used to retrieve an HTML 5 client that uses REST-resources on this server - server.default_resource["GET"] = [&server]( shared_ptr response, shared_ptr request ) { + server.default_resource["GET"] = [&]( shared_ptr response, shared_ptr request ) { print_request_info( request ); try @@ -690,7 +716,7 @@ int main() } }; - thread server_thread( [&server]() { + thread server_thread( [&]() { //Start server server.start(); } );