Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
BasedOnStyle: Microsoft

...
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ set(CMAKE_PREFIX_PATH ${ROR_DEPENDENCY_DIR} ${CMAKE_PREFIX_PATH})

set(CMAKE_THREAD_PREFER_PTHREAD YES)
find_package(Threads REQUIRED)
find_package(Angelscript)
find_package(jsoncpp REQUIRED)
find_package(Poco REQUIRED COMPONENTS Foundation JSON)
find_package(SocketW REQUIRED)
find_package(CURL)
find_package(Angelscript)
cmake_dependent_option(RORSERVER_WITH_ANGELSCRIPT "Adds scripting support" ON "TARGET Angelscript::angelscript" OFF)
cmake_dependent_option(RORSERVER_WITH_CURL "Adds CURL request support (needs AngelScript)" ON "TARGET CURL::libcurl" OFF)

Expand Down
6 changes: 5 additions & 1 deletion conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,17 @@ class RoRServer(ConanFile):
name = "RoRServer"
settings = "os", "compiler", "build_type", "arch"
generators = "CMakeToolchain", "CMakeDeps"
default_options = {
"poco*:enable_pagecompiler": True,
"poco*:enable_data_mysql": False,
}

def layout(self):
self.folders.generators = os.path.join(self.folders.build, "generators")

def requirements(self):
self.requires("angelscript/2.37.0")
self.requires("jsoncpp/1.9.5")
self.requires("poco/1.13.3")
self.requires("openssl/3.3.2", override=True)
self.requires("socketw/3.11.0@anotherfoxguy/stable")
self.requires("libcurl/8.10.1")
7 changes: 6 additions & 1 deletion source/server/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ if (RORSERVER_WITH_CURL)
target_link_libraries(${PROJECT_NAME} PRIVATE CURL::libcurl)
endif ()

target_link_libraries(${PROJECT_NAME} PRIVATE Threads::Threads SocketW::SocketW jsoncpp_lib)
target_link_libraries(${PROJECT_NAME} PRIVATE
Poco::Foundation
Poco::JSON
Threads::Threads
SocketW::SocketW
)

IF (WIN32)
target_compile_definitions(${PROJECT_NAME} PRIVATE WIN32_LEAN_AND_MEAN NOMINMAX)
Expand Down
84 changes: 50 additions & 34 deletions source/server/blacklist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,21 @@ along with Rigs of Rods Server. If not, see <http://www.gnu.org/licenses/>.
#include "sequencer.h"
#include "utils.h"

#include <Poco/Dynamic/Var.h>
#include <Poco/JSON/Array.h>
#include <Poco/JSON/JSONException.h>
#include <Poco/JSON/Object.h>
#include <Poco/JSON/ParseHandler.h>
#include <Poco/JSON/Parser.h>
#include <Poco/JSON/Stringifier.h>

using namespace Poco;
using namespace Poco::JSON;
using namespace Poco::Dynamic;

#include <fstream>
#include <json/json.h>

Blacklist::Blacklist(Sequencer* database)
: m_database(database)
Blacklist::Blacklist(Sequencer *database) : m_database(database)
{
}

Expand All @@ -38,31 +48,29 @@ void Blacklist::SaveBlacklistToFile()
f.open(Config::getBlacklistFile(), std::ios::out);
if (!f.is_open() || !f.good())
{
Logger::Log(LogLevel::LOG_WARN,
"Couldn't open the local blacklist file ('%s'). Bans were not saved.",
Config::getBlacklistFile().c_str());
Logger::Log(LogLevel::LOG_WARN, "Couldn't open the local blacklist file ('%s'). Bans were not saved.",
Config::getBlacklistFile().c_str());
return;
}

Json::Value j_bans(Json::arrayValue);
JSON::Array j_bans;
std::vector<ban_t> bans = m_database->GetBanListCopy();

for (ban_t& ban : bans)
for (ban_t &ban : bans)
{
Json::Value j_ban(Json::objectValue);
j_ban["bid"] = ban.bid;
DynamicStruct j_ban;
j_ban["bid"] = ban.bid;
j_ban["ip"] = ban.ip;
j_ban["nickname"] = ban.nickname;
j_ban["banned_by_nickname"] = ban.bannedby_nick;
j_ban["message"] = ban.banmsg;
j_bans.append(j_ban);
j_bans.add(j_ban);
}

Json::Value j_doc(Json::objectValue);
DynamicStruct j_doc;
j_doc["bans"] = j_bans;

Json::StyledStreamWriter j_writer;
j_writer.write(f, j_doc);
Poco::JSON::Stringifier::stringify(j_doc, f, 1);
}

