forked from aya/aya
Initial commit
This commit is contained in:
53
client/server/CMakeLists.txt
Normal file
53
client/server/CMakeLists.txt
Normal file
@@ -0,0 +1,53 @@
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
add_executable(Server
|
||||
resources/qt.qrc
|
||||
src/main.cpp
|
||||
src/server.cpp
|
||||
src/server.hpp
|
||||
src/grid.cpp
|
||||
src/grid.hpp
|
||||
src/AppView.hpp
|
||||
src/AppView.cpp
|
||||
src/MainWindow.cpp
|
||||
src/MainWindow.hpp
|
||||
|
||||
src/linenoise.hpp
|
||||
${CLIENT_DIR}/common/AppSettings.cpp
|
||||
${CLIENT_DIR}/common/AppSettings.hpp
|
||||
${CLIENT_DIR}/common/SDLGameController.cpp
|
||||
${CLIENT_DIR}/common/SDLGameController.hpp
|
||||
)
|
||||
|
||||
target_link_libraries(Server
|
||||
3D
|
||||
AppServer
|
||||
Core
|
||||
RakNet
|
||||
BulletPhysics
|
||||
NetworkServer
|
||||
Graphics
|
||||
)
|
||||
|
||||
if(AYA_OS_WINDOWS)
|
||||
target_sources(Server PRIVATE
|
||||
resources/winrc.h
|
||||
resources/script.rc
|
||||
)
|
||||
|
||||
set_target_properties(Server PROPERTIES WIN32_EXECUTABLE TRUE)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(Server PRIVATE QT_NO_KEYWORDS)
|
||||
|
||||
target_include_directories(Server PRIVATE src resources)
|
||||
set_target_properties(Server PROPERTIES OUTPUT_NAME "Aya.Server")
|
||||
|
||||
add_custom_command(TARGET Server POST_BUILD
|
||||
COMMENT "Copying runtime files to build directory"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${RUNTIME_FILES}"
|
||||
"${CMAKE_RUNTIME_OUTPUT_DIRECTORY}"
|
||||
)
|
||||
BIN
client/server/resources/icon.ico
Normal file
BIN
client/server/resources/icon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
5
client/server/resources/qt.qrc
Normal file
5
client/server/resources/qt.qrc
Normal file
@@ -0,0 +1,5 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource>
|
||||
<file>icon.ico</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
49
client/server/resources/script.rc
Normal file
49
client/server/resources/script.rc
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "winrc.h"
|
||||
|
||||
#if defined(__MINGW64__) || defined(__MINGW32__)
|
||||
// MinGW-w64, MinGW
|
||||
#if defined(__has_include) && __has_include(<winres.h>)
|
||||
#include <winres.h>
|
||||
#else
|
||||
#include <afxres.h>
|
||||
#include <winresrc.h>
|
||||
#endif
|
||||
#else
|
||||
// MSVC, Windows SDK
|
||||
#include <winres.h>
|
||||
#endif
|
||||
|
||||
IDI_ICON1 ICON APP_ICON
|
||||
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION VERSION_RESOURCE
|
||||
PRODUCTVERSION VERSION_RESOURCE
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x4L
|
||||
FILETYPE 0x1L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", APP_ORGANIZATION
|
||||
VALUE "FileDescription", APP_DESCRIPTION
|
||||
VALUE "FileVersion", VERSION_RESOURCE_STR
|
||||
VALUE "LegalCopyright", APP_COPYRIGHT
|
||||
VALUE "ProductName", APP_NAME
|
||||
VALUE "ProductVersion", VERSION_RESOURCE_STR
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", PRODUCT_LANGUAGE, PRODUCT_CHARSET
|
||||
END
|
||||
END
|
||||
24
client/server/resources/winrc.h
Normal file
24
client/server/resources/winrc.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#define VERSION_MAJOR_MINOR_STR AYA_VERSION_MAJOR_STR "." AYA_VERSION_MINOR_STR
|
||||
#define VERSION_MAJOR_MINOR_PATCH_STR VERSION_MAJOR_MINOR_STR "." AYA_VERSION_PATCH_STR
|
||||
#ifdef AYA_VERSION_TYPE
|
||||
#define VERSION_FULL_STR VERSION_MAJOR_MINOR_PATCH_STR "-" AYA_VERSION_TYPE
|
||||
#else
|
||||
#define VERSION_FULL_STR VERSION_MAJOR_MINOR_PATCH_STR
|
||||
#endif
|
||||
#define VERSION_RESOURCE AYA_VERSION_MAJOR, AYA_VERSION_MINOR, AYA_VERSION_PATCH, 0
|
||||
#define VERSION_RESOURCE_STR VERSION_FULL_STR "\0"
|
||||
|
||||
/*
|
||||
* These properties are part of VarFileInfo.
|
||||
* For more information, please see: https://learn.microsoft.com/en-us/windows/win32/menurc/varfileinfo-block
|
||||
*/
|
||||
#define PRODUCT_LANGUAGE 0x0409 // en-US
|
||||
#define PRODUCT_CHARSET 1200 // Unicode
|
||||
|
||||
#define APP_ICON "icon.ico"
|
||||
#define APP_NAME AYA_PROJECT_NAME "\0"
|
||||
#define APP_DESCRIPTION AYA_PROJECT_NAME " Server\0"
|
||||
#define APP_ORGANIZATION AYA_PROJECT_NAME "\0"
|
||||
#define APP_COPYRIGHT AYA_PROJECT_NAME " License\0"
|
||||
56
client/server/src/AppView.cpp
Normal file
56
client/server/src/AppView.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
#include "AppView.hpp"
|
||||
|
||||
#include <QWebEngineSettings>
|
||||
#include <QWebEngineScript>
|
||||
#include <QWebEngineScriptCollection>
|
||||
#include <QNetworkRequest>
|
||||
#include <QMessageBox>
|
||||
#include <QCheckBox>
|
||||
#include <QDialog>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QFileDialog>
|
||||
#include <QInputDialog>
|
||||
#include <QProgressDialog>
|
||||
#include <QFrame>
|
||||
#include <QVBoxLayout>
|
||||
#include <QString>
|
||||
#include <QSettings>
|
||||
|
||||
AppView::AppView(QWidget* parent, std::string mode)
|
||||
: QWebEngineView(parent)
|
||||
{
|
||||
setContextMenuPolicy(Qt::NoContextMenu);
|
||||
|
||||
QWebEngineSettings* settings = page()->settings();
|
||||
settings->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls, true);
|
||||
settings->setAttribute(QWebEngineSettings::LocalContentCanAccessFileUrls, true);
|
||||
settings->setAttribute(QWebEngineSettings::LocalStorageEnabled, true);
|
||||
settings->setAttribute(QWebEngineSettings::JavascriptEnabled, true);
|
||||
settings->setAttribute(QWebEngineSettings::DnsPrefetchEnabled, true);
|
||||
settings->setAttribute(QWebEngineSettings::Accelerated2dCanvasEnabled, true);
|
||||
|
||||
// pre-load the QWebChannel API
|
||||
QFile apiFile(":/qtwebchannel/qwebchannel.js");
|
||||
if (!apiFile.open(QIODevice::ReadOnly))
|
||||
qDebug() << "Couldn't load Qt's QWebChannel API!";
|
||||
QString apiScript = QString::fromLatin1(apiFile.readAll());
|
||||
apiFile.close();
|
||||
|
||||
QWebEngineScript script;
|
||||
script.setSourceCode(apiScript);
|
||||
script.setName("QWebChannel");
|
||||
script.setWorldId(QWebEngineScript::MainWorld);
|
||||
script.setInjectionPoint(QWebEngineScript::DocumentCreation);
|
||||
script.setRunsOnSubFrames(false);
|
||||
page()->scripts().insert(script);
|
||||
|
||||
// setup the transport interface
|
||||
transport = new AppTransport();
|
||||
channel = new QWebChannel(page());
|
||||
channel->registerObject(QStringLiteral("transport"), transport);
|
||||
page()->setWebChannel(channel);
|
||||
|
||||
load(QUrl::fromLocalFile(QString::fromStdString(GetAssetFolder() + "/app/index.html?mode=" + mode)));
|
||||
}
|
||||
|
||||
// #include "AppView.moc"
|
||||
30
client/server/src/AppView.hpp
Normal file
30
client/server/src/AppView.hpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QtWebChannel>
|
||||
#include <QWebEngineView>
|
||||
|
||||
class AppTransport : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
QWidget* parent;
|
||||
QNetworkAccessManager* manager;
|
||||
};
|
||||
|
||||
class AppView : public QWebEngineView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
QWebChannel* channel;
|
||||
AppTransport* transport;
|
||||
|
||||
public:
|
||||
AppView(QWidget* parent, std::string mode);
|
||||
|
||||
AppTransport* getTransport()
|
||||
{
|
||||
return transport;
|
||||
};
|
||||
};
|
||||
19
client/server/src/MainWindow.cpp
Normal file
19
client/server/src/MainWindow.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "MainWindow.hpp"
|
||||
|
||||
#include <QIcon>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
MainWindow::MainWindow(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
QWidget* widget = new QWidget(this);
|
||||
app = new AppView(widget, "server");
|
||||
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
layout->addWidget(widget);
|
||||
|
||||
setWindowIcon(QIcon(":/icon.ico"));
|
||||
setMinimumSize(800, 600);
|
||||
setMaximumSize(800, 600);
|
||||
setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
|
||||
}
|
||||
19
client/server/src/MainWindow.hpp
Normal file
19
client/server/src/MainWindow.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QEvent>
|
||||
|
||||
#include "AppView.hpp"
|
||||
|
||||
class MainWindow : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
AppView* app;
|
||||
|
||||
public:
|
||||
MainWindow(QWidget* parent = NULL);
|
||||
// ~MainWindow();
|
||||
//
|
||||
// bool event(QEvent* event);
|
||||
};
|
||||
205
client/server/src/grid.cpp
Normal file
205
client/server/src/grid.cpp
Normal file
@@ -0,0 +1,205 @@
|
||||
#include "grid.hpp"
|
||||
#include <boost/beast.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
boost::scoped_ptr<Grid> Grid::singleton;
|
||||
|
||||
Grid::Grid(int port)
|
||||
: acceptor(ioc)
|
||||
, running(false)
|
||||
, port(port)
|
||||
{
|
||||
}
|
||||
|
||||
Grid::~Grid()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
bool Grid::start()
|
||||
{
|
||||
if (running.load())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
auto const address = net::ip::make_address("0.0.0.0");
|
||||
tcp::endpoint endpoint{address, static_cast<unsigned short>(port)};
|
||||
|
||||
acceptor.open(endpoint.protocol());
|
||||
acceptor.set_option(net::socket_base::reuse_address(true));
|
||||
acceptor.bind(endpoint);
|
||||
acceptor.listen(net::socket_base::max_listen_connections);
|
||||
|
||||
running.store(true);
|
||||
server_thread = std::make_unique<std::thread>(&Grid::run_server, this);
|
||||
|
||||
std::cout << "Grid started on port " << port << std::endl;
|
||||
return true;
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
std::cerr << "Error starting Grid: " << e.what() << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Grid::stop()
|
||||
{
|
||||
if (!running.load())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
running.store(false);
|
||||
|
||||
try
|
||||
{
|
||||
acceptor.close();
|
||||
ioc.stop();
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
std::cerr << "Error stopping Grid: " << e.what() << std::endl;
|
||||
}
|
||||
|
||||
if (server_thread && server_thread->joinable())
|
||||
{
|
||||
server_thread->join();
|
||||
}
|
||||
|
||||
std::cout << "Grid stopped" << std::endl;
|
||||
}
|
||||
|
||||
bool Grid::is_running() const
|
||||
{
|
||||
return running.load();
|
||||
}
|
||||
|
||||
void Grid::run_server()
|
||||
{
|
||||
do_accept();
|
||||
ioc.run();
|
||||
}
|
||||
|
||||
void Grid::do_accept()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Grid::handle_session(tcp::socket socket)
|
||||
{
|
||||
try
|
||||
{
|
||||
beast::flat_buffer buffer;
|
||||
http::request<http::string_body> req;
|
||||
|
||||
// Read the request
|
||||
http::read(socket, buffer, req);
|
||||
|
||||
http::response<http::string_body> res;
|
||||
res.version(req.version());
|
||||
res.set(http::field::server, "Grid/1.0");
|
||||
res.set(http::field::content_type, "application/json");
|
||||
res.set(http::field::access_control_allow_origin, "*");
|
||||
res.set(http::field::access_control_allow_methods, "GET, POST");
|
||||
res.set(http::field::access_control_allow_headers, "Content-Type");
|
||||
|
||||
std::string method = std::string(req.method_string());
|
||||
std::string path = std::string(req.target());
|
||||
std::string body = req.body();
|
||||
/*
|
||||
if (method == "GET" || method == "POST")
|
||||
{
|
||||
if (method == "POST" && !body.empty())
|
||||
{
|
||||
rapidjson::Document doc;
|
||||
if (doc.Parse(body.c_str()).HasParseError())
|
||||
{
|
||||
res.result(http::status::bad_request);
|
||||
res.body() = R"({"error":"Invalid JSON"})";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string response_body = handle_request(method, path, doc);
|
||||
res.result(http::status::ok);
|
||||
res.body() = response_body;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string response_body = handle_request(method, path, rapidjson::Document());
|
||||
res.result(http::status::ok);
|
||||
res.body() = response_body;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
res.result(http::status::method_not_allowed);
|
||||
res.body() = R"({"error":"Method not allowed"})";
|
||||
}
|
||||
*/
|
||||
res.prepare_payload();
|
||||
|
||||
http::write(socket, res);
|
||||
socket.shutdown(tcp::socket::shutdown_send);
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
std::cerr << "Session error: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::string Grid::handle_request(const std::string& method, const std::string& path, const rapidjson::Document& json_body)
|
||||
{
|
||||
if (json_handler)
|
||||
{
|
||||
return json_handler(method, path, json_body);
|
||||
}
|
||||
|
||||
return R"({"status":"ok","message":"Grid server is running"})";
|
||||
}
|
||||
|
||||
bool Grid::is_valid_json(const std::string& str)
|
||||
{
|
||||
if (str.empty())
|
||||
return false;
|
||||
|
||||
rapidjson::Document doc;
|
||||
if (doc.Parse(str.c_str()).HasParseError())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return doc.IsObject() || doc.IsArray();
|
||||
}
|
||||
|
||||
void start_grid_server(int port)
|
||||
{
|
||||
if (!Grid::singleton)
|
||||
{
|
||||
Grid::singleton.reset(new Grid(port));
|
||||
}
|
||||
Grid::singleton->start();
|
||||
}
|
||||
|
||||
void stop_grid_server()
|
||||
{
|
||||
if (Grid::singleton)
|
||||
{
|
||||
Grid::singleton->stop();
|
||||
}
|
||||
}
|
||||
|
||||
bool is_grid_server_running()
|
||||
{
|
||||
return Grid::singleton && Grid::singleton->is_running();
|
||||
}
|
||||
49
client/server/src/grid.hpp
Normal file
49
client/server/src/grid.hpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <boost/beast.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <boost/smart_ptr/scoped_ptr.hpp>
|
||||
#include <rapidjson/document.h>
|
||||
|
||||
namespace beast = boost::beast;
|
||||
namespace http = beast::http;
|
||||
namespace net = boost::asio;
|
||||
using tcp = net::ip::tcp;
|
||||
|
||||
class Grid : public std::enable_shared_from_this<Grid>
|
||||
{
|
||||
private:
|
||||
net::io_context ioc;
|
||||
tcp::acceptor acceptor;
|
||||
std::unique_ptr<std::thread> server_thread;
|
||||
std::atomic<bool> running;
|
||||
int port;
|
||||
|
||||
void run_server();
|
||||
void do_accept();
|
||||
void handle_session(tcp::socket socket);
|
||||
std::string handle_request(const std::string& method, const std::string& path, const rapidjson::Document& body);
|
||||
bool is_valid_json(const std::string& str);
|
||||
|
||||
public:
|
||||
static boost::scoped_ptr<Grid> singleton;
|
||||
|
||||
Grid(int port);
|
||||
~Grid();
|
||||
|
||||
bool start();
|
||||
void stop();
|
||||
bool is_running() const;
|
||||
|
||||
std::function<std::string(const std::string& method, const std::string& path, const rapidjson::Document& json_body)> json_handler;
|
||||
};
|
||||
|
||||
void start_grid_server(int port);
|
||||
void stop_grid_server();
|
||||
bool is_grid_server_running();
|
||||
2415
client/server/src/linenoise.hpp
Normal file
2415
client/server/src/linenoise.hpp
Normal file
File diff suppressed because it is too large
Load Diff
230
client/server/src/main.cpp
Normal file
230
client/server/src/main.cpp
Normal file
@@ -0,0 +1,230 @@
|
||||
// clang-format off
|
||||
|
||||
#include <QApplication>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <string>
|
||||
|
||||
#include "DataModel/ContentProvider.hpp"
|
||||
#include "DataModel/DataModel.hpp"
|
||||
#include "DataModel/DebugSettings.hpp"
|
||||
#include "DataModel/GameBasicSettings.hpp"
|
||||
|
||||
#include "Script/ScriptContext.hpp"
|
||||
#include "Utility/StandardOut.hpp"
|
||||
#include "Utility/Statistics.hpp"
|
||||
|
||||
#include "AppSettings.hpp"
|
||||
#include "MainWindow.hpp"
|
||||
#include "server.hpp"
|
||||
#include "winrc.h"
|
||||
|
||||
namespace po = boost::program_options;
|
||||
|
||||
bool tryRead(const std::string& input, std::string& output)
|
||||
{
|
||||
std::ifstream file(input);
|
||||
if (file)
|
||||
{
|
||||
std::stringstream buffer;
|
||||
buffer << file.rdbuf();
|
||||
output = buffer.str();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Aya::ContentProvider::isHttpUrl(input))
|
||||
{
|
||||
try
|
||||
{
|
||||
Aya::Http http(input);
|
||||
http.get(output);
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
Aya::StandardOut::singleton()->printf(Aya::MESSAGE_ERROR, "Error trying to fetch '%s': %s", input.c_str(), e.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
output = input;
|
||||
return true;
|
||||
}
|
||||
|
||||
QCoreApplication* createApplication(int &argc, const char *argv[])
|
||||
{
|
||||
if (!argc)
|
||||
return new QApplication(argc, (char**)argv);
|
||||
|
||||
return new QCoreApplication(argc, (char**)argv);
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
QScopedPointer<QCoreApplication> app(createApplication(argc, argv));
|
||||
bool ui = qobject_cast<QApplication*>(app.data()) != nullptr;
|
||||
|
||||
QCoreApplication::setOrganizationName(AYA_PROJECT_NAME);
|
||||
QCoreApplication::setApplicationName(AYA_PROJECT_NAME " Server");
|
||||
QCoreApplication::setApplicationVersion(VERSION_FULL_STR);
|
||||
|
||||
po::options_description desc("Aya Server options");
|
||||
|
||||
std::string testScript, evaluateScript;
|
||||
std::string instanceUrl, instanceAccessKey;
|
||||
std::string trustCheckUrl;
|
||||
std::string masterServerUrl, masterServerKey, masterServerHost, masterServerName, masterServerDescription;
|
||||
std::string localServerPlace, localServerPassword;
|
||||
std::string contentPath;
|
||||
|
||||
int gridPort, localServerPort;
|
||||
|
||||
desc.add_options()
|
||||
("help,?", "Usage help")
|
||||
("version,V", "Print version and exit")
|
||||
("verbose", "Enable verbose logging (prints all output messages including FastLogs)")
|
||||
("lan,L", "For local network or single-player servers (disables all online interaction)")
|
||||
("insecure,I", "Disables anti-cheat & authentication checks")
|
||||
("test", po::value<std::string>(&testScript)->implicit_value("ayaasset://scripts/ServerCoreScripts/Test.lua"), "Runs a test job with the given Lua script")
|
||||
("eval,E", po::value<std::string>(&evaluateScript), "Lua script to run")
|
||||
("port,G", po::value<int>(&gridPort)->implicit_value(64989), "Runs the Grid HTTP service on the given port")
|
||||
("instance-url,U", po::value<std::string>(&instanceUrl)/*->default_value("http://www.kiseki.lol")*/, "Instance URL (leave blank for no connected instance)")
|
||||
("instance-access-key,k", po::value<std::string>(&instanceAccessKey), "Instance access key (for sensitive instance actions)")
|
||||
("trust-check-url,T", po::value<std::string>(&trustCheckUrl), "Only allow asset requests from the given domain (leave blank for no trust check)")
|
||||
("ms-url,a", po::value<std::string>(&masterServerUrl), "Master server URL for broadcasting server details (leave blank for no master server connection)")
|
||||
("ms-key,A", po::value<std::string>(&masterServerKey), "Master server authorization key (if the master server requires it)")
|
||||
("ms-host,H", po::value<std::string>(&masterServerHost)->default_value("Bloxhead"), "Name of the host to be broadcasted")
|
||||
("ms-name,N", po::value<std::string>(&masterServerName)->default_value("Aya Server"), "Name of the server to be broadcasted")
|
||||
("ms-description,d", po::value<std::string>(&masterServerDescription)->default_value("Welcome to my server!"), "Short description of the server to be broadcasted")
|
||||
("server-port,P", po::value<int>(&localServerPort)->implicit_value(53640), "Runs a server on the given port")
|
||||
("server-place,f", po::value<std::string>(&localServerPlace)->default_value("ayaasset://place.rbxl"), "Path to place file for local server")
|
||||
("server-password,K", po::value<std::string>(&localServerPassword), "Local server password for direct connections")
|
||||
("content-path", po::value<std::string>(&contentPath)->default_value(GetAssetFolder()), "Path to the content directory")
|
||||
("no-repl", "Disable terminal REPL");
|
||||
|
||||
po::variables_map vm;
|
||||
po::store(po::parse_command_line(argc, argv, desc), vm);
|
||||
po::notify(vm);
|
||||
|
||||
if (vm.count("help"))
|
||||
{
|
||||
std::cout << desc << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vm.count("version"))
|
||||
{
|
||||
std::cout << VERSION_FULL_STR << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
AppSettings settings(QCoreApplication::applicationDirPath().toStdString());
|
||||
if (!settings.load())
|
||||
{
|
||||
Aya::StandardOut::singleton()->printf(Aya::MESSAGE_ERROR, "Failed to load AppSettings.ini - please make sure it exists with a valid ContentPath under the Aya group, and make sure that it is free of any errors.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Override AppSettings loaded settings with anything from the command line:
|
||||
if (!IsVerboseLogging())
|
||||
SetVerboseLogging(vm.count("verbose") > 0);
|
||||
|
||||
if (!IsInsecureMode())
|
||||
SetInsecureMode(vm.count("insecure") > 0);
|
||||
|
||||
if (!instanceUrl.empty())
|
||||
{
|
||||
SetBaseURL(instanceUrl.c_str());
|
||||
if (!instanceAccessKey.empty())
|
||||
{
|
||||
SetInstanceAccessKey(instanceAccessKey.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (!trustCheckUrl.empty())
|
||||
{
|
||||
SetTrustCheckURL(trustCheckUrl.c_str());
|
||||
}
|
||||
|
||||
if (!masterServerUrl.empty())
|
||||
{
|
||||
SetMasterServerURL(masterServerUrl.c_str());
|
||||
if (!masterServerKey.empty())
|
||||
{
|
||||
SetMasterServerKey(masterServerKey.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (vm.count("test"))
|
||||
{
|
||||
std::string script;
|
||||
if (!tryRead(testScript, script))
|
||||
return 1;
|
||||
|
||||
// queue_job("Test Job", script, 60 * 60 * 24);
|
||||
}
|
||||
|
||||
if (!evaluateScript.empty())
|
||||
{
|
||||
// Evaluate script and exit
|
||||
// May be a Lua script or a path to a file or a path to an asset
|
||||
bool success = true;
|
||||
|
||||
try
|
||||
{
|
||||
auto dm = Aya::DataModel::createDataModel(false, new Aya::NullVerb(NULL, ""), false);
|
||||
Aya::DataModel::LegacyLock lock(dm, Aya::DataModelJob::Write);
|
||||
|
||||
std::string script;
|
||||
if (Aya::ContentProvider::isUrl(evaluateScript))
|
||||
{
|
||||
std::auto_ptr<std::istream> stream = Aya::ServiceProvider::create<Aya::ContentProvider>(dm.get())->getContent(Aya::ContentId(evaluateScript));
|
||||
script = std::string(static_cast<std::stringstream const&>(std::stringstream() << stream->rdbuf()).str());
|
||||
}
|
||||
else
|
||||
{
|
||||
success = tryRead(evaluateScript, script);
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
if (script.empty())
|
||||
{
|
||||
throw std::runtime_error("Could not load script '" + evaluateScript + "'");
|
||||
}
|
||||
|
||||
Aya::ScriptContext* sc = Aya::ServiceProvider::create<Aya::ScriptContext>(dm.get());
|
||||
sc->executeInNewThread(Aya::Security::WebService, Aya::ProtectedString::fromTrustedSource(script), "Script");
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
Aya::StandardOut::singleton()->print(Aya::MESSAGE_ERROR, e);
|
||||
success = false;
|
||||
}
|
||||
|
||||
return success ? 0 : 1;
|
||||
}
|
||||
|
||||
bool isLAN = vm.count("lan") > 0;
|
||||
if (true)
|
||||
{
|
||||
MainWindow window(NULL);
|
||||
window.setWindowTitle("Aya Server");
|
||||
window.show();
|
||||
window.setFocus();
|
||||
}
|
||||
|
||||
start_aya_server(
|
||||
ui,
|
||||
isLAN,
|
||||
gridPort,
|
||||
localServerPort,
|
||||
localServerPlace,
|
||||
localServerPassword,
|
||||
masterServerHost,
|
||||
masterServerName,
|
||||
masterServerDescription
|
||||
);
|
||||
|
||||
return app->exec();
|
||||
}
|
||||
569
client/server/src/oldmain.cpp
Normal file
569
client/server/src/oldmain.cpp
Normal file
@@ -0,0 +1,569 @@
|
||||
#include <boost/program_options.hpp>
|
||||
#include <generated/RCCServiceSoap.nsmap>
|
||||
#include <generated/soapRCCServiceSoapService.h>
|
||||
|
||||
#include "DataModel/GameBasicSettings.hpp"
|
||||
#include "Windows/Information.h"
|
||||
|
||||
#include "Script/ScriptContext.hpp"
|
||||
#include "DataModel/ContentProvider.hpp"
|
||||
|
||||
#include "DataModel/DataModel.hpp"
|
||||
|
||||
#include "DataModel/DebugSettings.hpp"
|
||||
|
||||
#include "Utility/ContentId.hpp"
|
||||
|
||||
#include "Utility/Http.hpp"
|
||||
|
||||
#include "Utility/ProtectedString.hpp"
|
||||
|
||||
#include "Utility/StandardOut.hpp"
|
||||
|
||||
#include "Utility/Statistics.hpp"
|
||||
|
||||
#include "API.hpp"
|
||||
|
||||
#include "boost.hpp"
|
||||
#include "TaskScheduler.hpp"
|
||||
|
||||
#include "linenoise.hpp"
|
||||
#include "Lua/lua.h"
|
||||
|
||||
#include "Utility/AyaService.hpp"
|
||||
|
||||
#ifdef __linux
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
#include <boost/signals2.hpp>
|
||||
#include <boost/bind/bind.hpp>
|
||||
#include <SDL3/SDL.h>
|
||||
#endif
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
namespace po = boost::program_options;
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
class PrintfLogger
|
||||
{
|
||||
Aya::signals::scoped_connection messageConnection;
|
||||
HANDLE handle;
|
||||
Aya::spin_mutex mutex;
|
||||
|
||||
public:
|
||||
PrintfLogger()
|
||||
: handle(GetStdHandle(STD_OUTPUT_HANDLE))
|
||||
{
|
||||
messageConnection = Aya::StandardOut::singleton()->messageOut.connect(boost::bind(&PrintfLogger::onMessage, this, _1));
|
||||
}
|
||||
|
||||
protected:
|
||||
void onMessage(const Aya::StandardOutMessage& message)
|
||||
{
|
||||
Aya::spin_mutex::scoped_lock lock(mutex);
|
||||
|
||||
switch (message.type)
|
||||
{
|
||||
case Aya::MESSAGE_OUTPUT:
|
||||
SetConsoleTextAttribute(handle, FOREGROUND_BLUE | FOREGROUND_INTENSITY);
|
||||
break;
|
||||
case Aya::MESSAGE_INFO:
|
||||
SetConsoleTextAttribute(handle, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
break;
|
||||
case Aya::MESSAGE_WARNING:
|
||||
SetConsoleTextAttribute(handle, FOREGROUND_RED | FOREGROUND_GREEN);
|
||||
break;
|
||||
case Aya::MESSAGE_ERROR:
|
||||
SetConsoleTextAttribute(handle, FOREGROUND_RED | FOREGROUND_INTENSITY);
|
||||
break;
|
||||
}
|
||||
|
||||
printf("%s\n", message.message.c_str());
|
||||
SetConsoleTextAttribute(handle, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
}
|
||||
};
|
||||
#else
|
||||
class PrintfLogger
|
||||
{
|
||||
Aya::signals::scoped_connection messageConnection;
|
||||
std::mutex mutex;
|
||||
|
||||
public:
|
||||
PrintfLogger()
|
||||
{
|
||||
messageConnection = Aya::StandardOut::singleton()->messageOut.connect(boost::bind(&PrintfLogger::onMessage, this, boost::placeholders::_1));
|
||||
}
|
||||
|
||||
protected:
|
||||
void onMessage(const Aya::StandardOutMessage& message)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
|
||||
// ANSI escape codes for color output
|
||||
const char* colorCode = "\033[0m";
|
||||
switch (message.type)
|
||||
{
|
||||
case Aya::MESSAGE_OUTPUT:
|
||||
colorCode = "\033[34m";
|
||||
break;
|
||||
case Aya::MESSAGE_INFO:
|
||||
colorCode = "\033[37m";
|
||||
break;
|
||||
case Aya::MESSAGE_WARNING:
|
||||
colorCode = "\033[33m";
|
||||
break;
|
||||
case Aya::MESSAGE_ERROR:
|
||||
colorCode = "\033[31m";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
std::cout << colorCode << message.message << "\033[0m" << std::endl;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template<class Soap>
|
||||
class ExceptionAwareSoap : public Soap
|
||||
{
|
||||
public:
|
||||
virtual int dispatch()
|
||||
{
|
||||
try
|
||||
{
|
||||
return Soap::dispatch();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
return soap_receiver_fault(this, e.what(), NULL); // return fault to sender
|
||||
}
|
||||
catch (std::string& s)
|
||||
{
|
||||
AYACRASH();
|
||||
return soap_receiver_fault(this, s.c_str(), NULL); // return fault to sender
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
AYACRASH();
|
||||
return soap_receiver_fault(this, "Unexpected C++ exception type", NULL); // return fault to sender
|
||||
}
|
||||
}
|
||||
|
||||
virtual RCCServiceSoapService* copy()
|
||||
{
|
||||
ExceptionAwareSoap<Soap>* dup = new ExceptionAwareSoap<Soap>();
|
||||
soap_copy_context(dup, this);
|
||||
return dup;
|
||||
}
|
||||
};
|
||||
|
||||
ExceptionAwareSoap<RCCServiceSoapService> service;
|
||||
|
||||
// TODO: Move this into some sort of RCCServiceSoap.hpp?
|
||||
void start_CWebService();
|
||||
void stop_CWebService();
|
||||
|
||||
static void startupRCC(int port)
|
||||
{
|
||||
#ifdef USE_BLOXBLOX_BRANDING
|
||||
printf("Starting Bloxblox.Aya.Server v%s...\n", VERSION_MAJOR_MINOR_PATCH_STR);
|
||||
#else
|
||||
printf("Starting Aya.Server v%s...\n", VERSION_MAJOR_MINOR_PATCH_STR);
|
||||
#endif
|
||||
|
||||
start_CWebService();
|
||||
|
||||
if (port != -1)
|
||||
{
|
||||
service.accept_timeout = 1; // server stops after 1 second of client inactivity
|
||||
// service.send_timeout = 60; // 60 seconds
|
||||
// service.recv_timeout = 60; // 60 seconds
|
||||
// soap.max_keep_alive = 100; // max keep-alive sequence
|
||||
SOAP_SOCKET m = service.bind(NULL, port, 100);
|
||||
|
||||
if (!soap_valid_socket(m))
|
||||
throw std::runtime_error(*soap_faultstring(&service));
|
||||
}
|
||||
printf("Started Aya.Server!\n");
|
||||
|
||||
if (port != -1)
|
||||
{
|
||||
Aya::StandardOut::singleton()->printf(Aya::MESSAGE_SENSITIVE, "Now listening for incoming SOAP requests on port TCP/%d", port);
|
||||
}
|
||||
}
|
||||
|
||||
static void stepRCC()
|
||||
{
|
||||
SOAP_SOCKET s = service.accept();
|
||||
|
||||
if (!soap_valid_socket(s))
|
||||
{
|
||||
if (service.errnum)
|
||||
throw std::runtime_error(*soap_faultstring(&service));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
RCCServiceSoapService* copy = service.copy(); // make a safe copy
|
||||
|
||||
if (!copy)
|
||||
throw std::runtime_error(*soap_faultstring(&service));
|
||||
|
||||
try
|
||||
{
|
||||
copy->serve();
|
||||
delete copy;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
AYACRASH();
|
||||
}
|
||||
}
|
||||
|
||||
static void shutdownRCC()
|
||||
{
|
||||
printf("Shutting down...\n");
|
||||
stop_CWebService();
|
||||
|
||||
// if on linux, SDL_Quit() for DummyWindow
|
||||
#ifdef __linux
|
||||
SDL_Quit();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void handleScriptCommand(std::string& execCommand)
|
||||
{
|
||||
if (execCommand.empty())
|
||||
return;
|
||||
|
||||
ns1__ScriptExecution se;
|
||||
// d9mz - error: taking the address of a temporary object of type 'std::string'
|
||||
std::string serverName = "Command Line";
|
||||
se.name = &serverName;
|
||||
se.script = &execCommand;
|
||||
|
||||
_ns1__Execute execute;
|
||||
_ns1__ExecuteResponse response;
|
||||
execute.script = &se;
|
||||
execute.jobID = "Test";
|
||||
|
||||
RCCServiceSoapService* copy = service.copy();
|
||||
copy->Execute(&execute, response);
|
||||
}
|
||||
|
||||
static void escapeLuaString(std::string& string)
|
||||
{
|
||||
boost::replace_all(string, "[", "\\[");
|
||||
boost::replace_all(string, "]", "\\]");
|
||||
boost::replace_all(string, "\"", "\\\"");
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
// Pipe Aya::StandardOut to printf
|
||||
static boost::scoped_ptr<PrintfLogger> standardOutLog(new PrintfLogger());
|
||||
|
||||
// Parse arguments
|
||||
std::string evaluateScript;
|
||||
int port = 64989;
|
||||
std::string contentPath = "content";
|
||||
std::string httpAccessKey;
|
||||
std::string baseUrl;
|
||||
std::string testScript;
|
||||
std::string password;
|
||||
std::string masterServerAuthorization;
|
||||
std::string masterServerUrl;
|
||||
std::string masterServerHost;
|
||||
std::string masterServerName;
|
||||
std::string masterServerMotdPreview;
|
||||
std::string masterServerMotdFile;
|
||||
int localServerPort;
|
||||
int virtualVersion;
|
||||
std::string localServerPlace;
|
||||
|
||||
po::options_description desc("Aya options");
|
||||
|
||||
desc.add_options()("help,?", "Usage help")("version,V", "Print version and exit")("eval,E", po::value<std::string>(&evaluateScript),
|
||||
"Lua script to run")("port", po::value<int>(&port)->default_value(64989), "SOAP port to listen on. Set to -1 to disable")("contentPath",
|
||||
po::value<std::string>(&contentPath)->default_value(DEFAULT_CONTENT_PATH),
|
||||
"Path to the content directory")("httpAccessKey", po::value<std::string>(&httpAccessKey)->default_value(""), "HTTP access key")("baseUrl",
|
||||
po::value<std::string>(&baseUrl)->default_value("http://www.kiseki.lol"),
|
||||
"Base URL")("test", po::value<std::string>(&testScript)->implicit_value("test.lua"), "Runs a test job with the given Lua script")(
|
||||
"insecure", "Disables anti-cheat & authentication checks")("verbose", "Enable verbose logging")("noconsole,x", "Disable command line REPL")(
|
||||
"password,K", po::value<std::string>(&password), "Set password")("masterServerAuthorization,A",
|
||||
po::value<std::string>(&masterServerAuthorization))("masterServerUrl,a", po::value<std::string>(&masterServerUrl))(
|
||||
"localServer", "Aya local server flag")("msHost,H", po::value<std::string>(&masterServerHost)->default_value("Bloxhead"))(
|
||||
"msName,N", po::value<std::string>(&masterServerName)->default_value("Aya Server"))(
|
||||
"msMotdPreview,m", po::value<std::string>(&masterServerMotdPreview)->default_value("Set -m to set a preview"))(
|
||||
"msMotdFile,M", po::value<std::string>(&masterServerMotdFile)->default_value("motd.htm"))("localServerPort,P",
|
||||
po::value<int>(&localServerPort)->default_value(53640))("virtualVersion,vv", po::value<int>(&virtualVersion)->default_value(0))(
|
||||
"localServerPlace,p", po::value<std::string>(&localServerPlace)->default_value("ayaasset://test.rbxl"))(
|
||||
"httpClientSettings,S", "use website for clientsettings");
|
||||
|
||||
po::variables_map vm;
|
||||
po::store(po::parse_command_line(argc, argv, desc), vm);
|
||||
po::notify(vm);
|
||||
|
||||
Aya::GameBasicSettings::VirtualVersion vv = static_cast<Aya::GameBasicSettings::VirtualVersion>(virtualVersion);
|
||||
Aya::GameBasicSettings::singleton().setVirtualVersionInternal(vv);
|
||||
|
||||
bool isTest = vm.count("test") > 0;
|
||||
bool isInsecure = vm.count("insecure") > 0;
|
||||
bool isVerbose = vm.count("verbose") > 0;
|
||||
bool noConsole = vm.count("noconsole") > 0;
|
||||
bool isLocalServer = vm.count("localServer") > 0;
|
||||
|
||||
SetFetchLocalClientSettings(!vm.count("httpClientSettings"));
|
||||
|
||||
if (vm.count("help"))
|
||||
{
|
||||
std::cout << desc << "\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vm.count("version"))
|
||||
{
|
||||
std::cout << VERSION_FULL_STR << "\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vm.count("eval"))
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
try
|
||||
{
|
||||
std::string code = vm["eval"].as<std::string>();
|
||||
|
||||
std::ifstream file(code);
|
||||
if (file)
|
||||
{
|
||||
std::stringstream buffer;
|
||||
buffer << file.rdbuf();
|
||||
code = buffer.str();
|
||||
}
|
||||
|
||||
// TODO: Account for ayaasset://, ayaassetid://, etc.
|
||||
if (Aya::ContentProvider::isHttpUrl(code))
|
||||
{
|
||||
Aya::Http http(code);
|
||||
http.get(code);
|
||||
}
|
||||
|
||||
Aya::GameBasicSettings::VirtualVersion vv = static_cast<Aya::GameBasicSettings::VirtualVersion>(virtualVersion);
|
||||
|
||||
shared_ptr<Aya::DataModel> dm = Aya::DataModel::createDataModel(false, new Aya::NullVerb(NULL, ""), false, vv);
|
||||
Aya::ScriptContext* sc = Aya::ServiceProvider::create<Aya::ScriptContext>(dm.get());
|
||||
Aya::AyaService* ayaService = Aya::ServiceProvider::create<Aya::AyaService>(dm.get());
|
||||
ayaService->setInitialVersion(vv);
|
||||
sc->executeInNewThread(Aya::Security::WebService, Aya::ProtectedString::fromTrustedSource(code), "Script");
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
Aya::StandardOut::singleton()->print(Aya::MESSAGE_ERROR, e);
|
||||
success = false;
|
||||
}
|
||||
|
||||
return success ? 0 : 1;
|
||||
}
|
||||
|
||||
// Main startup
|
||||
try
|
||||
{
|
||||
Aya::ContentProvider::setAssetFolder(contentPath.c_str());
|
||||
SetBaseURL(baseUrl.c_str());
|
||||
|
||||
startupRCC(port);
|
||||
|
||||
if (vm.count("password"))
|
||||
{
|
||||
Aya::Network::setPassword(vm["password"].as<std::string>());
|
||||
Aya::AyaService::passwordProtected = true;
|
||||
}
|
||||
|
||||
if (isVerbose)
|
||||
{
|
||||
// TODO: Pipe FastLog to console
|
||||
}
|
||||
|
||||
if (isInsecure)
|
||||
{
|
||||
// TODO: Disable all security checks
|
||||
}
|
||||
|
||||
bool testJob = false;
|
||||
|
||||
if (isLocalServer)
|
||||
{
|
||||
Aya::StandardOut::singleton()->print(Aya::MESSAGE_WARNING, "Running an Aya Local Server.");
|
||||
Aya::AyaService::masterServerUrl = masterServerUrl;
|
||||
Aya::AyaService::masterServerAuthorization = masterServerAuthorization;
|
||||
Aya::AyaService::localServer = true;
|
||||
}
|
||||
|
||||
if (isTest || isLocalServer)
|
||||
{
|
||||
|
||||
if (!isTest)
|
||||
{
|
||||
testScript = "content/scripts/Host.lua";
|
||||
}
|
||||
|
||||
std::ifstream file(testScript);
|
||||
std::string script;
|
||||
if (!file)
|
||||
{
|
||||
std::cout << "Could not open file " << testScript << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::stringstream buffer;
|
||||
buffer << file.rdbuf();
|
||||
|
||||
if (isLocalServer)
|
||||
{
|
||||
// TODO: escape all the text so it doesn't break Lua
|
||||
|
||||
std::string motd;
|
||||
std::ifstream file(masterServerMotdFile);
|
||||
if (!file)
|
||||
{
|
||||
std::cout << "Could not open file " << masterServerMotdFile << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::stringstream motdBuffer;
|
||||
motdBuffer << file.rdbuf();
|
||||
motd = motdBuffer.str();
|
||||
|
||||
escapeLuaString(motd);
|
||||
|
||||
buffer << "\ngame:GetService(\"AyaService\").ServerMotdContent = [[" << motd << "]]";
|
||||
}
|
||||
|
||||
escapeLuaString(masterServerMotdPreview);
|
||||
buffer << "\ngame:GetService(\"AyaService\").ServerMotdPreview = \"" << masterServerMotdPreview << "\"";
|
||||
escapeLuaString(masterServerHost);
|
||||
buffer << "\ngame:GetService(\"AyaService\").Host = \"" << masterServerHost << "\"";
|
||||
escapeLuaString(masterServerName);
|
||||
buffer << "\ngame:GetService(\"AyaService\").ServerName = \"" << masterServerName << "\"";
|
||||
|
||||
escapeLuaString(localServerPlace);
|
||||
buffer << "\ngame:GetService(\"AyaService\"):AnnounceMasterServer()";
|
||||
buffer
|
||||
<< "\ngame:GetService(\"Players\").PlayerAdded:connect(function() game:GetSerivce(\"AyaService\"):AnnounceMasterServer() "
|
||||
"end)"
|
||||
<< "\ngame:GetService(\"Players\").PlayerRemoving:connect(function() game:GetSerivce(\"AyaService\"):AnnounceMasterServer() end)";
|
||||
|
||||
char startLine[2048];
|
||||
snprintf(startLine, 2048, "Start(%i, \"%s\")", localServerPort, localServerPlace.c_str());
|
||||
|
||||
if (masterServerUrl == "")
|
||||
{
|
||||
Aya::StandardOut::singleton()->printf(
|
||||
Aya::MESSAGE_ERROR, "Master server ping will be disabled. Specify a master server with -a <url> -A <master server key>");
|
||||
}
|
||||
|
||||
buffer << "\n" << startLine;
|
||||
}
|
||||
script = buffer.str();
|
||||
|
||||
testJob = true;
|
||||
|
||||
RCCServiceSoapService* copy = service.copy(); // make a safe copy
|
||||
|
||||
if (!copy)
|
||||
throw std::runtime_error(*soap_faultstring(&service));
|
||||
|
||||
ns1__Job job;
|
||||
job.id = "Test";
|
||||
job.expirationInSeconds = 60 * 60 * 24;
|
||||
|
||||
ns1__ScriptExecution se;
|
||||
// d9mz - error: taking the address of a temporary object of type 'std::string'
|
||||
std::string serverName = "Start Server";
|
||||
se.name = &serverName;
|
||||
se.script = &script;
|
||||
_ns1__OpenJob openJob;
|
||||
_ns1__OpenJobResponse response;
|
||||
openJob.script = &se;
|
||||
openJob.job = &job;
|
||||
|
||||
copy->OpenJob(&openJob, response);
|
||||
}
|
||||
|
||||
std::thread heartbeat(
|
||||
[]
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
stepRCC();
|
||||
}
|
||||
});
|
||||
|
||||
if (!testJob && !noConsole)
|
||||
{
|
||||
Aya::StandardOut::singleton()->print(Aya::MESSAGE_ERROR,
|
||||
"Im sorry but I will not let you use the console unless if you are using --test. Specify --noconsole to suppress this message");
|
||||
noConsole = true;
|
||||
}
|
||||
|
||||
if (!noConsole)
|
||||
{
|
||||
std::cout << "Lua interactive command prompt" << std::endl;
|
||||
|
||||
linenoise::SetHistoryMaxLen(100);
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (noConsole)
|
||||
{
|
||||
std::string toExecute;
|
||||
|
||||
std::getline(std::cin, toExecute);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string toExecute;
|
||||
auto quit = linenoise::Readline(LUA_RELEASE "> ", toExecute);
|
||||
|
||||
if (quit)
|
||||
break;
|
||||
|
||||
linenoise::AddHistory(toExecute.c_str());
|
||||
|
||||
try
|
||||
{
|
||||
int errorLine = 0;
|
||||
std::string errorMessage;
|
||||
if (Aya::ScriptContext::checkSyntax(toExecute.c_str(), errorLine, errorMessage))
|
||||
{
|
||||
Aya::StandardOut::singleton()->printf(Aya::MESSAGE_OUTPUT, "%s", toExecute.c_str());
|
||||
handleScriptCommand(toExecute);
|
||||
}
|
||||
else
|
||||
{
|
||||
Aya::StandardOut::singleton()->printf(Aya::MESSAGE_ERROR, "Error in script: %s", errorMessage.c_str());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
heartbeat.detach();
|
||||
|
||||
shutdownRCC();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
Aya::StandardOut::singleton()->print(Aya::MESSAGE_ERROR, e);
|
||||
}
|
||||
}
|
||||
1828
client/server/src/oldserver.cpp
Normal file
1828
client/server/src/oldserver.cpp
Normal file
File diff suppressed because it is too large
Load Diff
75
client/server/src/server.cpp
Normal file
75
client/server/src/server.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
#include "server.hpp"
|
||||
|
||||
#include <boost/bind/bind.hpp>
|
||||
#include <mutex>
|
||||
#include "grid.hpp"
|
||||
#include "Utility/StandardOut.hpp"
|
||||
|
||||
#ifdef _WIN32
|
||||
// static boost::scoped_ptr<MainLogManager> mainLogManager(new MainLogManager("Aya Server", ".dmp", ".crashevent"));
|
||||
#endif
|
||||
static boost::scoped_ptr<StandardOutLogger> standardOutLog;
|
||||
|
||||
namespace Aya
|
||||
{
|
||||
class Explosion;
|
||||
class Cofm;
|
||||
class NormalBreakConnector;
|
||||
class ContactConnector;
|
||||
class RevoluteLink;
|
||||
class SimBody;
|
||||
class BallBallContact;
|
||||
class BallBlockContact;
|
||||
class BlockBlockContact;
|
||||
} // namespace Aya
|
||||
|
||||
class StandardOutLogger
|
||||
{
|
||||
Aya::signals::scoped_connection messageConnection;
|
||||
std::mutex mutex;
|
||||
|
||||
public:
|
||||
StandardOutLogger()
|
||||
{
|
||||
messageConnection =
|
||||
Aya::StandardOut::singleton()->messageOut.connect(boost::bind(&StandardOutLogger::onMessage, this, boost::placeholders::_1));
|
||||
}
|
||||
|
||||
protected:
|
||||
void onMessage(const Aya::StandardOutMessage& message)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
|
||||
// ANSI escape codes for color output
|
||||
const char* colorCode = "\033[0m";
|
||||
switch (message.type)
|
||||
{
|
||||
case Aya::MESSAGE_OUTPUT:
|
||||
colorCode = "\033[34m";
|
||||
break;
|
||||
case Aya::MESSAGE_INFO:
|
||||
colorCode = "\033[37m";
|
||||
break;
|
||||
case Aya::MESSAGE_WARNING:
|
||||
colorCode = "\033[33m";
|
||||
break;
|
||||
case Aya::MESSAGE_ERROR:
|
||||
colorCode = "\033[31m";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
std::cout << colorCode << message.message << "\033[0m" << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
void start_aya_server(bool ui, bool isLAN, int gridPort, int localServerPort, const std::string& localServerPlace,
|
||||
const std::string& localServerPassword, const std::string& masterServerHost, const std::string& masterServerName,
|
||||
const std::string& masterServerDescription)
|
||||
{
|
||||
if (gridPort != -1)
|
||||
{
|
||||
start_grid_server(gridPort);
|
||||
}
|
||||
}
|
||||
84
client/server/src/server.hpp
Normal file
84
client/server/src/server.hpp
Normal file
@@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
class StandardOutLogger;
|
||||
|
||||
struct Job : boost::noncopyable
|
||||
{
|
||||
enum JobStatus
|
||||
{
|
||||
RUNNING_JOB,
|
||||
JOB_DONE,
|
||||
JOB_ERROR
|
||||
};
|
||||
|
||||
JobStatus status;
|
||||
const std::string id;
|
||||
shared_ptr<Aya::DataModel> dataModel;
|
||||
Aya::signals::connection notifyAliveConnection;
|
||||
|
||||
Aya::Time expirationTime;
|
||||
|
||||
Job(const char* id)
|
||||
: id(id)
|
||||
, status(RUNNING_JOB)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
void touch(double seconds);
|
||||
double secondsToTimeout() const;
|
||||
};
|
||||
|
||||
typedef std::map<std::string, boost::shared_ptr<Job>> JobMap;
|
||||
|
||||
class Service
|
||||
{
|
||||
private:
|
||||
JobMap jobs;
|
||||
boost::mutex sync;
|
||||
long dataModelCount;
|
||||
boost::mutex currentlyClosingMutex;
|
||||
|
||||
shared_ptr<Job> createJob(std::string id, std::string name);
|
||||
|
||||
public:
|
||||
static boost::scoped_ptr<Service> singleton;
|
||||
|
||||
int jobCount() const;
|
||||
|
||||
Service();
|
||||
~Service();
|
||||
|
||||
void closeDataModel(shared_ptr<Aya::DataModel> dataModel);
|
||||
|
||||
void arbiterActivityDump(const std::string& dump); // produces JSON dump of task scheduler avg activity for all jobs
|
||||
void diagnosticDump(const std::string& dump); // produces JSON diagnostic dump
|
||||
|
||||
JobMap::iterator getJob(std::string id);
|
||||
void openJob(const std::string& id, const std::string& name, int expirationInSeconds, const std::string& scriptName, const std::string& scriptContent);
|
||||
void closeJob(const std::string& id, const char* errorMessage = NULL);
|
||||
void closeExpiredJobs(int* result);
|
||||
void getAllJobs(const std::string& result); // JSON result of running jobs
|
||||
void renderThumbnail(const std::string& type, const std::vector<std::string> arguments, const std::string& result);
|
||||
void auditLease(boost::shared_ptr<Job> job);
|
||||
void renewLease(const std::string& jobID, double expirationInSeconds);
|
||||
|
||||
void executeScript(const std::string& jobID, const std::string& script, const std::string& result);
|
||||
double getExpiration(const std::string& jobID);
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
void start_aya_server(
|
||||
bool ui,
|
||||
bool isLAN,
|
||||
int gridPort,
|
||||
int localServerPort,
|
||||
const std::string& localServerPlace,
|
||||
const std::string& localServerPassword,
|
||||
const std::string& masterServerHost,
|
||||
const std::string& masterServerName,
|
||||
const std::string& masterServerDescription
|
||||
);
|
||||
|
||||
void stop_aya_server();
|
||||
bool is_aya_server_running();
|
||||
Reference in New Issue
Block a user