Skip to content

Commit 4fc61f3

Browse files
committed
Add config
Rename commands
1 parent a5a9915 commit 4fc61f3

14 files changed

Lines changed: 297 additions & 45 deletions

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@
1010
[submodule "wolfssl"]
1111
path = wolfssl
1212
url = https://github.com/wolfSSL/wolfssl
13+
[submodule "yaml-cpp"]
14+
path = yaml-cpp
15+
url = https://github.com/jbeder/yaml-cpp.git

CMakeLists.txt

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ else()
2929
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/build/win32/")
3030
endif()
3131

32+
33+
#yaml resets c++17 so I just move it above ours so we don't have to re-set
34+
SET(YAML_CPP_BUILD_TESTS OFF CACHE BOOL "Don't want" FORCE)
35+
SET(YAML_CPP_BUILD_TOOLS OFF CACHE BOOL "Don't want" FORCE)
36+
SET(YAML_CPP_BUILD_TESTS OFF CACHE BOOL "Don't want" FORCE)
37+
SET(YAML_CPP_INSTALL OFF CACHE BOOL "Don't want" FORCE)
38+
SET(MSVC_SHARED_RT OFF CACHE BOOL "want static" FORCE)
39+
40+
add_subdirectory(yaml-cpp)
41+
3242
set(CMAKE_CXX_STANDARD 17)
3343
set(CMAKE_CXX_STANDARD_REQUIRED ON)
3444
set(CMAKE_CXX_EXTENSIONS OFF)
@@ -53,7 +63,7 @@ if(CMAKE_COMPILER_IS_GNUCXX)
5363
else()
5464
set(CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /MTd /Zi /Ob0 /Od /RTC1 /MP /EHsc")
5565
set(CMAKE_CXX_FLAGS_RELEASE "/MT /Zi /O2 /Ob1 /EHsc /MP") #with debug info
56-
set(CMAKE_C_FLAGS_DEBUG "/D_DEBUG /MTd /Zi /Ob0 /Od /RTC1 /MP /EHsc")
66+
set(CMAKE_C_FLAGS_DEBUG "/D_DEBUG /MTd /Zi /Ob0 /Od /RTC1 /MP /EHsc")
5767
set(CMAKE_C_FLAGS_RELEASE "/MT /Zi /O2 /Ob1 /EHsc /MP") #with debug info
5868
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "/OPT:REF /DEBUG:FULL")
5969
endif()
@@ -70,5 +80,11 @@ add_subdirectory(mariadbpp)
7080

7181
include_directories(AFTER "${PROJECT_SOURCE_DIR}/mariadbpp/include")
7282
include_directories(AFTER "${PROJECT_SOURCE_DIR}/mariadb-connector-c/include")
83+
84+
85+
86+
87+
88+
7389
add_subdirectory(src)
7490

CMakeSettings.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,19 @@
1212
"cmakeCommandArgs": "",
1313
"buildCommandArgs": "",
1414
"ctestCommandArgs": ""
15+
},
16+
{
17+
"name": "x64-Release",
18+
"generator": "Visual Studio 15 2017 Win64",
19+
"configurationType": "Release",
20+
"inheritEnvironments": [
21+
"msvc_x64_x64"
22+
],
23+
"buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}",
24+
"installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}",
25+
"cmakeCommandArgs": "",
26+
"buildCommandArgs": "",
27+
"ctestCommandArgs": ""
1528
}
1629
]
1730
}

src/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ file(GLOB INTERCEPT_HOST_SOURCES "${INTERCEPT_CLIENT_PATH}/intercept/client/*.cp
3838
SOURCE_GROUP("intercept" FILES ${INTERCEPT_HOST_SOURCES})
3939

4040
add_library(${INTERCEPT_PLUGIN_NAME} SHARED ${INTERCEPT_PLUGIN_SOURCES} ${INTERCEPT_HOST_SOURCES})
41-
target_link_libraries(${INTERCEPT_PLUGIN_NAME} mariadbclientpp)
41+
target_link_libraries(${INTERCEPT_PLUGIN_NAME} mariadbclientpp yaml-cpp)
4242

4343
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${INTERCEPT_INCLUDE_PATH})
4444

