summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/erebos/network.h3
-rw-r--r--src/main.cpp11
-rw-r--r--src/network.cpp42
-rw-r--r--test/sync.test49
4 files changed, 102 insertions, 3 deletions
diff --git a/include/erebos/network.h b/include/erebos/network.h
index ed31823..66edfa4 100644
--- a/include/erebos/network.h
+++ b/include/erebos/network.h
@@ -14,6 +14,7 @@ using std::vector;
using std::unique_ptr;
class ServerConfig;
+class Peer;
class Server
{
@@ -33,6 +34,8 @@ public:
template<class S> S & svc();
class PeerList & peerList() const;
+ void addPeer(const string & node) const;
+ void addPeer(const string & node, const string & service) const;
struct Peer;
private:
diff --git a/src/main.cpp b/src/main.cpp
index 63b78dd..f33bcc4 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -328,6 +328,16 @@ void stopServer(const vector<string> &)
server.reset();
}
+void peerAdd(const vector<string> & args)
+{
+ if (args.size() == 1)
+ server->addPeer(args.at(0));
+ else if (args.size() == 2)
+ server->addPeer(args.at(0), args.at(1));
+ else
+ throw invalid_argument("usage: peer-add <node> [<port>]");
+}
+
void sharedStateGet(const vector<string> &)
{
ostringstream ss;
@@ -530,6 +540,7 @@ vector<Command> commands = {
{ "create-identity", createIdentity },
{ "start-server", startServer },
{ "stop-server", stopServer },
+ { "peer-add", peerAdd },
{ "shared-state-get", sharedStateGet },
{ "shared-state-wait", sharedStateWait },
{ "watch-local-identity", watchLocalIdentity },
diff --git a/src/network.cpp b/src/network.cpp
index ecf7ca0..226095b 100644
--- a/src/network.cpp
+++ b/src/network.cpp
@@ -11,6 +11,9 @@
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <net/if.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <sys/types.h>
#include <unistd.h>
using std::get;
@@ -70,6 +73,43 @@ PeerList & Server::peerList() const
return p->plist;
}
+void Server::addPeer(const string & node) const
+{
+ return addPeer(node, to_string(Priv::discoveryPort));
+}
+
+void Server::addPeer(const string & node, const string & service) const
+{
+ addrinfo hints {};
+ hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG;
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = SOCK_DGRAM;
+ addrinfo *aptr;
+
+ int r = getaddrinfo(node.c_str(), service.c_str(), &hints, &aptr);
+ if (r != 0)
+ throw runtime_error(string("Server::addPeer: getaddrinfo failed: ") + gai_strerror(r));
+
+ unique_ptr<addrinfo, void(*)(addrinfo*)> result { aptr, &freeaddrinfo };
+
+ for (addrinfo * rp = result.get(); rp != nullptr; rp = rp->ai_next) {
+ if (rp->ai_family == AF_INET6) {
+ Peer & peer = p->getPeer(*(sockaddr_in6 *)rp->ai_addr);
+
+ vector<TransportHeader::Item> header;
+ {
+ shared_lock lock(p->selfMutex);
+ header.push_back(TransportHeader::Item {
+ TransportHeader::Type::AnnounceSelf, *p->self.ref() });
+ }
+ peer.send(header, {}, false);
+ return;
+ }
+ }
+
+ throw runtime_error("Server::addPeer: no suitable peer address found");
+}
+
Peer::Peer(const shared_ptr<Priv> & p): p(p) {}
Peer::~Peer() = default;
@@ -424,6 +464,8 @@ bool Server::Priv::isSelfAddress(const sockaddr_in6 & paddr)
Server::Peer & Server::Priv::getPeer(const sockaddr_in6 & paddr)
{
+ scoped_lock lock(dataMutex);
+
for (auto & peer : peers)
if (memcmp(&peer->addr, &paddr, sizeof paddr) == 0)
return *peer;
diff --git a/test/sync.test b/test/sync.test
index 3cc7cba..91e8f08 100644
--- a/test/sync.test
+++ b/test/sync.test
@@ -20,9 +20,10 @@ test:
/peer 1 id Device1 Owner/
send "attach-to 1" to p2
- expect /attach-request 1 ([0-9]*)/ from p1 capture code1
- expect /attach-response 1 ([0-9]*)/ from p2 capture code2
- guard (code1 == code2)
+ local:
+ expect /attach-request 1 ([0-9]*)/ from p1 capture code1
+ expect /attach-response 1 ([0-9]*)/ from p2 capture code2
+ guard (code1 == code2)
send "attach-accept 1" to p1
send "attach-accept 1" to p2
@@ -48,3 +49,45 @@ test:
expect /shared-state-get (.*)/ from p1 capture p1state
send "shared-state-wait $p1state" to p2
expect /shared-state-wait $p1state/ from p2
+
+ subnet s
+ spawn on s as p3
+
+ with p3:
+ send "create-identity Device3"
+ send "watch-local-identity"
+ send "watch-shared-identity"
+ send "start-server"
+
+ send "peer-add ${p1.node.ip}"
+
+ expect:
+ /local-identity Device3/
+ /peer 1 addr ${p1.node.ip} 29665/
+ /peer 1 id Device1 .*/
+
+ expect from p1:
+ /peer 2 addr ${p3.node.ip} 29665/
+ /peer 2 id Device3/
+
+ send "attach-to 1" to p3
+ local:
+ expect /attach-request 2 ([0-9]*)/ from p1 capture code1
+ expect /attach-response 1 ([0-9]*)/ from p3 capture code2
+ guard (code1 == code2)
+
+ send "attach-accept 2" to p1
+ send "attach-accept 1" to p3
+
+ expect /local-identity Device3 NewOwner3/ from p3
+ expect /shared-identity NewOwner3/ from p3
+
+ send "update-shared-identity NewOwner4" to p3
+ expect /shared-identity NewOwner4/ from p1
+ expect /shared-identity NewOwner4/ from p2
+ expect /shared-identity NewOwner4/ from p3
+
+ send "update-shared-identity NewOwner5" to p2
+ expect /shared-identity NewOwner5/ from p1
+ expect /shared-identity NewOwner5/ from p2
+ expect /shared-identity NewOwner5/ from p3