From 602d62cf52cc78c80355d8d4ee1ee07d21db98e8 Mon Sep 17 00:00:00 2001 From: Lukas Werling Date: Sun, 8 Jan 2017 18:34:26 +0100 Subject: [PATCH] Implement netpunching for IPv6 --- src/netpuncher/C4PuncherPacket.cpp | 5 ++++ src/netpuncher/C4PuncherPacket.h | 11 +++++-- src/netpuncher/main.cpp | 2 +- src/network/C4Network2.cpp | 30 ++++++++++++++----- src/network/C4Network2.h | 7 +++-- src/network/C4Network2IO.cpp | 46 ++++++++++++++++++++++------- src/network/C4Network2IO.h | 5 ++-- src/network/C4Network2Reference.cpp | 4 +-- src/network/C4Network2Reference.h | 4 +-- 9 files changed, 84 insertions(+), 30 deletions(-) diff --git a/src/netpuncher/C4PuncherPacket.cpp b/src/netpuncher/C4PuncherPacket.cpp index 53619ccc6..22b4aa107 100644 --- a/src/netpuncher/C4PuncherPacket.cpp +++ b/src/netpuncher/C4PuncherPacket.cpp @@ -18,6 +18,11 @@ #include "network/C4Network2Address.h" #include +void C4NetpuncherID::CompileFunc(StdCompiler *pComp) { + pComp->Value(mkNamingAdapt(v4, "IPv4", 0u)); + pComp->Value(mkNamingAdapt(v6, "IPv6", 0u)); +} + std::unique_ptr C4NetpuncherPacket::Construct(const C4NetIOPacket& rpack) { if (!rpack.getPData()) return nullptr; try { diff --git a/src/netpuncher/C4PuncherPacket.h b/src/netpuncher/C4PuncherPacket.h index e1e2be45a..e69508578 100644 --- a/src/netpuncher/C4PuncherPacket.h +++ b/src/netpuncher/C4PuncherPacket.h @@ -27,7 +27,14 @@ enum C4NetpuncherPacketType { // extend this with exchanging ICE parameters, some day? }; -typedef uint32_t C4NetpuncherID_t; +struct C4NetpuncherID { + typedef uint32_t value; + + value v4 = 0, v6 = 0; + + void CompileFunc(StdCompiler *pComp); + bool operator==(const C4NetpuncherID& other) const { return v4 == other.v4 && v6 == other.v6; } +}; class C4NetpuncherPacket { public: @@ -38,7 +45,7 @@ public: C4NetIOPacket PackTo(const C4NetIO::addr_t&) const; protected: virtual StdBuf PackInto() const = 0; - typedef C4NetpuncherID_t CID; + typedef C4NetpuncherID::value CID; }; template diff --git a/src/netpuncher/main.cpp b/src/netpuncher/main.cpp index 571492131..aab35dc27 100644 --- a/src/netpuncher/main.cpp +++ b/src/netpuncher/main.cpp @@ -29,7 +29,7 @@ class C4PuncherServer : public C4NetIOUDP, private C4NetIO::CBClass { public: - typedef C4NetpuncherID_t CID; + typedef C4NetpuncherID::value CID; C4PuncherServer() { C4NetIOUDP::SetCallback(this); rng = std::bind(std::uniform_int_distribution(1/*, max*/), std::ref(random_device)); diff --git a/src/network/C4Network2.cpp b/src/network/C4Network2.cpp index 8940e4299..8bbf99150 100644 --- a/src/network/C4Network2.cpp +++ b/src/network/C4Network2.cpp @@ -148,7 +148,7 @@ C4Network2::C4Network2() fPausedForVote(false), iLastOwnVoting(0), fStreaming(false), - NetpuncherGameID(0) + NetpuncherGameID(C4NetpuncherID()) { } @@ -169,7 +169,7 @@ bool C4Network2::InitHost(bool fLobby) fChasing = false; fAllowJoin = false; iNextClientID = C4ClientIDStart; - NetpuncherGameID = 0; + NetpuncherGameID = C4NetpuncherID(); NetpuncherAddr = ::Config.Network.PuncherAddress; // initialize client list Clients.Init(&Game.Clients, true); @@ -689,7 +689,7 @@ void C4Network2::Clear() delete pVoteDialog; pVoteDialog = nullptr; fPausedForVote = false; iLastOwnVoting = 0; - NetpuncherGameID = 0; + NetpuncherGameID = C4NetpuncherID(); Votes.Clear(); // don't clear fPasswordNeeded here, it's needed by InitClient } @@ -907,7 +907,7 @@ void C4Network2::HandleLobbyPacket(char cStatus, const C4PacketBase *pBasePkt, C if (pLobby) pLobby->HandlePacket(cStatus, pBasePkt, pClient); } -bool C4Network2::HandlePuncherPacket(C4NetpuncherPacket::uptr pkt) +bool C4Network2::HandlePuncherPacket(C4NetpuncherPacket::uptr pkt, C4NetIO::HostAddress::AddressFamily family) { // TODO: is this all thread-safe? assert(pkt); @@ -928,20 +928,30 @@ bool C4Network2::HandlePuncherPacket(C4NetpuncherPacket::uptr pkt) case PID_Puncher_AssID: if (isHost()) { - NetpuncherGameID = GETPKT(AssID)->GetID(); + getNetpuncherGameID(family) = GETPKT(AssID)->GetID(); InvalidateReference(); } else { // While we don't need the ID as a client, this nicely serves as the signal that we can start using the netpuncher - if (Status.getState() == GS_Init && getNetpuncherGameID()) - NetIO.SendPuncherPacket(C4NetpuncherPacketSReq(getNetpuncherGameID())); + if (Status.getState() == GS_Init && getNetpuncherGameID(family)) + NetIO.SendPuncherPacket(C4NetpuncherPacketSReq(getNetpuncherGameID(family)), family); } return true; default: return false; } } +C4NetpuncherID::value& C4Network2::getNetpuncherGameID(C4NetIO::HostAddress::AddressFamily family) +{ + switch (family) + { + case C4NetIO::HostAddress::IPv4: return NetpuncherGameID.v4; + case C4NetIO::HostAddress::IPv6: return NetpuncherGameID.v6; + default: assert(false); + } +} + void C4Network2::InitPuncher() { // We have an internet connection, so let's punch the puncher server here in order to open an udp port @@ -952,6 +962,12 @@ void C4Network2::InitPuncher() PuncherAddr.SetDefaultPort(C4NetStdPortPuncher); NetIO.InitPuncher(PuncherAddr); } + PuncherAddr.SetAddress(getNetpuncherAddr(), C4NetIO::HostAddress::IPv6); + if (!PuncherAddr.IsNull()) + { + PuncherAddr.SetDefaultPort(C4NetStdPortPuncher); + NetIO.InitPuncher(PuncherAddr); + } } void C4Network2::OnGameSynchronized() diff --git a/src/network/C4Network2.h b/src/network/C4Network2.h index 958553dc3..0dff2e35d 100644 --- a/src/network/C4Network2.h +++ b/src/network/C4Network2.h @@ -194,7 +194,7 @@ protected: unsigned int iCurrentStreamAmount, iCurrentStreamPosition; // puncher - C4NetpuncherID_t NetpuncherGameID; + C4NetpuncherID NetpuncherGameID; StdCopyStrBuf NetpuncherAddr; public: @@ -257,7 +257,7 @@ public: void OnDisconn(C4Network2IOConnection *pConn); void HandlePacket(char cStatus, const C4PacketBase *pBasePkt, C4Network2IOConnection *pConn); void HandleLobbyPacket(char cStatus, const C4PacketBase *pBasePkt, C4Network2IOConnection *pConn); - bool HandlePuncherPacket(C4NetpuncherPacket::uptr); + bool HandlePuncherPacket(C4NetpuncherPacket::uptr, C4NetIO::HostAddress::AddressFamily family); // runtime join stuff void OnGameSynchronized(); @@ -303,7 +303,8 @@ public: bool StopStreaming(); // netpuncher - C4NetpuncherID_t getNetpuncherGameID() const { return NetpuncherGameID; } + C4NetpuncherID::value& getNetpuncherGameID(C4NetIO::HostAddress::AddressFamily family); + C4NetpuncherID getNetpuncherGameID() const { return NetpuncherGameID; }; StdStrBuf getNetpuncherAddr() const { return NetpuncherAddr; } protected: diff --git a/src/network/C4Network2IO.cpp b/src/network/C4Network2IO.cpp index edf0a2c84..8e06dda56 100644 --- a/src/network/C4Network2IO.cpp +++ b/src/network/C4Network2IO.cpp @@ -460,28 +460,49 @@ bool C4Network2IO::InitPuncher(C4NetIO::addr_t nPuncherAddr) if (!pNetIO_UDP) return false; // save address - PuncherAddr = nPuncherAddr; + switch (nPuncherAddr.GetFamily()) + { + case C4NetIO::HostAddress::IPv4: + PuncherAddrIPv4 = nPuncherAddr; + break; + case C4NetIO::HostAddress::IPv6: + PuncherAddrIPv6 = nPuncherAddr; + break; + default: + assert(false); + } // let's punch - return pNetIO_UDP->Connect(PuncherAddr); + return pNetIO_UDP->Connect(nPuncherAddr); } -void C4Network2IO::Punch(const C4NetIO::addr_t &punchee_addr) { +void C4Network2IO::Punch(const C4NetIO::addr_t &punchee_addr) +{ if (!pNetIO_UDP) return; C4PacketPing PktPeng; dynamic_cast(pNetIO_UDP)->SendDirect(MkC4NetIOPacket(PID_Pong, PktPeng, punchee_addr)); } -void C4Network2IO::SendPuncherPacket(const C4NetpuncherPacket& p) { - if (!pNetIO_UDP || PuncherAddr.IsNull()) return; - pNetIO_UDP->Send(p.PackTo(PuncherAddr)); +void C4Network2IO::SendPuncherPacket(const C4NetpuncherPacket& p, C4NetIO::HostAddress::AddressFamily family) +{ + if (!pNetIO_UDP) return; + if (family == C4NetIO::HostAddress::IPv4 && !PuncherAddrIPv4.IsNull()) + pNetIO_UDP->Send(p.PackTo(PuncherAddrIPv4)); + else if (family == C4NetIO::HostAddress::IPv6 && !PuncherAddrIPv6.IsNull()) + pNetIO_UDP->Send(p.PackTo(PuncherAddrIPv6)); +} + +bool C4Network2IO::IsPuncherAddr(const C4NetIO::addr_t& addr) const +{ + return (!PuncherAddrIPv4.IsNull() && PuncherAddrIPv4 == addr) + || (!PuncherAddrIPv6.IsNull() && PuncherAddrIPv6 == addr); } // C4NetIO interface bool C4Network2IO::OnConn(const C4NetIO::addr_t &PeerAddr, const C4NetIO::addr_t &ConnectAddr, const C4NetIO::addr_t *pOwnAddr, C4NetIO *pNetIO) { // puncher answer? - if (pNetIO == pNetIO_UDP && !PuncherAddr.IsNull() && PuncherAddr == ConnectAddr) + if (pNetIO == pNetIO_UDP && IsPuncherAddr(ConnectAddr)) { // got an address? if (pOwnAddr) @@ -537,9 +558,12 @@ bool C4Network2IO::OnConn(const C4NetIO::addr_t &PeerAddr, const C4NetIO::addr_t void C4Network2IO::OnDisconn(const C4NetIO::addr_t &addr, C4NetIO *pNetIO, const char *szReason) { // punch? - if (pNetIO == pNetIO_UDP && !PuncherAddr.IsNull() && PuncherAddr == addr) + if (pNetIO == pNetIO_UDP && IsPuncherAddr(addr)) { - PuncherAddr.Clear(); + if (PuncherAddrIPv4 == addr) + PuncherAddrIPv4.Clear(); + else + PuncherAddrIPv6.Clear(); return; } #if(C4NET2IO_DUMP_LEVEL > 1) @@ -579,7 +603,7 @@ void C4Network2IO::OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO) C4TimeMilliseconds::Now().AsString().getData(), rPacket.getStatus(), getNetIOName(pNetIO)); #endif - if (pNetIO == pNetIO_UDP && !PuncherAddr.IsNull() && PuncherAddr == rPacket.getAddr()) + if (pNetIO == pNetIO_UDP && IsPuncherAddr(rPacket.getAddr())) { HandlePuncherPacket(rPacket); return; @@ -1141,7 +1165,7 @@ void C4Network2IO::HandleFwdReq(const C4PacketFwd &rFwd, C4Network2IOConnection void C4Network2IO::HandlePuncherPacket(const C4NetIOPacket& rPacket) { auto pkt = C4NetpuncherPacket::Construct(rPacket); - if (pkt && ::Network.HandlePuncherPacket(move(pkt))); + if (pkt && ::Network.HandlePuncherPacket(move(pkt), rPacket.getAddr().GetFamily())); else { assert(pNetIO_UDP); diff --git a/src/network/C4Network2IO.h b/src/network/C4Network2IO.h index d561fa149..ef1914e4b 100644 --- a/src/network/C4Network2IO.h +++ b/src/network/C4Network2IO.h @@ -97,7 +97,8 @@ protected: iUDPIRate, iUDPORate, iUDPBCRate; // punching - C4NetIO::addr_t PuncherAddr; + C4NetIO::addr_t PuncherAddrIPv4, PuncherAddrIPv6; + bool IsPuncherAddr(const C4NetIO::addr_t& addr) const; public: @@ -137,7 +138,7 @@ public: // punch bool InitPuncher(C4NetIO::addr_t PuncherAddr); // by main thread - void SendPuncherPacket(const C4NetpuncherPacket&); + void SendPuncherPacket(const C4NetpuncherPacket&, C4NetIO::HostAddress::AddressFamily family); void Punch(const C4NetIO::addr_t&); // sends a ping packet // stuff diff --git a/src/network/C4Network2Reference.cpp b/src/network/C4Network2Reference.cpp index 7e717f5f4..a8c4b9b0e 100644 --- a/src/network/C4Network2Reference.cpp +++ b/src/network/C4Network2Reference.cpp @@ -30,7 +30,7 @@ C4Network2Reference::C4Network2Reference() : Icon(0), GameMode(), Time(0), Frame(0), StartTime(0), LeaguePerformance(0), JoinAllowed(true), ObservingAllowed(true), PasswordNeeded(false), OfficialServer(false), - IsEditor(false), iAddrCnt(0), NetpuncherGameID(0) + IsEditor(false), iAddrCnt(0), NetpuncherGameID(C4NetpuncherID()) { } @@ -127,7 +127,7 @@ void C4Network2Reference::CompileFunc(StdCompiler *pComp) pComp->Value(mkNamingAdapt(Game.sEngineName, "Game", "None")); pComp->Value(mkNamingAdapt(mkArrayAdaptDM(Game.iVer,0),"Version" )); pComp->Value(mkNamingAdapt(OfficialServer, "OfficialServer", false)); - pComp->Value(mkNamingAdapt(NetpuncherGameID, "NetpuncherID", 0, false, false)); + pComp->Value(mkNamingAdapt(NetpuncherGameID, "NetpuncherID", C4NetpuncherID(), false, false)); pComp->Value(mkNamingAdapt(NetpuncherAddr, "NetpuncherAddr", "", false, false)); pComp->Value(Parameters); diff --git a/src/network/C4Network2Reference.h b/src/network/C4Network2Reference.h index 3a47c0409..37705ec52 100644 --- a/src/network/C4Network2Reference.h +++ b/src/network/C4Network2Reference.h @@ -51,7 +51,7 @@ private: bool PasswordNeeded; bool OfficialServer; bool IsEditor; - C4NetpuncherID_t NetpuncherGameID; + C4NetpuncherID NetpuncherGameID; StdCopyStrBuf NetpuncherAddr; // Engine information @@ -79,7 +79,7 @@ public: int32_t getStartTime() const { return StartTime; } StdStrBuf getGameGoalString() const; bool isEditor() const { return IsEditor; } - C4NetpuncherID_t getNetpuncherGameID() const { return NetpuncherGameID; } + C4NetpuncherID getNetpuncherGameID() const { return NetpuncherGameID; } StdStrBuf getNetpuncherAddr() const { return NetpuncherAddr; } void SetSourceAddress(const C4NetIO::EndpointAddress &ip);