src/config.cpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
#include "config.h"
2+
#include <filesystem>
3+
#include "yaml-cpp/yaml.h"
4+
5+
6+
namespace YAML {
7+
template<>
8+
struct convert<r_string> {
9+
static Node encode(const r_string& rhs) {
10+
Node node;
11+
node = static_cast<std::string>(rhs);
12+
return node;
13+
}
14+
15+
static bool decode(const Node& node, r_string& rhs) {
16+
if (!node.IsScalar()) {
17+
return false;
18+
}
19+
20+
rhs = node.as<std::string>();
21+
return true;
22+
}
23+
};
24+
}
25+
26+
27+
28+
void Config::reloadConfig() {
29+
std::filesystem::path configFilePath("@InterceptDB/config.yaml");
30+
31+
if (!std::filesystem::exists(configFilePath))
32+
throw std::filesystem::filesystem_error("File not found", configFilePath, std::error_code());
33+
34+
auto stringpath = configFilePath.string();
35+
YAML::Node config = YAML::LoadFile(configFilePath.string());
36+
37+
if (!config["accounts"].IsMap()) throw std::runtime_error("Config Accounts entry is not a map");
38+
39+
for (auto& it : config["accounts"]) {
40+
r_string accountName = it.first.as<r_string>();
41+
auto value = it.second;
42+
43+
if (!value["ip"]) throw std::runtime_error("Undefined account value: ip");
44+
if (!value["username"]) throw std::runtime_error("Undefined account value: username");
45+
if (!value["password"]) throw std::runtime_error("Undefined account value: password");
46+
if (!value["database"]) throw std::runtime_error("Undefined account value: database");
47+
48+
auto ip = value["ip"].as<r_string>();
49+
auto user = value["username"].as<r_string>();
50+
auto password = value["password"].as<r_string>();
51+
auto database = value["database"].as<r_string>();
52+
auto port = value["port"].as<int>(3306);
53+
54+
auto acc = mariadb::account::create(ip, user, password, database, port);
55+
56+
accounts[accountName] = acc;
57+
}
58+
59+
for (auto& it : config["statements"]) {
60+
r_string stmtName = it.first.as<r_string>();
61+
statements[stmtName] = it.second.as<r_string>();
62+
}
63+
64+
65+
}
66+
67+
68+
game_value cmd_reloadConfig(uintptr_t) {
69+
70+
71+
72+
try {
73+
Config::get().reloadConfig();
74+
}
75+
catch (YAML::BadConversion& x) {
76+
return "error " + x.msg + " in L" + std::to_string(x.mark.line);
77+
}
78+
catch (std::runtime_error& x) {
79+
return r_string("error ") + x.what();
80+
}
81+
catch (YAML::ParserException& x) {
82+
return "error " + x.msg + " in L" + std::to_string(x.mark.line);
83+
}
84+
return {};
85+
}
86+
87+
void Config::initCommands() {
88+
89+
handle_cmd_reloadConfig = intercept::client::host::register_sqf_command("dbReloadConfig", "TODO", cmd_reloadConfig, game_data_type::STRING);
90+
91+
92+
}

src/config.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#pragma once
2+
#include <intercept.hpp>
3+
#include "../intercept/src/host/common/singleton.hpp"
4+
#include <vector>
5+
#include "mariadb++/account.hpp"
6+
#include "../intercept/src/client/headers/shared/containers.hpp"
7+
8+
class Config : public intercept::singleton<Config> {
9+
10+
public:
11+
void reloadConfig();
12+
13+
r_string getQuery(r_string name) {
14+
auto found = statements.find(name);
15+
if (found == statements.end()) return r_string();
16+
return found->second;
17+
}
18+
19+
mariadb::account_ref getAccount(r_string name) {
20+
auto found = accounts.find(name);
21+
if (found == accounts.end()) return {};
22+
return found->second;
23+
}
24+
25+
static void initCommands();
26+
static inline registered_sqf_function handle_cmd_reloadConfig;
27+
28+
private:
29+
std::map<intercept::types::r_string, mariadb::account_ref> accounts;
30+
std::map<intercept::types::r_string, intercept::types::r_string> statements;
31+
32+
33+
34+
};

src/connection.cpp

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#include <mariadb++/connection.hpp>
33
#include "query.h"
44
#include "res.h"
5+
#include "mariadb++/exceptions.hpp"
6+
#include <winsock2.h>
57

