Implement netpunching for IPv6

ipv6
Lukas Werling 2017-01-08 18:34:26 +01:00
parent c94b4cc3b0
commit 33a32cb6bd
9 changed files with 84 additions and 30 deletions

View File

@ -18,6 +18,11 @@
#include "network/C4Network2Address.h" #include "network/C4Network2Address.h"
#include <sstream> #include <sstream>
void C4NetpuncherID::CompileFunc(StdCompiler *pComp) {
pComp->Value(mkNamingAdapt(v4, "IPv4", 0u));
pComp->Value(mkNamingAdapt(v6, "IPv6", 0u));
}
std::unique_ptr<C4NetpuncherPacket> C4NetpuncherPacket::Construct(const C4NetIOPacket& rpack) { std::unique_ptr<C4NetpuncherPacket> C4NetpuncherPacket::Construct(const C4NetIOPacket& rpack) {
if (!rpack.getPData()) return nullptr; if (!rpack.getPData()) return nullptr;
try { try {

View File

@ -27,7 +27,14 @@ enum C4NetpuncherPacketType {
// extend this with exchanging ICE parameters, some day? // 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 { class C4NetpuncherPacket {
public: public:
@ -38,7 +45,7 @@ public:
C4NetIOPacket PackTo(const C4NetIO::addr_t&) const; C4NetIOPacket PackTo(const C4NetIO::addr_t&) const;
protected: protected:
virtual StdBuf PackInto() const = 0; virtual StdBuf PackInto() const = 0;
typedef C4NetpuncherID_t CID; typedef C4NetpuncherID::value CID;
}; };
template<C4NetpuncherPacketType TYPE> template<C4NetpuncherPacketType TYPE>

View File

@ -29,7 +29,7 @@
class C4PuncherServer : public C4NetIOUDP, private C4NetIO::CBClass class C4PuncherServer : public C4NetIOUDP, private C4NetIO::CBClass
{ {
public: public:
typedef C4NetpuncherID_t CID; typedef C4NetpuncherID::value CID;
C4PuncherServer() { C4PuncherServer() {
C4NetIOUDP::SetCallback(this); C4NetIOUDP::SetCallback(this);
rng = std::bind(std::uniform_int_distribution<CID>(1/*, max*/), std::ref(random_device)); rng = std::bind(std::uniform_int_distribution<CID>(1/*, max*/), std::ref(random_device));

View File

@ -148,7 +148,7 @@ C4Network2::C4Network2()
fPausedForVote(false), fPausedForVote(false),
iLastOwnVoting(0), iLastOwnVoting(0),
fStreaming(false), fStreaming(false),
NetpuncherGameID(0) NetpuncherGameID(C4NetpuncherID())
{ {
} }
@ -169,7 +169,7 @@ bool C4Network2::InitHost(bool fLobby)
fChasing = false; fChasing = false;
fAllowJoin = false; fAllowJoin = false;
iNextClientID = C4ClientIDStart; iNextClientID = C4ClientIDStart;
NetpuncherGameID = 0; NetpuncherGameID = C4NetpuncherID();
NetpuncherAddr = ::Config.Network.PuncherAddress; NetpuncherAddr = ::Config.Network.PuncherAddress;
// initialize client list // initialize client list
Clients.Init(&Game.Clients, true); Clients.Init(&Game.Clients, true);
@ -689,7 +689,7 @@ void C4Network2::Clear()
delete pVoteDialog; pVoteDialog = nullptr; delete pVoteDialog; pVoteDialog = nullptr;
fPausedForVote = false; fPausedForVote = false;
iLastOwnVoting = 0; iLastOwnVoting = 0;
NetpuncherGameID = 0; NetpuncherGameID = C4NetpuncherID();
Votes.Clear(); Votes.Clear();
// don't clear fPasswordNeeded here, it's needed by InitClient // 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); 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? // TODO: is this all thread-safe?
assert(pkt); assert(pkt);
@ -928,20 +928,30 @@ bool C4Network2::HandlePuncherPacket(C4NetpuncherPacket::uptr pkt)
case PID_Puncher_AssID: case PID_Puncher_AssID:
if (isHost()) if (isHost())
{ {
NetpuncherGameID = GETPKT(AssID)->GetID(); getNetpuncherGameID(family) = GETPKT(AssID)->GetID();
InvalidateReference(); InvalidateReference();
} }
else else
{ {
// While we don't need the ID as a client, this nicely serves as the signal that we can start using the netpuncher // 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()) if (Status.getState() == GS_Init && getNetpuncherGameID(family))
NetIO.SendPuncherPacket(C4NetpuncherPacketSReq(getNetpuncherGameID())); NetIO.SendPuncherPacket(C4NetpuncherPacketSReq(getNetpuncherGameID(family)), family);
} }
return true; return true;
default: return false; 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() void C4Network2::InitPuncher()
{ {
// We have an internet connection, so let's punch the puncher server here in order to open an udp port // 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); PuncherAddr.SetDefaultPort(C4NetStdPortPuncher);
NetIO.InitPuncher(PuncherAddr); NetIO.InitPuncher(PuncherAddr);
} }
PuncherAddr.SetAddress(getNetpuncherAddr(), C4NetIO::HostAddress::IPv6);
if (!PuncherAddr.IsNull())
{
PuncherAddr.SetDefaultPort(C4NetStdPortPuncher);
NetIO.InitPuncher(PuncherAddr);
}
} }
void C4Network2::OnGameSynchronized() void C4Network2::OnGameSynchronized()

View File

@ -194,7 +194,7 @@ protected:
unsigned int iCurrentStreamAmount, iCurrentStreamPosition; unsigned int iCurrentStreamAmount, iCurrentStreamPosition;
// puncher // puncher
C4NetpuncherID_t NetpuncherGameID; C4NetpuncherID NetpuncherGameID;
StdCopyStrBuf NetpuncherAddr; StdCopyStrBuf NetpuncherAddr;
public: public:
@ -257,7 +257,7 @@ public:
void OnDisconn(C4Network2IOConnection *pConn); void OnDisconn(C4Network2IOConnection *pConn);
void HandlePacket(char cStatus, const C4PacketBase *pBasePkt, C4Network2IOConnection *pConn); void HandlePacket(char cStatus, const C4PacketBase *pBasePkt, C4Network2IOConnection *pConn);
void HandleLobbyPacket(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 // runtime join stuff
void OnGameSynchronized(); void OnGameSynchronized();
@ -303,7 +303,8 @@ public:
bool StopStreaming(); bool StopStreaming();
// netpuncher // netpuncher
C4NetpuncherID_t getNetpuncherGameID() const { return NetpuncherGameID; } C4NetpuncherID::value& getNetpuncherGameID(C4NetIO::HostAddress::AddressFamily family);
C4NetpuncherID getNetpuncherGameID() const { return NetpuncherGameID; };
StdStrBuf getNetpuncherAddr() const { return NetpuncherAddr; } StdStrBuf getNetpuncherAddr() const { return NetpuncherAddr; }
protected: protected:

View File

@ -460,28 +460,49 @@ bool C4Network2IO::InitPuncher(C4NetIO::addr_t nPuncherAddr)
if (!pNetIO_UDP) if (!pNetIO_UDP)
return false; return false;
// save address // 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 // 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) if (!pNetIO_UDP)
return; return;
C4PacketPing PktPeng; C4PacketPing PktPeng;
dynamic_cast<C4NetIOUDP*>(pNetIO_UDP)->SendDirect(MkC4NetIOPacket(PID_Pong, PktPeng, punchee_addr)); dynamic_cast<C4NetIOUDP*>(pNetIO_UDP)->SendDirect(MkC4NetIOPacket(PID_Pong, PktPeng, punchee_addr));
} }
void C4Network2IO::SendPuncherPacket(const C4NetpuncherPacket& p) { void C4Network2IO::SendPuncherPacket(const C4NetpuncherPacket& p, C4NetIO::HostAddress::AddressFamily family)
if (!pNetIO_UDP || PuncherAddr.IsNull()) return; {
pNetIO_UDP->Send(p.PackTo(PuncherAddr)); 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 // C4NetIO interface
bool C4Network2IO::OnConn(const C4NetIO::addr_t &PeerAddr, const C4NetIO::addr_t &ConnectAddr, const C4NetIO::addr_t *pOwnAddr, C4NetIO *pNetIO) bool C4Network2IO::OnConn(const C4NetIO::addr_t &PeerAddr, const C4NetIO::addr_t &ConnectAddr, const C4NetIO::addr_t *pOwnAddr, C4NetIO *pNetIO)
{ {
// puncher answer? // puncher answer?
if (pNetIO == pNetIO_UDP && !PuncherAddr.IsNull() && PuncherAddr == ConnectAddr) if (pNetIO == pNetIO_UDP && IsPuncherAddr(ConnectAddr))
{ {
// got an address? // got an address?
if (pOwnAddr) 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) void C4Network2IO::OnDisconn(const C4NetIO::addr_t &addr, C4NetIO *pNetIO, const char *szReason)
{ {
// punch? // 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; return;
} }
#if(C4NET2IO_DUMP_LEVEL > 1) #if(C4NET2IO_DUMP_LEVEL > 1)
@ -579,7 +603,7 @@ void C4Network2IO::OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO)
C4TimeMilliseconds::Now().AsString().getData(), C4TimeMilliseconds::Now().AsString().getData(),
rPacket.getStatus(), getNetIOName(pNetIO)); rPacket.getStatus(), getNetIOName(pNetIO));
#endif #endif
if (pNetIO == pNetIO_UDP && !PuncherAddr.IsNull() && PuncherAddr == rPacket.getAddr()) if (pNetIO == pNetIO_UDP && IsPuncherAddr(rPacket.getAddr()))
{ {
HandlePuncherPacket(rPacket); HandlePuncherPacket(rPacket);
return; return;
@ -1141,7 +1165,7 @@ void C4Network2IO::HandleFwdReq(const C4PacketFwd &rFwd, C4Network2IOConnection
void C4Network2IO::HandlePuncherPacket(const C4NetIOPacket& rPacket) void C4Network2IO::HandlePuncherPacket(const C4NetIOPacket& rPacket)
{ {
auto pkt = C4NetpuncherPacket::Construct(rPacket); auto pkt = C4NetpuncherPacket::Construct(rPacket);
if (pkt && ::Network.HandlePuncherPacket(move(pkt))); if (pkt && ::Network.HandlePuncherPacket(move(pkt), rPacket.getAddr().GetFamily()));
else else
{ {
assert(pNetIO_UDP); assert(pNetIO_UDP);

View File

@ -97,7 +97,8 @@ protected:
iUDPIRate, iUDPORate, iUDPBCRate; iUDPIRate, iUDPORate, iUDPBCRate;
// punching // punching
C4NetIO::addr_t PuncherAddr; C4NetIO::addr_t PuncherAddrIPv4, PuncherAddrIPv6;
bool IsPuncherAddr(const C4NetIO::addr_t& addr) const;
public: public:
@ -137,7 +138,7 @@ public:
// punch // punch
bool InitPuncher(C4NetIO::addr_t PuncherAddr); // by main thread 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 void Punch(const C4NetIO::addr_t&); // sends a ping packet
// stuff // stuff

View File

@ -30,7 +30,7 @@
C4Network2Reference::C4Network2Reference() C4Network2Reference::C4Network2Reference()
: Icon(0), GameMode(), Time(0), Frame(0), StartTime(0), LeaguePerformance(0), : Icon(0), GameMode(), Time(0), Frame(0), StartTime(0), LeaguePerformance(0),
JoinAllowed(true), ObservingAllowed(true), PasswordNeeded(false), OfficialServer(false), 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(Game.sEngineName, "Game", "None"));
pComp->Value(mkNamingAdapt(mkArrayAdaptDM(Game.iVer,0),"Version" )); pComp->Value(mkNamingAdapt(mkArrayAdaptDM(Game.iVer,0),"Version" ));
pComp->Value(mkNamingAdapt(OfficialServer, "OfficialServer", false)); 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(mkNamingAdapt(NetpuncherAddr, "NetpuncherAddr", "", false, false));
pComp->Value(Parameters); pComp->Value(Parameters);

View File

@ -51,7 +51,7 @@ private:
bool PasswordNeeded; bool PasswordNeeded;
bool OfficialServer; bool OfficialServer;
bool IsEditor; bool IsEditor;
C4NetpuncherID_t NetpuncherGameID; C4NetpuncherID NetpuncherGameID;
StdCopyStrBuf NetpuncherAddr; StdCopyStrBuf NetpuncherAddr;
// Engine information // Engine information
@ -79,7 +79,7 @@ public:
int32_t getStartTime() const { return StartTime; } int32_t getStartTime() const { return StartTime; }
StdStrBuf getGameGoalString() const; StdStrBuf getGameGoalString() const;
bool isEditor() const { return IsEditor; } bool isEditor() const { return IsEditor; }
C4NetpuncherID_t getNetpuncherGameID() const { return NetpuncherGameID; } C4NetpuncherID getNetpuncherGameID() const { return NetpuncherGameID; }
StdStrBuf getNetpuncherAddr() const { return NetpuncherAddr; } StdStrBuf getNetpuncherAddr() const { return NetpuncherAddr; }
void SetSourceAddress(const C4NetIO::EndpointAddress &ip); void SetSourceAddress(const C4NetIO::EndpointAddress &ip);