factor IPC out of server RPC
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
|
||||
#include <ipc/IpcMessage.h>
|
||||
#include <rpc/RpcValue.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
// Кодек, который знает, как упаковать/распаковать RPC-запросы/ответы
|
||||
// в/IpcMessage. Живёт в IPC-слое, но опирается на типы RPC-ядра
|
||||
// (RpcValue/RpcArgs).
|
||||
namespace IpcCodec {
|
||||
|
||||
// Запрос: имя метода + вектор аргументов.
|
||||
inline IpcMessage encodeRequest(const std::string& method,
|
||||
const RpcArgs& args) {
|
||||
IpcMessage msg;
|
||||
|
||||
// имя метода
|
||||
msg.add(method);
|
||||
|
||||
// аргументы (PoC: только int)
|
||||
for (const auto& a : args) {
|
||||
msg.add(a.asInt());
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
inline void decodeRequest(const IpcMessage& msg,
|
||||
std::string& method,
|
||||
RpcArgs& args) {
|
||||
IpcMessage copy = msg;
|
||||
|
||||
// имя метода
|
||||
method = copy.get<std::string>();
|
||||
|
||||
// аргументы (PoC: только int, читаем до конца сообщения)
|
||||
args.clear();
|
||||
while (!copy.empty()) {
|
||||
int v = copy.get<int>();
|
||||
args.emplace_back(RpcValue::fromInt(v));
|
||||
}
|
||||
}
|
||||
|
||||
// Ответ: одно RpcValue (PoC: считаем, что это int).
|
||||
inline IpcMessage encodeResponse(const RpcValue& result) {
|
||||
IpcMessage msg;
|
||||
msg.add(result.asInt()); // PoC: только int
|
||||
return msg;
|
||||
}
|
||||
|
||||
inline RpcValue decodeResponse(const IpcMessage& msg) {
|
||||
IpcMessage copy = msg;
|
||||
int v = copy.get<int>();
|
||||
return RpcValue::fromInt(v);
|
||||
}
|
||||
|
||||
} // namespace IpcCodec
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include <ipc/IpcChannel.h>
|
||||
#include <ipc/IpcCodec.h>
|
||||
#include <rpc/RpcInvoker.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
// Серверный диспетчер, который получает IpcMessage с канала,
|
||||
// декодирует его в RPC-вызов, вызывает RpcInvoker и шлёт ответ.
|
||||
class IpcDispatcher {
|
||||
public:
|
||||
IpcDispatcher(IpcChannel& ch, RpcInvoker& invoker)
|
||||
: channel_(ch)
|
||||
, invoker_(invoker) {}
|
||||
|
||||
// Обработать один запрос. Возвращает false, если получили "пустое"
|
||||
// сообщение и цикл стоит завершить.
|
||||
bool handleOnce() {
|
||||
IpcMessage req = channel_.receive();
|
||||
if (req.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string method;
|
||||
RpcArgs args;
|
||||
IpcCodec::decodeRequest(req, method, args);
|
||||
|
||||
RpcValue result = invoker_.dispatch(method, args);
|
||||
IpcMessage resp = IpcCodec::encodeResponse(result);
|
||||
channel_.send(resp);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Простой цикл обработки до тех пор, пока канал не вернёт пустое сообщение.
|
||||
void loop() {
|
||||
while (handleOnce()) {
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
IpcChannel& channel_;
|
||||
RpcInvoker& invoker_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <ipc/IpcChannel.h>
|
||||
#include <ipc/IpcCodec.h>
|
||||
#include <rpc/RpcValue.h>
|
||||
|
||||
class ProxyMarshaller {
|
||||
@@ -9,22 +10,15 @@ public:
|
||||
|
||||
// Базовый type-erased вызов: принимает вектор RpcValue и возвращает RpcValue.
|
||||
RpcValue call(const std::string& method, const RpcArgs& args) {
|
||||
IpcMessage msg;
|
||||
|
||||
// имя метода
|
||||
msg.add(method);
|
||||
|
||||
// аргументы (PoC: только int)
|
||||
for (const auto& a : args) {
|
||||
msg.add(a.asInt());
|
||||
}
|
||||
// упаковать запрос в IpcMessage
|
||||
IpcMessage msg = IpcCodec::encodeRequest(method, args);
|
||||
|
||||
// отправить
|
||||
channel.send(msg);
|
||||
|
||||
// получить ответ
|
||||
// получить ответ и распаковать
|
||||
IpcMessage resp = channel.receive();
|
||||
return RpcValue::fromInt(resp.get<int>());
|
||||
return IpcCodec::decodeResponse(resp);
|
||||
}
|
||||
|
||||
// Удобный шаблонный хелпер для сгенерированных прокси.
|
||||
|
||||
Reference in New Issue
Block a user