68
using namespace intercept::client;
79
extern auto_array<ref<GameDataDBAsyncResult>> asyncWork;
@@ -72,6 +74,18 @@ game_value Connection::cmd_createConnectionArray(uintptr_t, game_value_parameter
7274

7375
newCon->session = mariadb::connection::create(acc);
7476

77+
return newCon;
78+
}
79+
80+
game_value Connection::cmd_createConnectionConfig(uintptr_t, game_value_parameter right) {
81+
82+
auto acc = Config::get().getAccount(right);
83+
if (!acc) return {};
84+
85+
86+
auto newCon = new GameDataDBConnection();
87+
88+
newCon->session = mariadb::connection::create(acc);
7589

7690
return newCon;
7791
}
@@ -119,7 +133,7 @@ class callstack_item_WaitForQueryResult : public vm_context::callstack_item {
119133

120134
};
121135

122-
game_value Connection::cmd_query(uintptr_t g , game_value_parameter con, game_value_parameter qu) {
136+
game_value Connection::cmd_execute(uintptr_t g , game_value_parameter con, game_value_parameter qu) {
123137

124138
auto gs = reinterpret_cast<game_state*>(g);
125139

@@ -129,7 +143,7 @@ game_value Connection::cmd_query(uintptr_t g , game_value_parameter con, game_va
129143
auto session = con.get_as<GameDataDBConnection>()->session;
130144
auto query = qu.get_as<GameDataDBQuery>();
131145

132-
auto statement = session->create_statement(query->queryString);
146+
auto statement = session->create_statement(query->getQueryString());
133147

134148
uint32_t idx = 0;
135149
for (auto& it : query->boundValues) {
@@ -172,28 +186,38 @@ game_value Connection::cmd_query(uintptr_t g , game_value_parameter con, game_va
172186
return 123;
173187
}
174188

175-
game_value Connection::cmd_queryAsync(uintptr_t, game_value_parameter con, game_value_parameter qu) {
189+
game_value Connection::cmd_executeAsync(uintptr_t, game_value_parameter con, game_value_parameter qu) {
176190

177191
auto session = con.get_as<GameDataDBConnection>()->session;
178192
auto query = qu.get_as<GameDataDBQuery>();
179193

180194
auto gd_res = new GameDataDBAsyncResult();
181195
gd_res->data = std::make_shared<GameDataDBAsyncResult::dataT>();
182196
gd_res->data->res =
183-
std::async(std::launch::async,[session, stmt = query->queryString, boundV = query->boundValues]() -> mariadb::result_set_ref
197+
std::async(std::launch::async,[session, stmt = query->getQueryString(), boundV = query->boundValues]() -> mariadb::result_set_ref
184198
{
185-
auto statement = session->create_statement(stmt);
186199

187-
uint32_t idx = 0;
188-
for (auto& it : boundV) {
200+
try {
201+
auto statement = session->create_statement(stmt);
202+
uint32_t idx = 0;
203+
for (auto& it : boundV) {
189204

190-
switch (it.type_enum()) {
205+
switch (it.type_enum()) {
191206
case game_data_type::SCALAR: statement->set_float(idx++, static_cast<float>(it)); break;
192207
case game_data_type::BOOL: statement->set_boolean(idx++, static_cast<bool>(it)); break;
193208
case game_data_type::STRING: statement->set_string(idx++, static_cast<r_string>(it)); break;
209+
}
194210
}
211+
return statement->query();
212+
} catch (mariadb::exception::connection& x) {
213+
__debugbreak();
214+
215+
216+
return {};
195217
}
196-
return statement->query();
218+
219+
220+
197221
});
198222
asyncWork.emplace_back(gd_res);
199223
return gd_res;
@@ -206,7 +230,8 @@ void Connection::initCommands() {
206230
GameDataDBConnection_type = dbType.second;
207231

208232

209-
handle_cmd_createConnection = host::register_sqf_command("db_createConnection", "TODO", Connection::cmd_createConnectionArray, GameDataDBConnection_typeE, game_data_type::ARRAY);
210-
handle_cmd_query = host::register_sqf_command("db_query", "TODO", Connection::cmd_query, Result::GameDataDBResult_typeE, GameDataDBConnection_typeE, Query::GameDataDBQuery_typeE);
211-
handle_cmd_queryAsync = host::register_sqf_command("db_queryAsync", "TODO", Connection::cmd_queryAsync, Result::GameDataDBAsyncResult_typeE, GameDataDBConnection_typeE, Query::GameDataDBQuery_typeE);
233+
handle_cmd_createConnection = host::register_sqf_command("dbCreateConnection", "TODO", Connection::cmd_createConnectionArray, GameDataDBConnection_typeE, game_data_type::ARRAY);
234+
handle_cmd_createConnectionConfig = host::register_sqf_command("dbCreateConnection", "TODO", Connection::cmd_createConnectionConfig, GameDataDBConnection_typeE, game_data_type::STRING);
235+
handle_cmd_execute = host::register_sqf_command("dbExecute", "TODO", Connection::cmd_execute, Result::GameDataDBResult_typeE, GameDataDBConnection_typeE, Query::GameDataDBQuery_typeE);
236+
handle_cmd_executeAsync = host::register_sqf_command("dbExecuteAsync", "TODO", Connection::cmd_executeAsync, Result::GameDataDBAsyncResult_typeE, GameDataDBConnection_typeE, Query::GameDataDBQuery_typeE);
212237
}

src/connection.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ using namespace intercept::types;
88
class Connection {
99
public:
1010

11-
static game_value cmd_createConnectionArray(uintptr_t, game_value_parameter right);
12-
static game_value cmd_query(uintptr_t, game_value_parameter con, game_value_parameter qu);
13-
static game_value cmd_queryAsync(uintptr_t, game_value_parameter con, game_value_parameter qu);
11+
static game_value cmd_createConnectionArray(uintptr_t, game_value_parameter right);
12+
static game_value cmd_createConnectionConfig(uintptr_t, game_value_parameter right);
13+
static game_value cmd_execute(uintptr_t, game_value_parameter con, game_value_parameter qu);
14+
static game_value cmd_executeAsync(uintptr_t, game_value_parameter con, game_value_parameter qu);
1415

1516

1617

@@ -20,7 +21,8 @@ class Connection {
2021
static inline game_data_type GameDataDBConnection_typeE;
2122

2223

23-
static inline types::registered_sqf_function handle_cmd_createConnection;
24-
static inline types::registered_sqf_function handle_cmd_query;
25-
static inline types::registered_sqf_function handle_cmd_queryAsync;
24+
static inline types::registered_sqf_function handle_cmd_createConnection;
25+
static inline types::registered_sqf_function handle_cmd_createConnectionConfig;
26+
static inline types::registered_sqf_function handle_cmd_execute;
27+
static inline types::registered_sqf_function handle_cmd_executeAsync;
2628
};

src/main.cpp

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "res.h"
44
#include "query.h"
55
#include "connection.h"
6+
#include "yaml-cpp/exceptions.h"
67

78
int intercept::api_version() { //This is required for the plugin to work.
89
return 1;
@@ -16,18 +17,25 @@ void intercept::pre_start() {
1617
Result::initCommands();
1718
Query::initCommands();
1819
Connection::initCommands();
20+
Config::initCommands();
1921
}
2022

2123
void intercept::pre_init() {
22-
23-
//mysqlx::Session sess("localhost", 3306, "intercepttest", "password");
24-
//
25-
//auto db = sess.sql("USE ?").bind("databasename").execute();
26-
//
27-
//
28-
//auto query = sess.sql("SELECT * FROM ?").bind("testdata");
29-
//query.execute();
30-
24+
try {
25+
Config::get().reloadConfig();
26+
}
27+
catch (YAML::BadConversion& x) {
28+
sqf::diag_log ("Database config error " + x.msg + " in L" + std::to_string(x.mark.line));
29+
sqf::system_chat("Database config error " + x.msg + " in L" + std::to_string(x.mark.line));
30+
}
31+
catch (std::runtime_error& x) {
32+
sqf::diag_log(r_string("Database config error ") + x.what());
33+
sqf::system_chat(r_string("Database config error ") + x.what());
34+
}
35+
catch (YAML::ParserException& x) {
36+
sqf::diag_log("Database config error " + x.msg + " in L" + std::to_string(x.mark.line));
37+
sqf::system_chat("Database config error " + x.msg + " in L" + std::to_string(x.mark.line));
38+
}
3139

3240
intercept::sqf::system_chat("Intercept database has been loaded");
3341
}

0 commit comments

Comments
 (0)