diff options
author | Roman Smrž <roman.smrz@seznam.cz> | 2023-05-07 11:23:31 +0200 |
---|---|---|
committer | Roman Smrž <roman.smrz@seznam.cz> | 2023-05-07 17:47:11 +0200 |
commit | 3fc29ed18ea46e83e2ba2d4b39e52239771f427c (patch) | |
tree | 1aa1fc5e6806b8c7cc51d6fa536978a427aa3d85 | |
parent | 0c790e6850f0575f4d5ba8182c580182869ad57d (diff) |
Network: use IPv6 socket internally
-rw-r--r-- | include/erebos/network.h | 6 | ||||
-rw-r--r-- | src/main.cpp | 3 | ||||
-rw-r--r-- | src/network.cpp | 57 | ||||
-rw-r--r-- | src/network.h | 6 |
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> &); |