forked from Mirrors/openclonk
Implement netpunching for IPv6
parent
c94b4cc3b0
commit
33a32cb6bd
|
@ -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 {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue