diff options
| author | Roman Smrž <roman.smrz@seznam.cz> | 2023-05-07 22:28:12 +0200 | 
|---|---|---|
| committer | Roman Smrž <roman.smrz@seznam.cz> | 2023-05-17 20:34:24 +0200 | 
| commit | 8386482fb9ee76bcfa79ba11915a9bcdf9745948 (patch) | |
| tree | 675a88d31eabd7a6bf3a4c04912d7dbf7d85c0b7 | |
| parent | 2d5508898e90c01680cab60295b9c1e8164d65da (diff) | |
Server function to manually add peer
| -rw-r--r-- | include/erebos/network.h | 3 | ||||
| -rw-r--r-- | src/main.cpp | 11 | ||||
| -rw-r--r-- | src/network.cpp | 42 | ||||
| -rw-r--r-- | test/sync.test | 49 | 
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 |