bool Blacklist::LoadBlacklistFromFile()
Expand All @@ -71,41 +79,49 @@ bool Blacklist::LoadBlacklistFromFile()
f.open(Config::getBlacklistFile(), std::ios::in);
if (!f.is_open() || !f.good())
{
Logger::Log(LogLevel::LOG_WARN,
"Couldn't open the local blacklist file ('%s'). No bans were loaded.",
Logger::Log(LogLevel::LOG_WARN, "Couldn't open the local blacklist file ('%s'). No bans were loaded.",
Config::getBlacklistFile().c_str());
return false;
}

if (Utils::IsEmptyFile(f))
{
f.close();
Logger::Log(LogLevel::LOG_WARN,
"Local blacklist file ('%s') is empty.",
Config::getBlacklistFile().c_str());
Logger::Log(LogLevel::LOG_WARN, "Local blacklist file ('%s') is empty.", Config::getBlacklistFile().c_str());
return false;
}

Json::Value j_doc;
Json::Reader j_reader;
j_reader.parse(f, j_doc);
if (!j_reader.good())
Parser parser;
Var result;

try
{
Logger::Log(LogLevel::LOG_WARN,
"Couldn't parse blacklist file, messages:\n%s",
j_reader.getFormattedErrorMessages());
result = parser.parse(f);
}
catch (JSONException &jsonException)
{
Logger::Log(LogLevel::LOG_WARN, "Couldn't parse blacklist file, messages:\n%s",
jsonException.message().c_str());
return false;
}

for (Json::Value& j_ban: j_doc["bans"])
try
{
m_database->RecordBan(
// ban IDs are reset to start at 1 on every start/restart
j_ban["ip"].asString(),
j_ban["nickname"].asString(),
j_ban["banned_by_nickname"].asString(),
j_ban["message"].asString());
Poco::JSON::Object::Ptr root = result.extract<Poco::JSON::Object::Ptr>();
JSON::Array::Ptr bans = root->getArray("bans");

for (int i = 0; i < bans->size(); ++i)
{
auto j_ban = bans->getObject(i);
m_database->RecordBan(j_ban->getValue<std::string>("ip"),
j_ban->getValue<std::string>("nickname"),
j_ban->getValue<std::string>("banned_by_nickname"),
j_ban->getValue<std::string>("message"));
}
}
catch (Exception e)
{
Logger::Log(LogLevel::LOG_WARN, "Couldn't parse blacklist file, messages:\n%s", e.message().c_str());
}

return true;
}
59 changes: 38 additions & 21 deletions source/server/master-server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,30 @@ along with Foobar. If not, see <http://www.gnu.org/licenses/>.
#include "rornet.h"
#include "logger.h"
#include "http.h"
#include "json/json.h"
#include "utils.h"

#include <assert.h>

#include <Poco/JSON/Array.h>
#include <Poco/JSON/Object.h>
#include <Poco/JSON/Stringifier.h>
#include <Poco/JSON/Parser.h>
#include <Poco/JSON/ParseHandler.h>
#include <Poco/JSON/JSONException.h>
#include <Poco/Dynamic/Var.h>

using namespace Poco;
using namespace Poco::JSON;
using namespace Poco::Dynamic;

