summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Smrž <roman.smrz@seznam.cz>2023-05-07 11:23:31 +0200
committerRoman Smrž <roman.smrz@seznam.cz>2023-05-07 17:47:11 +0200
commit3fc29ed18ea46e83e2ba2d4b39e52239771f427c (patch)
tree1aa1fc5e6806b8c7cc51d6fa536978a427aa3d85
parent0c790e6850f0575f4d5ba8182c580182869ad57d (diff)
Network: use IPv6 socket internally
-rw-r--r--include/erebos/network.h6
-rw-r--r--src/main.cpp3
-rw-r--r--src/network.cpp57
-rw-r--r--src/network.h6
4 files changed, 48 insertions, 24 deletions
diff --git a/include/erebos/network.h b/include/erebos/network.h
index c211fbf..ed31823 100644
--- a/include/erebos/network.h
+++ b/include/erebos/network.h
@@ -6,7 +6,7 @@
#include <functional>
#include <typeinfo>
-struct sockaddr_in;
+struct sockaddr_in6;
namespace erebos {
@@ -91,7 +91,9 @@ public:
std::string name() const;
std::optional<Identity> identity() const;
- const struct sockaddr_in & address() const;
+ const struct sockaddr_in6 & address() const;
+ string addressStr() const;
+ uint16_t port() const;
bool hasChannel() const;
bool send(UUID, const Ref &) const;
diff --git a/src/main.cpp b/src/main.cpp
index d0015c2..63b78dd 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -303,10 +303,9 @@ void startServer(const vector<string> &)
if (peer) {
if (i >= testPeers.size()) {
testPeers.push_back(TestPeer { .peer = *peer, .id = i + 1 });
- const auto & paddr = peer->address();
ostringstream ss;
- ss << prefix << " addr " << inet_ntoa(paddr.sin_addr) << " " << ntohs(paddr.sin_port);
+ ss << prefix << " addr " << peer->addressStr() << " " << peer->port();
printLine(ss.str());
}
diff --git a/src/network.cpp b/src/network.cpp
index 5c268ae..ecf7ca0 100644
--- a/src/network.cpp
+++ b/src/network.cpp
@@ -104,10 +104,7 @@ string Peer::name() const
if (holds_alternative<shared_ptr<WaitingRef>>(speer->identity))
return string(std::get<shared_ptr<WaitingRef>>(speer->identity)->ref.digest());
- char buf[16];
- if (inet_ntop(AF_INET, &speer->addr.sin_addr, buf, sizeof(buf)))
- return string(buf) + ":" + to_string(ntohs(speer->addr.sin_port));
- return "<invalid address>";
+ return addressStr();
}
return "<server closed>";
}
@@ -120,13 +117,32 @@ optional<Identity> Peer::identity() const
return nullopt;
}
-const sockaddr_in & Peer::address() const
+const sockaddr_in6 & Peer::address() const
{
if (auto speer = p->speer.lock())
return speer->addr;
throw runtime_error("Server no longer running");
}
+string Peer::addressStr() const
+{
+ char buf[INET6_ADDRSTRLEN];
+ const in6_addr & addr = address().sin6_addr;
+
+ if (inet_ntop(AF_INET6, &addr, buf, sizeof(buf))) {
+ if (IN6_IS_ADDR_V4MAPPED(&addr) && strncmp(buf, "::ffff:", 7) == 0)
+ return buf + 7;
+ return buf;
+ }
+
+ return "<invalid address>";
+}
+
+uint16_t Peer::port() const
+{
+ return ntohs(address().sin6_port);
+}
+
void Peer::Priv::notifyWatchers()
{
if (auto slist = list.lock()) {
@@ -242,11 +258,17 @@ Server::Priv::Priv(const Head<LocalState> & local, const Identity & self):
bcastAddresses.push_back(((sockaddr_in*)ifa->ifa_broadaddr)->sin_addr);
}
}
-
- sock = socket(AF_INET, SOCK_DGRAM, 0);
+
+ sock = socket(AF_INET6, SOCK_DGRAM, 0);
if (sock < 0)
throw std::system_error(errno, std::generic_category());
+ int disable = 0;
+ // Should be disabled by default, but try to make sure. On platforms
+ // where the calls fails, IPv4 might not work.
+ setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
+ &disable, sizeof(disable));
+
int enable = 1;
if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST,
&enable, sizeof(enable)) < 0)
@@ -256,9 +278,9 @@ Server::Priv::Priv(const Head<LocalState> & local, const Identity & self):
&enable, sizeof(enable)) < 0)
throw std::system_error(errno, std::generic_category());
- sockaddr_in laddr = {};
- laddr.sin_family = AF_INET;
- laddr.sin_port = htons(discoveryPort);
+ sockaddr_in6 laddr = {};
+ laddr.sin6_family = AF_INET6;
+ laddr.sin6_port = htons(discoveryPort);
if (::bind(sock, (sockaddr *) &laddr, sizeof(laddr)) < 0)
throw std::system_error(errno, std::generic_category());
@@ -296,7 +318,7 @@ void Server::Priv::doListen()
unique_lock lock(dataMutex);
for (; !finish; lock.lock()) {
- sockaddr_in paddr;
+ sockaddr_in6 paddr;
lock.unlock();
socklen_t addrlen = sizeof(paddr);
@@ -390,16 +412,17 @@ void Server::Priv::doAnnounce()
}
}
-bool Server::Priv::isSelfAddress(const sockaddr_in & paddr)
+bool Server::Priv::isSelfAddress(const sockaddr_in6 & paddr)
{
- for (const auto & in : localAddresses)
- if (in.s_addr == paddr.sin_addr.s_addr &&
- ntohs(paddr.sin_port) == discoveryPort)
- return true;
+ if (IN6_IS_ADDR_V4MAPPED(&paddr.sin6_addr))
+ for (const auto & in : localAddresses)
+ if (in.s_addr == *reinterpret_cast<const in_addr_t*>(paddr.sin6_addr.s6_addr + 12) &&
+ ntohs(paddr.sin6_port) == discoveryPort)
+ return true;
return false;
}
-Server::Peer & Server::Priv::getPeer(const sockaddr_in & paddr)
+Server::Peer & Server::Priv::getPeer(const sockaddr_in6 & paddr)
{
for (auto & peer : peers)
if (memcmp(&peer->addr, &paddr, sizeof paddr) == 0)
diff --git a/src/network.h b/src/network.h
index 4d232b3..a6ba3cd 100644
--- a/src/network.h
+++ b/src/network.h
@@ -43,7 +43,7 @@ struct Server::Peer
Peer & operator=(const Peer &) = delete;
Priv & server;
- const sockaddr_in addr;
+ const sockaddr_in6 addr;
variant<monostate,
shared_ptr<struct WaitingRef>,
@@ -151,8 +151,8 @@ struct Server::Priv
void doListen();
void doAnnounce();
- bool isSelfAddress(const sockaddr_in & paddr);
- Peer & getPeer(const sockaddr_in & paddr);
+ bool isSelfAddress(const sockaddr_in6 & paddr);
+ Peer & getPeer(const sockaddr_in6 & paddr);
void handlePacket(Peer &, const TransportHeader &, ReplyBuilder &);
void handleLocalHeadChange(const Head<LocalState> &);