Files
EVEngine/src/modules/network/NetRpc.cpp
T
西风逍遥游 d75e3bcf0d network: reliable UDP transport, RPC and multi-peer host
- UdpLink: reliable/unreliable/unreliable-ordered UDP with ACK/retransmit,
  fragmentation, heartbeat and loss simulation; main-thread pump routing
- NetRpc: u16 msgId + payload envelope, C++ handlers and script closures
- NetHost: shared-socket multi-peer routing with auto peer ids and lifecycle
  events (peerconn/peerdisconn)
- NetReader/NetWriter: typed little-endian serialization primitives
- TcpSocket: queued sends with partial-write/would-block handling; connect
  timeout unit fix; UDP socket buffers raised to 1MiB
- Tests mirrored in test/network.cpp; docs: design spec + user module doc
2026-08-19 04:08:24 +08:00

89 lines
2.6 KiB
C++

#include "network/NetRpc.h"
#include "network/NetStream.h"
#include <simplesquirrel/simplesquirrel.hpp>
#include <cstring>
namespace eve::network {
namespace {
void callScriptFn(const ssq::Object& fn, const std::string& arg) {
if (fn.isEmpty()) return;
ssq::Function f = fn.toFunction();
if (f.isEmpty()) return;
HSQUIRRELVM raw = f.getHandle();
SQInteger top = sq_gettop(raw);
sq_pushobject(raw, f.getRaw());
sq_pushroottable(raw);
ssq::detail::pushValue(raw, arg);
if (SQ_SUCCEEDED(sq_call(raw, 2, SQFalse, SQTrue))) {
// discard result
}
sq_settop(raw, top);
}
} // namespace
NetRpc::NetRpc(UdpLink* link) : link_(link) {
if (link_) {
link_->setMessageHandler(
[this](UdpLink::MsgType type, uint8_t channel, const char* data, size_t n) {
onLinkMessage(type, channel, data, n);
});
}
}
NetRpc::~NetRpc() {
if (link_) link_->setMessageHandler(nullptr);
}
void NetRpc::call(uint16_t msgId, const void* data, size_t n, bool reliable) {
if (!link_ || (data == nullptr && n > 0)) return;
std::vector<char> env;
env.push_back(static_cast<char>(msgId & 0xff));
env.push_back(static_cast<char>((msgId >> 8) & 0xff));
const char* p = static_cast<const char*>(data);
env.insert(env.end(), p, p + n);
link_->send(reliable ? UdpLink::MsgType::Reliable : UdpLink::MsgType::Unreliable, 0,
env.data(), env.size());
}
bool NetRpc::callString(uint16_t msgId, const std::string& payload, bool reliable) {
if (!link_) return false;
call(msgId, payload.data(), payload.size(), reliable);
return true;
}
void NetRpc::registerHandler(uint16_t msgId, Handler h) {
handlers_[msgId] = std::move(h);
}
void NetRpc::registerScript(uint16_t msgId, ssq::Object fn) {
if (fn.isEmpty()) return;
scriptHandlers_[msgId] = fn;
}
void NetRpc::onLinkMessage(UdpLink::MsgType type, uint8_t channel,
const char* data, size_t n) {
(void)type;
if (channel != 0 || n < 2) return;
const uint16_t msgId = static_cast<uint16_t>(uint8_t(data[0])) |
(static_cast<uint16_t>(uint8_t(data[1])) << 8);
const char* payload = data + 2;
const size_t payloadLen = n - 2;
auto sit = scriptHandlers_.find(msgId);
if (sit != scriptHandlers_.end()) {
callScriptFn(sit->second, std::string(payload, payloadLen));
return;
}
auto it = handlers_.find(msgId);
if (it == handlers_.end()) return;
NetReader reader(payload, payloadLen);
it->second(reader);
}
} // namespace eve::network