feat: add websocket server
This commit is contained in:
@@ -23,11 +23,16 @@ Spoofer::Spoofer()
|
|||||||
_log->info("Spoofer init");
|
_log->info("Spoofer init");
|
||||||
|
|
||||||
loadConfig();
|
loadConfig();
|
||||||
|
|
||||||
|
_log->info("Starting WebSocket server");
|
||||||
|
initServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
Spoofer::~Spoofer()
|
Spoofer::~Spoofer()
|
||||||
{
|
{
|
||||||
_log->info("Stopping WebSocket server");
|
_log->info("Stopping WebSocket server");
|
||||||
|
stopServer();
|
||||||
|
|
||||||
delete _log;
|
delete _log;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,6 +118,127 @@ void Spoofer::saveConfig()
|
|||||||
auto errCtx = glz::write_file_json(conf, configPath, buffer);
|
auto errCtx = glz::write_file_json(conf, configPath, buffer);
|
||||||
if (errCtx.ec != glz::error_code::none) _log->error("Failed to save config to {}", configPath);
|
if (errCtx.ec != glz::error_code::none) _log->error("Failed to save config to {}", configPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
websocket
|
||||||
|
*/
|
||||||
|
void Spoofer::initServer()
|
||||||
|
{
|
||||||
|
if (_wsServer) PANIC("Attempted to init websocket server from invalid state");
|
||||||
|
_wsServer = new ix::WebSocketServer(WS_PORT, WS_ADDR);
|
||||||
|
|
||||||
|
_wsServer->setOnClientMessageCallback([this](std::shared_ptr<ix::ConnectionState> connectionState,
|
||||||
|
ix::WebSocket& webSocket,
|
||||||
|
const std::unique_ptr<ix::WebSocketMessage>& msg) {
|
||||||
|
this->wsMessageCallback(connectionState, webSocket, msg);
|
||||||
|
});
|
||||||
|
|
||||||
|
std::pair<bool, std::string> res = _wsServer->listen();
|
||||||
|
if (!res.first) PANIC("Websocket server failed to start");
|
||||||
|
|
||||||
|
_log->verbose("WebSocket server running @ {}:{}", WS_ADDR, WS_PORT);
|
||||||
|
|
||||||
|
_wsServer->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Spoofer::stopServer()
|
||||||
|
{
|
||||||
|
if (_wsServer)
|
||||||
|
{
|
||||||
|
_wsServer->stop();
|
||||||
|
delete _wsServer;
|
||||||
|
_wsServer = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Spoofer::wsMessageCallback(std::shared_ptr<ix::ConnectionState> /*connectionState*/, ix::WebSocket& webSocket,
|
||||||
|
const std::unique_ptr<ix::WebSocketMessage>& msg)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
|
switch (msg->type)
|
||||||
|
{
|
||||||
|
case ix::WebSocketMessageType::Open:
|
||||||
|
{
|
||||||
|
_log->verbose("Websocket connection open, URI: {}", msg->openInfo.uri);
|
||||||
|
WSMessages::Init initMsg;
|
||||||
|
initMsg.profile.camperItems = _camperItems;
|
||||||
|
initMsg.profile.camperAddons = _camperAddons;
|
||||||
|
initMsg.profile.slasherAddons = _slasherAddons;
|
||||||
|
initMsg.profile.camperOfferings = _camperOfferings;
|
||||||
|
initMsg.profile.slasherOfferings = _slasherOfferings;
|
||||||
|
initMsg.profile.globalOfferings = _globalOfferings;
|
||||||
|
initMsg.profile.camperPerks = _camperPerks;
|
||||||
|
initMsg.profile.slasherPerks = _slasherPerks;
|
||||||
|
initMsg.profile.catalogItemIds = _catalogItemIds;
|
||||||
|
initMsg.profile.dlcListGRDK = _dlcListGRDK;
|
||||||
|
initMsg.profile.dlcListEGS = _dlcListEGS;
|
||||||
|
initMsg.profile.dlcListSteam = _dlcListSteam;
|
||||||
|
initMsg.profile.unlockedCharacters = _unlockedCharacters;
|
||||||
|
initMsg.toggles.spoofItems = _spoofItems;
|
||||||
|
initMsg.toggles.spoofPerks = _spoofPerks;
|
||||||
|
initMsg.toggles.spoofCatalog = _spoofCatalog;
|
||||||
|
initMsg.toggles.spoofDLCs = _spoofDLCs;
|
||||||
|
std::string out;
|
||||||
|
auto errCtx = glz::write_json(initMsg, out);
|
||||||
|
if (errCtx && errCtx.ec != glz::error_code::none)
|
||||||
|
_log->error("Error occurred while writing init msg");
|
||||||
|
else
|
||||||
|
webSocket.send(out);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ix::WebSocketMessageType::Close:
|
||||||
|
_log->verbose("Websocket connection close");
|
||||||
|
break;
|
||||||
|
case ix::WebSocketMessageType::Message:
|
||||||
|
{
|
||||||
|
WSMessages::Request req;
|
||||||
|
auto err = glz::read_json(req, msg->str);
|
||||||
|
if (err.ec != glz::error_code::none)
|
||||||
|
{
|
||||||
|
_log->error("Failed to parse websocket message");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (req.action)
|
||||||
|
{
|
||||||
|
case WSMessages::SYNC_STATE:
|
||||||
|
{
|
||||||
|
_camperItems = std::move(req.profile.camperItems);
|
||||||
|
_camperAddons = std::move(req.profile.camperAddons);
|
||||||
|
_slasherAddons = std::move(req.profile.slasherAddons);
|
||||||
|
_camperOfferings = std::move(req.profile.camperOfferings);
|
||||||
|
_slasherOfferings = std::move(req.profile.slasherOfferings);
|
||||||
|
_globalOfferings = std::move(req.profile.globalOfferings);
|
||||||
|
_camperPerks = std::move(req.profile.camperPerks);
|
||||||
|
_slasherPerks = std::move(req.profile.slasherPerks);
|
||||||
|
_catalogItemIds = std::move(req.profile.catalogItemIds);
|
||||||
|
_dlcListGRDK = std::move(req.profile.dlcListGRDK);
|
||||||
|
_dlcListEGS = std::move(req.profile.dlcListEGS);
|
||||||
|
_dlcListSteam = std::move(req.profile.dlcListSteam);
|
||||||
|
_unlockedCharacters = std::move(req.profile.unlockedCharacters);
|
||||||
|
saveConfig();
|
||||||
|
_log->verbose("Profile state synchronized.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WSMessages::SYNC_TOGGLES:
|
||||||
|
{
|
||||||
|
_spoofItems = req.toggles.spoofItems;
|
||||||
|
_spoofPerks = req.toggles.spoofPerks;
|
||||||
|
_spoofCatalog = req.toggles.spoofCatalog;
|
||||||
|
_spoofDLCs = req.toggles.spoofDLCs;
|
||||||
|
saveConfig();
|
||||||
|
_log->verbose("Toggles synchronized.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
_log->warning("Unknown action: {}", static_cast<int>(req.action));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
proxy handlers
|
proxy handlers
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -9,6 +9,20 @@
|
|||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
|
#define WS_ADDR "0.0.0.0"
|
||||||
|
#define WS_PORT 4444
|
||||||
|
|
||||||
|
class TinyMITMProxy;
|
||||||
|
|
||||||
|
namespace ix
|
||||||
|
{
|
||||||
|
class WebSocket;
|
||||||
|
class WebSocketServer;
|
||||||
|
struct WebSocketMessage;
|
||||||
|
|
||||||
|
class ConnectionState;
|
||||||
|
} // namespace ix
|
||||||
|
|
||||||
namespace seallib
|
namespace seallib
|
||||||
{
|
{
|
||||||
class Logger;
|
class Logger;
|
||||||
@@ -31,6 +45,35 @@ struct SpooferConfig
|
|||||||
std::unordered_set<std::string> unlockedCharacters;
|
std::unordered_set<std::string> unlockedCharacters;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace WSMessages
|
||||||
|
{
|
||||||
|
enum Action : int
|
||||||
|
{
|
||||||
|
INIT_CONFIG = 0,
|
||||||
|
SYNC_STATE = 1,
|
||||||
|
SYNC_TOGGLES = 2
|
||||||
|
};
|
||||||
|
struct Toggles
|
||||||
|
{
|
||||||
|
bool spoofItems = false;
|
||||||
|
bool spoofPerks = false;
|
||||||
|
bool spoofCatalog = false;
|
||||||
|
bool spoofDLCs = false;
|
||||||
|
};
|
||||||
|
struct Init
|
||||||
|
{
|
||||||
|
Action action = INIT_CONFIG;
|
||||||
|
SpooferConfig profile;
|
||||||
|
Toggles toggles;
|
||||||
|
};
|
||||||
|
struct Request
|
||||||
|
{
|
||||||
|
Action action;
|
||||||
|
SpooferConfig profile{};
|
||||||
|
Toggles toggles{};
|
||||||
|
};
|
||||||
|
} // namespace WSMessages
|
||||||
|
|
||||||
class Spoofer
|
class Spoofer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -45,6 +88,15 @@ class Spoofer
|
|||||||
*/
|
*/
|
||||||
void loadConfig();
|
void loadConfig();
|
||||||
void saveConfig();
|
void saveConfig();
|
||||||
|
|
||||||
|
/*
|
||||||
|
websocket server stuff
|
||||||
|
*/
|
||||||
|
void initServer();
|
||||||
|
void stopServer();
|
||||||
|
|
||||||
|
void wsMessageCallback(std::shared_ptr<ix::ConnectionState> connectionState, ix::WebSocket& webSocket,
|
||||||
|
const std::unique_ptr<ix::WebSocketMessage>& msg);
|
||||||
/*
|
/*
|
||||||
proxy handlers
|
proxy handlers
|
||||||
*/
|
*/
|
||||||
@@ -77,6 +129,11 @@ class Spoofer
|
|||||||
std::unordered_set<std::string> _dlcListSteam;
|
std::unordered_set<std::string> _dlcListSteam;
|
||||||
|
|
||||||
std::unordered_set<std::string> _unlockedCharacters;
|
std::unordered_set<std::string> _unlockedCharacters;
|
||||||
|
|
||||||
|
/*
|
||||||
|
internal variables
|
||||||
|
*/
|
||||||
|
ix::WebSocketServer* _wsServer = nullptr;
|
||||||
seallib::Logger* _log = nullptr;
|
seallib::Logger* _log = nullptr;
|
||||||
std::mutex _mutex;
|
std::mutex _mutex;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user