Files
EVEngine/src/modules/network/NetHost.cpp
T

128 lines
3.8 KiB
C++

#include "network/NetHost.h"
#include "data/ByteData.h"
#include "network/Network.h"
#include "network/UdpSocket.h"
#include "platform_event/PlatformEvent.h"
namespace eve::network {
NetHost::NetHost(Network* net) : net_(net) {}
NetHost::~NetHost() {
if (net_ && sock_) net_->unbindUdpHost(sock_);
for (UdpLink* l : owned_) delete l;
owned_.clear();
byAddr_.clear();
byId_.clear();
delete sock_;
sock_ = nullptr;
}
bool NetHost::start(uint16_t port) {
if (!net_ || sock_) return false;
sock_ = net_->newUdp();
if (!sock_ || !sock_->bind(port)) {
delete sock_;
sock_ = nullptr;
return false;
}
net_->bindUdpHost(sock_, this);
return true;
}
void NetHost::setLossRate(float rate) {
lossRate_ = rate;
for (auto& kv : byId_) kv.second->setLossRate(rate);
}
void NetHost::setTimeoutMs(int ms) {
timeoutMs_ = ms;
for (auto& kv : byId_) kv.second->setTimeoutMs(ms);
}
void NetHost::onDatagram(const std::vector<char>& bytes, const std::string& from) {
auto it = byAddr_.find(from);
if (it != byAddr_.end()) {
it->second->onDatagram(bytes, from);
return;
}
auto* link = new UdpLink(net_, sock_);
link->setRemoteString(from);
const uint32_t id = nextPeerId_++;
link->setPeerId(id);
link->setLossRate(lossRate_);
link->setTimeoutMs(timeoutMs_);
link->setMessageHandler(
[this, id](UdpLink::MsgType t, uint8_t ch, const char* d, size_t n) {
if (onMessage_) onMessage_(id, t, ch, d, n);
});
link->setDisconnectHandler([this, id](const std::string&) {
pendingRemove_.push_back(id);
});
byAddr_[from] = link;
byId_[id] = link;
owned_.push_back(link);
emitPeerConnected(id);
link->onDatagram(bytes, from);
}
void NetHost::pump(int64_t nowMs) {
pendingRemove_.clear();
for (auto& kv : byId_) kv.second->pump(nowMs);
for (uint32_t id : pendingRemove_) emitPeerDisconnected(id);
}
UdpLink* NetHost::linkByPeerId(uint32_t peerId) const {
auto it = byId_.find(peerId);
return it == byId_.end() ? nullptr : it->second;
}
void NetHost::sendTo(uint32_t peerId, UdpLink::MsgType type, uint8_t channel,
const void* data, size_t n) {
UdpLink* link = linkByPeerId(peerId);
if (link) link->send(type, channel, data, n);
}
bool NetHost::sendStringTo(uint32_t peerId, UdpLink::MsgType type, uint8_t channel,
const std::string& s) {
UdpLink* link = linkByPeerId(peerId);
return link && link->sendString(type, channel, s);
}
void NetHost::emitPeerConnected(uint32_t peerId) {
if (onConnect_) onConnect_(peerId);
if (net_) {
auto* ev = eve::ModuleManager::getInstance<eve::platform_event::PlatformEvent>("PlatformEvent");
if (ev) {
std::vector<eve::platform_event::Variant> args;
args.push_back(eve::platform_event::Variant::makeInt(peerId));
ev->push(new eve::platform_event::Message("peerconn", args));
}
}
}
void NetHost::emitPeerDisconnected(uint32_t peerId) {
auto it = byId_.find(peerId);
if (it == byId_.end()) return; // already removed
UdpLink* link = it->second;
byId_.erase(it);
for (auto a = byAddr_.begin(); a != byAddr_.end(); ++a) {
if (a->second == link) {
byAddr_.erase(a);
break;
}
}
if (onDisconnect_) onDisconnect_(peerId);
if (net_) {
auto* ev = eve::ModuleManager::getInstance<eve::platform_event::PlatformEvent>("PlatformEvent");
if (ev) {
std::vector<eve::platform_event::Variant> args;
args.push_back(eve::platform_event::Variant::makeInt(peerId));
ev->push(new eve::platform_event::Message("peerdisconn", args));
}
}
}
} // namespace eve::network