From 0e9e9c4d233a331e10dfb2db889fe437d0911ba2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Smr=C5=BE?= Date: Sun, 16 Feb 2020 20:18:32 +0100 Subject: Peer list in public API --- src/network.cpp | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 91 insertions(+), 4 deletions(-) (limited to 'src/network.cpp') diff --git a/src/network.cpp b/src/network.cpp index f778bf9..f3a3651 100644 --- a/src/network.cpp +++ b/src/network.cpp @@ -6,12 +6,14 @@ #include #include +#include #include #include #include using std::holds_alternative; using std::scoped_lock; +using std::to_string; using std::unique_lock; using namespace erebos; @@ -23,6 +25,87 @@ Server::Server(const Identity & self): Server::~Server() = default; +PeerList & Server::peerList() const +{ + return p->plist; +} + + +Peer::Peer(const shared_ptr & p): p(p) {} +Peer::~Peer() = default; + +string Peer::name() const +{ + if (auto speer = p->speer.lock()) { + if (holds_alternative(speer->identity)) + if (auto name = std::get(speer->identity).finalOwner().name()) + return *name; + if (holds_alternative>(speer->identity)) + return string(std::get>(speer->identity)->ref.digest()); + + char buf[16]; + if (inet_ntop(AF_INET, &speer->addr.sin_addr, buf, sizeof(buf))) + return string(buf) + ":" + to_string(ntohs(speer->addr.sin_port)); + return ""; + } + return ""; +} + +optional Peer::identity() const +{ + if (auto speer = p->speer.lock()) + if (holds_alternative(speer->identity)) + return std::get(speer->identity); + return nullopt; +} + +void Peer::Priv::notifyWatchers() +{ + if (auto slist = list.lock()) { + Peer p(shared_from_this()); + for (const auto & w : slist->watchers) + w(listIndex, &p); + } +} + + +PeerList::PeerList(): p(new Priv) {} +PeerList::PeerList(const shared_ptr & p): p(p) {} +PeerList::~PeerList() = default; + +void PeerList::Priv::push(const shared_ptr & speer) +{ + scoped_lock lock(dataMutex); + size_t s = peers.size(); + + speer->lpeer.reset(new Peer::Priv); + speer->lpeer->speer = speer; + speer->lpeer->list = shared_from_this(); + speer->lpeer->listIndex = s; + + Peer p(speer->lpeer); + + peers.push_back(speer->lpeer); + for (const auto & w : watchers) + w(s, &p); +} + +size_t PeerList::size() const +{ + return p->peers.size(); +} + +Peer PeerList::at(size_t i) const +{ + return Peer(p->peers.at(i)); +} + +void PeerList::onUpdate(function w) +{ + p->watchers.push_back(w); +} + + Server::Priv::Priv(const Identity & self): self(self) { @@ -174,15 +257,16 @@ Server::Peer & Server::Priv::getPeer(const sockaddr_in & paddr) return *peer; auto st = self.ref()->storage().deriveEphemeralStorage(); - Peer * peer = new Peer { + shared_ptr peer(new Peer { .server = *this, .addr = paddr, .identity = monostate(), .channel = monostate(), .tempStorage = st, .partStorage = st.derivePartialStorage(), - }; - peers.emplace_back(peer); + }); + peers.push_back(peer); + plist.p->push(peer); return *peer; } @@ -328,8 +412,11 @@ void Server::Peer::updateIdentity(ReplyBuilder & reply) { if (holds_alternative>(identity)) if (auto ref = std::get>(identity)->check(&reply.header)) - if (auto id = Identity::load(*ref)) + if (auto id = Identity::load(*ref)) { identity.emplace(*id); + if (lpeer) + lpeer->notifyWatchers(); + } } void Server::Peer::updateChannel(ReplyBuilder & reply) -- cgit v1.2.3