forked from Mirrors/openclonk
Merge branch 'ipv6'
commit
ef4f1d9231
|
@ -1254,6 +1254,7 @@ target_link_libraries(netpuncher
|
||||||
)
|
)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
|
target_link_libraries(libmisc iphlpapi)
|
||||||
target_link_libraries(openclonk ws2_32)
|
target_link_libraries(openclonk ws2_32)
|
||||||
target_link_libraries(openclonk-server ws2_32)
|
target_link_libraries(openclonk-server ws2_32)
|
||||||
target_link_libraries(c4group ws2_32)
|
target_link_libraries(c4group ws2_32)
|
||||||
|
|
|
@ -743,8 +743,8 @@ IDS_NET_CLIENT_IGNORE=Ignorieren
|
||||||
IDS_NET_CLIENT_IGNORE_DESC=%s ignorieren. Du kannst Nachrichten von diesem Client dann in der Lobby nicht mehr lesen.
|
IDS_NET_CLIENT_IGNORE_DESC=%s ignorieren. Du kannst Nachrichten von diesem Client dann in der Lobby nicht mehr lesen.
|
||||||
IDS_NET_CLIENT_INFO=Client-Informationen
|
IDS_NET_CLIENT_INFO=Client-Informationen
|
||||||
IDS_NET_CLIENT_INFO_ADDRESSES=Adressen:
|
IDS_NET_CLIENT_INFO_ADDRESSES=Adressen:
|
||||||
IDS_NET_CLIENT_INFO_CONNDATA= Daten: %s (%s:%d, %d ms)
|
IDS_NET_CLIENT_INFO_CONNDATA= Daten: %s (%s, %d ms)
|
||||||
IDS_NET_CLIENT_INFO_CONNECTIONS=Verbindungen: %s: %s (%s:%d, %d ms)
|
IDS_NET_CLIENT_INFO_CONNECTIONS=Verbindungen: %s: %s (%s, %d ms)
|
||||||
IDS_NET_CLIENT_INFO_NOADDRESSES=Addressen: Keine
|
IDS_NET_CLIENT_INFO_NOADDRESSES=Addressen: Keine
|
||||||
IDS_NET_CLIENT_INFO_NOCONNECTIONS=Verbindungen: Nicht verbunden
|
IDS_NET_CLIENT_INFO_NOCONNECTIONS=Verbindungen: Nicht verbunden
|
||||||
IDS_NET_CLIENT_INFO_UNKNOWNID=Unbekannte client ID #%d.
|
IDS_NET_CLIENT_INFO_UNKNOWNID=Unbekannte client ID #%d.
|
||||||
|
@ -816,7 +816,7 @@ IDS_NET_NEWGAME=&Neues Spiel
|
||||||
IDS_NET_NEWGAME_DESC=Startet ein neues Netzwerk- oder Internetspiel.
|
IDS_NET_NEWGAME_DESC=Startet ein neues Netzwerk- oder Internetspiel.
|
||||||
IDS_NET_NODIRECTSTART=Netzwerkspieldaten können nicht direkt gestartet werden.
|
IDS_NET_NODIRECTSTART=Netzwerkspieldaten können nicht direkt gestartet werden.
|
||||||
IDS_NET_NODISCOVERY=Fehler bei der Suche nach Spielen
|
IDS_NET_NODISCOVERY=Fehler bei der Suche nach Spielen
|
||||||
IDS_NET_NODISCOVERY_DESC=Suche nach Spielen fehlgeschlagen: %s
|
IDS_NET_NODISCOVERY_DESC=Suche nach Spielen im lokalen Netzwerk fehlgeschlagen: %s
|
||||||
IDS_NET_NOFILEPUBLISH=Datei %s kann nicht ans Netzwerk übertragen werden!
|
IDS_NET_NOFILEPUBLISH=Datei %s kann nicht ans Netzwerk übertragen werden!
|
||||||
IDS_NET_NOHOSTCON=Konnte nicht mit Host %s verbinden.
|
IDS_NET_NOHOSTCON=Konnte nicht mit Host %s verbinden.
|
||||||
IDS_NET_NOJOIN=Beitritt nicht möglich
|
IDS_NET_NOJOIN=Beitritt nicht möglich
|
||||||
|
|
|
@ -743,8 +743,8 @@ IDS_NET_CLIENT_IGNORE=Ignore
|
||||||
IDS_NET_CLIENT_IGNORE_DESC=Ignores %s. You will not be able to see messages from this client.
|
IDS_NET_CLIENT_IGNORE_DESC=Ignores %s. You will not be able to see messages from this client.
|
||||||
IDS_NET_CLIENT_INFO=Client info
|
IDS_NET_CLIENT_INFO=Client info
|
||||||
IDS_NET_CLIENT_INFO_ADDRESSES=Addresses:
|
IDS_NET_CLIENT_INFO_ADDRESSES=Addresses:
|
||||||
IDS_NET_CLIENT_INFO_CONNDATA= Data: %s (%s:%d, %d ms)
|
IDS_NET_CLIENT_INFO_CONNDATA= Data: %s (%s, %d ms)
|
||||||
IDS_NET_CLIENT_INFO_CONNECTIONS=Connections: %s: %s (%s:%d, %d ms)
|
IDS_NET_CLIENT_INFO_CONNECTIONS=Connections: %s: %s (%s, %d ms)
|
||||||
IDS_NET_CLIENT_INFO_NOADDRESSES=Addresses: none
|
IDS_NET_CLIENT_INFO_NOADDRESSES=Addresses: none
|
||||||
IDS_NET_CLIENT_INFO_NOCONNECTIONS=Connections: Not connected
|
IDS_NET_CLIENT_INFO_NOCONNECTIONS=Connections: Not connected
|
||||||
IDS_NET_CLIENT_INFO_UNKNOWNID=Unknown client ID #%d.
|
IDS_NET_CLIENT_INFO_UNKNOWNID=Unknown client ID #%d.
|
||||||
|
@ -815,8 +815,8 @@ IDS_NET_MSSEARCH_DESC=Search masterserver games for keywords.
|
||||||
IDS_NET_NEWGAME=&New game
|
IDS_NET_NEWGAME=&New game
|
||||||
IDS_NET_NEWGAME_DESC=Create a new network or internet game.
|
IDS_NET_NEWGAME_DESC=Create a new network or internet game.
|
||||||
IDS_NET_NODIRECTSTART=Cannot start network game data directly.
|
IDS_NET_NODIRECTSTART=Cannot start network game data directly.
|
||||||
IDS_NET_NODISCOVERY=Search Error
|
IDS_NET_NODISCOVERY=Game Search Error
|
||||||
IDS_NET_NODISCOVERY_DESC=Search failed: %s
|
IDS_NET_NODISCOVERY_DESC=Game search in local network failed: %s
|
||||||
IDS_NET_NOFILEPUBLISH=File %s cannot be published on network!
|
IDS_NET_NOFILEPUBLISH=File %s cannot be published on network!
|
||||||
IDS_NET_NOHOSTCON=Could not connect to host %s.
|
IDS_NET_NOHOSTCON=Could not connect to host %s.
|
||||||
IDS_NET_NOJOIN=Cannot join game
|
IDS_NET_NOJOIN=Cannot join game
|
||||||
|
|
|
@ -920,8 +920,7 @@ void C4StartupNetDlg::UpdateList(bool fGotReference)
|
||||||
C4NetIO::addr_t Discover;
|
C4NetIO::addr_t Discover;
|
||||||
while (DiscoverClient.PopDiscover(Discover))
|
while (DiscoverClient.PopDiscover(Discover))
|
||||||
{
|
{
|
||||||
StdStrBuf Address;
|
StdStrBuf Address(Discover.ToString());
|
||||||
Address.Format("%s:%d", inet_ntoa(Discover.sin_addr), htons(Discover.sin_port));
|
|
||||||
AddReferenceQuery(Address.getData(), C4StartupNetListEntry::NRQT_GameDiscovery);
|
AddReferenceQuery(Address.getData(), C4StartupNetListEntry::NRQT_GameDiscovery);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,10 +60,26 @@ namespace std {
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct hash<::sockaddr_in> {
|
struct hash<C4NetIO::addr_t> {
|
||||||
size_t operator()(const ::sockaddr_in& addr) const {
|
size_t operator()(const C4NetIO::addr_t& addr) const {
|
||||||
auto unpack = make_tuple(addr.sin_family, addr.sin_addr.s_addr, addr.sin_port);
|
switch (addr.GetFamily())
|
||||||
return hash<decltype(unpack)>()(unpack);
|
{
|
||||||
|
case C4NetIO::HostAddress::IPv4:
|
||||||
|
{
|
||||||
|
sockaddr_in v4 = addr;
|
||||||
|
auto unpack = make_tuple(v4.sin_family, v4.sin_addr.s_addr, v4.sin_port);
|
||||||
|
return hash<decltype(unpack)>()(unpack);
|
||||||
|
}
|
||||||
|
case C4NetIO::HostAddress::IPv6:
|
||||||
|
{
|
||||||
|
sockaddr_in6 v6 = addr;
|
||||||
|
auto unpack = make_tuple(v6.sin6_family, v6.sin6_port, v6.sin6_flowinfo, std::string((char*) v6.sin6_addr.s6_addr, 16), v6.sin6_scope_id);
|
||||||
|
return hash<decltype(unpack)>()(unpack);
|
||||||
|
}
|
||||||
|
case C4NetIO::HostAddress::UnknownFamily:
|
||||||
|
assert(!"Unexpected address family");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
@ -47,9 +52,7 @@ C4NetpuncherPacketCReq::C4NetpuncherPacketCReq(const C4NetIOPacket& rpack) {
|
||||||
C4Network2Address parse_addr;
|
C4Network2Address parse_addr;
|
||||||
CompileFromBuf<StdCompilerBinRead>(parse_addr, rpack.getPBuf());
|
CompileFromBuf<StdCompilerBinRead>(parse_addr, rpack.getPBuf());
|
||||||
if (parse_addr.getProtocol() != P_UDP) throw P_UDP;
|
if (parse_addr.getProtocol() != P_UDP) throw P_UDP;
|
||||||
addr.sin_addr.s_addr = parse_addr.getAddr().sin_addr.s_addr,
|
addr = parse_addr.getAddr();
|
||||||
addr.sin_family = parse_addr.getAddr().sin_family,
|
|
||||||
addr.sin_port = parse_addr.getAddr().sin_port;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StdBuf C4NetpuncherPacketCReq::PackInto() const {
|
StdBuf C4NetpuncherPacketCReq::PackInto() const {
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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));
|
||||||
|
@ -48,7 +48,7 @@ private:
|
||||||
peer_ids.emplace(AddrPeer, nid);
|
peer_ids.emplace(AddrPeer, nid);
|
||||||
peer_addrs.emplace(nid, AddrPeer);
|
peer_addrs.emplace(nid, AddrPeer);
|
||||||
Send(C4NetpuncherPacketAssID(nid).PackTo(AddrPeer));
|
Send(C4NetpuncherPacketAssID(nid).PackTo(AddrPeer));
|
||||||
printf("Punched %s:%d... #%u\n", inet_ntoa(AddrPeer.sin_addr), htons(AddrPeer.sin_port), nid);
|
printf("Punched %s... #%u\n", AddrPeer.ToString().getData(), nid);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
virtual void OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO) {
|
virtual void OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO) {
|
||||||
|
@ -63,12 +63,12 @@ private:
|
||||||
virtual void OnDisconn(const addr_t &AddrPeer, C4NetIO *pNetIO, const char *szReason) {
|
virtual void OnDisconn(const addr_t &AddrPeer, C4NetIO *pNetIO, const char *szReason) {
|
||||||
auto it = peer_ids.find(AddrPeer);
|
auto it = peer_ids.find(AddrPeer);
|
||||||
if (it == peer_ids.end()) {
|
if (it == peer_ids.end()) {
|
||||||
printf("ERROR: closing connection for %s:%d: (%s) but no connection is known\n", inet_ntoa(AddrPeer.sin_addr), htons(AddrPeer.sin_port), szReason);
|
printf("ERROR: closing connection for %s: (%s) but no connection is known\n", AddrPeer.ToString().getData(), szReason);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
peer_addrs.erase(it->second);
|
peer_addrs.erase(it->second);
|
||||||
peer_ids.erase(it);
|
peer_ids.erase(it);
|
||||||
printf("Stopped punching %s:%d: %s...\n", inet_ntoa(AddrPeer.sin_addr), htons(AddrPeer.sin_port), szReason);
|
printf("Stopped punching %s: %s...\n", AddrPeer.ToString().getData(), szReason);
|
||||||
};
|
};
|
||||||
} Puncher;
|
} Puncher;
|
||||||
|
|
||||||
|
@ -96,7 +96,11 @@ int main(int argc, char * argv[])
|
||||||
printf("Listening on port %d...\n", iPort);
|
printf("Listening on port %d...\n", iPort);
|
||||||
|
|
||||||
// Execute forever
|
// Execute forever
|
||||||
Puncher.ExecuteUntil(-1);
|
for (;;)
|
||||||
|
{
|
||||||
|
Puncher.ExecuteUntil(-1);
|
||||||
|
fprintf(stderr, "ERROR: %s\n", Puncher.GetError());
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -65,9 +65,152 @@ public:
|
||||||
|
|
||||||
// *** constants / types
|
// *** constants / types
|
||||||
static const int TO_INF; // = -1;
|
static const int TO_INF; // = -1;
|
||||||
static const uint16_t P_NONE; // = -1
|
|
||||||
|
|
||||||
typedef sockaddr_in addr_t;
|
struct HostAddress
|
||||||
|
{
|
||||||
|
enum AddressFamily
|
||||||
|
{
|
||||||
|
IPv6 = AF_INET6,
|
||||||
|
IPv4 = AF_INET,
|
||||||
|
UnknownFamily = 0
|
||||||
|
};
|
||||||
|
enum SpecialAddress
|
||||||
|
{
|
||||||
|
Loopback, // IPv6 localhost (::1)
|
||||||
|
Any, // IPv6 any-address (::)
|
||||||
|
AnyIPv4 // IPv4 any-address (0.0.0.0)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ToStringFlags
|
||||||
|
{
|
||||||
|
TSF_SkipZoneId = 1,
|
||||||
|
TSF_SkipPort = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
HostAddress() { Clear(); }
|
||||||
|
HostAddress(const HostAddress &other) { SetHost(other); }
|
||||||
|
HostAddress(SpecialAddress addr) { SetHost(addr); }
|
||||||
|
explicit HostAddress(uint32_t addr) { SetHost(addr); }
|
||||||
|
HostAddress(const StdStrBuf &addr) { SetHost(addr); }
|
||||||
|
HostAddress(const sockaddr *addr) { SetHost(addr); }
|
||||||
|
|
||||||
|
AddressFamily GetFamily() const;
|
||||||
|
|
||||||
|
void SetScopeId(int scopeId);
|
||||||
|
int GetScopeId() const;
|
||||||
|
|
||||||
|
void Clear();
|
||||||
|
void SetHost(const sockaddr *addr);
|
||||||
|
void SetHost(const HostAddress &host);
|
||||||
|
void SetHost(SpecialAddress host);
|
||||||
|
void SetHost(const StdStrBuf &host, AddressFamily family = UnknownFamily);
|
||||||
|
void SetHost(uint32_t host);
|
||||||
|
|
||||||
|
C4NetIO::HostAddress AsIPv6() const; // convert an IPv4 address to an IPv6-mapped IPv4 address
|
||||||
|
C4NetIO::HostAddress AsIPv4() const; // try to convert an IPv6-mapped IPv4 address to an IPv4 address (returns unchanged address if not possible)
|
||||||
|
|
||||||
|
// General categories
|
||||||
|
bool IsNull() const;
|
||||||
|
bool IsMulticast() const;
|
||||||
|
bool IsLoopback() const;
|
||||||
|
bool IsLocal() const;
|
||||||
|
// bool IsBroadcast() const;
|
||||||
|
|
||||||
|
StdStrBuf ToString(int flags = 0) const;
|
||||||
|
|
||||||
|
bool operator ==(const HostAddress &rhs) const;
|
||||||
|
bool operator !=(const HostAddress &rhs) const { return !(*this == rhs); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// data
|
||||||
|
union
|
||||||
|
{
|
||||||
|
sockaddr gen;
|
||||||
|
sockaddr_in v4;
|
||||||
|
sockaddr_in6 v6;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EndpointAddress : public HostAddress // Host and port
|
||||||
|
{
|
||||||
|
static const uint16_t IPPORT_NONE = 0;
|
||||||
|
|
||||||
|
EndpointAddress() { Clear(); }
|
||||||
|
EndpointAddress(const EndpointAddress &other) : HostAddress() { SetAddress(other); }
|
||||||
|
EndpointAddress(const HostAddress &host, uint16_t port = IPPORT_NONE) : HostAddress(host) { SetPort(port); }
|
||||||
|
EndpointAddress(HostAddress::SpecialAddress addr, uint16_t port = IPPORT_NONE) : HostAddress(addr) { SetPort(port); }
|
||||||
|
explicit EndpointAddress(const StdStrBuf &addr) { SetAddress(addr); }
|
||||||
|
|
||||||
|
StdStrBuf ToString(int flags = 0) const;
|
||||||
|
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
void SetAddress(const sockaddr *addr);
|
||||||
|
void SetAddress(const EndpointAddress &other);
|
||||||
|
void SetAddress(HostAddress::SpecialAddress addr, uint16_t port = IPPORT_NONE);
|
||||||
|
void SetAddress(const HostAddress &host, uint16_t port = IPPORT_NONE);
|
||||||
|
void SetAddress(const StdStrBuf &addr, AddressFamily family = UnknownFamily);
|
||||||
|
|
||||||
|
HostAddress GetHost() const { return *this; } // HostAddress copy ctor slices off port information
|
||||||
|
EndpointAddress AsIPv6() const; // convert an IPv4 address to an IPv6-mapped IPv4 address
|
||||||
|
EndpointAddress AsIPv4() const; // try to convert an IPv6-mapped IPv4 address to an IPv4 address (returns unchanged address if not possible)
|
||||||
|
|
||||||
|
void SetPort(uint16_t port);
|
||||||
|
void SetDefaultPort(uint16_t port); // set a port only if there is none
|
||||||
|
uint16_t GetPort() const;
|
||||||
|
|
||||||
|
bool IsNull() const;
|
||||||
|
bool IsNullHost() const { return HostAddress::IsNull(); }
|
||||||
|
|
||||||
|
// Pointer wrapper to be able to implicitly convert to sockaddr*
|
||||||
|
class EndpointAddressPtr;
|
||||||
|
const EndpointAddressPtr operator &() const;
|
||||||
|
EndpointAddressPtr operator &();
|
||||||
|
class EndpointAddressPtr
|
||||||
|
{
|
||||||
|
EndpointAddress * const p;
|
||||||
|
friend EndpointAddressPtr EndpointAddress::operator &();
|
||||||
|
friend const EndpointAddressPtr EndpointAddress::operator &() const;
|
||||||
|
EndpointAddressPtr(EndpointAddress *p) : p(p) {}
|
||||||
|
public:
|
||||||
|
const EndpointAddress &operator *() const { return *p; }
|
||||||
|
EndpointAddress &operator *() { return *p; }
|
||||||
|
|
||||||
|
const EndpointAddress &operator ->() const { return *p; }
|
||||||
|
EndpointAddress &operator ->() { return *p; }
|
||||||
|
|
||||||
|
operator const EndpointAddress*() const { return p; }
|
||||||
|
operator EndpointAddress*() { return p; }
|
||||||
|
|
||||||
|
operator const sockaddr*() const { return &p->gen; }
|
||||||
|
operator sockaddr*() { return &p->gen; }
|
||||||
|
|
||||||
|
operator const sockaddr_in*() const { return &p->v4; }
|
||||||
|
operator sockaddr_in*() { return &p->v4; }
|
||||||
|
|
||||||
|
operator const sockaddr_in6*() const { return &p->v6; }
|
||||||
|
operator sockaddr_in6*() { return &p->v6; }
|
||||||
|
};
|
||||||
|
|
||||||
|
bool operator ==(const EndpointAddress &rhs) const;
|
||||||
|
bool operator !=(const EndpointAddress &rhs) const { return !(*this == rhs); }
|
||||||
|
|
||||||
|
// conversions
|
||||||
|
operator sockaddr() const { return gen; }
|
||||||
|
operator sockaddr_in() const { assert(gen.sa_family == AF_INET); return v4; }
|
||||||
|
operator sockaddr_in6() const { assert(gen.sa_family == AF_INET6); return v6; }
|
||||||
|
|
||||||
|
// StdCompiler
|
||||||
|
void CompileFunc(StdCompiler *comp);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool SetAddressByString(const StdStrBuf &address, short family);
|
||||||
|
|
||||||
|
friend class EndpointAddressPtr;
|
||||||
|
};
|
||||||
|
typedef EndpointAddress addr_t;
|
||||||
|
|
||||||
|
static std::vector<HostAddress> GetLocalAddresses();
|
||||||
|
|
||||||
// callback class
|
// callback class
|
||||||
class CBClass
|
class CBClass
|
||||||
|
@ -108,10 +251,8 @@ public:
|
||||||
// *** interface
|
// *** interface
|
||||||
|
|
||||||
// * not multithreading safe
|
// * not multithreading safe
|
||||||
virtual bool Init(uint16_t iPort = P_NONE) = 0;
|
virtual bool Init(uint16_t iPort = addr_t::IPPORT_NONE) = 0;
|
||||||
virtual bool InitBroadcast(addr_t *pBroadcastAddr) = 0;
|
|
||||||
virtual bool Close() = 0;
|
virtual bool Close() = 0;
|
||||||
virtual bool CloseBroadcast() = 0;
|
|
||||||
|
|
||||||
virtual bool Execute(int iTimeout = -1, pollfd * = 0) = 0; // (for StdSchedulerProc)
|
virtual bool Execute(int iTimeout = -1, pollfd * = 0) = 0; // (for StdSchedulerProc)
|
||||||
virtual bool IsNotify() { return true; }
|
virtual bool IsNotify() { return true; }
|
||||||
|
@ -129,6 +270,12 @@ public:
|
||||||
virtual bool GetConnStatistic(const addr_t &addr, int *pIRate, int *pORate, int *pLoss) = 0;
|
virtual bool GetConnStatistic(const addr_t &addr, int *pIRate, int *pORate, int *pLoss) = 0;
|
||||||
virtual void ClearStatistic() = 0;
|
virtual void ClearStatistic() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// virtual SOCKET CreateSocket() = 0;
|
||||||
|
|
||||||
|
// Makes IPv4 connections from an IPv6 socket work.
|
||||||
|
bool EnableDualStack(SOCKET socket);
|
||||||
|
|
||||||
// *** errors
|
// *** errors
|
||||||
protected:
|
protected:
|
||||||
StdCopyStrBuf Error;
|
StdCopyStrBuf Error;
|
||||||
|
@ -193,7 +340,7 @@ public:
|
||||||
// *** interface
|
// *** interface
|
||||||
|
|
||||||
// * not multithreading safe
|
// * not multithreading safe
|
||||||
virtual bool Init(uint16_t iPort = P_NONE);
|
virtual bool Init(uint16_t iPort = addr_t::IPPORT_NONE);
|
||||||
virtual bool InitBroadcast(addr_t *pBroadcastAddr);
|
virtual bool InitBroadcast(addr_t *pBroadcastAddr);
|
||||||
virtual bool Close();
|
virtual bool Close();
|
||||||
virtual bool CloseBroadcast();
|
virtual bool CloseBroadcast();
|
||||||
|
@ -352,7 +499,7 @@ public:
|
||||||
C4NetIOSimpleUDP();
|
C4NetIOSimpleUDP();
|
||||||
virtual ~C4NetIOSimpleUDP();
|
virtual ~C4NetIOSimpleUDP();
|
||||||
|
|
||||||
virtual bool Init(uint16_t iPort = P_NONE);
|
virtual bool Init(uint16_t iPort = addr_t::IPPORT_NONE);
|
||||||
virtual bool InitBroadcast(addr_t *pBroadcastAddr);
|
virtual bool InitBroadcast(addr_t *pBroadcastAddr);
|
||||||
virtual bool Close();
|
virtual bool Close();
|
||||||
virtual bool CloseBroadcast();
|
virtual bool CloseBroadcast();
|
||||||
|
@ -395,7 +542,7 @@ private:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// multicast
|
// multicast
|
||||||
addr_t MCAddr; ip_mreq MCGrpInfo;
|
addr_t MCAddr; ipv6_mreq MCGrpInfo;
|
||||||
bool fMCLoopback;
|
bool fMCLoopback;
|
||||||
|
|
||||||
// multibind
|
// multibind
|
||||||
|
@ -440,7 +587,7 @@ public:
|
||||||
|
|
||||||
// *** interface
|
// *** interface
|
||||||
|
|
||||||
virtual bool Init(uint16_t iPort = P_NONE);
|
virtual bool Init(uint16_t iPort = addr_t::IPPORT_NONE);
|
||||||
virtual bool InitBroadcast(addr_t *pBroadcastAddr);
|
virtual bool InitBroadcast(addr_t *pBroadcastAddr);
|
||||||
virtual bool Close();
|
virtual bool Close();
|
||||||
virtual bool CloseBroadcast();
|
virtual bool CloseBroadcast();
|
||||||
|
@ -479,6 +626,7 @@ protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
// packet structures
|
// packet structures
|
||||||
|
struct BinAddr;
|
||||||
struct PacketHdr; struct TestPacket; struct ConnPacket; struct ConnOKPacket; struct AddAddrPacket;
|
struct PacketHdr; struct TestPacket; struct ConnPacket; struct ConnOKPacket; struct AddAddrPacket;
|
||||||
struct DataPacketHdr; struct CheckPacketHdr; struct ClosePacket;
|
struct DataPacketHdr; struct CheckPacketHdr; struct ClosePacket;
|
||||||
|
|
||||||
|
@ -806,48 +954,9 @@ private:
|
||||||
void EnlargeIO(int iBy);
|
void EnlargeIO(int iBy);
|
||||||
};
|
};
|
||||||
|
|
||||||
// helpers
|
|
||||||
inline bool AddrEqual(const C4NetIO::addr_t addr1, const C4NetIO::addr_t addr2)
|
|
||||||
{
|
|
||||||
return addr1.sin_addr.s_addr == addr2.sin_addr.s_addr &&
|
|
||||||
addr1.sin_family == addr2.sin_family &&
|
|
||||||
addr1.sin_port == addr2.sin_port;
|
|
||||||
}
|
|
||||||
inline bool operator == (const C4NetIO::addr_t addr1, const C4NetIO::addr_t addr2) { return AddrEqual(addr1, addr2); }
|
|
||||||
inline bool operator != (const C4NetIO::addr_t addr1, const C4NetIO::addr_t addr2) { return !AddrEqual(addr1, addr2); }
|
|
||||||
|
|
||||||
// there seems to be no standard way to get these numbers, so let's do it the dirty way...
|
|
||||||
inline uint8_t &in_addr_b(in_addr &addr, int i)
|
|
||||||
{
|
|
||||||
assert(0 <= i && i < 4);
|
|
||||||
return *(reinterpret_cast<uint8_t *>(&addr.s_addr) + i);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void CompileFunc(in_addr &ip, StdCompiler *pComp)
|
|
||||||
{
|
|
||||||
pComp->Value(in_addr_b(ip, 0)); pComp->Separator(StdCompiler::SEP_PART);
|
|
||||||
pComp->Value(in_addr_b(ip, 1)); pComp->Separator(StdCompiler::SEP_PART);
|
|
||||||
pComp->Value(in_addr_b(ip, 2)); pComp->Separator(StdCompiler::SEP_PART);
|
|
||||||
pComp->Value(in_addr_b(ip, 3));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void CompileFunc(C4NetIO::addr_t &addr, StdCompiler *pComp)
|
|
||||||
{
|
|
||||||
pComp->Value(addr.sin_addr); pComp->Separator(StdCompiler::SEP_PART2);
|
|
||||||
uint16_t iPort = htons(addr.sin_port);
|
|
||||||
pComp->Value(iPort);
|
|
||||||
addr.sin_port = htons(iPort);
|
|
||||||
if (pComp->isCompiler())
|
|
||||||
{
|
|
||||||
addr.sin_family = AF_INET;
|
|
||||||
ZeroMem(addr.sin_zero, sizeof(addr.sin_zero));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_WINSOCK
|
#ifdef HAVE_WINSOCK
|
||||||
bool AcquireWinSock();
|
bool AcquireWinSock();
|
||||||
void ReleaseWinSock();
|
void ReleaseWinSock();
|
||||||
#endif
|
#endif
|
||||||
bool ResolveAddress(const char *szAddress, C4NetIO::addr_t *paddr, uint16_t iPort);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -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);
|
||||||
|
@ -247,7 +247,10 @@ C4Network2::InitResult C4Network2::InitClient(const C4Network2Reference &Ref, bo
|
||||||
// copy addresses
|
// copy addresses
|
||||||
C4Network2Address Addrs[C4ClientMaxAddr];
|
C4Network2Address Addrs[C4ClientMaxAddr];
|
||||||
for (int i = 0; i < Ref.getAddrCnt(); i++)
|
for (int i = 0; i < Ref.getAddrCnt(); i++)
|
||||||
|
{
|
||||||
Addrs[i] = Ref.getAddr(i);
|
Addrs[i] = Ref.getAddr(i);
|
||||||
|
Addrs[i].getAddr().SetScopeId(Ref.GetSourceAddress().GetScopeId());
|
||||||
|
}
|
||||||
// Try to connect to host
|
// Try to connect to host
|
||||||
if (InitClient(Addrs, Ref.getAddrCnt(), HostCore, Password.getData()) == IR_Fatal)
|
if (InitClient(Addrs, Ref.getAddrCnt(), HostCore, Password.getData()) == IR_Fatal)
|
||||||
return IR_Fatal;
|
return IR_Fatal;
|
||||||
|
@ -307,9 +310,25 @@ C4Network2::InitResult C4Network2::InitClient(const class C4Network2Address *pAd
|
||||||
for (int i = 0; i < iAddrCount; i++)
|
for (int i = 0; i < iAddrCount; i++)
|
||||||
if (!pAddrs[i].isIPNull())
|
if (!pAddrs[i].isIPNull())
|
||||||
{
|
{
|
||||||
|
auto addr = pAddrs[i].getAddr();
|
||||||
|
std::vector<C4NetIO::addr_t> addrs;
|
||||||
|
if (addr.IsLocal())
|
||||||
|
{
|
||||||
|
// Local IPv6 addresses need a scope id.
|
||||||
|
for (auto& id : Clients.GetLocal()->getInterfaceIDs())
|
||||||
|
{
|
||||||
|
addr.SetScopeId(id);
|
||||||
|
addrs.push_back(addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
addrs.push_back(addr);
|
||||||
// connection
|
// connection
|
||||||
if (!NetIO.Connect(pAddrs[i].getAddr(), pAddrs[i].getProtocol(), HostCore, szPassword))
|
int cnt = 0;
|
||||||
continue;
|
for (auto& a : addrs)
|
||||||
|
if (NetIO.Connect(a, pAddrs[i].getProtocol(), HostCore, szPassword))
|
||||||
|
cnt++;
|
||||||
|
if (cnt == 0) continue;
|
||||||
// format for message
|
// format for message
|
||||||
if (strAddresses.getLength())
|
if (strAddresses.getLength())
|
||||||
strAddresses.Append(", ");
|
strAddresses.Append(", ");
|
||||||
|
@ -670,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
|
||||||
}
|
}
|
||||||
|
@ -888,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);
|
||||||
|
@ -909,26 +928,48 @@ 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;
|
||||||
|
case C4NetIO::HostAddress::UnknownFamily: assert(!"Unexpected address family");
|
||||||
|
}
|
||||||
|
// We need to return a valid reference to satisfy the compiler, even though the code here is unreachable.
|
||||||
|
return NetpuncherGameID.v4;
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
C4NetIO::addr_t PuncherAddr;
|
C4NetIO::addr_t PuncherAddr;
|
||||||
if (ResolveAddress(getNetpuncherAddr().getData(), &PuncherAddr, C4NetStdPortPuncher))
|
PuncherAddr.SetAddress(getNetpuncherAddr(), C4NetIO::HostAddress::IPv4);
|
||||||
NetIO.InitPuncher(PuncherAddr);
|
if (!PuncherAddr.IsNull())
|
||||||
|
{
|
||||||
|
PuncherAddr.SetDefaultPort(C4NetStdPortPuncher);
|
||||||
|
NetIO.InitPuncher(PuncherAddr);
|
||||||
|
}
|
||||||
|
PuncherAddr.SetAddress(getNetpuncherAddr(), C4NetIO::HostAddress::IPv6);
|
||||||
|
if (!PuncherAddr.IsNull())
|
||||||
|
{
|
||||||
|
PuncherAddr.SetDefaultPort(C4NetStdPortPuncher);
|
||||||
|
NetIO.InitPuncher(PuncherAddr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void C4Network2::OnGameSynchronized()
|
void C4Network2::OnGameSynchronized()
|
||||||
|
@ -1043,18 +1084,16 @@ void C4Network2::DrawStatus(C4TargetFacet &cgo)
|
||||||
// connections
|
// connections
|
||||||
if (pClient->isConnected())
|
if (pClient->isConnected())
|
||||||
{
|
{
|
||||||
Stat.AppendFormat( "| Connections: %s: %s (%s:%d p%d l%d)",
|
Stat.AppendFormat( "| Connections: %s: %s (%s p%d l%d)",
|
||||||
pClient->getMsgConn() == pClient->getDataConn() ? "Msg/Data" : "Msg",
|
pClient->getMsgConn() == pClient->getDataConn() ? "Msg/Data" : "Msg",
|
||||||
NetIO.getNetIOName(pClient->getMsgConn()->getNetClass()),
|
NetIO.getNetIOName(pClient->getMsgConn()->getNetClass()),
|
||||||
inet_ntoa(pClient->getMsgConn()->getPeerAddr().sin_addr),
|
pClient->getMsgConn()->getPeerAddr().ToString().getData(),
|
||||||
htons(pClient->getMsgConn()->getPeerAddr().sin_port),
|
|
||||||
pClient->getMsgConn()->getPingTime(),
|
pClient->getMsgConn()->getPingTime(),
|
||||||
pClient->getMsgConn()->getPacketLoss());
|
pClient->getMsgConn()->getPacketLoss());
|
||||||
if (pClient->getMsgConn() != pClient->getDataConn())
|
if (pClient->getMsgConn() != pClient->getDataConn())
|
||||||
Stat.AppendFormat( ", Data: %s (%s:%d p%d l%d)",
|
Stat.AppendFormat( ", Data: %s (%s:%d p%d l%d)",
|
||||||
NetIO.getNetIOName(pClient->getDataConn()->getNetClass()),
|
NetIO.getNetIOName(pClient->getDataConn()->getNetClass()),
|
||||||
inet_ntoa(pClient->getDataConn()->getPeerAddr().sin_addr),
|
pClient->getDataConn()->getPeerAddr().ToString().getData(),
|
||||||
htons(pClient->getDataConn()->getPeerAddr().sin_port),
|
|
||||||
pClient->getDataConn()->getPingTime(),
|
pClient->getDataConn()->getPingTime(),
|
||||||
pClient->getDataConn()->getPacketLoss());
|
pClient->getDataConn()->getPacketLoss());
|
||||||
}
|
}
|
||||||
|
@ -1183,7 +1222,7 @@ void C4Network2::HandleConn(const C4PacketConn &Pkt, C4Network2IOConnection *pCo
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// log & close
|
// log & close
|
||||||
LogSilentF("Network: connection by %s (%s:%d) blocked: %s", CCore.getName(), inet_ntoa(pConn->getPeerAddr().sin_addr), htons(pConn->getPeerAddr().sin_port), reply.getData());
|
LogSilentF("Network: connection by %s (%s) blocked: %s", CCore.getName(), pConn->getPeerAddr().ToString().getData(), reply.getData());
|
||||||
pConn->Close();
|
pConn->Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1197,9 +1236,6 @@ bool C4Network2::CheckConn(const C4ClientCore &CCore, C4Network2IOConnection *pC
|
||||||
// check core
|
// check core
|
||||||
if (CCore.getDiffLevel(pClient->getCore()) > C4ClientCoreDL_IDMatch)
|
if (CCore.getDiffLevel(pClient->getCore()) > C4ClientCoreDL_IDMatch)
|
||||||
{ *szReply = "wrong client core"; return false; }
|
{ *szReply = "wrong client core"; return false; }
|
||||||
// check address
|
|
||||||
if (pClient->isConnected() && pClient->getMsgConn()->getPeerAddr().sin_addr.s_addr != pConn->getPeerAddr().sin_addr.s_addr)
|
|
||||||
{ *szReply = "wrong address"; return false; }
|
|
||||||
// accept
|
// accept
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1277,7 +1313,7 @@ void C4Network2::HandleConnRe(const C4PacketConnRe &Pkt, C4Network2IOConnection
|
||||||
// wrong password?
|
// wrong password?
|
||||||
fWrongPassword = Pkt.isPasswordWrong();
|
fWrongPassword = Pkt.isPasswordWrong();
|
||||||
// show message
|
// show message
|
||||||
LogSilentF("Network: connection to %s (%s:%d) refused: %s", pClient->getName(), inet_ntoa(pConn->getPeerAddr().sin_addr), htons(pConn->getPeerAddr().sin_port), Pkt.getMsg());
|
LogSilentF("Network: connection to %s (%s) refused: %s", pClient->getName(), pConn->getPeerAddr().ToString().getData(), Pkt.getMsg());
|
||||||
// close connection
|
// close connection
|
||||||
pConn->Close();
|
pConn->Close();
|
||||||
return;
|
return;
|
||||||
|
@ -1302,7 +1338,7 @@ void C4Network2::HandleConnRe(const C4PacketConnRe &Pkt, C4Network2IOConnection
|
||||||
if (pConn->getNetClass() == NetIO.DataIO()) pClient->SetDataConn(pConn);
|
if (pConn->getNetClass() == NetIO.DataIO()) pClient->SetDataConn(pConn);
|
||||||
|
|
||||||
// add peer connect address to client address list
|
// add peer connect address to client address list
|
||||||
if (pConn->getConnectAddr().sin_addr.s_addr)
|
if (!pConn->getConnectAddr().IsNull())
|
||||||
{
|
{
|
||||||
C4Network2Address Addr(pConn->getConnectAddr(), pConn->getProtocol());
|
C4Network2Address Addr(pConn->getConnectAddr(), pConn->getProtocol());
|
||||||
pClient->AddAddr(Addr, Status.getState() != GS_Init);
|
pClient->AddAddr(Addr, Status.getState() != GS_Init);
|
||||||
|
@ -1432,8 +1468,8 @@ void C4Network2::HandleJoinData(const C4PacketJoinData &rPkt)
|
||||||
void C4Network2::OnConnect(C4Network2Client *pClient, C4Network2IOConnection *pConn, const char *szMsg, bool fFirstConnection)
|
void C4Network2::OnConnect(C4Network2Client *pClient, C4Network2IOConnection *pConn, const char *szMsg, bool fFirstConnection)
|
||||||
{
|
{
|
||||||
// log
|
// log
|
||||||
LogSilentF("Network: %s %s connected (%s:%d/%s) (%s)", pClient->isHost() ? "host" : "client",
|
LogSilentF("Network: %s %s connected (%s/%s) (%s)", pClient->isHost() ? "host" : "client",
|
||||||
pClient->getName(), inet_ntoa(pConn->getPeerAddr().sin_addr), htons(pConn->getPeerAddr().sin_port),
|
pClient->getName(), pConn->getPeerAddr().ToString().getData(),
|
||||||
NetIO.getNetIOName(pConn->getNetClass()), szMsg ? szMsg : "");
|
NetIO.getNetIOName(pConn->getNetClass()), szMsg ? szMsg : "");
|
||||||
|
|
||||||
// first connection for this peer? call special handler
|
// first connection for this peer? call special handler
|
||||||
|
@ -1442,8 +1478,8 @@ void C4Network2::OnConnect(C4Network2Client *pClient, C4Network2IOConnection *pC
|
||||||
|
|
||||||
void C4Network2::OnConnectFail(C4Network2IOConnection *pConn)
|
void C4Network2::OnConnectFail(C4Network2IOConnection *pConn)
|
||||||
{
|
{
|
||||||
LogSilentF("Network: %s connection to %s:%d failed!", NetIO.getNetIOName(pConn->getNetClass()),
|
LogSilentF("Network: %s connection to %s failed!", NetIO.getNetIOName(pConn->getNetClass()),
|
||||||
inet_ntoa(pConn->getPeerAddr().sin_addr), htons(pConn->getPeerAddr().sin_port));
|
pConn->getPeerAddr().ToString().getData());
|
||||||
|
|
||||||
// maybe client connection failure
|
// maybe client connection failure
|
||||||
// (happens if the connection is not fully accepted and the client disconnects.
|
// (happens if the connection is not fully accepted and the client disconnects.
|
||||||
|
@ -1455,8 +1491,8 @@ void C4Network2::OnConnectFail(C4Network2IOConnection *pConn)
|
||||||
|
|
||||||
void C4Network2::OnDisconnect(C4Network2Client *pClient, C4Network2IOConnection *pConn)
|
void C4Network2::OnDisconnect(C4Network2Client *pClient, C4Network2IOConnection *pConn)
|
||||||
{
|
{
|
||||||
LogSilentF("Network: %s connection to %s (%s:%d) lost!", NetIO.getNetIOName(pConn->getNetClass()),
|
LogSilentF("Network: %s connection to %s (%s) lost!", NetIO.getNetIOName(pConn->getNetClass()),
|
||||||
pClient->getName(), inet_ntoa(pConn->getPeerAddr().sin_addr), htons(pConn->getPeerAddr().sin_port));
|
pClient->getName(), pConn->getPeerAddr().ToString().getData());
|
||||||
|
|
||||||
// connection lost?
|
// connection lost?
|
||||||
if (!pClient->isConnected())
|
if (!pClient->isConnected())
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -31,8 +31,7 @@ void C4Network2Address::CompileFunc(StdCompiler *pComp)
|
||||||
// Clear
|
// Clear
|
||||||
if (pComp->isCompiler())
|
if (pComp->isCompiler())
|
||||||
{
|
{
|
||||||
ZeroMem(&addr, sizeof(addr));
|
addr.Clear();
|
||||||
addr.sin_family = AF_INET;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write protocol
|
// Write protocol
|
||||||
|
@ -41,34 +40,27 @@ void C4Network2Address::CompileFunc(StdCompiler *pComp)
|
||||||
{ "UDP", P_UDP },
|
{ "UDP", P_UDP },
|
||||||
{ "TCP", P_TCP },
|
{ "TCP", P_TCP },
|
||||||
|
|
||||||
{ nullptr, P_NONE },
|
{ nullptr, P_NONE },
|
||||||
};
|
};
|
||||||
pComp->Value(mkEnumAdaptT<uint8_t>(eProtocol, Protocols));
|
pComp->Value(mkEnumAdaptT<uint8_t>(eProtocol, Protocols));
|
||||||
pComp->Separator(StdCompiler::SEP_PART2); // ':'
|
pComp->Separator(StdCompiler::SEP_PART2); // ':'
|
||||||
|
|
||||||
// Write IP (no IP = 0.0.0.0)
|
pComp->Value(mkDefaultAdapt(addr, C4NetIO::addr_t()));
|
||||||
in_addr zero; zero.s_addr = INADDR_ANY;
|
|
||||||
pComp->Value(mkDefaultAdapt(addr.sin_addr, zero));
|
|
||||||
pComp->Separator(StdCompiler::SEP_PART2); // ':'
|
|
||||||
|
|
||||||
// Write port
|
|
||||||
uint16_t iPort = htons(addr.sin_port);
|
|
||||||
pComp->Value(iPort);
|
|
||||||
addr.sin_port = htons(iPort);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StdStrBuf C4Network2Address::toString() const
|
StdStrBuf C4Network2Address::toString() const
|
||||||
{
|
{
|
||||||
switch (eProtocol)
|
switch (eProtocol)
|
||||||
{
|
{
|
||||||
case P_UDP: return FormatString("UDP:%s:%d", inet_ntoa(addr.sin_addr), htons(addr.sin_port));
|
case P_UDP: return FormatString("UDP:%s", addr.ToString().getData());
|
||||||
case P_TCP: return FormatString("TCP:%s:%d", inet_ntoa(addr.sin_addr), htons(addr.sin_port));
|
case P_TCP: return FormatString("TCP:%s", addr.ToString().getData());
|
||||||
default: return StdStrBuf("INVALID");
|
default: return StdStrBuf("INVALID");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool C4Network2Address::operator == (const C4Network2Address &addr2) const
|
bool C4Network2Address::operator == (const C4Network2Address &addr2) const
|
||||||
{
|
{
|
||||||
return eProtocol == addr2.getProtocol() && AddrEqual(addr, addr2.getAddr());
|
return eProtocol == addr2.getProtocol() && addr == addr2.getAddr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ class C4Network2Address
|
||||||
public:
|
public:
|
||||||
C4Network2Address()
|
C4Network2Address()
|
||||||
: eProtocol(P_NONE)
|
: eProtocol(P_NONE)
|
||||||
{ ZeroMem(&addr, sizeof(addr)); }
|
{ }
|
||||||
|
|
||||||
C4Network2Address(C4NetIO::addr_t addr, C4Network2IOProtocol eProtocol)
|
C4Network2Address(C4NetIO::addr_t addr, C4Network2IOProtocol eProtocol)
|
||||||
: addr(addr), eProtocol(eProtocol)
|
: addr(addr), eProtocol(eProtocol)
|
||||||
|
@ -45,16 +45,18 @@ protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const C4NetIO::addr_t &getAddr() const { return addr; }
|
const C4NetIO::addr_t &getAddr() const { return addr; }
|
||||||
in_addr getIPAddr() const { return addr.sin_addr; }
|
C4NetIO::addr_t &getAddr() { return addr; }
|
||||||
bool isIPNull() const { return !addr.sin_addr.s_addr; }
|
//in_addr getIPAddr() const { return addr.sin_addr; }
|
||||||
uint16_t getPort() const { return htons(addr.sin_port); }
|
bool isIPNull() const { return addr.IsNull(); }
|
||||||
|
uint16_t getPort() const { return addr.GetPort(); }
|
||||||
C4Network2IOProtocol getProtocol() const { return eProtocol; }
|
C4Network2IOProtocol getProtocol() const { return eProtocol; }
|
||||||
|
|
||||||
StdStrBuf toString() const;
|
StdStrBuf toString() const;
|
||||||
|
|
||||||
void SetAddr(C4NetIO::addr_t naddr) { addr = naddr; }
|
void SetAddr(C4NetIO::addr_t naddr) { addr = naddr; }
|
||||||
void SetIP(in_addr ip) { addr.sin_addr = ip; }
|
//void SetIP(in_addr ip) { addr.SetAddress(ip); }
|
||||||
void SetPort(uint16_t iPort) { addr.sin_port = htons(iPort); }
|
void SetIP(C4NetIO::addr_t ip) { addr.SetAddress(ip); }
|
||||||
|
void SetPort(uint16_t iPort) { addr.SetPort(iPort); }
|
||||||
void SetProtocol(C4Network2IOProtocol enProtocol) { eProtocol = enProtocol; }
|
void SetProtocol(C4Network2IOProtocol enProtocol) { eProtocol = enProtocol; }
|
||||||
|
|
||||||
void CompileFunc(StdCompiler *pComp);
|
void CompileFunc(StdCompiler *pComp);
|
||||||
|
|
|
@ -25,13 +25,6 @@
|
||||||
#include "game/C4Game.h"
|
#include "game/C4Game.h"
|
||||||
#include "player/C4PlayerList.h"
|
#include "player/C4PlayerList.h"
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <ifaddrs.h>
|
|
||||||
#include <net/if.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// *** C4Network2Client
|
// *** C4Network2Client
|
||||||
|
|
||||||
C4Network2Client::C4Network2Client(C4Client *pClient)
|
C4Network2Client::C4Network2Client(C4Client *pClient)
|
||||||
|
@ -144,10 +137,22 @@ bool C4Network2Client::DoConnectAttempt(C4Network2IO *pIO)
|
||||||
{ iNextConnAttempt = time(nullptr) + 10; return true; }
|
{ iNextConnAttempt = time(nullptr) + 10; return true; }
|
||||||
// save attempt
|
// save attempt
|
||||||
AddrAttempts[iBestAddress]++; iNextConnAttempt = time(nullptr) + C4NetClientConnectInterval;
|
AddrAttempts[iBestAddress]++; iNextConnAttempt = time(nullptr) + C4NetClientConnectInterval;
|
||||||
// log
|
auto addr = Addr[iBestAddress].getAddr();
|
||||||
LogSilentF("Network: connecting client %s on %s...", getName(), Addr[iBestAddress].toString().getData());
|
std::set<int> interfaceIDs;
|
||||||
// connect
|
if (addr.IsLocal())
|
||||||
return pIO->Connect(Addr[iBestAddress].getAddr(), Addr[iBestAddress].getProtocol(), pClient->getCore());
|
interfaceIDs = Network.Clients.GetLocal()->getInterfaceIDs();
|
||||||
|
else
|
||||||
|
interfaceIDs = {0};
|
||||||
|
for (auto id : interfaceIDs)
|
||||||
|
{
|
||||||
|
addr.SetScopeId(id);
|
||||||
|
// log
|
||||||
|
LogSilentF("Network: connecting client %s on %s...", getName(), addr.ToString().getData());
|
||||||
|
// connect
|
||||||
|
if (pIO->Connect(addr, Addr[iBestAddress].getProtocol(), pClient->getCore()))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool C4Network2Client::hasAddr(const C4Network2Address &addr) const
|
bool C4Network2Client::hasAddr(const C4Network2Address &addr) const
|
||||||
|
@ -184,70 +189,24 @@ bool C4Network2Client::AddAddr(const C4Network2Address &addr, bool fAnnounce)
|
||||||
|
|
||||||
void C4Network2Client::AddLocalAddrs(int16_t iPortTCP, int16_t iPortUDP)
|
void C4Network2Client::AddLocalAddrs(int16_t iPortTCP, int16_t iPortUDP)
|
||||||
{
|
{
|
||||||
// set up address struct
|
C4NetIO::addr_t addr;
|
||||||
sockaddr_in addr; ZeroMem(&addr, sizeof addr);
|
|
||||||
addr.sin_family = AF_INET;
|
|
||||||
|
|
||||||
// get local address(es)
|
for (auto& ha : C4NetIO::GetLocalAddresses())
|
||||||
in_addr **ppAddr = nullptr;
|
|
||||||
#ifdef HAVE_WINSOCK
|
|
||||||
bool fGotWinSock = AcquireWinSock();
|
|
||||||
if (fGotWinSock)
|
|
||||||
{
|
{
|
||||||
// get local host name
|
addr.SetAddress(ha);
|
||||||
char szLocalHostName[128+1]; *szLocalHostName = '\0';
|
if (iPortTCP)
|
||||||
::gethostname(szLocalHostName, 128);
|
|
||||||
// get hostent-struct
|
|
||||||
hostent *ph = ::gethostbyname(szLocalHostName);
|
|
||||||
// check type, get addr list
|
|
||||||
if (ph)
|
|
||||||
{
|
{
|
||||||
if (ph->h_addrtype != AF_INET)
|
addr.SetPort(iPortTCP);
|
||||||
ph = nullptr;
|
|
||||||
else
|
|
||||||
ppAddr = reinterpret_cast<in_addr **>(ph->h_addr_list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
std::vector<in_addr*> addr_vec;
|
|
||||||
struct ifaddrs* addrs;
|
|
||||||
getifaddrs(&addrs);
|
|
||||||
for(struct ifaddrs* addr = addrs; addr != nullptr; addr = addr->ifa_next)
|
|
||||||
{
|
|
||||||
struct sockaddr* ad = addr->ifa_addr;
|
|
||||||
if(ad == nullptr) continue;
|
|
||||||
|
|
||||||
if(ad->sa_family == AF_INET && (~addr->ifa_flags & IFF_LOOPBACK)) // Choose only non-loopback IPv4 devices
|
|
||||||
addr_vec.push_back(&reinterpret_cast<sockaddr_in*>(ad)->sin_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
addr_vec.push_back(nullptr);
|
|
||||||
ppAddr = &addr_vec[0];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// add address(es)
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (iPortTCP >= 0)
|
|
||||||
{
|
|
||||||
addr.sin_port = htons(iPortTCP);
|
|
||||||
AddAddr(C4Network2Address(addr, P_TCP), false);
|
AddAddr(C4Network2Address(addr, P_TCP), false);
|
||||||
}
|
}
|
||||||
if (iPortUDP >= 0)
|
if (iPortUDP)
|
||||||
{
|
{
|
||||||
addr.sin_port = htons(iPortUDP);
|
addr.SetPort(iPortUDP);
|
||||||
AddAddr(C4Network2Address(addr, P_UDP), false);
|
AddAddr(C4Network2Address(addr, P_UDP), false);
|
||||||
}
|
}
|
||||||
// get next
|
if (addr.GetScopeId())
|
||||||
if (!ppAddr || !*ppAddr) break;
|
InterfaceIDs.insert(addr.GetScopeId());
|
||||||
addr.sin_addr = **ppAddr++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_WINSOCK
|
|
||||||
if (fGotWinSock) ReleaseWinSock();
|
|
||||||
#else
|
|
||||||
if(addrs) freeifaddrs(addrs);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void C4Network2Client::SendAddresses(C4Network2IOConnection *pConn)
|
void C4Network2Client::SendAddresses(C4Network2IOConnection *pConn)
|
||||||
|
@ -255,7 +214,11 @@ void C4Network2Client::SendAddresses(C4Network2IOConnection *pConn)
|
||||||
// send all addresses
|
// send all addresses
|
||||||
for (int32_t i = 0; i < iAddrCnt; i++)
|
for (int32_t i = 0; i < iAddrCnt; i++)
|
||||||
{
|
{
|
||||||
C4NetIOPacket Pkt = MkC4NetIOPacket(PID_Addr, C4PacketAddr(getID(), Addr[i]));
|
if (Addr[i].getAddr().GetScopeId() && (!pConn || pConn->getPeerAddr().GetScopeId() != Addr[i].getAddr().GetScopeId()))
|
||||||
|
continue;
|
||||||
|
C4Network2Address addr(Addr[i]);
|
||||||
|
addr.getAddr().SetScopeId(0);
|
||||||
|
C4NetIOPacket Pkt = MkC4NetIOPacket(PID_Addr, C4PacketAddr(getID(), addr));
|
||||||
if (pConn)
|
if (pConn)
|
||||||
pConn->Send(Pkt);
|
pConn->Send(Pkt);
|
||||||
else
|
else
|
||||||
|
@ -534,7 +497,9 @@ void C4Network2ClientList::HandlePacket(char cStatus, const C4PacketBase *pBaseP
|
||||||
C4Network2Address addr = rPkt.getAddr();
|
C4Network2Address addr = rPkt.getAddr();
|
||||||
// IP zero? Set to IP from where the packet came
|
// IP zero? Set to IP from where the packet came
|
||||||
if (addr.isIPNull())
|
if (addr.isIPNull())
|
||||||
addr.SetIP(pConn->getPeerAddr().sin_addr);
|
{
|
||||||
|
addr.SetIP(pConn->getPeerAddr());
|
||||||
|
}
|
||||||
// add (no announce)
|
// add (no announce)
|
||||||
if (pClient->AddAddr(addr, true))
|
if (pClient->AddAddr(addr, true))
|
||||||
// new address? Try to connect
|
// new address? Try to connect
|
||||||
|
|
|
@ -57,6 +57,9 @@ protected:
|
||||||
int32_t AddrAttempts[C4ClientMaxAddr];
|
int32_t AddrAttempts[C4ClientMaxAddr];
|
||||||
int32_t iAddrCnt;
|
int32_t iAddrCnt;
|
||||||
|
|
||||||
|
// interface ids
|
||||||
|
std::set<int> InterfaceIDs;
|
||||||
|
|
||||||
// status
|
// status
|
||||||
C4Network2ClientStatus eStatus;
|
C4Network2ClientStatus eStatus;
|
||||||
|
|
||||||
|
@ -88,6 +91,8 @@ public:
|
||||||
int32_t getAddrCnt() const { return iAddrCnt; }
|
int32_t getAddrCnt() const { return iAddrCnt; }
|
||||||
const C4Network2Address &getAddr(int32_t i) const { return Addr[i]; }
|
const C4Network2Address &getAddr(int32_t i) const { return Addr[i]; }
|
||||||
|
|
||||||
|
const std::set<int> &getInterfaceIDs() const { return InterfaceIDs; }
|
||||||
|
|
||||||
C4Network2ClientStatus getStatus() const { return eStatus; }
|
C4Network2ClientStatus getStatus() const { return eStatus; }
|
||||||
bool hasJoinData() const { return getStatus() != NCS_Joining; }
|
bool hasJoinData() const { return getStatus() != NCS_Joining; }
|
||||||
bool isChasing() const { return getStatus() == NCS_Chasing; }
|
bool isChasing() const { return getStatus() == NCS_Chasing; }
|
||||||
|
|
|
@ -96,14 +96,12 @@ void C4Network2ClientDlg::UpdateText()
|
||||||
AddLineFmt(LoadResStr("IDS_NET_CLIENT_INFO_CONNECTIONS"),
|
AddLineFmt(LoadResStr("IDS_NET_CLIENT_INFO_CONNECTIONS"),
|
||||||
pNetClient->getMsgConn() == pNetClient->getDataConn() ? "Msg/Data" : "Msg",
|
pNetClient->getMsgConn() == pNetClient->getDataConn() ? "Msg/Data" : "Msg",
|
||||||
::Network.NetIO.getNetIOName(pNetClient->getMsgConn()->getNetClass()),
|
::Network.NetIO.getNetIOName(pNetClient->getMsgConn()->getNetClass()),
|
||||||
inet_ntoa(pNetClient->getMsgConn()->getPeerAddr().sin_addr),
|
pNetClient->getMsgConn()->getPeerAddr().ToString().getData(),
|
||||||
htons(pNetClient->getMsgConn()->getPeerAddr().sin_port),
|
|
||||||
pNetClient->getMsgConn()->getPingTime());
|
pNetClient->getMsgConn()->getPingTime());
|
||||||
if (pNetClient->getMsgConn() != pNetClient->getDataConn())
|
if (pNetClient->getMsgConn() != pNetClient->getDataConn())
|
||||||
AddLineFmt(LoadResStr("IDS_NET_CLIENT_INFO_CONNDATA"),
|
AddLineFmt(LoadResStr("IDS_NET_CLIENT_INFO_CONNDATA"),
|
||||||
::Network.NetIO.getNetIOName(pNetClient->getDataConn()->getNetClass()),
|
::Network.NetIO.getNetIOName(pNetClient->getDataConn()->getNetClass()),
|
||||||
inet_ntoa(pNetClient->getDataConn()->getPeerAddr().sin_addr),
|
pNetClient->getDataConn()->getPeerAddr().ToString().getData(),
|
||||||
htons(pNetClient->getDataConn()->getPeerAddr().sin_port),
|
|
||||||
pNetClient->getDataConn()->getPingTime());
|
pNetClient->getDataConn()->getPingTime());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -386,11 +384,10 @@ void C4Network2ClientListBox::ConnectionListItem::Update()
|
||||||
else
|
else
|
||||||
szConnType = "Data";
|
szConnType = "Data";
|
||||||
// display info
|
// display info
|
||||||
pDesc->SetText(FormatString("%s: %s (%s:%d l%d)",
|
pDesc->SetText(FormatString("%s: %s (%s l%d)",
|
||||||
szConnType,
|
szConnType,
|
||||||
::Network.NetIO.getNetIOName(pConn->getNetClass()),
|
::Network.NetIO.getNetIOName(pConn->getNetClass()),
|
||||||
inet_ntoa(pConn->getPeerAddr().sin_addr),
|
pConn->getPeerAddr().ToString().getData(),
|
||||||
htons(pConn->getPeerAddr().sin_port),
|
|
||||||
pConn->getPacketLoss()).getData());
|
pConn->getPacketLoss()).getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,17 @@
|
||||||
#include "network/C4Network2Discover.h"
|
#include "network/C4Network2Discover.h"
|
||||||
|
|
||||||
// *** C4Network2IODiscover
|
// *** C4Network2IODiscover
|
||||||
|
//
|
||||||
|
// Quick multicast discovery guide by Luchs:
|
||||||
|
//
|
||||||
|
// All engines in network mode join a multicast group (defined by C4NetDiscoveryAddress).
|
||||||
|
//
|
||||||
|
// Engines searching for a game ("client") send a single byte c = 3 to that multicast group. This
|
||||||
|
// happens while on the network list on each refresh.
|
||||||
|
//
|
||||||
|
// Engines hosting a game (when going into the lobby) send a byte c = 4 plus their reference server
|
||||||
|
// port to the multicast group. Additionally, they listen for the c = 3 bytes and will reply with
|
||||||
|
// another multicast answer.
|
||||||
|
|
||||||
struct C4Network2IODiscoverReply
|
struct C4Network2IODiscoverReply
|
||||||
{
|
{
|
||||||
|
@ -41,10 +52,8 @@ bool C4Network2IODiscover::Init(uint16_t iPort)
|
||||||
// Set callback
|
// Set callback
|
||||||
C4NetIOSimpleUDP::SetCallback(this);
|
C4NetIOSimpleUDP::SetCallback(this);
|
||||||
// Build broadcast address
|
// Build broadcast address
|
||||||
DiscoveryAddr.sin_addr.s_addr = C4NetDiscoveryAddress;
|
DiscoveryAddr.SetAddress(C4NetDiscoveryAddress);
|
||||||
DiscoveryAddr.sin_port = htons(iPort);
|
DiscoveryAddr.SetPort(iPort);
|
||||||
DiscoveryAddr.sin_family = AF_INET;
|
|
||||||
ZeroMem(DiscoveryAddr.sin_zero, sizeof(DiscoveryAddr.sin_zero));
|
|
||||||
// Initialize broadcast
|
// Initialize broadcast
|
||||||
if (!C4NetIOSimpleUDP::InitBroadcast(&DiscoveryAddr))
|
if (!C4NetIOSimpleUDP::InitBroadcast(&DiscoveryAddr))
|
||||||
return false;
|
return false;
|
||||||
|
@ -55,7 +64,7 @@ bool C4Network2IODiscover::Init(uint16_t iPort)
|
||||||
bool C4Network2IODiscover::Announce()
|
bool C4Network2IODiscover::Announce()
|
||||||
{
|
{
|
||||||
// Announce our presence
|
// Announce our presence
|
||||||
C4Network2IODiscoverReply Reply = { 4, htons(iRefServerPort) };
|
C4Network2IODiscoverReply Reply = { 4, iRefServerPort };
|
||||||
return Send(C4NetIOPacket(&Reply, sizeof(Reply), false, DiscoveryAddr));
|
return Send(C4NetIOPacket(&Reply, sizeof(Reply), false, DiscoveryAddr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +80,7 @@ void C4Network2IODiscoverClient::OnPacket(const class C4NetIOPacket &rPacket, C4
|
||||||
{
|
{
|
||||||
const C4Network2IODiscoverReply *pReply = reinterpret_cast<const C4Network2IODiscoverReply *>(rPacket.getData());
|
const C4Network2IODiscoverReply *pReply = reinterpret_cast<const C4Network2IODiscoverReply *>(rPacket.getData());
|
||||||
Discovers[iDiscoverCount] = rPacket.getAddr();
|
Discovers[iDiscoverCount] = rPacket.getAddr();
|
||||||
Discovers[iDiscoverCount].sin_port = pReply->Port;
|
Discovers[iDiscoverCount].SetPort(pReply->Port);
|
||||||
iDiscoverCount++;
|
iDiscoverCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,10 +96,8 @@ bool C4Network2IODiscoverClient::Init(uint16_t iPort)
|
||||||
// Set callback
|
// Set callback
|
||||||
C4NetIOSimpleUDP::SetCallback(this);
|
C4NetIOSimpleUDP::SetCallback(this);
|
||||||
// Build broadcast address
|
// Build broadcast address
|
||||||
DiscoveryAddr.sin_addr.s_addr = C4NetDiscoveryAddress;
|
DiscoveryAddr.SetAddress(C4NetDiscoveryAddress);
|
||||||
DiscoveryAddr.sin_port = htons(iPort);
|
DiscoveryAddr.SetPort(iPort);
|
||||||
DiscoveryAddr.sin_family = AF_INET;
|
|
||||||
ZeroMem(DiscoveryAddr.sin_zero, sizeof(DiscoveryAddr.sin_zero));
|
|
||||||
// Initialize broadcast
|
// Initialize broadcast
|
||||||
if (!C4NetIOSimpleUDP::InitBroadcast(&DiscoveryAddr))
|
if (!C4NetIOSimpleUDP::InitBroadcast(&DiscoveryAddr))
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
const int C4NetMaxDiscover = 64;
|
const int C4NetMaxDiscover = 64;
|
||||||
|
|
||||||
const unsigned long C4NetDiscoveryAddress = 0xef; // 239.0.0.0
|
const C4NetIO::HostAddress C4NetDiscoveryAddress = C4NetIO::HostAddress(StdStrBuf("ff02::1"));
|
||||||
|
|
||||||
class C4Network2IODiscover : public C4NetIOSimpleUDP, private C4NetIO::CBClass
|
class C4Network2IODiscover : public C4NetIOSimpleUDP, private C4NetIO::CBClass
|
||||||
{
|
{
|
||||||
|
@ -34,12 +34,12 @@ protected:
|
||||||
virtual void OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO);
|
virtual void OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool Init(uint16_t iPort = P_NONE);
|
bool Init(uint16_t iPort = C4NetIO::addr_t::IPPORT_NONE);
|
||||||
void SetDiscoverable(bool fnEnabled) { fEnabled = fnEnabled; }
|
void SetDiscoverable(bool fnEnabled) { fEnabled = fnEnabled; }
|
||||||
bool Announce();
|
bool Announce();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sockaddr_in DiscoveryAddr;
|
C4NetIO::addr_t DiscoveryAddr;
|
||||||
|
|
||||||
uint16_t iRefServerPort;
|
uint16_t iRefServerPort;
|
||||||
bool fEnabled;
|
bool fEnabled;
|
||||||
|
@ -61,7 +61,7 @@ public:
|
||||||
const C4NetIO::addr_t &getDiscover(int i) { return Discovers[i]; }
|
const C4NetIO::addr_t &getDiscover(int i) { return Discovers[i]; }
|
||||||
|
|
||||||
void Clear() { iDiscoverCount = 0; }
|
void Clear() { iDiscoverCount = 0; }
|
||||||
bool Init(uint16_t iPort = P_NONE);
|
bool Init(uint16_t iPort = C4NetIO::addr_t::IPPORT_NONE);
|
||||||
bool StartDiscovery();
|
bool StartDiscovery();
|
||||||
bool PopDiscover(C4NetIO::addr_t &Discover);
|
bool PopDiscover(C4NetIO::addr_t &Discover);
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,6 @@ C4Network2IO::C4Network2IO()
|
||||||
iTCPIRate(0), iTCPORate(0), iTCPBCRate(0),
|
iTCPIRate(0), iTCPORate(0), iTCPBCRate(0),
|
||||||
iUDPIRate(0), iUDPORate(0), iUDPBCRate(0)
|
iUDPIRate(0), iUDPORate(0), iUDPBCRate(0)
|
||||||
{
|
{
|
||||||
ZeroMem(&PuncherAddr, sizeof(PuncherAddr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
C4Network2IO::~C4Network2IO()
|
C4Network2IO::~C4Network2IO()
|
||||||
|
@ -253,7 +252,7 @@ bool C4Network2IO::Connect(const C4NetIO::addr_t &addr, C4Network2IOProtocol ePr
|
||||||
if (GetConnectionByConnAddr(addr, pNetIO)) return true;
|
if (GetConnectionByConnAddr(addr, pNetIO)) return true;
|
||||||
// assign new connection ID, peer address isn't known yet
|
// assign new connection ID, peer address isn't known yet
|
||||||
uint32_t iConnID = iNextConnID++;
|
uint32_t iConnID = iNextConnID++;
|
||||||
C4NetIO::addr_t paddr; ZeroMem(&paddr, sizeof paddr);
|
C4NetIO::addr_t paddr;
|
||||||
// create connection object and add to list
|
// create connection object and add to list
|
||||||
C4Network2IOConnection *pConn = new C4Network2IOConnection();
|
C4Network2IOConnection *pConn = new C4Network2IOConnection();
|
||||||
pConn->Set(pNetIO, eProt, paddr, addr, CS_Connect, szPassword, iConnID);
|
pConn->Set(pNetIO, eProt, paddr, addr, CS_Connect, szPassword, iConnID);
|
||||||
|
@ -263,7 +262,7 @@ bool C4Network2IO::Connect(const C4NetIO::addr_t &addr, C4Network2IOProtocol ePr
|
||||||
if (!pConn->Connect())
|
if (!pConn->Connect())
|
||||||
{
|
{
|
||||||
// show error
|
// show error
|
||||||
LogF("Network: could not connect to %s:%d using %s: %s", inet_ntoa(addr.sin_addr), htons(addr.sin_port),
|
LogF("Network: could not connect to %s using %s: %s", addr.ToString().getData(),
|
||||||
getNetIOName(pNetIO), pNetIO->GetError() ? pNetIO->GetError() : "");
|
getNetIOName(pNetIO), pNetIO->GetError() ? pNetIO->GetError() : "");
|
||||||
pNetIO->ResetError();
|
pNetIO->ResetError();
|
||||||
// remove class
|
// remove class
|
||||||
|
@ -461,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;
|
||||||
|
case C4NetIO::HostAddress::UnknownFamily:
|
||||||
|
assert(!"Unexpected address family");
|
||||||
|
}
|
||||||
// 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.sin_addr.s_addr) 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.sin_addr.s_addr && AddrEqual(PuncherAddr, ConnectAddr))
|
if (pNetIO == pNetIO_UDP && IsPuncherAddr(ConnectAddr))
|
||||||
{
|
{
|
||||||
// got an address?
|
// got an address?
|
||||||
if (pOwnAddr)
|
if (pOwnAddr)
|
||||||
|
@ -497,7 +517,7 @@ bool C4Network2IO::OnConn(const C4NetIO::addr_t &PeerAddr, const C4NetIO::addr_t
|
||||||
#endif
|
#endif
|
||||||
// search connection
|
// search connection
|
||||||
C4Network2IOConnection *pConn = nullptr;
|
C4Network2IOConnection *pConn = nullptr;
|
||||||
if (ConnectAddr.sin_addr.s_addr)
|
if (!ConnectAddr.IsNull())
|
||||||
pConn = GetConnectionByConnAddr(ConnectAddr, pNetIO);
|
pConn = GetConnectionByConnAddr(ConnectAddr, pNetIO);
|
||||||
// not found?
|
// not found?
|
||||||
if (!pConn)
|
if (!pConn)
|
||||||
|
@ -527,7 +547,7 @@ bool C4Network2IO::OnConn(const C4NetIO::addr_t &PeerAddr, const C4NetIO::addr_t
|
||||||
SendConnPackets();
|
SendConnPackets();
|
||||||
#if(C4NET2IO_DUMP_LEVEL > 0)
|
#if(C4NET2IO_DUMP_LEVEL > 0)
|
||||||
// log
|
// log
|
||||||
Application.InteractiveThread.ThreadLogS("Network: got %s connection from %s:%d", getNetIOName(pNetIO), inet_ntoa(PeerAddr.sin_addr), htons(PeerAddr.sin_port));
|
Application.InteractiveThread.ThreadLogS("Network: got %s connection from %s", getNetIOName(pNetIO), PeerAddr.ToString().getData());
|
||||||
#endif
|
#endif
|
||||||
// do event (disabled - unused)
|
// do event (disabled - unused)
|
||||||
// pConn->AddRef(); PushNetEv(NE_Conn, pConn);
|
// pConn->AddRef(); PushNetEv(NE_Conn, pConn);
|
||||||
|
@ -538,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.sin_addr.s_addr && AddrEqual(PuncherAddr, addr))
|
if (pNetIO == pNetIO_UDP && IsPuncherAddr(addr))
|
||||||
{
|
{
|
||||||
ZeroMem(&PuncherAddr, sizeof(PuncherAddr));
|
if (PuncherAddrIPv4 == addr)
|
||||||
|
PuncherAddrIPv4.Clear();
|
||||||
|
else
|
||||||
|
PuncherAddrIPv6.Clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#if(C4NET2IO_DUMP_LEVEL > 1)
|
#if(C4NET2IO_DUMP_LEVEL > 1)
|
||||||
|
@ -554,8 +577,8 @@ void C4Network2IO::OnDisconn(const C4NetIO::addr_t &addr, C4NetIO *pNetIO, const
|
||||||
if (!pConn) return;
|
if (!pConn) return;
|
||||||
#if(C4NET2IO_DUMP_LEVEL > 0)
|
#if(C4NET2IO_DUMP_LEVEL > 0)
|
||||||
// log
|
// log
|
||||||
Application.InteractiveThread.ThreadLogS("Network: %s connection to %s:%d %s (%s)",
|
Application.InteractiveThread.ThreadLogS("Network: %s connection to %s %s (%s)",
|
||||||
getNetIOName(pNetIO), inet_ntoa(addr.sin_addr), htons(addr.sin_port), pConn->isConnecting() ? "failed" : "closed" , szReason);
|
getNetIOName(pNetIO), addr.ToString().getData(), pConn->isConnecting() ? "failed" : "closed" , szReason);
|
||||||
#endif
|
#endif
|
||||||
// already closed? ignore
|
// already closed? ignore
|
||||||
if (!pConn->isClosed())
|
if (!pConn->isClosed())
|
||||||
|
@ -580,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.sin_addr.s_addr && AddrEqual(PuncherAddr, rPacket.getAddr()))
|
if (pNetIO == pNetIO_UDP && IsPuncherAddr(rPacket.getAddr()))
|
||||||
{
|
{
|
||||||
HandlePuncherPacket(rPacket);
|
HandlePuncherPacket(rPacket);
|
||||||
return;
|
return;
|
||||||
|
@ -588,7 +611,11 @@ void C4Network2IO::OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO)
|
||||||
if (!rPacket.getSize()) return;
|
if (!rPacket.getSize()) return;
|
||||||
// find connection
|
// find connection
|
||||||
C4Network2IOConnection *pConn = GetConnection(rPacket.getAddr(), pNetIO);
|
C4Network2IOConnection *pConn = GetConnection(rPacket.getAddr(), pNetIO);
|
||||||
if (!pConn) { Application.InteractiveThread.ThreadLog("Network: could not find connection for packet from %s:%d!", inet_ntoa(rPacket.getAddr().sin_addr), htons(rPacket.getAddr().sin_port)); return; }
|
if (!pConn)
|
||||||
|
{
|
||||||
|
Application.InteractiveThread.ThreadLog("Network: could not find connection for %s packet (status %02x) from %s!", getNetIOName(pNetIO), rPacket.getStatus(), rPacket.getAddr().ToString().getData());
|
||||||
|
return;
|
||||||
|
}
|
||||||
#if(C4NET2IO_DUMP_LEVEL > 2)
|
#if(C4NET2IO_DUMP_LEVEL > 2)
|
||||||
uint32_t iFindConnectionBlocked = C4TimeMilliseconds::Now() - tTime;
|
uint32_t iFindConnectionBlocked = C4TimeMilliseconds::Now() - tTime;
|
||||||
if (iFindConnectionBlocked > 100)
|
if (iFindConnectionBlocked > 100)
|
||||||
|
@ -748,7 +775,7 @@ C4Network2IOConnection *C4Network2IO::GetConnection(const C4NetIO::addr_t &addr,
|
||||||
CStdLock ConnListLock(&ConnListCSec);
|
CStdLock ConnListLock(&ConnListCSec);
|
||||||
// search
|
// search
|
||||||
for (C4Network2IOConnection *pConn = pConnList; pConn; pConn = pConn->pNext)
|
for (C4Network2IOConnection *pConn = pConnList; pConn; pConn = pConn->pNext)
|
||||||
if (pConn->getNetClass() == pNetIO && AddrEqual(pConn->getPeerAddr(), addr))
|
if (pConn->getNetClass() == pNetIO && pConn->getPeerAddr() == addr)
|
||||||
return pConn;
|
return pConn;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -758,7 +785,7 @@ C4Network2IOConnection *C4Network2IO::GetConnectionByConnAddr(const C4NetIO::add
|
||||||
CStdLock ConnListLock(&ConnListCSec);
|
CStdLock ConnListLock(&ConnListCSec);
|
||||||
// search
|
// search
|
||||||
for (C4Network2IOConnection *pConn = pConnList; pConn; pConn = pConn->pNext)
|
for (C4Network2IOConnection *pConn = pConnList; pConn; pConn = pConn->pNext)
|
||||||
if (pConn->getNetClass() == pNetIO && AddrEqual(pConn->getConnectAddr(), addr))
|
if (pConn->getNetClass() == pNetIO && pConn->getConnectAddr() == addr)
|
||||||
return pConn;
|
return pConn;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -798,7 +825,7 @@ bool C4Network2IO::doAutoAccept(const C4ClientCore &CCore, const C4Network2IOCon
|
||||||
for (C4Network2IOConnection *pConn = pConnList; pConn; pConn = pConn->pNext)
|
for (C4Network2IOConnection *pConn = pConnList; pConn; pConn = pConn->pNext)
|
||||||
if (pConn->isAccepted() &&
|
if (pConn->isAccepted() &&
|
||||||
pConn->getCCore().getDiffLevel(CCore) <= C4ClientCoreDL_IDMatch &&
|
pConn->getCCore().getDiffLevel(CCore) <= C4ClientCoreDL_IDMatch &&
|
||||||
pConn->getPeerAddr().sin_addr.s_addr != Conn.getPeerAddr().sin_addr.s_addr)
|
pConn->getPeerAddr().GetHost() != Conn.getPeerAddr().GetHost())
|
||||||
return false;
|
return false;
|
||||||
// not found or IP matches? Let pass
|
// not found or IP matches? Let pass
|
||||||
return true;
|
return true;
|
||||||
|
@ -837,9 +864,9 @@ bool C4Network2IO::HandlePacket(const C4NetIOPacket &rPacket, C4Network2IOConnec
|
||||||
if (Config.Network.PacketLogging && fThread && Pkt.getPktType() != PID_Ping && Pkt.getPktType() != PID_Pong && Pkt.getPktType() != PID_NetResData)
|
if (Config.Network.PacketLogging && fThread && Pkt.getPktType() != PID_Ping && Pkt.getPktType() != PID_Pong && Pkt.getPktType() != PID_NetResData)
|
||||||
{
|
{
|
||||||
// StdStrBuf PacketDump = DecompileToBuf<StdCompilerINIWrite>(mkNamingAdaptrPacket);
|
// StdStrBuf PacketDump = DecompileToBuf<StdCompilerINIWrite>(mkNamingAdaptrPacket);
|
||||||
StdStrBuf PacketHeader = FormatString("HandlePacket: %s by %s:%d (%lu bytes, counter %d)",
|
StdStrBuf PacketHeader = FormatString("HandlePacket: %s by %s (%lu bytes, counter %d)",
|
||||||
C4TimeMilliseconds::Now().AsString().getData(),
|
C4TimeMilliseconds::Now().AsString().getData(),
|
||||||
inet_ntoa(pConn->getPeerAddr().sin_addr), htons(pConn->getPeerAddr().sin_port),
|
pConn->getPeerAddr().ToString().getData(),
|
||||||
static_cast<unsigned long>(rPacket.getSize()), pConn->getInPacketCounter());
|
static_cast<unsigned long>(rPacket.getSize()), pConn->getInPacketCounter());
|
||||||
StdStrBuf Dump = DecompileToBuf<StdCompilerINIWrite>(mkNamingAdapt(Pkt, PacketHeader.getData()));
|
StdStrBuf Dump = DecompileToBuf<StdCompilerINIWrite>(mkNamingAdapt(Pkt, PacketHeader.getData()));
|
||||||
// Put it directly. The standard functions behind StdBuf.Format seem to choke when you pass them too much data.
|
// Put it directly. The standard functions behind StdBuf.Format seem to choke when you pass them too much data.
|
||||||
|
@ -1138,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);
|
||||||
|
@ -1172,7 +1199,7 @@ void C4Network2IO::CheckTimeout()
|
||||||
if (!pConn->isClosed() && !pConn->isAccepted())
|
if (!pConn->isClosed() && !pConn->isAccepted())
|
||||||
if (difftime(time(nullptr), pConn->getTimestamp()) > C4NetAcceptTimeout)
|
if (difftime(time(nullptr), pConn->getTimestamp()) > C4NetAcceptTimeout)
|
||||||
{
|
{
|
||||||
Application.InteractiveThread.ThreadLogS("Network: connection accept timeout to %s:%d", inet_ntoa(pConn->getPeerAddr().sin_addr), htons(pConn->getPeerAddr().sin_port));
|
Application.InteractiveThread.ThreadLogS("Network: connection accept timeout to %s", pConn->getPeerAddr().ToString().getData());
|
||||||
pConn->Close();
|
pConn->Close();
|
||||||
}
|
}
|
||||||
// ping timeout
|
// ping timeout
|
||||||
|
@ -1181,7 +1208,7 @@ void C4Network2IO::CheckTimeout()
|
||||||
> C4NetPingTimeout)
|
> C4NetPingTimeout)
|
||||||
{
|
{
|
||||||
Application.InteractiveThread.ThreadLogS("%d %d %d", (int)pConn->getLag(), (int)time(nullptr), (int)pConn->getTimestamp());
|
Application.InteractiveThread.ThreadLogS("%d %d %d", (int)pConn->getLag(), (int)time(nullptr), (int)pConn->getTimestamp());
|
||||||
Application.InteractiveThread.ThreadLogS("Network: ping timeout to %s:%d", inet_ntoa(pConn->getPeerAddr().sin_addr), htons(pConn->getPeerAddr().sin_port));
|
Application.InteractiveThread.ThreadLogS("Network: ping timeout to %s", pConn->getPeerAddr().ToString().getData());
|
||||||
pConn->Close();
|
pConn->Close();
|
||||||
}
|
}
|
||||||
// delayed connection removal
|
// delayed connection removal
|
||||||
|
@ -1265,19 +1292,23 @@ void C4Network2IO::SendConnPackets()
|
||||||
|
|
||||||
void C4Network2IO::OnPuncherConnect(C4NetIO::addr_t addr)
|
void C4Network2IO::OnPuncherConnect(C4NetIO::addr_t addr)
|
||||||
{
|
{
|
||||||
// Sanity check
|
// NAT punching is only relevant for IPv4, so convert here to show a proper address.
|
||||||
assert (addr.sin_family == AF_INET);
|
auto maybe_v4 = addr.AsIPv4();
|
||||||
if (addr.sin_family != AF_INET)
|
Application.InteractiveThread.ThreadLogS("Adding address from puncher: %s", maybe_v4.ToString().getData());
|
||||||
return;
|
|
||||||
|
|
||||||
Application.InteractiveThread.ThreadLogS("Adding address from puncher: %s:%d", inet_ntoa(addr.sin_addr), htons(addr.sin_port));
|
|
||||||
|
|
||||||
ZeroMem(addr.sin_zero, sizeof(addr.sin_zero));
|
|
||||||
// Add for local client
|
// Add for local client
|
||||||
C4Network2Client *pLocal = ::Network.Clients.GetLocal();
|
C4Network2Client *pLocal = ::Network.Clients.GetLocal();
|
||||||
if (pLocal)
|
if (pLocal)
|
||||||
pLocal->AddAddr(C4Network2Address(addr, P_UDP), true);
|
{
|
||||||
|
pLocal->AddAddr(C4Network2Address(maybe_v4, P_UDP), true);
|
||||||
|
// If the outside port matches the inside port, there is no port translation and the
|
||||||
|
// TCP address will probably work as well.
|
||||||
|
if (addr.GetPort() == Config.Network.PortUDP && Config.Network.PortTCP > 0)
|
||||||
|
{
|
||||||
|
maybe_v4.SetPort(Config.Network.PortTCP);
|
||||||
|
pLocal->AddAddr(C4Network2Address(maybe_v4, P_TCP), true);
|
||||||
|
}
|
||||||
// Do not ::Network.InvalidateReference(); yet, we're expecting an ID from the netpuncher
|
// Do not ::Network.InvalidateReference(); yet, we're expecting an ID from the netpuncher
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// *** C4Network2IOConnection
|
// *** C4Network2IOConnection
|
||||||
|
|
|
@ -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
|
||||||
|
@ -261,7 +262,7 @@ protected:
|
||||||
public:
|
public:
|
||||||
C4NetIO *getNetClass() const { return pNetClass; }
|
C4NetIO *getNetClass() const { return pNetClass; }
|
||||||
C4Network2IOProtocol getProtocol() const { return eProt; }
|
C4Network2IOProtocol getProtocol() const { return eProt; }
|
||||||
const C4NetIO::addr_t &getPeerAddr() const { return PeerAddr.sin_port ? PeerAddr : ConnectAddr; }
|
const C4NetIO::addr_t &getPeerAddr() const { return PeerAddr.GetPort() ? PeerAddr : ConnectAddr; }
|
||||||
const C4NetIO::addr_t &getConnectAddr() const { return ConnectAddr; }
|
const C4NetIO::addr_t &getConnectAddr() const { return ConnectAddr; }
|
||||||
uint32_t getID() const { return iID; }
|
uint32_t getID() const { return iID; }
|
||||||
uint32_t getRemoteID() const { return iRemoteID; }
|
uint32_t getRemoteID() const { return iRemoteID; }
|
||||||
|
|
|
@ -246,7 +246,7 @@ size_t C4Network2IRCClient::UnpackPacket(const StdBuf &rInBuf, const C4NetIO::ad
|
||||||
bool C4Network2IRCClient::OnConn(const C4NetIO::addr_t &AddrPeer, const C4NetIO::addr_t &AddrConnect, const addr_t *pOwnAddr, C4NetIO *pNetIO)
|
bool C4Network2IRCClient::OnConn(const C4NetIO::addr_t &AddrPeer, const C4NetIO::addr_t &AddrConnect, const addr_t *pOwnAddr, C4NetIO *pNetIO)
|
||||||
{
|
{
|
||||||
// Security checks
|
// Security checks
|
||||||
if (!fConnecting || fConnected || !AddrEqual(AddrConnect, ServerAddr)) return false;
|
if (!fConnecting || fConnected || AddrConnect != ServerAddr) return false;
|
||||||
CStdLock Lock(&CSec);
|
CStdLock Lock(&CSec);
|
||||||
// Save connection data
|
// Save connection data
|
||||||
fConnected = true;
|
fConnected = true;
|
||||||
|
@ -318,8 +318,10 @@ bool C4Network2IRCClient::Connect(const char *szServer, const char *szNick, cons
|
||||||
if (!Init())
|
if (!Init())
|
||||||
return false;
|
return false;
|
||||||
// Resolve address
|
// Resolve address
|
||||||
if (!ResolveAddress(szServer, &ServerAddr, 6666))
|
ServerAddr.SetAddress(StdStrBuf(szServer));
|
||||||
|
if (ServerAddr.IsNull())
|
||||||
{ SetError("Could no resolve server address!"); return false; }
|
{ SetError("Could no resolve server address!"); return false; }
|
||||||
|
ServerAddr.SetDefaultPort(6666);
|
||||||
// Set connection data
|
// Set connection data
|
||||||
Nick = szNick; RealName = szRealName;
|
Nick = szNick; RealName = szRealName;
|
||||||
Password = szPassword; AutoJoin = szAutoJoin;
|
Password = szPassword; AutoJoin = szAutoJoin;
|
||||||
|
|
|
@ -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())
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -40,11 +40,11 @@ C4Network2Reference::~C4Network2Reference()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void C4Network2Reference::SetSourceIP(in_addr ip)
|
void C4Network2Reference::SetSourceAddress(const C4NetIO::EndpointAddress &ip)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < iAddrCnt; i++)
|
source = ip;
|
||||||
if (Addrs[i].isIPNull())
|
if (iAddrCnt < C4ClientMaxAddr)
|
||||||
Addrs[i].SetIP(ip);
|
Addrs[++iAddrCnt].SetAddr(ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
void C4Network2Reference::InitLocal()
|
void C4Network2Reference::InitLocal()
|
||||||
|
@ -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);
|
||||||
|
@ -407,12 +407,15 @@ bool C4Network2HTTPClient::Decompress(StdBuf *pData)
|
||||||
bool C4Network2HTTPClient::OnConn(const C4NetIO::addr_t &AddrPeer, const C4NetIO::addr_t &AddrConnect, const C4NetIO::addr_t *pOwnAddr, C4NetIO *pNetIO)
|
bool C4Network2HTTPClient::OnConn(const C4NetIO::addr_t &AddrPeer, const C4NetIO::addr_t &AddrConnect, const C4NetIO::addr_t *pOwnAddr, C4NetIO *pNetIO)
|
||||||
{
|
{
|
||||||
// Make sure we're actually waiting for this connection
|
// Make sure we're actually waiting for this connection
|
||||||
if (!AddrEqual(AddrConnect, ServerAddr))
|
if (fConnected || (AddrConnect != ServerAddr && AddrConnect != ServerAddrFallback))
|
||||||
return false;
|
return false;
|
||||||
// Save pack peer address
|
// Save pack peer address
|
||||||
PeerAddr = AddrPeer;
|
PeerAddr = AddrPeer;
|
||||||
// Send the request
|
// Send the request
|
||||||
Send(C4NetIOPacket(Request, AddrPeer));
|
if (!Send(C4NetIOPacket(Request, AddrPeer)))
|
||||||
|
{
|
||||||
|
Error.Format("Unable to send HTTP request: %s", Error.getData());
|
||||||
|
}
|
||||||
Request.Clear();
|
Request.Clear();
|
||||||
fConnected = true;
|
fConnected = true;
|
||||||
return true;
|
return true;
|
||||||
|
@ -442,10 +445,19 @@ void C4Network2HTTPClient::OnPacket(const class C4NetIOPacket &rPacket, C4NetIO
|
||||||
bool C4Network2HTTPClient::Execute(int iMaxTime)
|
bool C4Network2HTTPClient::Execute(int iMaxTime)
|
||||||
{
|
{
|
||||||
// Check timeout
|
// Check timeout
|
||||||
if (fBusy && time(nullptr) > iRequestTimeout)
|
if (fBusy)
|
||||||
{
|
{
|
||||||
Cancel("Request timeout");
|
if (C4TimeMilliseconds::Now() > HappyEyeballsTimeout)
|
||||||
return true;
|
{
|
||||||
|
HappyEyeballsTimeout = C4TimeMilliseconds::PositiveInfinity;
|
||||||
|
Application.InteractiveThread.ThreadLogS("HTTP: Starting fallback connection to %s (%s)", Server.getData(), ServerAddrFallback.ToString().getData());
|
||||||
|
Connect(ServerAddrFallback);
|
||||||
|
}
|
||||||
|
if (time(nullptr) > iRequestTimeout)
|
||||||
|
{
|
||||||
|
Cancel("Request timeout");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Execute normally
|
// Execute normally
|
||||||
return C4NetIOTCP::Execute(iMaxTime);
|
return C4NetIOTCP::Execute(iMaxTime);
|
||||||
|
@ -459,7 +471,9 @@ C4TimeMilliseconds C4Network2HTTPClient::GetNextTick(C4TimeMilliseconds tNow)
|
||||||
|
|
||||||
C4TimeMilliseconds tHTTPClientTick = tNow + 1000 * std::max<time_t>(iRequestTimeout - time(nullptr), 0);
|
C4TimeMilliseconds tHTTPClientTick = tNow + 1000 * std::max<time_t>(iRequestTimeout - time(nullptr), 0);
|
||||||
|
|
||||||
return std::max(tNetIOTCPTick, tHTTPClientTick);
|
C4TimeMilliseconds HappyEyeballsTick = tNow + std::max(HappyEyeballsTimeout - C4TimeMilliseconds::Now(), 0);
|
||||||
|
|
||||||
|
return std::min({tNetIOTCPTick, tHTTPClientTick, HappyEyeballsTick});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool C4Network2HTTPClient::Query(const StdBuf &Data, bool fBinary)
|
bool C4Network2HTTPClient::Query(const StdBuf &Data, bool fBinary)
|
||||||
|
@ -509,6 +523,11 @@ bool C4Network2HTTPClient::Query(const StdBuf &Data, bool fBinary)
|
||||||
// Start connecting
|
// Start connecting
|
||||||
if (!Connect(ServerAddr))
|
if (!Connect(ServerAddr))
|
||||||
return false;
|
return false;
|
||||||
|
// Also try the fallback address after some time (if there is one)
|
||||||
|
if (!ServerAddrFallback.IsNull())
|
||||||
|
HappyEyeballsTimeout = C4TimeMilliseconds::Now() + C4Network2HTTPHappyEyeballsTimeout;
|
||||||
|
else
|
||||||
|
HappyEyeballsTimeout = C4TimeMilliseconds::PositiveInfinity;
|
||||||
// Okay, request will be performed when connection is complete
|
// Okay, request will be performed when connection is complete
|
||||||
fBusy = true;
|
fBusy = true;
|
||||||
iDataOffset = 0;
|
iDataOffset = 0;
|
||||||
|
@ -526,7 +545,7 @@ void C4Network2HTTPClient::ResetRequestTimeout()
|
||||||
void C4Network2HTTPClient::Cancel(const char *szReason)
|
void C4Network2HTTPClient::Cancel(const char *szReason)
|
||||||
{
|
{
|
||||||
// Close connection - and connection attempt
|
// Close connection - and connection attempt
|
||||||
Close(ServerAddr); Close(PeerAddr);
|
Close(ServerAddr); Close(ServerAddrFallback); Close(PeerAddr);
|
||||||
// Reset flags
|
// Reset flags
|
||||||
fBusy = fSuccess = fConnected = fBinary = false;
|
fBusy = fSuccess = fConnected = fBinary = false;
|
||||||
iDownloadedSize = iTotalSize = iDataOffset = 0;
|
iDownloadedSize = iTotalSize = iDataOffset = 0;
|
||||||
|
@ -557,15 +576,29 @@ bool C4Network2HTTPClient::SetServer(const char *szServerAddress)
|
||||||
RequestPath = "/";
|
RequestPath = "/";
|
||||||
}
|
}
|
||||||
// Resolve address
|
// Resolve address
|
||||||
if (!ResolveAddress(Server.getData(), &ServerAddr, GetDefaultPort()))
|
ServerAddr.SetAddress(Server);
|
||||||
|
if (ServerAddr.IsNull())
|
||||||
{
|
{
|
||||||
SetError(FormatString("Could not resolve server address %s!", Server.getData()).getData());
|
SetError(FormatString("Could not resolve server address %s!", Server.getData()).getData());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
ServerAddr.SetDefaultPort(GetDefaultPort());
|
||||||
|
if (ServerAddr.GetFamily() == C4NetIO::HostAddress::IPv6)
|
||||||
|
{
|
||||||
|
// Try to find a fallback IPv4 address for Happy Eyeballs.
|
||||||
|
ServerAddrFallback.SetAddress(Server, C4NetIO::HostAddress::IPv4);
|
||||||
|
ServerAddrFallback.SetDefaultPort(GetDefaultPort());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ServerAddrFallback.Clear();
|
||||||
// Remove port
|
// Remove port
|
||||||
const char *pColon = strchr(Server.getData(), ':');
|
const char *firstColon = strchr(Server.getData(), ':');
|
||||||
if (pColon)
|
const char *lastColon = strrchr(Server.getData(), ':');
|
||||||
Server.SetLength(pColon - Server.getData());
|
if (firstColon)
|
||||||
|
// hostname/IPv4 address or IPv6 address with port (e.g. [::1]:1234)
|
||||||
|
if (firstColon == lastColon || (Server[0] == '[' && *(lastColon - 1) == ']'))
|
||||||
|
Server.SetLength(lastColon - Server.getData());
|
||||||
|
|
||||||
// Done
|
// Done
|
||||||
ResetError();
|
ResetError();
|
||||||
return true;
|
return true;
|
||||||
|
@ -657,7 +690,7 @@ bool C4Network2RefClient::GetReferences(C4Network2Reference **&rpReferences, int
|
||||||
}
|
}
|
||||||
// Set source ip
|
// Set source ip
|
||||||
for (int i = 0; i < rRefCount; i++)
|
for (int i = 0; i < rRefCount; i++)
|
||||||
rpReferences[i]->SetSourceIP(getServerAddress().sin_addr);
|
rpReferences[i]->SetSourceAddress(getServerAddress());
|
||||||
// Done
|
// Done
|
||||||
ResetError();
|
ResetError();
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "lib/C4InputValidation.h"
|
#include "lib/C4InputValidation.h"
|
||||||
|
|
||||||
const int C4Network2HTTPQueryTimeout = 10; // (s)
|
const int C4Network2HTTPQueryTimeout = 10; // (s)
|
||||||
|
const uint32_t C4Network2HTTPHappyEyeballsTimeout = 300; // (ms)
|
||||||
|
|
||||||
// Session data
|
// Session data
|
||||||
class C4Network2Reference
|
class C4Network2Reference
|
||||||
|
@ -51,7 +52,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
|
||||||
|
@ -60,9 +61,11 @@ private:
|
||||||
// Network addresses
|
// Network addresses
|
||||||
uint8_t iAddrCnt;
|
uint8_t iAddrCnt;
|
||||||
C4Network2Address Addrs[C4ClientMaxAddr];
|
C4Network2Address Addrs[C4ClientMaxAddr];
|
||||||
|
C4NetIO::EndpointAddress source;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const C4Network2Address &getAddr(int i) const { return Addrs[i]; }
|
const C4Network2Address &getAddr(int i) const { return Addrs[i]; }
|
||||||
|
C4Network2Address &getAddr(int i) { return Addrs[i]; }
|
||||||
int getAddrCnt() const { return iAddrCnt; }
|
int getAddrCnt() const { return iAddrCnt; }
|
||||||
const char *getTitle() const { return Title.getData(); }
|
const char *getTitle() const { return Title.getData(); }
|
||||||
int32_t getIcon() const { return Icon; }
|
int32_t getIcon() const { return Icon; }
|
||||||
|
@ -77,10 +80,11 @@ 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 SetSourceIP(in_addr ip);
|
void SetSourceAddress(const C4NetIO::EndpointAddress &ip);
|
||||||
|
const C4NetIO::EndpointAddress &GetSourceAddress() const { return source; }
|
||||||
|
|
||||||
void InitLocal();
|
void InitLocal();
|
||||||
|
|
||||||
|
@ -126,7 +130,7 @@ public:
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Address information
|
// Address information
|
||||||
C4NetIO::addr_t ServerAddr, PeerAddr;
|
C4NetIO::addr_t ServerAddr, ServerAddrFallback, PeerAddr;
|
||||||
StdCopyStrBuf Server, RequestPath;
|
StdCopyStrBuf Server, RequestPath;
|
||||||
|
|
||||||
bool fBinary;
|
bool fBinary;
|
||||||
|
@ -134,6 +138,7 @@ private:
|
||||||
size_t iDataOffset;
|
size_t iDataOffset;
|
||||||
StdCopyBuf Request;
|
StdCopyBuf Request;
|
||||||
time_t iRequestTimeout;
|
time_t iRequestTimeout;
|
||||||
|
C4TimeMilliseconds HappyEyeballsTimeout;
|
||||||
|
|
||||||
// Response header data
|
// Response header data
|
||||||
size_t iDownloadedSize, iTotalSize;
|
size_t iDownloadedSize, iTotalSize;
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
C4AulDebug::C4AulDebug()
|
C4AulDebug::C4AulDebug()
|
||||||
: fInit(false), fConnected(false)
|
: fInit(false), fConnected(false)
|
||||||
{
|
{
|
||||||
ZeroMem(&PeerAddr, sizeof PeerAddr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
C4AulDebug::~C4AulDebug()
|
C4AulDebug::~C4AulDebug()
|
||||||
|
@ -125,15 +124,15 @@ bool C4AulDebug::OnConn(const C4NetIO::addr_t &AddrPeer, const C4NetIO::addr_t &
|
||||||
// Already have a connection?
|
// Already have a connection?
|
||||||
if (fConnected) return false;
|
if (fConnected) return false;
|
||||||
// Check address
|
// Check address
|
||||||
if (AllowedAddr.sin_addr.s_addr)
|
if (!AllowedAddr.IsNull())
|
||||||
if (AllowedAddr.sin_addr.s_addr != AddrPeer.sin_addr.s_addr ||
|
if (AllowedAddr.GetHost() != AddrPeer.GetHost() ||
|
||||||
(AllowedAddr.sin_port && AllowedAddr.sin_port != AddrPeer.sin_port))
|
(AllowedAddr.GetPort() && AllowedAddr.GetPort() != AddrPeer.GetPort()))
|
||||||
{
|
{
|
||||||
LogF("C4AulDebug blocked connection from %s:%d", inet_ntoa(AddrPeer.sin_addr), htons(AddrPeer.sin_port));
|
LogF("C4AulDebug blocked connection from %s", AddrPeer.ToString().getData());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Log
|
// Log
|
||||||
LogF("C4AulDebug got connection from %s:%d", inet_ntoa(AddrPeer.sin_addr), htons(AddrPeer.sin_port));
|
LogF("C4AulDebug got connection from %s", AddrPeer.ToString().getData());
|
||||||
// Accept connection
|
// Accept connection
|
||||||
PeerAddr = AddrPeer;
|
PeerAddr = AddrPeer;
|
||||||
return true;
|
return true;
|
||||||
|
@ -144,7 +143,7 @@ void C4AulDebug::OnDisconn(const C4NetIO::addr_t &AddrPeer, C4NetIO *pNetIO, con
|
||||||
LogF("C4AulDebug lost connection (%s)", szReason);
|
LogF("C4AulDebug lost connection (%s)", szReason);
|
||||||
fConnected = false;
|
fConnected = false;
|
||||||
eState = DS_Go;
|
eState = DS_Go;
|
||||||
ZeroMem(&PeerAddr, sizeof PeerAddr);
|
PeerAddr.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void C4AulDebug::OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO)
|
void C4AulDebug::OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO)
|
||||||
|
@ -155,17 +154,18 @@ void C4AulDebug::OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO)
|
||||||
bool C4AulDebug::SetAllowed(const char *szHost)
|
bool C4AulDebug::SetAllowed(const char *szHost)
|
||||||
{
|
{
|
||||||
// Clear
|
// Clear
|
||||||
ZeroMem(&AllowedAddr, sizeof(AllowedAddr));
|
AllowedAddr.Clear();
|
||||||
// No host?
|
// No host?
|
||||||
if (!szHost || !*szHost) return true;
|
if (!szHost || !*szHost) return true;
|
||||||
// Resolve the address
|
// Resolve the address
|
||||||
return ResolveAddress(szHost, &AllowedAddr, 0);
|
AllowedAddr.SetAddress(StdStrBuf(szHost));
|
||||||
|
return !AllowedAddr.IsNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool C4AulDebug::Init(uint16_t iPort)
|
bool C4AulDebug::Init(uint16_t iPort)
|
||||||
{
|
{
|
||||||
if (fInit) Close();
|
if (fInit) Close();
|
||||||
if (iPort == P_NONE) return false;
|
if (iPort == EndpointAddress::IPPORT_NONE) return false;
|
||||||
|
|
||||||
// Register self as callback for network events
|
// Register self as callback for network events
|
||||||
C4NetIOTCP::SetCallback(this);
|
C4NetIOTCP::SetCallback(this);
|
||||||
|
|
Loading…
Reference in New Issue