summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Smrž <roman.smrz@seznam.cz>2023-05-06 17:09:32 +0200
committerRoman Smrž <roman.smrz@seznam.cz>2023-05-06 18:54:24 +0200
commit25a1ba71e3cf4250489291f688423963aa603498 (patch)
treefb1e23060b810237316f4cde6524c0b1a66d5d0e
parent07f61b1ad6363cd471b7dab3f94c3160636fd6a0 (diff)
Server and services configuration using separate objects
-rw-r--r--include/erebos/attach.h2
-rw-r--r--include/erebos/contact.h6
-rw-r--r--include/erebos/message.h19
-rw-r--r--include/erebos/network.h37
-rw-r--r--include/erebos/pairing.h41
-rw-r--r--include/erebos/service.h6
-rw-r--r--include/erebos/sync.h6
-rw-r--r--src/attach.cpp6
-rw-r--r--src/contact.cpp15
-rw-r--r--src/main.cpp50
-rw-r--r--src/message.cpp18
-rw-r--r--src/message.h6
-rw-r--r--src/network.cpp15
-rw-r--r--src/network.h3
-rw-r--r--src/pairing.cpp37
-rw-r--r--src/service.cpp4
-rw-r--r--src/sync.cpp27
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())