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 <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) {
if (!rpack.getPData()) return nullptr;
try {

View File

@ -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<C4NetpuncherPacketType TYPE>

View File

@ -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<CID>(1/*, max*/), std::ref(random_device));

View File

@ -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()

View File

@ -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:

View File

@ -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<C4NetIOUDP*>(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);

View File

@ -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

View File

@ -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);

View File

@ -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);