diff options
-rw-r--r-- | src/main.cpp | 93 | ||||
-rw-r--r-- | test/attach.test | 27 |
2 files changed, 118 insertions, 2 deletions
diff --git a/src/main.cpp b/src/main.cpp index bca802b..0c786e2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,23 +1,37 @@ +#include <erebos/attach.h> #include <erebos/identity.h> #include <erebos/network.h> #include <erebos/storage.h> #include <filesystem> #include <functional> +#include <future> #include <iostream> +#include <map> #include <memory> +#include <mutex> #include <optional> #include <sstream> +#include <stdexcept> #include <string> +#include <thread> #include <vector> using std::cerr; using std::cout; using std::endl; using std::function; +using std::future; +using std::invalid_argument; +using std::make_unique; +using std::map; +using std::mutex; using std::optional; using std::ostringstream; +using std::promise; +using std::scoped_lock; using std::string; +using std::thread; using std::unique_ptr; using std::vector; @@ -35,9 +49,28 @@ fs::path getErebosDir() return "./.erebos"; } +mutex outputMutex; +void printLine(const string & line) +{ + scoped_lock lock(outputMutex); + cout << line << std::endl; +} + Storage st(getErebosDir()); optional<Head<LocalState>> h; optional<Server> server; +map<Peer, promise<bool>> attachAnswer; + +Peer getPeer(const string & name) +{ + auto & plist = server->peerList(); + for (size_t i = 0; i < plist.size(); i++) + if (plist.at(i).name() == name) + return plist.at(i); + ostringstream ss; + ss << "peer '" << name << "' not found"; + throw invalid_argument(ss.str().c_str()); +} struct Command { @@ -48,7 +81,8 @@ struct Command void createIdentity(const vector<string> & args) { optional<Identity> identity; - for (const auto & name : args) { + for (ssize_t i = args.size() - 1; i >= 0; i--) { + const auto & name = args[i]; auto builder = Identity::create(st); builder.name(name); if (identity) @@ -65,10 +99,37 @@ void createIdentity(const vector<string> & args) } } +void printAttachResult(Peer peer, future<bool> && success) +{ + bool s = success.get(); + ostringstream ss; + ss << "attach-result " << peer.name() << " " << s; + printLine(ss.str()); +} + +future<bool> confirmAttach(const Peer & peer, string confirm, future<bool> && success) +{ + thread(printAttachResult, peer, move(success)).detach(); + + promise<bool> promise; + auto input = promise.get_future(); + attachAnswer[peer] = move(promise); + + ostringstream ss; + ss << "attach-confirm " << peer.name() << " " << confirm; + printLine(ss.str()); + return input; +} + void startServer(const vector<string> &) { vector<unique_ptr<Service>> services; + auto atts = make_unique<AttachService>(); + atts->onRequest(confirmAttach); + atts->onResponse(confirmAttach); + services.push_back(move(atts)); + server.emplace(*h, move(services)); server->peerList().onUpdate([](size_t idx, const Peer * peer) { @@ -81,7 +142,7 @@ void startServer(const vector<string> &) } else { ss << " deleted"; } - cout << ss.str() << endl; + printLine(ss.str()); }); } @@ -90,10 +151,38 @@ void stopServer(const vector<string> &) server.reset(); } +void watchLocalIdentity(const vector<string> &) +{ + auto bhv = h->behavior().lens<optional<Identity>>(); + static auto watchedLocalIdentity = bhv.watch([] (const optional<Identity> & idt) { + if (idt) { + ostringstream ss; + ss << "local-identity"; + for (optional<Identity> i = idt; i; i = i->owner()) + ss << " " << i->name().value(); + printLine(ss.str()); + } + }); +} + +void attach(const vector<string> & params) +{ + server->svc<AttachService>().attachTo(getPeer(params.at(0))); +} + +void attachAccept(const vector<string> & params) +{ + attachAnswer.extract(getPeer(params[0])) + .mapped().set_value(params[1] == "1"); +} + vector<Command> commands = { { "create-identity", createIdentity }, { "start-server", startServer }, { "stop-server", stopServer }, + { "watch-local-identity", watchLocalIdentity }, + { "attach", attach }, + { "attach-accept", attachAccept }, }; } diff --git a/test/attach.test b/test/attach.test new file mode 100644 index 0000000..0c97fb1 --- /dev/null +++ b/test/attach.test @@ -0,0 +1,27 @@ +test: + spawn on node1 as p1 + spawn on node2 as p2 + send "create-identity Device1 Owner" to p1 + send "create-identity Device2" to p2 + send "watch-local-identity" to p1 + send "watch-local-identity" to p2 + send "start-server" to p1 + send "start-server" to p2 + expect /local-identity Device1 Owner/ from p1 + expect /local-identity Device2/ from p2 + expect /peer [0-9]+ 192.168.0.11:29665/ from p1 + expect /peer [0-9]+ 192.168.0.12:29665/ from p1 + expect /peer [0-9]+ 192.168.0.12:29665/ from p2 + expect /peer [0-9]+ 192.168.0.11:29665/ from p2 + expect /peer [0-9]+ Device2 Device2/ from p1 + expect /peer [0-9]+ Owner Device1/ from p2 + send "attach Owner" to p2 + expect /attach-confirm .*/ from p1 + expect /attach-confirm .*/ from p2 + # TODO: check code match + send "attach-accept Device2 1" to p1 + send "attach-accept Owner 1" to p2 + expect /attach-result Device2 1/ from p1 + expect /attach-result Owner 1/ from p2 + expect /local-identity Device2 Owner/ from p2 + expect /peer [0-9]+ Owner Device2/ from p1 |