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/identity.cpp | 7 +++++ src/network.cpp | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- src/network.h | 26 +++++++++++++++- 3 files changed, 123 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/identity.cpp b/src/identity.cpp index 00abf0b..61059ab 100644 --- a/src/identity.cpp +++ b/src/identity.cpp @@ -46,6 +46,13 @@ optional Identity::owner() const return p->owner; } +const Identity & Identity::finalOwner() const +{ + if (p->owner) + return p->owner->finalOwner(); + return *this; +} + Stored Identity::keyMessage() const { return p->keyMessage; 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) diff --git a/src/network.h b/src/network.h index e07e020..07b5363 100644 --- a/src/network.h +++ b/src/network.h @@ -23,6 +23,8 @@ using std::variant; using std::vector; using std::weak_ptr; +using std::enable_shared_from_this; + namespace chrono = std::chrono; using chrono::steady_clock; @@ -49,11 +51,31 @@ struct Server::Peer Storage tempStorage; PartialStorage partStorage; + shared_ptr lpeer = nullptr; + void send(const struct TransportHeader &, const vector &) const; void updateIdentity(struct ReplyBuilder &); void updateChannel(struct ReplyBuilder &); }; +struct Peer::Priv : enable_shared_from_this +{ + weak_ptr speer; + weak_ptr list; + size_t listIndex; + + void notifyWatchers(); +}; + +struct PeerList::Priv : enable_shared_from_this +{ + mutex dataMutex; + vector> peers; + vector> watchers; + + void push(const shared_ptr &); +}; + struct TransportHeader { enum class Type { @@ -118,7 +140,9 @@ struct Server::Priv thread threadListen; thread threadAnnounce; - vector> peers; + vector> peers; + PeerList plist; + vector outgoing; vector> waiting; -- cgit v1.2.3