namespace MasterServer {

Client::Client() :
m_trust_level(-1),
m_is_registered(false) {}

bool Client::Register() {
Json::Value data(Json::objectValue);
DynamicStruct data;
data["ip"] = Config::getIPAddr();
data["port"] = Config::getListenPort();
data["name"] = Config::getServerName();
Expand All @@ -46,9 +58,11 @@ namespace MasterServer {

m_server_path = "/" + Config::GetServerlistPath() + "/server-list";

auto json_str = JsonToString(data);

Logger::Log(LOG_INFO, "Attempting to register on serverlist (%s)", m_server_path.c_str());
Http::Response response;
int result_code = this->HttpRequest(Http::METHOD_POST, data.toStyledString().c_str(), &response);
int result_code = this->HttpRequest(Http::METHOD_POST, json_str.c_str(), &response);
if (result_code < 0) {
Logger::Log(LOG_ERROR, "Registration failed, result code: %d", result_code);
return false;
Expand All @@ -58,33 +72,34 @@ namespace MasterServer {
return false;
}

Json::Value root;
Json::Reader reader;
if (!reader.parse(response.GetBody().c_str(), root)) {
Logger::Log(LOG_ERROR, "Registration failed, invalid server response (JSON parsing failed)");
Logger::Log(LOG_DEBUG, "Raw response: %s", response.GetBody().c_str());
return false;
}
Parser parser;
Var result;

Json::Value trust_level = root["verified-level"];
Json::Value challenge = root["challenge"];
if (!root.isObject() || !trust_level.isNumeric() || !challenge.isString()) {
Logger::Log(LOG_ERROR, "Registration failed, incorrect response from server");
try
{
result = parser.parse(response.GetBody());
}
catch(JSONException& jsonException)
{
Logger::Log(LOG_ERROR, "Registration failed, invalid server response (%s)", jsonException.message().c_str());
Logger::Log(LOG_DEBUG, "Raw response: %s", response.GetBody().c_str());
return false;
}

m_token = challenge.asString();
m_trust_level = trust_level.asInt();
DynamicStruct root = result.extract<Object>();

m_trust_level = root["verified-level"];
m_token = root["challenge"].toString();
m_is_registered = true;
return true;
}

bool Client::SendHeatbeat(Json::Value &user_list) {
Json::Value data(Json::objectValue);
bool Client::SendHeatbeat(Poco::JSON::Array &user_list) {
DynamicStruct data;
data["challenge"] = m_token;
data["users"] = user_list;
std::string json_str = data.toStyledString();

auto json_str = JsonToString(data);
Logger::Log(LOG_DEBUG, "Heartbeat JSON:\n%s", json_str.c_str());

Http::Response response;
Expand All @@ -100,9 +115,11 @@ namespace MasterServer {
bool Client::UnRegister() {
assert(m_is_registered == true);

Json::Value data(Json::objectValue);
DynamicStruct data;
data["challenge"] = m_token;
std::string json_str = data.toStyledString();

auto json_str = JsonToString(data);

Logger::Log(LOG_DEBUG, "UnRegister JSON:\n%s", json_str.c_str());

Http::Response response;
Expand Down
5 changes: 2 additions & 3 deletions source/server/master-server.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ along with Foobar. If not, see <http://www.gnu.org/licenses/>.

#include "prerequisites.h"
#include "UnicodeStrings.h"

#include "json/json.h"
#include <Poco/JSON/Array.h>

namespace MasterServer {

Expand All @@ -33,7 +32,7 @@ namespace MasterServer {

bool Register();

bool SendHeatbeat(Json::Value &user_list);
bool SendHeatbeat(Poco::JSON::Array &user_list);

bool UnRegister();

Expand Down
3 changes: 2 additions & 1 deletion source/server/rorserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ along with Foobar. If not, see <http://www.gnu.org/licenses/>.

#include <stdio.h>
#include <string.h>
#include <Poco/Dynamic/Struct.h>

#ifdef _WIN32
# include "windows.h"
Expand Down Expand Up @@ -343,7 +344,7 @@ int main(int argc, char *argv[]) {
Utils::SleepSeconds(Config::GetHeartbeatIntervalSec());

Logger::Log(LOG_VERBOSE, "Sending heartbeat...");
Json::Value user_list(Json::arrayValue);
Poco::JSON::Array user_list;
s_sequencer.GetHeartbeatUserList(user_list);
if (!s_master_server.SendHeatbeat(user_list)) {
unsigned int timeout = Config::GetHeartbeatRetrySeconds();
Expand Down
11 changes: 8 additions & 3 deletions source/server/sequencer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ along with Foobar. If not, see <http://www.gnu.org/licenses/>.
#include <stdexcept>
#include <sstream>

#include <Poco/JSON/Array.h>
#include <Poco/JSON/Object.h>
#include <Poco/JSON/ParseHandler.h>

#ifdef __GNUC__

#include <stdlib.h>
Expand Down Expand Up @@ -409,14 +413,15 @@ void Sequencer::broadcastUserInfo(int client_id) {
}
}

void Sequencer::GetHeartbeatUserList(Json::Value &out_array) {
void Sequencer::GetHeartbeatUserList(Poco::JSON::Array &out_array)
{
std::lock_guard<std::mutex> scoped_lock(m_clients_mutex);

auto itor = m_clients.begin();
auto endi = m_clients.end();
for (; itor != endi; ++itor) {
Client *client = *itor;
Json::Value user_data(Json::objectValue);
Poco::DynamicStruct user_data;
user_data["is_admin"] = (client->user.authstatus & RoRnet::AUTH_ADMIN);
user_data["is_mod"] = (client->user.authstatus & RoRnet::AUTH_MOD);
user_data["is_ranked"] = (client->user.authstatus & RoRnet::AUTH_RANKED);
Expand All @@ -425,7 +430,7 @@ void Sequencer::GetHeartbeatUserList(Json::Value &out_array) {
user_data["ip_address"] = client->GetIpAddress();
user_data["client_id"] = client->user.uniqueid;

out_array.append(user_data);
out_array.add(user_data);
}
}

Expand Down
5 changes: 3 additions & 2 deletions source/server/sequencer.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ along with Foobar. If not, see <http://www.gnu.org/licenses/>.
#include "broadcaster.h"
#include "receiver.h"
#include "spamfilter.h"
#include "json/json.h"
#include <Poco/JSON/Array.h>

#ifdef WITH_ANGELSCRIPT

Expand All @@ -44,6 +44,7 @@ along with Foobar. If not, see <http://www.gnu.org/licenses/>.
#include <thread>
#include <condition_variable>


// How many not-vehicles streams has every user by default? (e.g.: "default" and "chat" are not-vehicles streams)
// This is used for the vehicle-limit
#define NON_VEHICLE_STREAMS 2
Expand Down Expand Up @@ -214,7 +215,7 @@ class Sequencer {
void queueMessage(int uid, int type, unsigned int streamid, char *data, unsigned int len);
void sendMOTDSynchronized(int uid);
void frameStepScripts(float dt);
void GetHeartbeatUserList(Json::Value &out_array);
void GetHeartbeatUserList(Poco::JSON::Array &out_array);
void UpdateMinuteStats();
int AuthorizeNick(std::string token, std::string &nickname);
std::vector<WebserverClientInfo> GetClientListCopy();
Expand Down
Loading