diff options
author | Roman Smrž <roman.smrz@seznam.cz> | 2023-05-06 17:09:32 +0200 |
---|---|---|
committer | Roman Smrž <roman.smrz@seznam.cz> | 2023-05-06 18:54:24 +0200 |
commit | 25a1ba71e3cf4250489291f688423963aa603498 (patch) | |
tree | fb1e23060b810237316f4cde6524c0b1a66d5d0e | |
parent | 07f61b1ad6363cd471b7dab3f94c3160636fd6a0 (diff) |
Server and services configuration using separate objects
-rw-r--r-- | include/erebos/attach.h | 2 | ||||
-rw-r--r-- | include/erebos/contact.h | 6 | ||||
-rw-r--r-- | include/erebos/message.h | 19 | ||||
-rw-r--r-- | include/erebos/network.h | 37 | ||||
-rw-r--r-- | include/erebos/pairing.h | 41 | ||||
-rw-r--r-- | include/erebos/service.h | 6 | ||||
-rw-r--r-- | include/erebos/sync.h | 6 | ||||
-rw-r--r-- | src/attach.cpp | 6 | ||||
-rw-r--r-- | src/contact.cpp | 15 | ||||
-rw-r--r-- | src/main.cpp | 50 | ||||
-rw-r--r-- | src/message.cpp | 18 | ||||
-rw-r--r-- | src/message.h | 6 | ||||
-rw-r--r-- | src/network.cpp | 15 | ||||
-rw-r--r-- | src/network.h | 3 | ||||
-rw-r--r-- | src/pairing.cpp | 37 | ||||
-rw-r--r-- | src/service.cpp | 4 | ||||
-rw-r--r-- | src/sync.cpp | 27 |
17 files changed, 173 insertions, 125 deletions
diff --git a/include/erebos/attach.h b/include/erebos/attach.h index dab0110..6ea3d64 100644 --- a/include/erebos/attach.h +++ b/include/erebos/attach.h @@ -21,7 +21,7 @@ struct AttachIdentity; class AttachService : public PairingService<AttachIdentity> { public: - AttachService(); + AttachService(Config &&, const Server &); virtual ~AttachService(); UUID uuid() const override; diff --git a/include/erebos/contact.h b/include/erebos/contact.h index 24a4c89..963e22a 100644 --- a/include/erebos/contact.h +++ b/include/erebos/contact.h @@ -73,20 +73,18 @@ struct ContactAccepted; class ContactService : public PairingService<ContactAccepted> { public: - ContactService(); + ContactService(Config &&, const Server &); virtual ~ContactService(); UUID uuid() const override; - void serverStarted(const class Server &) override; - void request(const Peer &); protected: virtual Stored<ContactAccepted> handlePairingComplete(const Peer &) override; virtual void handlePairingResult(Context &, Stored<ContactAccepted>) override; - const class Server * server; + const Server & server; }; template<class T> class Signed; diff --git a/include/erebos/message.h b/include/erebos/message.h index 70a11bc..436c0ed 100644 --- a/include/erebos/message.h +++ b/include/erebos/message.h @@ -74,21 +74,30 @@ private: class DirectMessageService : public Service { public: - DirectMessageService(); + using ThreadWatcher = std::function<void(const DirectMessageThread &, ssize_t, ssize_t)>; + + class Config + { + public: + Config & onUpdate(ThreadWatcher); + + private: + friend class DirectMessageService; + vector<ThreadWatcher> watchers; + }; + + DirectMessageService(Config &&, const Server &); virtual ~DirectMessageService(); UUID uuid() const override; void handle(Context &) override; - typedef std::function<void(const DirectMessageThread &, ssize_t, ssize_t)> ThreadWatcher; - void onUpdate(ThreadWatcher); DirectMessageThread thread(const Identity &); DirectMessage send(const Identity &, const Peer &, const std::string &); private: - struct Priv; - unique_ptr<Priv> p; + const Config config; }; } diff --git a/include/erebos/network.h b/include/erebos/network.h index b47efee..c211fbf 100644 --- a/include/erebos/network.h +++ b/include/erebos/network.h @@ -10,11 +10,16 @@ struct sockaddr_in; namespace erebos { +using std::vector; +using std::unique_ptr; + +class ServerConfig; + class Server { struct Priv; public: - Server(const Head<LocalState> &, std::vector<std::unique_ptr<Service>> &&); + Server(const Head<LocalState> &, ServerConfig &&); Server(const std::shared_ptr<Priv> &); ~Server(); @@ -36,12 +41,42 @@ private: const std::shared_ptr<Priv> p; }; +class ServerConfig +{ +public: + ServerConfig() = default; + ServerConfig(const ServerConfig &) = delete; + ServerConfig(ServerConfig &&) = default; + ServerConfig & operator=(const ServerConfig &) = delete; + ServerConfig & operator=(ServerConfig &&) = default; + + template<class S> + typename S::Config & service(); + +private: + friend class Server; + vector<function<unique_ptr<Service>(const Server &)>> services; +}; + template<class S> S & Server::svc() { return dynamic_cast<S&>(svcHelper(typeid(S))); } +template<class S> +typename S::Config & ServerConfig::service() +{ + auto config = make_shared<typename S::Config>(); + auto & configRef = *config; + + services.push_back([config = move(config)](const Server & server) { + return make_unique<S>(move(*config), server); + }); + + return configRef; +} + class Peer { public: diff --git a/include/erebos/pairing.h b/include/erebos/pairing.h index ea349a9..71c9288 100644 --- a/include/erebos/pairing.h +++ b/include/erebos/pairing.h @@ -29,11 +29,6 @@ using std::vector; class PairingServiceBase : public Service { public: - virtual ~PairingServiceBase(); - - typedef function<void(const Peer &)> RequestInitHook; - void onRequestInit(RequestInitHook); - enum class Outcome { Success, @@ -44,12 +39,28 @@ public: Stale, }; - typedef function<future<bool>(const Peer &, string, future<Outcome> &&)> ConfirmHook; - void onResponse(ConfirmHook); - void onRequest(ConfirmHook); + using RequestInitHook = function<void(const Peer &)>; + using ConfirmHook = function<future<bool>(const Peer &, string, future<Outcome> &&)>; + using RequestNonceFailedHook = function<void(const Peer &)>; + + class Config + { + public: + Config & onRequestInit(RequestInitHook); + Config & onResponse(PairingServiceBase::ConfirmHook); + Config & onRequest(PairingServiceBase::ConfirmHook); + Config & onRequestNonceFailed(RequestNonceFailedHook); + + private: + friend class PairingServiceBase; + RequestInitHook requestInitHook; + ConfirmHook responseHook; + ConfirmHook requestHook; + RequestNonceFailedHook requestNonceFailedHook; + }; - typedef function<void(const Peer &)> RequestNonceFailedHook; - void onRequestNonceFailed(RequestNonceFailedHook); + PairingServiceBase(Config &&); + virtual ~PairingServiceBase(); protected: void requestPairing(UUID serviceId, const Peer & peer); @@ -62,11 +73,7 @@ private: const vector<uint8_t> & nonce1, const vector<uint8_t> & nonce2); static string confirmationNumber(const vector<uint8_t> &); - RequestInitHook requestInitHook; - ConfirmHook responseHook; - ConfirmHook requestHook; - RequestNonceFailedHook requestNonceFailedHook; - + const Config config; optional<Ref> result; enum class StatePhase { @@ -99,6 +106,10 @@ private: template<class Result> class PairingService : public PairingServiceBase { +public: + PairingService(Config && config): + PairingServiceBase(move(config)) {} + protected: virtual Stored<Result> handlePairingComplete(const Peer &) = 0; virtual void handlePairingResult(Context &, Stored<Result>) = 0; diff --git a/include/erebos/service.h b/include/erebos/service.h index 7a9a366..7e037f8 100644 --- a/include/erebos/service.h +++ b/include/erebos/service.h @@ -7,12 +7,16 @@ namespace erebos { +class Server; + class Service { public: Service(); virtual ~Service(); + using Config = monostate; + class Context { public: @@ -35,8 +39,6 @@ public: virtual UUID uuid() const = 0; virtual void handle(Context &) = 0; - - virtual void serverStarted(const class Server &); }; } diff --git a/include/erebos/sync.h b/include/erebos/sync.h index 1ab927d..662a558 100644 --- a/include/erebos/sync.h +++ b/include/erebos/sync.h @@ -15,19 +15,17 @@ using std::vector; class SyncService : public Service { public: - SyncService(); + SyncService(Config &&, const Server &); virtual ~SyncService(); UUID uuid() const override; void handle(Context &) override; - void serverStarted(const class Server &) override; - private: void peerWatcher(size_t, const class Peer *); void localStateWatcher(const vector<Ref> &); - const class Server * server; + const Server & server; Watched<vector<Ref>> watchedLocal; }; diff --git a/src/attach.cpp b/src/attach.cpp index 2bc2b74..4bf06b1 100644 --- a/src/attach.cpp +++ b/src/attach.cpp @@ -14,7 +14,11 @@ using std::runtime_error; static const UUID myUUID("4995a5f9-2d4d-48e9-ad3b-0bf1c2a1be7f"); -AttachService::AttachService() = default; +AttachService::AttachService(Config && config, const Server &): + PairingService(move(config)) +{ +} + AttachService::~AttachService() = default; UUID AttachService::uuid() const diff --git a/src/contact.cpp b/src/contact.cpp index 787831c..0050f95 100644 --- a/src/contact.cpp +++ b/src/contact.cpp @@ -142,7 +142,12 @@ Ref ContactData::store(const Storage & st) const return st.storeObject(Record(std::move(items))); } -ContactService::ContactService() = default; +ContactService::ContactService(Config && config, const Server & s): + PairingService(move(config)), + server(s) +{ +} + ContactService::~ContactService() = default; UUID ContactService::uuid() const @@ -150,12 +155,6 @@ UUID ContactService::uuid() const return serviceUUID; } -void ContactService::serverStarted(const Server & s) -{ - PairingService<ContactAccepted>::serverStarted(s); - server = &s; -} - void ContactService::request(const Peer & peer) { requestPairing(serviceUUID, peer); @@ -163,7 +162,7 @@ void ContactService::request(const Peer & peer) Stored<ContactAccepted> ContactService::handlePairingComplete(const Peer & peer) { - server->localHead().update([&] (const Stored<LocalState> & local) { + server.localHead().update([&] (const Stored<LocalState> & local) { auto cdata = local.ref().storage().store(ContactData { .prev = {}, .identity = peer.identity()->finalOwner().data(), diff --git a/src/main.cpp b/src/main.cpp index aa70c48..0052c8e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -257,39 +257,39 @@ future<bool> confirmPairing(string prefix, const Peer & peer, string confirm, fu void startServer(const vector<string> &) { - vector<unique_ptr<Service>> services; - using namespace std::placeholders; - auto atts = make_unique<AttachService>(); - atts->onRequest(bind(confirmPairing, "attach-request", _1, _2, _3)); - atts->onResponse(bind(confirmPairing, "attach-response", _1, _2, _3)); - services.push_back(move(atts)); + ServerConfig config; - auto conts = make_unique<ContactService>(); - conts->onRequest(bind(confirmPairing, "contact-request", _1, _2, _3)); - conts->onResponse(bind(confirmPairing, "contact-response", _1, _2, _3)); - services.push_back(move(conts)); + config.service<AttachService>() + .onRequest(bind(confirmPairing, "attach-request", _1, _2, _3)) + .onResponse(bind(confirmPairing, "attach-response", _1, _2, _3)) + ; - auto dms = make_unique<DirectMessageService>(); - dms->onUpdate([](const DirectMessageThread & thread, ssize_t, ssize_t) { - ostringstream ss; + config.service<ContactService>() + .onRequest(bind(confirmPairing, "contact-request", _1, _2, _3)) + .onResponse(bind(confirmPairing, "contact-response", _1, _2, _3)) + ; - string name = "<unnamed>"; - if (auto opt = thread.peer().name()) - name = *opt; + config.service<DirectMessageService>() + .onUpdate([](const DirectMessageThread & thread, ssize_t, ssize_t) { + ostringstream ss; - ss << "dm-received" - << " from " << name - << " text " << thread.at(0).text() - ; - printLine(ss.str()); - }); - services.push_back(move(dms)); + string name = "<unnamed>"; + if (auto opt = thread.peer().name()) + name = *opt; + + ss << "dm-received" + << " from " << name + << " text " << thread.at(0).text() + ; + printLine(ss.str()); + }) + ; - services.push_back(make_unique<SyncService>()); + config.service<SyncService>(); - server.emplace(*h, move(services)); + server.emplace(*h, move(config)); server->peerList().onUpdate([](size_t idx, const Peer * peer) { size_t i = 0; diff --git a/src/message.cpp b/src/message.cpp index eb1212c..fd8e847 100644 --- a/src/message.cpp +++ b/src/message.cpp @@ -202,8 +202,14 @@ const Identity & DirectMessageThread::peer() const } -DirectMessageService::DirectMessageService(): - p(new Priv) +DirectMessageService::Config & DirectMessageService::Config::onUpdate(ThreadWatcher w) +{ + watchers.push_back(w); + return *this; +} + +DirectMessageService::DirectMessageService(Config && c, const Server &): + config(move(c)) {} DirectMessageService::~DirectMessageService() = default; @@ -229,16 +235,10 @@ void DirectMessageService::handle(Context & ctx) lock.unlock(); - for (const auto & w : p->watchers) + for (const auto & w : config.watchers) w(dmt, -1, -1); } -void DirectMessageService::onUpdate(ThreadWatcher w) -{ - scoped_lock l(p->watcherLock); - p->watchers.push_back(w); -} - DirectMessageThread DirectMessageService::thread(const Identity & peer) { scoped_lock lock(threadLock); diff --git a/src/message.h b/src/message.h index efdec8f..c3c6ba4 100644 --- a/src/message.h +++ b/src/message.h @@ -49,10 +49,4 @@ struct DirectMessageThread::Iterator::Priv vector<Stored<DirectMessageData>> next; }; -struct DirectMessageService::Priv -{ - vector<ThreadWatcher> watchers; - mutex watcherLock; -}; - } diff --git a/src/network.cpp b/src/network.cpp index dafab67..5c268ae 100644 --- a/src/network.cpp +++ b/src/network.cpp @@ -24,11 +24,12 @@ using std::unique_lock; using namespace erebos; -Server::Server(const Head<LocalState> & head, vector<unique_ptr<Service>> && svcs): - p(new Priv(head, *head->identity(), std::move(svcs))) +Server::Server(const Head<LocalState> & head, ServerConfig && config): + p(new Priv(head, *head->identity())) { - for (const auto & s : p->services) - s->serverStarted(*this); + p->services.reserve(config.services.size()); + for (const auto & ctor : config.services) + p->services.emplace_back(ctor(*this)); } Server:: Server(const std::shared_ptr<Priv> & ptr): @@ -223,13 +224,11 @@ void PeerList::onUpdate(function<void(size_t, const Peer *)> w) } -Server::Priv::Priv(const Head<LocalState> & local, const Identity & self, - vector<unique_ptr<Service>> && svcs): +Server::Priv::Priv(const Head<LocalState> & local, const Identity & self): self(self), // Watching needs to start after self is initialized localState(local.behavior()), - localHead(local.watch(std::bind(&Priv::handleLocalHeadChange, this, std::placeholders::_1))), - services(std::move(svcs)) + localHead(local.watch(std::bind(&Priv::handleLocalHeadChange, this, std::placeholders::_1))) { struct ifaddrs * raddrs; if (getifaddrs(&raddrs) < 0) diff --git a/src/network.h b/src/network.h index 5a656cb..4d232b3 100644 --- a/src/network.h +++ b/src/network.h @@ -143,8 +143,7 @@ struct WaitingRef struct Server::Priv { - Priv(const Head<LocalState> & local, const Identity & self, - vector<unique_ptr<Service>> && svcs); + Priv(const Head<LocalState> & local, const Identity & self); ~Priv(); shared_ptr<Priv> getptr(); diff --git a/src/pairing.cpp b/src/pairing.cpp index d2d71f5..dca5b03 100644 --- a/src/pairing.cpp +++ b/src/pairing.cpp @@ -21,6 +21,11 @@ using std::scoped_lock; using std::thread; using std::unique_lock; +PairingServiceBase::PairingServiceBase(Config && c): + config(move(c)) +{ +} + PairingServiceBase::~PairingServiceBase() { // There may be some threads in waitForConfirmation waiting on client @@ -35,28 +40,28 @@ PairingServiceBase::~PairingServiceBase() } } -void PairingServiceBase::onRequestInit(RequestInitHook hook) +PairingServiceBase::Config & PairingServiceBase::Config::onRequestInit(RequestInitHook hook) { - lock_guard lock(stateLock); requestInitHook = hook; + return *this; } -void PairingServiceBase::onResponse(ConfirmHook hook) +PairingServiceBase::Config & PairingServiceBase::Config::onResponse(ConfirmHook hook) { - lock_guard lock(stateLock); responseHook = hook; + return *this; } -void PairingServiceBase::onRequest(ConfirmHook hook) +PairingServiceBase::Config & PairingServiceBase::Config::onRequest(ConfirmHook hook) { - lock_guard lock(stateLock); requestHook = hook; + return *this; } -void PairingServiceBase::onRequestNonceFailed(RequestNonceFailedHook hook) +PairingServiceBase::Config & PairingServiceBase::Config::onRequestNonceFailed(RequestNonceFailedHook hook) { - lock_guard lock(stateLock); requestNonceFailedHook = hook; + return *this; } void PairingServiceBase::handle(Context & ctx) @@ -99,8 +104,8 @@ void PairingServiceBase::handle(Context & ctx) } else if (state->phase != StatePhase::NoPairing) return; - if (requestInitHook) - requestInitHook(ctx.peer()); + if (config.requestInitHook) + config.requestInitHook(ctx.peer()); state->phase = StatePhase::PeerRequest; state->idReq = idReq; @@ -120,12 +125,12 @@ void PairingServiceBase::handle(Context & ctx) return; } - if (responseHook) { + if (config.responseHook) { string confirm = confirmationNumber(nonceDigest( *state->idReq, *state->idRsp, state->nonce, *response)); std::thread(&PairingServiceBase::waitForConfirmation, - this, ctx.peer(), state, confirm, responseHook).detach(); + this, ctx.peer(), state, confirm, config.responseHook).detach(); } state->phase = StatePhase::OurRequestConfirm; @@ -143,8 +148,8 @@ void PairingServiceBase::handle(Context & ctx) *state->idReq, *state->idRsp, *reqnonce, vector<uint8_t>()); if (check != state->peerCheck) { - if (requestNonceFailedHook) - requestNonceFailedHook(ctx.peer()); + if (config.requestNonceFailedHook) + config.requestNonceFailedHook(ctx.peer()); if (state->phase < StatePhase::PairingDone) { state->phase = StatePhase::PairingFailed; ctx.afterCommit([&]() { @@ -154,12 +159,12 @@ void PairingServiceBase::handle(Context & ctx) return; } - if (requestHook) { + if (config.requestHook) { string confirm = confirmationNumber(nonceDigest( *state->idReq, *state->idRsp, *reqnonce, state->nonce)); std::thread(&PairingServiceBase::waitForConfirmation, - this, ctx.peer(), state, confirm, requestHook).detach(); + this, ctx.peer(), state, confirm, config.requestHook).detach(); } state->phase = StatePhase::PeerRequestConfirm; diff --git a/src/service.cpp b/src/service.cpp index 397bebd..fc1ec5f 100644 --- a/src/service.cpp +++ b/src/service.cpp @@ -44,7 +44,3 @@ void Service::Context::runAfterCommitHooks() const for (const auto & hook : p->afterCommit) hook(); } - -void Service::serverStarted(const class Server &) -{ -} diff --git a/src/sync.cpp b/src/sync.cpp index 8263974..5680da6 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -9,7 +9,15 @@ using std::scoped_lock; static const UUID myUUID("a4f538d0-4e50-4082-8e10-7e3ec2af175d"); -SyncService::SyncService() = default; +SyncService::SyncService(Config &&, const Server & s): + server(s) +{ + server.peerList().onUpdate(std::bind(&SyncService::peerWatcher, this, + std::placeholders::_1, std::placeholders::_2)); + watchedLocal = server.localState().lens<vector<Ref>>().watch(std::bind(&SyncService::localStateWatcher, this, + std::placeholders::_1)); +} + SyncService::~SyncService() = default; UUID SyncService::uuid() const @@ -34,21 +42,12 @@ void SyncService::handle(Context & ctx) ); } -void SyncService::serverStarted(const Server & s) -{ - server = &s; - server->peerList().onUpdate(std::bind(&SyncService::peerWatcher, this, - std::placeholders::_1, std::placeholders::_2)); - watchedLocal = server->localState().lens<vector<Ref>>().watch(std::bind(&SyncService::localStateWatcher, this, - std::placeholders::_1)); -} - void SyncService::peerWatcher(size_t, const Peer * peer) { if (peer) { if (auto id = peer->identity()) { - if (id->finalOwner().sameAs(server->identity().finalOwner())) - for (const auto & r : server->localState().get().sharedRefs()) + if (id->finalOwner().sameAs(server.identity().finalOwner())) + for (const auto & r : server.localState().get().sharedRefs()) peer->send(myUUID, r); } } @@ -56,8 +55,8 @@ void SyncService::peerWatcher(size_t, const Peer * peer) void SyncService::localStateWatcher(const vector<Ref> & refs) { - const auto & plist = server->peerList(); - const Identity owner = server->identity().finalOwner(); + const auto & plist = server.peerList(); + const Identity owner = server.identity().finalOwner(); for (size_t i = 0; i < plist.size(); i++) if (auto id = plist.at(i).identity()) |