summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.cpp11
-rw-r--r--src/network.cpp42
2 files changed, 53 insertions, 0 deletions
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;