-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add an SSCSM controller and environment skeleton
- Loading branch information
Showing
12 changed files
with
467 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// SPDX-FileCopyrightText: 2024 Luanti authors | ||
// | ||
// SPDX-License-Identifier: LGPL-2.1-or-later | ||
|
||
#include "sscsm_controller.h" | ||
#include "sscsm_environment.h" | ||
#include "sscsm_requests.h" | ||
#include "sscsm_events.h" | ||
#include "sscsm_stupid_channel.h" | ||
|
||
std::unique_ptr<SSCSMController> SSCSMController::create() | ||
{ | ||
auto channel = std::make_shared<StupidChannel>(); | ||
auto thread = std::make_unique<SSCSMEnvironment>(channel); | ||
thread->start(); | ||
|
||
// Wait for thread to finish initializing. | ||
auto req0 = deserializeSSCSMRequest(channel->recvB()); | ||
FATAL_ERROR_IF(!dynamic_cast<SSCSMRequestPollNextEvent *>(req0.get()), | ||
"First request must be pollEvent."); | ||
|
||
return std::make_unique<SSCSMController>(std::move(thread), channel); | ||
} | ||
|
||
SSCSMController::SSCSMController(std::unique_ptr<SSCSMEnvironment> thread, | ||
std::shared_ptr<StupidChannel> channel) : | ||
m_thread(std::move(thread)), m_channel(std::move(channel)) | ||
{ | ||
} | ||
|
||
SSCSMController::~SSCSMController() | ||
{ | ||
// send tear-down | ||
m_channel->sendB(serializeSSCSMAnswer(SSCSMAnswerPollNextEvent{ | ||
std::make_unique<SSCSMEventTearDown>() | ||
})); | ||
// wait for death | ||
m_thread->stop(); | ||
m_thread->wait(); | ||
} | ||
|
||
SerializedSSCSMAnswer SSCSMController::handleRequest(Client *client, ISSCSMRequest *req) | ||
{ | ||
return req->exec(client); | ||
} | ||
|
||
void SSCSMController::runEvent(Client *client, std::unique_ptr<ISSCSMEvent> event) | ||
{ | ||
auto answer = serializeSSCSMAnswer(SSCSMAnswerPollNextEvent{std::move(event)}); | ||
|
||
while (true) { | ||
auto request = deserializeSSCSMRequest(m_channel->exchangeB(std::move(answer))); | ||
|
||
if (dynamic_cast<SSCSMRequestPollNextEvent *>(request.get()) != nullptr) { | ||
break; | ||
} | ||
|
||
answer = handleRequest(client, request.get()); | ||
} | ||
} | ||
|
||
void SSCSMController::eventOnStep(Client *client, f32 dtime) | ||
{ | ||
runEvent(client, std::make_unique<SSCSMEventOnStep>(dtime)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// SPDX-FileCopyrightText: 2024 Luanti authors | ||
// | ||
// SPDX-License-Identifier: LGPL-2.1-or-later | ||
|
||
#pragma once | ||
|
||
#include <memory> | ||
#include "irrlichttypes.h" | ||
#include "sscsm_irequest.h" | ||
#include "sscsm_ievent.h" | ||
#include "util/basic_macros.h" | ||
|
||
class SSCSMEnvironment; | ||
class StupidChannel; | ||
|
||
class SSCSMController | ||
{ | ||
std::unique_ptr<SSCSMEnvironment> m_thread; | ||
std::shared_ptr<StupidChannel> m_channel; | ||
|
||
SerializedSSCSMAnswer handleRequest(Client *client, ISSCSMRequest *req); | ||
|
||
public: | ||
static std::unique_ptr<SSCSMController> create(); | ||
|
||
SSCSMController(std::unique_ptr<SSCSMEnvironment> thread, | ||
std::shared_ptr<StupidChannel> channel); | ||
|
||
~SSCSMController(); | ||
|
||
DISABLE_CLASS_COPY(SSCSMController); | ||
|
||
// Handles requests until the next event is polled | ||
void runEvent(Client *client, std::unique_ptr<ISSCSMEvent> event); | ||
|
||
void eventOnStep(Client *client, f32 dtime); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// SPDX-FileCopyrightText: 2024 Luanti authors | ||
// | ||
// SPDX-License-Identifier: LGPL-2.1-or-later | ||
|
||
#include "sscsm_environment.h" | ||
#include "sscsm_requests.h" | ||
#include "sscsm_events.h" | ||
#include "sscsm_stupid_channel.h" | ||
|
||
|
||
void *SSCSMEnvironment::run() | ||
{ | ||
while (true) { | ||
auto next_event = cmdPollNextEvent(); | ||
|
||
if (dynamic_cast<SSCSMEventTearDown *>(next_event.get())) { | ||
break; | ||
} | ||
|
||
next_event->exec(this); | ||
} | ||
|
||
return nullptr; | ||
} | ||
|
||
SerializedSSCSMAnswer SSCSMEnvironment::exchange(SerializedSSCSMRequest req) | ||
{ | ||
return m_channel->exchangeA(std::move(req)); | ||
} | ||
|
||
std::unique_ptr<ISSCSMEvent> SSCSMEnvironment::cmdPollNextEvent() | ||
{ | ||
auto request = SSCSMRequestPollNextEvent{}; | ||
auto answer = deserializeSSCSMAnswer<SSCSMAnswerPollNextEvent>( | ||
exchange(serializeSSCSMRequest(request)) | ||
); | ||
return std::move(answer.next_event); | ||
} | ||
|
||
MapNode SSCSMEnvironment::cmdGetNode(v3s16 pos) | ||
{ | ||
auto request = SSCSMRequestGetNode{pos}; | ||
auto answer = deserializeSSCSMAnswer<SSCSMAnswerGetNode>( | ||
exchange(serializeSSCSMRequest(request)) | ||
); | ||
return answer.node; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// SPDX-FileCopyrightText: 2024 Luanti authors | ||
// | ||
// SPDX-License-Identifier: LGPL-2.1-or-later | ||
|
||
#pragma once | ||
|
||
#include <memory> | ||
#include "client/client.h" | ||
#include "threading/thread.h" | ||
#include "sscsm_controller.h" | ||
#include "sscsm_irequest.h" | ||
|
||
// The thread that runs SSCSM code. | ||
// Meant to be replaced by a sandboxed process. | ||
class SSCSMEnvironment : public Thread | ||
{ | ||
std::shared_ptr<StupidChannel> m_channel; | ||
|
||
void *run() override; | ||
|
||
SerializedSSCSMAnswer exchange(SerializedSSCSMRequest req); | ||
|
||
public: | ||
SSCSMEnvironment(std::shared_ptr<StupidChannel> channel) : | ||
Thread("SSCSMEnvironment-thread"), | ||
m_channel(std::move(channel)) | ||
{ | ||
} | ||
|
||
std::unique_ptr<ISSCSMEvent> cmdPollNextEvent(); | ||
MapNode cmdGetNode(v3s16 pos); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// SPDX-FileCopyrightText: 2024 Luanti authors | ||
// | ||
// SPDX-License-Identifier: LGPL-2.1-or-later | ||
|
||
#pragma once | ||
|
||
#include "sscsm_ievent.h" | ||
#include "debug.h" | ||
#include "irrlichttypes.h" | ||
#include "irr_v3d.h" | ||
#include "sscsm_environment.h" | ||
#include "mapnode.h" | ||
|
||
struct SSCSMEventTearDown : public ISSCSMEvent | ||
{ | ||
void exec(SSCSMEnvironment *env) override | ||
{ | ||
FATAL_ERROR("SSCSMEventTearDown needs to be handled by SSCSMEnvironment::run()"); | ||
} | ||
}; | ||
|
||
struct SSCSMEventOnStep : public ISSCSMEvent | ||
{ | ||
f32 dtime; | ||
|
||
SSCSMEventOnStep(f32 dtime_) : dtime(dtime_) {} | ||
|
||
void exec(SSCSMEnvironment *env) override | ||
{ | ||
// example | ||
env->cmdGetNode(v3s16(0, 0, 0)); | ||
} | ||
}; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// SPDX-FileCopyrightText: 2024 Luanti authors | ||
// | ||
// SPDX-License-Identifier: LGPL-2.1-or-later | ||
|
||
#pragma once | ||
|
||
#include <memory> | ||
#include <type_traits> | ||
|
||
class SSCSMEnvironment; | ||
|
||
// Event triggered from the main env for the SSCSM env. | ||
struct ISSCSMEvent | ||
{ | ||
virtual ~ISSCSMEvent() = default; | ||
|
||
// Note: No return value (difference to ISSCSMRequest). These are not callbacks | ||
// that you can run at arbitrary locations, because the untrusted code could | ||
// then clobber your local variables. | ||
virtual void exec(SSCSMEnvironment *cntrl) = 0; | ||
}; | ||
|
||
// FIXME: actually serialize, and replace this with a string | ||
using SerializedSSCSMEvent = std::unique_ptr<ISSCSMEvent>; | ||
|
||
template <typename T> | ||
inline SerializedSSCSMEvent serializeSSCSMEvent(const T &event) | ||
{ | ||
static_assert(std::is_base_of_v<ISSCSMEvent, T>); | ||
|
||
return std::make_unique<T>(event); | ||
} | ||
|
||
inline std::unique_ptr<ISSCSMEvent> deserializeSSCSMEvent(SerializedSSCSMEvent event_serialized) | ||
{ | ||
// The actual deserialization will have to use a type tag, and then choose | ||
// the appropriate deserializer. | ||
return event_serialized; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
// SPDX-FileCopyrightText: 2024 Luanti authors | ||
// | ||
// SPDX-License-Identifier: LGPL-2.1-or-later | ||
|
||
#pragma once | ||
|
||
#include "exceptions.h" | ||
#include <memory> | ||
#include <type_traits> | ||
|
||
class SSCSMController; | ||
class Client; | ||
|
||
struct ISSCSMAnswer | ||
{ | ||
virtual ~ISSCSMAnswer() = default; | ||
}; | ||
|
||
// FIXME: actually serialize, and replace this with a string | ||
using SerializedSSCSMAnswer = std::unique_ptr<ISSCSMAnswer>; | ||
|
||
// Request made by the sscsm env to the main env. | ||
struct ISSCSMRequest | ||
{ | ||
virtual ~ISSCSMRequest() = default; | ||
|
||
virtual SerializedSSCSMAnswer exec(Client *client) = 0; | ||
}; | ||
|
||
// FIXME: actually serialize, and replace this with a string | ||
using SerializedSSCSMRequest = std::unique_ptr<ISSCSMRequest>; | ||
|
||
template <typename T> | ||
inline SerializedSSCSMRequest serializeSSCSMRequest(const T &request) | ||
{ | ||
static_assert(std::is_base_of_v<ISSCSMRequest, T>); | ||
|
||
return std::make_unique<T>(request); | ||
} | ||
|
||
template <typename T> | ||
inline T deserializeSSCSMAnswer(SerializedSSCSMAnswer answer_serialized) | ||
{ | ||
static_assert(std::is_base_of_v<ISSCSMAnswer, T>); | ||
|
||
// dynamic cast in place of actual deserialization | ||
auto ptr = dynamic_cast<T *>(answer_serialized.get()); | ||
if (!ptr) { | ||
throw SerializationError("deserializeSSCSMAnswer failed"); | ||
} | ||
return std::move(*ptr); | ||
} | ||
|
||
template <typename T> | ||
inline SerializedSSCSMAnswer serializeSSCSMAnswer(T answer) | ||
{ | ||
static_assert(std::is_base_of_v<ISSCSMAnswer, T>); | ||
|
||
return std::make_unique<T>(std::move(answer)); | ||
} | ||
|
||
inline std::unique_ptr<ISSCSMRequest> deserializeSSCSMRequest(SerializedSSCSMRequest request_serialized) | ||
{ | ||
// The actual deserialization will have to use a type tag, and then choose | ||
// the appropriate deserializer. | ||
return request_serialized; | ||
} |
Oops, something went wrong.