forked from Mirrors/openclonk
Implement IPv6 support to C4NetIO
parent
3fe83986ce
commit
102047f537
|
@ -1248,6 +1248,7 @@ target_link_libraries(netpuncher
|
|||
)
|
||||
|
||||
if(WIN32)
|
||||
target_link_libraries(libmisc iphlpapi)
|
||||
target_link_libraries(openclonk ws2_32)
|
||||
target_link_libraries(openclonk-server 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_INFO=Client-Informationen
|
||||
IDS_NET_CLIENT_INFO_ADDRESSES=Adressen:
|
||||
IDS_NET_CLIENT_INFO_CONNDATA= Daten: %s (%s:%d, %d ms)
|
||||
IDS_NET_CLIENT_INFO_CONNECTIONS=Verbindungen: %s: %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 ms)
|
||||
IDS_NET_CLIENT_INFO_NOADDRESSES=Addressen: Keine
|
||||
IDS_NET_CLIENT_INFO_NOCONNECTIONS=Verbindungen: Nicht verbunden
|
||||
IDS_NET_CLIENT_INFO_UNKNOWNID=Unbekannte client ID #%d.
|
||||
|
|
|
@ -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_INFO=Client info
|
||||
IDS_NET_CLIENT_INFO_ADDRESSES=Addresses:
|
||||
IDS_NET_CLIENT_INFO_CONNDATA= Data: %s (%s:%d, %d ms)
|
||||
IDS_NET_CLIENT_INFO_CONNECTIONS=Connections: %s: %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 ms)
|
||||
IDS_NET_CLIENT_INFO_NOADDRESSES=Addresses: none
|
||||
IDS_NET_CLIENT_INFO_NOCONNECTIONS=Connections: Not connected
|
||||
IDS_NET_CLIENT_INFO_UNKNOWNID=Unknown client ID #%d.
|
||||
|
|
|
@ -920,8 +920,7 @@ void C4StartupNetDlg::UpdateList(bool fGotReference)
|
|||
C4NetIO::addr_t Discover;
|
||||
while (DiscoverClient.PopDiscover(Discover))
|
||||
{
|
||||
StdStrBuf Address;
|
||||
Address.Format("%s:%d", inet_ntoa(Discover.sin_addr), htons(Discover.sin_port));
|
||||
StdStrBuf Address(Discover.ToString());
|
||||
AddReferenceQuery(Address.getData(), C4StartupNetListEntry::NRQT_GameDiscovery);
|
||||
}
|
||||
|
||||
|
|
|
@ -60,10 +60,25 @@ namespace std {
|
|||
};
|
||||
|
||||
template<>
|
||||
struct hash<::sockaddr_in> {
|
||||
size_t operator()(const ::sockaddr_in& addr) const {
|
||||
auto unpack = make_tuple(addr.sin_family, addr.sin_addr.s_addr, addr.sin_port);
|
||||
return hash<decltype(unpack)>()(unpack);
|
||||
struct hash<C4NetIO::addr_t> {
|
||||
size_t operator()(const C4NetIO::addr_t& addr) const {
|
||||
switch (addr.GetFamily())
|
||||
{
|
||||
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);
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -47,9 +47,7 @@ C4NetpuncherPacketCReq::C4NetpuncherPacketCReq(const C4NetIOPacket& rpack) {
|
|||
C4Network2Address parse_addr;
|
||||
CompileFromBuf<StdCompilerBinRead>(parse_addr, rpack.getPBuf());
|
||||
if (parse_addr.getProtocol() != P_UDP) throw P_UDP;
|
||||
addr.sin_addr.s_addr = parse_addr.getAddr().sin_addr.s_addr,
|
||||
addr.sin_family = parse_addr.getAddr().sin_family,
|
||||
addr.sin_port = parse_addr.getAddr().sin_port;
|
||||
addr = parse_addr.getAddr();
|
||||
}
|
||||
|
||||
StdBuf C4NetpuncherPacketCReq::PackInto() const {
|
||||
|
|
|
@ -48,7 +48,7 @@ private:
|
|||
peer_ids.emplace(AddrPeer, nid);
|
||||
peer_addrs.emplace(nid, 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;
|
||||
}
|
||||
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) {
|
||||
auto it = peer_ids.find(AddrPeer);
|
||||
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;
|
||||
}
|
||||
peer_addrs.erase(it->second);
|
||||
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;
|
||||
|
||||
|
|
|
@ -57,7 +57,6 @@ int pipe(int *phandles) { return _pipe(phandles, 10, O_BINARY); }
|
|||
|
||||
// constants definition
|
||||
const int C4NetIO::TO_INF = -1;
|
||||
const uint16_t C4NetIO::P_NONE = ~0;
|
||||
|
||||
// simulate packet loss (loss probability in percent)
|
||||
// #define C4NETIO_SIMULATE_PACKETLOSS 10
|
||||
|
@ -203,6 +202,350 @@ void ResetSocketError()
|
|||
|
||||
#endif // HAVE_WINSOCK
|
||||
|
||||
// *** C4NetIO::HostAddress
|
||||
void C4NetIO::HostAddress::Clear()
|
||||
{
|
||||
v6.sin6_family = AF_INET6;
|
||||
v6.sin6_flowinfo = 0;
|
||||
v6.sin6_scope_id = 0;
|
||||
memset(&v6.sin6_addr, 0, sizeof(v6.sin6_addr));
|
||||
}
|
||||
|
||||
// *** C4NetIO::EndpointAddress
|
||||
const C4NetIO::EndpointAddress::EndpointAddressPtr C4NetIO::EndpointAddress::operator &() const { return EndpointAddressPtr(const_cast<EndpointAddress*>(this)); }
|
||||
C4NetIO::EndpointAddress::EndpointAddressPtr C4NetIO::EndpointAddress::operator &() { return EndpointAddressPtr(this); }
|
||||
|
||||
void C4NetIO::EndpointAddress::Clear()
|
||||
{
|
||||
HostAddress::Clear();
|
||||
SetPort(IPPORT_NONE);
|
||||
}
|
||||
|
||||
void C4NetIO::HostAddress::SetHost(const HostAddress &other)
|
||||
{
|
||||
SetHost(&other.gen);
|
||||
}
|
||||
|
||||
bool C4NetIO::HostAddress::IsMulticast() const
|
||||
{
|
||||
if (gen.sa_family == AF_INET6)
|
||||
return IN6_IS_ADDR_MULTICAST(&v6.sin6_addr) != 0;
|
||||
if (gen.sa_family == AF_INET)
|
||||
return (ntohl(v4.sin_addr.s_addr) >> 24) == 239;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool C4NetIO::HostAddress::IsLoopback() const
|
||||
{
|
||||
if (gen.sa_family == AF_INET6)
|
||||
return IN6_IS_ADDR_LOOPBACK(&v6.sin6_addr) != 0;
|
||||
if (gen.sa_family == AF_INET)
|
||||
return (ntohl(v4.sin_addr.s_addr) >> 24) == 127;
|
||||
return false;
|
||||
}
|
||||
|
||||
void C4NetIO::HostAddress::SetScopeId(int scopeId)
|
||||
{
|
||||
if (gen.sa_family != AF_INET6) return;
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&v6.sin6_addr) != 0)
|
||||
v6.sin6_scope_id = scopeId;
|
||||
}
|
||||
|
||||
int C4NetIO::HostAddress::GetScopeId() const
|
||||
{
|
||||
if (gen.sa_family == AF_INET6)
|
||||
return v6.sin6_scope_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
C4NetIO::HostAddress C4NetIO::HostAddress::AsIPv6() const
|
||||
{
|
||||
static const uint8_t v6_mapped_v4_prefix[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
|
||||
|
||||
HostAddress nrv(*this);
|
||||
switch (gen.sa_family)
|
||||
{
|
||||
case AF_INET6:
|
||||
// That was easy
|
||||
break;
|
||||
case AF_INET:
|
||||
memmove(((char*)&nrv.v6.sin6_addr) + sizeof(v6_mapped_v4_prefix), &v4.sin_addr, sizeof(v4.sin_addr));
|
||||
nrv.v6.sin6_family = AF_INET6;
|
||||
memcpy(&nrv.v6.sin6_addr, v6_mapped_v4_prefix, sizeof(v6_mapped_v4_prefix));
|
||||
nrv.v6.sin6_flowinfo = 0;
|
||||
nrv.v6.sin6_scope_id = 0;
|
||||
break;
|
||||
default: assert(!"Shouldn't reach this"); break;
|
||||
}
|
||||
return nrv;
|
||||
}
|
||||
|
||||
C4NetIO::EndpointAddress C4NetIO::EndpointAddress::AsIPv6() const
|
||||
{
|
||||
return EndpointAddress(HostAddress::AsIPv6(), GetPort());
|
||||
}
|
||||
|
||||
void C4NetIO::HostAddress::SetHost(const sockaddr *addr)
|
||||
{
|
||||
// Copy all but port number
|
||||
if (addr->sa_family == AF_INET6)
|
||||
{
|
||||
v6.sin6_family = ((const sockaddr_in6*)addr)->sin6_family;
|
||||
v6.sin6_flowinfo = ((const sockaddr_in6*)addr)->sin6_flowinfo;
|
||||
memcpy(&v6.sin6_addr, &((const sockaddr_in6*)addr)->sin6_addr, sizeof(v6.sin6_addr));
|
||||
v6.sin6_scope_id = ((const sockaddr_in6*)addr)->sin6_scope_id;
|
||||
}
|
||||
else if (addr->sa_family == AF_INET)
|
||||
{
|
||||
v4.sin_family = ((const sockaddr_in*)addr)->sin_family;
|
||||
v4.sin_addr.s_addr = ((const sockaddr_in*)addr)->sin_addr.s_addr;
|
||||
memset(&v4.sin_zero, 0, sizeof(v4.sin_zero));
|
||||
}
|
||||
}
|
||||
|
||||
void C4NetIO::EndpointAddress::SetAddress(const sockaddr *addr)
|
||||
{
|
||||
switch (addr->sa_family)
|
||||
{
|
||||
case AF_INET: memcpy(&v4, addr, sizeof(v4)); break;
|
||||
case AF_INET6: memcpy(&v6, addr, sizeof(v6)); break;
|
||||
default:
|
||||
assert(!"Unexpected address family");
|
||||
memcpy(&gen, addr, sizeof(gen)); break;
|
||||
}
|
||||
}
|
||||
|
||||
void C4NetIO::HostAddress::SetHost(SpecialAddress addr)
|
||||
{
|
||||
switch (addr)
|
||||
{
|
||||
case Any:
|
||||
v6.sin6_family = AF_INET6;
|
||||
memset(&v6.sin6_addr, 0, sizeof(v6.sin6_addr));
|
||||
v6.sin6_flowinfo = 0;
|
||||
v6.sin6_scope_id = 0;
|
||||
break;
|
||||
case AnyIPv4:
|
||||
v4.sin_family = AF_INET;
|
||||
v4.sin_addr.s_addr = 0;
|
||||
memset(&v4.sin_zero, 0, sizeof(v4.sin_zero));
|
||||
break;
|
||||
case Loopback:
|
||||
v6.sin6_family = AF_INET6;
|
||||
memset(&v6.sin6_addr, 0, sizeof(v6.sin6_addr)); v6.sin6_addr.s6_addr[15] = 1;
|
||||
v6.sin6_flowinfo = 0;
|
||||
v6.sin6_scope_id = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void C4NetIO::HostAddress::SetHost(uint32_t v4addr)
|
||||
{
|
||||
v4.sin_family = AF_INET;
|
||||
v4.sin_addr.s_addr = v4addr;
|
||||
memset(&v4.sin_zero, 0, sizeof(v4.sin_zero));
|
||||
}
|
||||
|
||||
void C4NetIO::EndpointAddress::SetAddress(const StdStrBuf &addr)
|
||||
{
|
||||
Clear();
|
||||
|
||||
if (addr.isNull()) return;
|
||||
|
||||
const char *begin = addr.getData();
|
||||
const char *end = begin + addr.getLength();
|
||||
|
||||
const char *ab = begin;
|
||||
const char *ae = end;
|
||||
|
||||
const char *pb = end;
|
||||
const char *pe = end;
|
||||
|
||||
bool isIPv6 = false;
|
||||
|
||||
// If addr begins with [, it's an IPv6 address
|
||||
if (ab[0] == '[')
|
||||
{
|
||||
++ab; // skip bracket
|
||||
const char *cbracket = std::find(ab, ae, ']');
|
||||
if (cbracket == ae)
|
||||
// No closing bracket found: invalid
|
||||
return;
|
||||
ae = cbracket++;
|
||||
if (cbracket != end && cbracket[0] == ':')
|
||||
{
|
||||
// port number given
|
||||
pb = ++cbracket;
|
||||
if (pb == end)
|
||||
// Trailing colon: invalid
|
||||
return;
|
||||
}
|
||||
isIPv6 = true;
|
||||
}
|
||||
// If there's more than 1 colon in the address, it's IPv6
|
||||
else if (std::count(ab, ae, ':') > 1)
|
||||
{
|
||||
isIPv6 = true;
|
||||
}
|
||||
// It's probably not IPv6, but look for a port specification
|
||||
else
|
||||
{
|
||||
const char *colon = std::find(ab, ae, ':');
|
||||
if (colon != ae)
|
||||
{
|
||||
ae = colon;
|
||||
pb = colon + 1;
|
||||
if (pb == end)
|
||||
// Trailing colon: invalid
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
addrinfo hints = addrinfo();
|
||||
//hints.ai_flags = AI_NUMERICHOST;
|
||||
addrinfo *addresses = nullptr;
|
||||
if (getaddrinfo(std::string(ab, ae).c_str(), pb != end ? std::string(pb, pe).c_str() : nullptr, &hints, &addresses) != 0)
|
||||
// GAI failed
|
||||
return;
|
||||
SetAddress(addresses->ai_addr);
|
||||
freeaddrinfo(addresses);
|
||||
}
|
||||
|
||||
void C4NetIO::EndpointAddress::SetAddress(const EndpointAddress &addr)
|
||||
{
|
||||
SetHost(addr);
|
||||
SetPort(addr.GetPort());
|
||||
}
|
||||
|
||||
void C4NetIO::EndpointAddress::SetAddress(HostAddress::SpecialAddress host, uint16_t port)
|
||||
{
|
||||
SetHost(host);
|
||||
SetPort(port);
|
||||
}
|
||||
|
||||
void C4NetIO::EndpointAddress::SetAddress(const HostAddress &host, uint16_t port)
|
||||
{
|
||||
SetHost(host);
|
||||
SetPort(port);
|
||||
}
|
||||
|
||||
bool C4NetIO::EndpointAddress::IsNull() const
|
||||
{
|
||||
return IsNullHost() && GetPort() == IPPORT_NONE;
|
||||
}
|
||||
|
||||
bool C4NetIO::HostAddress::IsNull() const
|
||||
{
|
||||
switch (gen.sa_family)
|
||||
{
|
||||
case AF_INET: return v4.sin_addr.s_addr == 0;
|
||||
case AF_INET6:
|
||||
return IN6_IS_ADDR_UNSPECIFIED(&v6.sin6_addr);
|
||||
}
|
||||
assert(!"Shouldn't reach this");
|
||||
return false;
|
||||
}
|
||||
|
||||
C4NetIO::HostAddress::AddressFamily C4NetIO::HostAddress::GetFamily() const
|
||||
{
|
||||
return gen.sa_family == AF_INET ? IPv4 :
|
||||
gen.sa_family == AF_INET6 ? IPv6 : UnknownFamily;
|
||||
}
|
||||
|
||||
void C4NetIO::EndpointAddress::SetPort(uint16_t port)
|
||||
{
|
||||
switch (gen.sa_family)
|
||||
{
|
||||
case AF_INET: v4.sin_port = htons(port); break;
|
||||
case AF_INET6: v6.sin6_port = htons(port); break;
|
||||
default: assert(!"Shouldn't reach this"); break;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t C4NetIO::EndpointAddress::GetPort() const
|
||||
{
|
||||
switch (gen.sa_family)
|
||||
{
|
||||
case AF_INET: return ntohs(v4.sin_port);
|
||||
case AF_INET6: return ntohs(v6.sin6_port);
|
||||
}
|
||||
assert(!"Shouldn't reach this");
|
||||
return IPPORT_NONE;
|
||||
}
|
||||
|
||||
bool C4NetIO::HostAddress::operator ==(const HostAddress &rhs) const
|
||||
{
|
||||
// Check for IPv4-mapped IPv6 addresses.
|
||||
if (gen.sa_family != rhs.gen.sa_family)
|
||||
return AsIPv6() == rhs.AsIPv6();
|
||||
if (gen.sa_family == AF_INET)
|
||||
return v4.sin_addr.s_addr == rhs.v4.sin_addr.s_addr;
|
||||
if (gen.sa_family == AF_INET6)
|
||||
return memcmp(&v6.sin6_addr, &rhs.v6.sin6_addr, sizeof(v6.sin6_addr)) == 0 &&
|
||||
v6.sin6_scope_id == rhs.v6.sin6_scope_id;
|
||||
assert(!"Shouldn't reach this");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool C4NetIO::EndpointAddress::operator ==(const addr_t &rhs) const
|
||||
{
|
||||
if (!HostAddress::operator==(rhs)) return false;
|
||||
if (gen.sa_family == AF_INET)
|
||||
{
|
||||
return v4.sin_port == rhs.v4.sin_port;
|
||||
}
|
||||
else if (gen.sa_family == AF_INET6)
|
||||
{
|
||||
return v6.sin6_port == rhs.v6.sin6_port &&
|
||||
v6.sin6_scope_id == rhs.v6.sin6_scope_id;
|
||||
}
|
||||
assert(!"Shouldn't reach this");
|
||||
return false;
|
||||
}
|
||||
|
||||
StdStrBuf C4NetIO::HostAddress::ToString(int flags) const
|
||||
{
|
||||
if (gen.sa_family == AF_INET6 && v6.sin6_scope_id != 0 && (flags & TSF_SkipZoneId))
|
||||
{
|
||||
HostAddress addr = *this;
|
||||
addr.v6.sin6_scope_id = 0;
|
||||
return addr.ToString(flags);
|
||||
}
|
||||
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
if (getnameinfo(&gen, sizeof(v6), buf, sizeof(buf), 0, 0, NI_NUMERICHOST) != 0)
|
||||
return StdStrBuf();
|
||||
|
||||
return StdStrBuf(buf, true);
|
||||
}
|
||||
|
||||
StdStrBuf C4NetIO::EndpointAddress::ToString(int flags) const
|
||||
{
|
||||
if (flags & TSF_SkipPort)
|
||||
return HostAddress::ToString(flags);
|
||||
|
||||
switch (GetFamily())
|
||||
{
|
||||
case IPv4: return FormatString("%s:%d", HostAddress::ToString(flags).getData(), GetPort());
|
||||
case IPv6: return FormatString("[%s]:%d", HostAddress::ToString(flags).getData(), GetPort());
|
||||
default: assert(!"Shouldn't reach this");
|
||||
}
|
||||
return StdStrBuf();
|
||||
}
|
||||
|
||||
void C4NetIO::EndpointAddress::CompileFunc(StdCompiler *comp)
|
||||
{
|
||||
if (!comp->isCompiler())
|
||||
{
|
||||
StdStrBuf val(ToString(TSF_SkipZoneId));
|
||||
comp->Value(val);
|
||||
} else {
|
||||
StdStrBuf val;
|
||||
comp->Value(val);
|
||||
SetAddress(val);
|
||||
}
|
||||
}
|
||||
|
||||
// *** C4NetIO
|
||||
|
||||
// construction / destruction
|
||||
|
@ -318,7 +661,7 @@ bool C4NetIOTCP::Init(uint16_t iPort)
|
|||
#endif
|
||||
|
||||
// create listen socket (if necessary)
|
||||
if (iPort != P_NONE)
|
||||
if (iPort != addr_t::IPPORT_NONE)
|
||||
if (!Listen(iPort))
|
||||
return false;
|
||||
|
||||
|
@ -633,7 +976,7 @@ bool C4NetIOTCP::Execute(int iMaxTime, pollfd *fds) // (mt-safe)
|
|||
bool C4NetIOTCP::Connect(const C4NetIO::addr_t &addr) // (mt-safe)
|
||||
{
|
||||
// create new socket
|
||||
SOCKET nsock = ::socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP);
|
||||
SOCKET nsock = ::socket(addr.GetFamily() == HostAddress::IPv6 ? AF_INET6 : AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP);
|
||||
if (nsock == INVALID_SOCKET)
|
||||
{
|
||||
SetError("socket creation failed", true);
|
||||
|
@ -675,7 +1018,7 @@ bool C4NetIOTCP::Connect(const C4NetIO::addr_t &addr) // (mt-safe)
|
|||
#endif
|
||||
|
||||
// connect (async)
|
||||
if (::connect(nsock, reinterpret_cast<const sockaddr *>(&addr), sizeof addr) == SOCKET_ERROR)
|
||||
if (::connect(nsock, &addr, sizeof addr) == SOCKET_ERROR)
|
||||
{
|
||||
if (!HaveWouldBlockError()) // expected
|
||||
{
|
||||
|
@ -853,9 +1196,9 @@ C4NetIOTCP::Peer *C4NetIOTCP::Accept(SOCKET nsock, const addr_t &ConnectAddr) //
|
|||
{
|
||||
// accept from listener
|
||||
#ifdef __linux__
|
||||
if ((nsock = ::accept4(lsock, reinterpret_cast<sockaddr *>(&addr), &iAddrSize, SOCK_CLOEXEC)) == INVALID_SOCKET)
|
||||
if ((nsock = ::accept4(lsock, &addr, &iAddrSize, SOCK_CLOEXEC)) == INVALID_SOCKET)
|
||||
#else
|
||||
if ((nsock = ::accept(lsock, reinterpret_cast<sockaddr *>(&addr), &iAddrSize)) == INVALID_SOCKET)
|
||||
if ((nsock = ::accept(lsock, &addr, &iAddrSize)) == INVALID_SOCKET)
|
||||
#endif
|
||||
{
|
||||
// set error
|
||||
|
@ -863,12 +1206,12 @@ C4NetIOTCP::Peer *C4NetIOTCP::Accept(SOCKET nsock, const addr_t &ConnectAddr) //
|
|||
return nullptr;
|
||||
}
|
||||
// connect address unknown, so zero it
|
||||
ZeroMem(&caddr, sizeof caddr);
|
||||
caddr.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
// get peer address
|
||||
if (::getpeername(nsock, reinterpret_cast<sockaddr *>(&addr), &iAddrSize) == SOCKET_ERROR)
|
||||
if (::getpeername(nsock, &addr, &iAddrSize) == SOCKET_ERROR)
|
||||
{
|
||||
#ifndef HAVE_WINSOCK
|
||||
// getpeername behaves strangely on exotic platforms. Just ignore it.
|
||||
|
@ -885,7 +1228,7 @@ C4NetIOTCP::Peer *C4NetIOTCP::Accept(SOCKET nsock, const addr_t &ConnectAddr) //
|
|||
}
|
||||
|
||||
// check address
|
||||
if (iAddrSize != sizeof addr || addr.sin_family != AF_INET)
|
||||
if (addr.GetFamily() == addr_t::UnknownFamily)
|
||||
{
|
||||
// set error
|
||||
SetError("socket accept failed: invalid address returned");
|
||||
|
@ -959,10 +1302,10 @@ bool C4NetIOTCP::Listen(uint16_t inListenPort)
|
|||
if (lsock != INVALID_SOCKET)
|
||||
// close existing socket
|
||||
closesocket(lsock);
|
||||
iListenPort = P_NONE;
|
||||
iListenPort = addr_t::IPPORT_NONE;
|
||||
|
||||
// create socket
|
||||
if ((lsock = ::socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP)) == INVALID_SOCKET)
|
||||
if ((lsock = ::socket(AF_INET6, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP)) == INVALID_SOCKET)
|
||||
{
|
||||
SetError("socket creation failed", true);
|
||||
return false;
|
||||
|
@ -973,12 +1316,9 @@ bool C4NetIOTCP::Listen(uint16_t inListenPort)
|
|||
setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char *>(&reuseaddr), sizeof(reuseaddr));
|
||||
#endif
|
||||
// bind listen socket
|
||||
C4NetIO::addr_t addr;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(inListenPort);
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
memset(addr.sin_zero, 0, sizeof addr.sin_zero);
|
||||
if (::bind(lsock, reinterpret_cast<sockaddr *>(&addr), sizeof addr) == SOCKET_ERROR)
|
||||
addr_t addr = addr_t::Any;
|
||||
addr.SetPort(inListenPort);
|
||||
if (::bind(lsock, &addr, sizeof(addr)) == SOCKET_ERROR)
|
||||
{
|
||||
SetError("socket bind failed", true);
|
||||
closesocket(lsock); lsock = INVALID_SOCKET;
|
||||
|
@ -1014,7 +1354,7 @@ C4NetIOTCP::Peer *C4NetIOTCP::GetPeer(const addr_t &addr) // (mt-safe)
|
|||
CStdShareLock PeerListLock(&PeerListCSec);
|
||||
for (Peer *pPeer = pPeerList; pPeer; pPeer = pPeer->Next)
|
||||
if (pPeer->Open())
|
||||
if (AddrEqual(pPeer->GetAddr(), addr))
|
||||
if (pPeer->GetAddr() == addr)
|
||||
return pPeer;
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1088,7 +1428,7 @@ C4NetIOTCP::ConnectWait *C4NetIOTCP::GetConnectWait(const addr_t &addr) // (mt-s
|
|||
CStdShareLock PeerListLock(&PeerListCSec);
|
||||
// search
|
||||
for (ConnectWait *pWait = pConnectWaits; pWait; pWait = pWait->Next)
|
||||
if (AddrEqual(pWait->addr, addr))
|
||||
if (pWait->addr == addr)
|
||||
return pWait;
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1335,8 +1675,8 @@ bool C4NetIOSimpleUDP::Init(uint16_t inPort)
|
|||
}
|
||||
#endif
|
||||
|
||||
// create socket
|
||||
if ((sock = ::socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP)) == INVALID_SOCKET)
|
||||
// create sockets
|
||||
if ((sock = ::socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP)) == INVALID_SOCKET)
|
||||
{
|
||||
SetError("could not create socket", true);
|
||||
return false;
|
||||
|
@ -1351,12 +1691,9 @@ bool C4NetIOSimpleUDP::Init(uint16_t inPort)
|
|||
|
||||
// bind socket
|
||||
iPort = inPort;
|
||||
C4NetIO::addr_t naddr;
|
||||
naddr.sin_family = AF_INET;
|
||||
naddr.sin_port = (iPort == P_NONE ? 0 : htons(iPort));
|
||||
naddr.sin_addr.s_addr = INADDR_ANY;
|
||||
memset(naddr.sin_zero, 0, sizeof naddr.sin_zero);
|
||||
if (::bind(sock, reinterpret_cast<sockaddr *>(&naddr), sizeof naddr) == SOCKET_ERROR)
|
||||
addr_t naddr = addr_t::Any;
|
||||
naddr.SetPort(iPort);
|
||||
if (::bind(sock, &naddr, sizeof(naddr)) == SOCKET_ERROR)
|
||||
{
|
||||
SetError("could not bind socket", true);
|
||||
return false;
|
||||
|
@ -1420,13 +1757,12 @@ bool C4NetIOSimpleUDP::InitBroadcast(addr_t *pBroadcastAddr)
|
|||
if (fMultiCast) CloseBroadcast();
|
||||
|
||||
// broadcast addr valid?
|
||||
if (pBroadcastAddr->sin_family != AF_INET ||
|
||||
in_addr_b(pBroadcastAddr->sin_addr, 0) != 239)
|
||||
if (pBroadcastAddr->IsMulticast())
|
||||
{
|
||||
SetError("invalid broadcast address");
|
||||
return false;
|
||||
}
|
||||
if (pBroadcastAddr->sin_port != htons(iPort))
|
||||
if (pBroadcastAddr->GetPort() != iPort)
|
||||
{
|
||||
SetError("invalid broadcast address (different port)");
|
||||
return false;
|
||||
|
@ -1442,7 +1778,7 @@ bool C4NetIOSimpleUDP::InitBroadcast(addr_t *pBroadcastAddr)
|
|||
|
||||
// set up multicast group information
|
||||
this->MCAddr = *pBroadcastAddr;
|
||||
MCGrpInfo.imr_multiaddr = MCAddr.sin_addr;
|
||||
MCGrpInfo.imr_multiaddr = static_cast<sockaddr_in*>(&MCAddr)->sin_addr;
|
||||
MCGrpInfo.imr_interface.s_addr = INADDR_ANY;
|
||||
|
||||
// join multicast group
|
||||
|
@ -1559,8 +1895,8 @@ bool C4NetIOSimpleUDP::Execute(int iMaxTime, pollfd *)
|
|||
// alloc buffer
|
||||
C4NetIOPacket Pkt; Pkt.New(iMaxMsgSize);
|
||||
// read data (note: it is _not_ garantueed that iMaxMsgSize bytes are available)
|
||||
addr_t SrcAddr; socklen_t iSrcAddrLen = sizeof(SrcAddr);
|
||||
int iMsgSize = ::recvfrom(sock, getMBufPtr<char>(Pkt), iMaxMsgSize, 0, reinterpret_cast<sockaddr *>(&SrcAddr), &iSrcAddrLen);
|
||||
addr_t SrcAddr; socklen_t iSrcAddrLen = sizeof(sockaddr_in6);
|
||||
int iMsgSize = ::recvfrom(sock, getMBufPtr<char>(Pkt), iMaxMsgSize, 0, &SrcAddr, &iSrcAddrLen);
|
||||
// error?
|
||||
if (iMsgSize == SOCKET_ERROR)
|
||||
{
|
||||
|
@ -1579,7 +1915,7 @@ bool C4NetIOSimpleUDP::Execute(int iMaxTime, pollfd *)
|
|||
}
|
||||
}
|
||||
// invalid address?
|
||||
if (iSrcAddrLen != sizeof(SrcAddr) || SrcAddr.sin_family != AF_INET)
|
||||
if ((iSrcAddrLen != sizeof(sockaddr_in) && iSrcAddrLen != sizeof(sockaddr_in6)) || SrcAddr.GetFamily() == addr_t::UnknownFamily)
|
||||
{
|
||||
SetError("recvfrom returned an invalid address");
|
||||
return false;
|
||||
|
@ -1607,7 +1943,7 @@ bool C4NetIOSimpleUDP::Send(const C4NetIOPacket &rPacket)
|
|||
// send it
|
||||
C4NetIO::addr_t addr = rPacket.getAddr();
|
||||
if (::sendto(sock, getBufPtr<char>(rPacket), rPacket.getSize(), 0,
|
||||
reinterpret_cast<sockaddr *>(&addr), sizeof(addr))
|
||||
&addr, sizeof(addr))
|
||||
!= int(rPacket.getSize()) &&
|
||||
!HaveWouldBlockError())
|
||||
{
|
||||
|
@ -1870,8 +2206,7 @@ bool C4NetIOUDP::InitBroadcast(addr_t *pBroadcastAddr)
|
|||
C4NetIO::addr_t MCAddr = *pBroadcastAddr;
|
||||
|
||||
// broadcast addr valid?
|
||||
if (MCAddr.sin_family != AF_INET ||
|
||||
in_addr_b(MCAddr.sin_addr, 0) != 239)
|
||||
if (!MCAddr.IsMulticast())
|
||||
{
|
||||
// port is needed in order to search a mc address automatically
|
||||
if (!iPort)
|
||||
|
@ -1880,15 +2215,12 @@ bool C4NetIOUDP::InitBroadcast(addr_t *pBroadcastAddr)
|
|||
return false;
|
||||
}
|
||||
// set up adress
|
||||
MCAddr.sin_family = AF_INET;
|
||||
MCAddr.sin_port = htons(iPort);
|
||||
memset(&MCAddr.sin_zero, 0, sizeof MCAddr.sin_zero);
|
||||
MCAddr.SetAddress(addr_t::AnyIPv4, iPort);
|
||||
// search for a free one
|
||||
for (int iRetries = 1000; iRetries; iRetries--)
|
||||
{
|
||||
// create new - random - address
|
||||
MCAddr.sin_addr.s_addr =
|
||||
0x000000ef | (UnsyncedRandom(0x1000000) << 8);
|
||||
MCAddr.SetAddress(C4NetIO::HostAddress(0x000000ef | (UnsyncedRandom(0x1000000) << 8)));
|
||||
// init broadcast
|
||||
if (!C4NetIOSimpleUDP::InitBroadcast(&MCAddr))
|
||||
return false;
|
||||
|
@ -1921,7 +2253,7 @@ bool C4NetIOUDP::InitBroadcast(addr_t *pBroadcastAddr)
|
|||
// Timeout? So expect this address to be unused
|
||||
if (LastPacket.isNull()) { fSuccess = true; break; }
|
||||
// looped back?
|
||||
if (C4NetIOSimpleUDP::getMCLoopback() && AddrEqual(LastPacket.getAddr(), MCLoopbackAddr))
|
||||
if (C4NetIOSimpleUDP::getMCLoopback() && LastPacket.getAddr() == MCLoopbackAddr)
|
||||
// ignore this one
|
||||
continue;
|
||||
// otherwise: there must be someone else in this MC group
|
||||
|
@ -1938,7 +2270,7 @@ bool C4NetIOUDP::InitBroadcast(addr_t *pBroadcastAddr)
|
|||
else
|
||||
{
|
||||
// check: must be same port
|
||||
if (MCAddr.sin_port != htons(iPort))
|
||||
if (MCAddr.GetPort() == iPort)
|
||||
{
|
||||
SetError("invalid multicast address: wrong port");
|
||||
return false;
|
||||
|
@ -2173,7 +2505,7 @@ void C4NetIOUDP::OnPacket(const C4NetIOPacket &Packet, C4NetIO *pNetIO)
|
|||
}
|
||||
// looped back?
|
||||
if (fMultiCast && !fDelayedLoopbackTest)
|
||||
if (AddrEqual(Packet.getAddr(), MCLoopbackAddr))
|
||||
if (Packet.getAddr() == MCLoopbackAddr)
|
||||
return;
|
||||
// loopback test packet? ignore
|
||||
if ((Packet.getStatus() & 0x7F) == IPID_Test) return;
|
||||
|
@ -2234,7 +2566,7 @@ void C4NetIOUDP::OnDisconn(const addr_t &AddrPeer, C4NetIO *pNetIO, const char *
|
|||
void C4NetIOUDP::OnAddAddress(const addr_t &FromAddr, const AddAddrPacket &Packet)
|
||||
{
|
||||
// Security (this would be strange behavior indeed...)
|
||||
if (!AddrEqual(FromAddr, Packet.Addr) && !AddrEqual(FromAddr, Packet.NewAddr)) return;
|
||||
if (FromAddr != Packet.Addr && FromAddr != Packet.NewAddr) return;
|
||||
// Search peer(s)
|
||||
Peer *pPeer = GetPeer(Packet.Addr);
|
||||
Peer *pPeer2 = GetPeer(Packet.NewAddr);
|
||||
|
@ -2494,7 +2826,7 @@ const unsigned int C4NetIOUDP::Peer::iReCheckInterval = 1000; // (ms)
|
|||
|
||||
// construction / destruction
|
||||
|
||||
C4NetIOUDP::Peer::Peer(const sockaddr_in &naddr, C4NetIOUDP *pnParent)
|
||||
C4NetIOUDP::Peer::Peer(const addr_t &naddr, C4NetIOUDP *pnParent)
|
||||
: pParent(pnParent), addr(naddr),
|
||||
eStatus(CS_None),
|
||||
fMultiCast(false), fDoBroadcast(false),
|
||||
|
@ -2506,8 +2838,6 @@ C4NetIOUDP::Peer::Peer(const sockaddr_in &naddr, C4NetIOUDP *pnParent)
|
|||
tNextReCheck(C4TimeMilliseconds::NegativeInfinity),
|
||||
iIRate(0), iORate(0), iLoss(0)
|
||||
{
|
||||
ZeroMem(&addr2, sizeof(addr2));
|
||||
ZeroMem(&PeerAddr, sizeof(PeerAddr));
|
||||
}
|
||||
|
||||
C4NetIOUDP::Peer::~Peer()
|
||||
|
@ -2610,7 +2940,7 @@ void C4NetIOUDP::Peer::OnRecv(const C4NetIOPacket &rPacket) // (mt-safe)
|
|||
if (!fBroadcasted)
|
||||
{
|
||||
// Second connection attempt using different address?
|
||||
if (PeerAddr.sin_addr.s_addr && !AddrEqual(PeerAddr, pPkt->Addr))
|
||||
if (!PeerAddr.IsNull() && PeerAddr != pPkt->Addr)
|
||||
{
|
||||
// Notify peer that he has two addresses to reach this connection.
|
||||
AddAddrPacket Pkt;
|
||||
|
@ -2647,7 +2977,7 @@ void C4NetIOUDP::Peer::OnRecv(const C4NetIOPacket &rPacket) // (mt-safe)
|
|||
iLastPacketAsked = iLastMCPacketAsked = 0;
|
||||
// Activate Multicast?
|
||||
if (!pParent->fMultiCast)
|
||||
if (pPkt->MCAddr.sin_addr.s_addr)
|
||||
if (!pPkt->MCAddr.IsNull())
|
||||
{
|
||||
addr_t MCAddr = pPkt->MCAddr;
|
||||
// Init Broadcast (with delayed loopback test)
|
||||
|
@ -2663,7 +2993,7 @@ void C4NetIOUDP::Peer::OnRecv(const C4NetIOPacket &rPacket) // (mt-safe)
|
|||
nPack.Addr = addr;
|
||||
if (fBroadcasted)
|
||||
nPack.MCMode = ConnOKPacket::MCM_MCOK; // multicast send ok
|
||||
else if (pParent->fMultiCast && addr.sin_port == pParent->iPort)
|
||||
else if (pParent->fMultiCast && addr.GetPort() == pParent->iPort)
|
||||
nPack.MCMode = ConnOKPacket::MCM_MC; // du ok, try multicast next
|
||||
else
|
||||
nPack.MCMode = ConnOKPacket::MCM_NoMC; // du ok
|
||||
|
@ -2774,7 +3104,7 @@ void C4NetIOUDP::Peer::OnRecv(const C4NetIOPacket &rPacket) // (mt-safe)
|
|||
if (rPacket.getSize() < sizeof(ClosePacket)) break;
|
||||
const ClosePacket *pPkt = getBufPtr<ClosePacket>(rPacket);
|
||||
// ignore if it's for another address
|
||||
if (PeerAddr.sin_addr.s_addr && !AddrEqual(PeerAddr, pPkt->Addr))
|
||||
if (!PeerAddr.IsNull() && PeerAddr != pPkt->Addr)
|
||||
break;
|
||||
// close
|
||||
OnClose("connection closed by peer");
|
||||
|
@ -2828,7 +3158,7 @@ bool C4NetIOUDP::Peer::DoConn(bool fMC) // (mt-safe)
|
|||
if (pParent->fMultiCast)
|
||||
Pkt.MCAddr = pParent->C4NetIOSimpleUDP::getMCAddr();
|
||||
else
|
||||
memset(&Pkt.MCAddr, 0, sizeof Pkt.MCAddr);
|
||||
Pkt.MCAddr.Clear();
|
||||
return SendDirect(C4NetIOPacket(&Pkt, sizeof(Pkt), false, addr));
|
||||
}
|
||||
|
||||
|
@ -2871,7 +3201,8 @@ bool C4NetIOUDP::Peer::SendDirect(const Packet &rPacket, unsigned int iNr)
|
|||
bool C4NetIOUDP::Peer::SendDirect(C4NetIOPacket &&rPacket) // (mt-safe)
|
||||
{
|
||||
// insert correct addr
|
||||
if (!(rPacket.getStatus() & 0x80)) rPacket.SetAddr(addr);
|
||||
C4NetIO::addr_t v6Addr(addr.AsIPv6());
|
||||
if (!(rPacket.getStatus() & 0x80)) rPacket.SetAddr(v6Addr);
|
||||
// count outgoing
|
||||
{ CStdLock StatLock(&StatCSec); iORate += rPacket.getSize() + iUDPHeaderSize; }
|
||||
// forward call
|
||||
|
@ -3123,7 +3454,7 @@ C4NetIOUDP::Peer *C4NetIOUDP::GetPeer(const addr_t &addr)
|
|||
CStdShareLock PeerListLock(&PeerListCSec);
|
||||
for (Peer *pPeer = pPeerList; pPeer; pPeer = pPeer->Next)
|
||||
if (!pPeer->Closed())
|
||||
if (AddrEqual(pPeer->GetAddr(), addr) || AddrEqual(pPeer->GetAltAddr(), addr))
|
||||
if (pPeer->GetAddr() == addr || pPeer->GetAltAddr() == addr)
|
||||
return pPeer;
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -3405,6 +3736,7 @@ bool ResolveAddress(const char *szAddress, C4NetIO::addr_t *paddr, uint16_t iPor
|
|||
raddr.sin_addr = *reinterpret_cast<in_addr *>(pHost->h_addr_list[0]);
|
||||
}
|
||||
// ok
|
||||
*paddr = raddr;
|
||||
paddr->SetAddress(reinterpret_cast<sockaddr*>(&raddr));
|
||||
paddr->SetPort(iPort);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -65,9 +65,145 @@ public:
|
|||
|
||||
// *** constants / types
|
||||
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); }
|
||||
|
||||
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);
|
||||
void SetHost(uint32_t host);
|
||||
|
||||
C4NetIO::HostAddress AsIPv6() const; // convert an IPv4 address to an IPv6-mapped IPv4 address
|
||||
|
||||
// General categories
|
||||
bool IsNull() const;
|
||||
bool IsMulticast() const;
|
||||
bool IsLoopback() 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);
|
||||
|
||||
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
|
||||
|
||||
void SetPort(uint16_t port);
|
||||
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;
|
||||
|
||||
// callback class
|
||||
class CBClass
|
||||
|
@ -108,10 +244,8 @@ public:
|
|||
// *** interface
|
||||
|
||||
// * not multithreading safe
|
||||
virtual bool Init(uint16_t iPort = P_NONE) = 0;
|
||||
virtual bool InitBroadcast(addr_t *pBroadcastAddr) = 0;
|
||||
virtual bool Init(uint16_t iPort = addr_t::IPPORT_NONE) = 0;
|
||||
virtual bool Close() = 0;
|
||||
virtual bool CloseBroadcast() = 0;
|
||||
|
||||
virtual bool Execute(int iTimeout = -1, pollfd * = 0) = 0; // (for StdSchedulerProc)
|
||||
virtual bool IsNotify() { return true; }
|
||||
|
@ -129,6 +263,9 @@ public:
|
|||
virtual bool GetConnStatistic(const addr_t &addr, int *pIRate, int *pORate, int *pLoss) = 0;
|
||||
virtual void ClearStatistic() = 0;
|
||||
|
||||
protected:
|
||||
// virtual SOCKET CreateSocket() = 0;
|
||||
|
||||
// *** errors
|
||||
protected:
|
||||
StdCopyStrBuf Error;
|
||||
|
@ -193,7 +330,7 @@ public:
|
|||
// *** interface
|
||||
|
||||
// * 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 Close();
|
||||
virtual bool CloseBroadcast();
|
||||
|
@ -352,7 +489,7 @@ public:
|
|||
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 Close();
|
||||
virtual bool CloseBroadcast();
|
||||
|
@ -440,7 +577,7 @@ public:
|
|||
|
||||
// *** 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 Close();
|
||||
virtual bool CloseBroadcast();
|
||||
|
@ -807,15 +944,6 @@ private:
|
|||
};
|
||||
|
||||
// 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)
|
||||
{
|
||||
|
@ -831,19 +959,6 @@ inline void CompileFunc(in_addr &ip, StdCompiler *pComp)
|
|||
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
|
||||
bool AcquireWinSock();
|
||||
void ReleaseWinSock();
|
||||
|
|
|
@ -247,7 +247,10 @@ C4Network2::InitResult C4Network2::InitClient(const C4Network2Reference &Ref, bo
|
|||
// copy addresses
|
||||
C4Network2Address Addrs[C4ClientMaxAddr];
|
||||
for (int i = 0; i < Ref.getAddrCnt(); i++)
|
||||
{
|
||||
Addrs[i] = Ref.getAddr(i);
|
||||
Addrs[i].getAddr().SetScopeId(Ref.GetSourceAddress().GetScopeId());
|
||||
}
|
||||
// Try to connect to host
|
||||
if (InitClient(Addrs, Ref.getAddrCnt(), HostCore, Password.getData()) == IR_Fatal)
|
||||
return IR_Fatal;
|
||||
|
@ -1043,18 +1046,16 @@ void C4Network2::DrawStatus(C4TargetFacet &cgo)
|
|||
// connections
|
||||
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",
|
||||
NetIO.getNetIOName(pClient->getMsgConn()->getNetClass()),
|
||||
inet_ntoa(pClient->getMsgConn()->getPeerAddr().sin_addr),
|
||||
htons(pClient->getMsgConn()->getPeerAddr().sin_port),
|
||||
pClient->getMsgConn()->getPeerAddr().ToString().getData(),
|
||||
pClient->getMsgConn()->getPingTime(),
|
||||
pClient->getMsgConn()->getPacketLoss());
|
||||
if (pClient->getMsgConn() != pClient->getDataConn())
|
||||
Stat.AppendFormat( ", Data: %s (%s:%d p%d l%d)",
|
||||
NetIO.getNetIOName(pClient->getDataConn()->getNetClass()),
|
||||
inet_ntoa(pClient->getDataConn()->getPeerAddr().sin_addr),
|
||||
htons(pClient->getDataConn()->getPeerAddr().sin_port),
|
||||
pClient->getDataConn()->getPeerAddr().ToString().getData(),
|
||||
pClient->getDataConn()->getPingTime(),
|
||||
pClient->getDataConn()->getPacketLoss());
|
||||
}
|
||||
|
@ -1183,7 +1184,7 @@ void C4Network2::HandleConn(const C4PacketConn &Pkt, C4Network2IOConnection *pCo
|
|||
else
|
||||
{
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
|
@ -1198,7 +1199,7 @@ bool C4Network2::CheckConn(const C4ClientCore &CCore, C4Network2IOConnection *pC
|
|||
if (CCore.getDiffLevel(pClient->getCore()) > C4ClientCoreDL_IDMatch)
|
||||
{ *szReply = "wrong client core"; return false; }
|
||||
// check address
|
||||
if (pClient->isConnected() && pClient->getMsgConn()->getPeerAddr().sin_addr.s_addr != pConn->getPeerAddr().sin_addr.s_addr)
|
||||
if (pClient->isConnected() && pClient->getMsgConn()->getPeerAddr() != pConn->getPeerAddr())
|
||||
{ *szReply = "wrong address"; return false; }
|
||||
// accept
|
||||
return true;
|
||||
|
@ -1277,7 +1278,7 @@ void C4Network2::HandleConnRe(const C4PacketConnRe &Pkt, C4Network2IOConnection
|
|||
// wrong password?
|
||||
fWrongPassword = Pkt.isPasswordWrong();
|
||||
// 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
|
||||
pConn->Close();
|
||||
return;
|
||||
|
@ -1302,7 +1303,7 @@ void C4Network2::HandleConnRe(const C4PacketConnRe &Pkt, C4Network2IOConnection
|
|||
if (pConn->getNetClass() == NetIO.DataIO()) pClient->SetDataConn(pConn);
|
||||
|
||||
// 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());
|
||||
pClient->AddAddr(Addr, Status.getState() != GS_Init);
|
||||
|
@ -1432,8 +1433,8 @@ void C4Network2::HandleJoinData(const C4PacketJoinData &rPkt)
|
|||
void C4Network2::OnConnect(C4Network2Client *pClient, C4Network2IOConnection *pConn, const char *szMsg, bool fFirstConnection)
|
||||
{
|
||||
// log
|
||||
LogSilentF("Network: %s %s connected (%s:%d/%s) (%s)", pClient->isHost() ? "host" : "client",
|
||||
pClient->getName(), inet_ntoa(pConn->getPeerAddr().sin_addr), htons(pConn->getPeerAddr().sin_port),
|
||||
LogSilentF("Network: %s %s connected (%s/%s) (%s)", pClient->isHost() ? "host" : "client",
|
||||
pClient->getName(), pConn->getPeerAddr().ToString().getData(),
|
||||
NetIO.getNetIOName(pConn->getNetClass()), szMsg ? szMsg : "");
|
||||
|
||||
// first connection for this peer? call special handler
|
||||
|
@ -1442,8 +1443,8 @@ void C4Network2::OnConnect(C4Network2Client *pClient, C4Network2IOConnection *pC
|
|||
|
||||
void C4Network2::OnConnectFail(C4Network2IOConnection *pConn)
|
||||
{
|
||||
LogSilentF("Network: %s connection to %s:%d failed!", NetIO.getNetIOName(pConn->getNetClass()),
|
||||
inet_ntoa(pConn->getPeerAddr().sin_addr), htons(pConn->getPeerAddr().sin_port));
|
||||
LogSilentF("Network: %s connection to %s failed!", NetIO.getNetIOName(pConn->getNetClass()),
|
||||
pConn->getPeerAddr().ToString().getData());
|
||||
|
||||
// maybe client connection failure
|
||||
// (happens if the connection is not fully accepted and the client disconnects.
|
||||
|
@ -1455,8 +1456,8 @@ void C4Network2::OnConnectFail(C4Network2IOConnection *pConn)
|
|||
|
||||
void C4Network2::OnDisconnect(C4Network2Client *pClient, C4Network2IOConnection *pConn)
|
||||
{
|
||||
LogSilentF("Network: %s connection to %s (%s:%d) lost!", NetIO.getNetIOName(pConn->getNetClass()),
|
||||
pClient->getName(), inet_ntoa(pConn->getPeerAddr().sin_addr), htons(pConn->getPeerAddr().sin_port));
|
||||
LogSilentF("Network: %s connection to %s (%s) lost!", NetIO.getNetIOName(pConn->getNetClass()),
|
||||
pClient->getName(), pConn->getPeerAddr().ToString().getData());
|
||||
|
||||
// connection lost?
|
||||
if (!pClient->isConnected())
|
||||
|
|
|
@ -31,8 +31,7 @@ void C4Network2Address::CompileFunc(StdCompiler *pComp)
|
|||
// Clear
|
||||
if (pComp->isCompiler())
|
||||
{
|
||||
ZeroMem(&addr, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.Clear();
|
||||
}
|
||||
|
||||
// Write protocol
|
||||
|
@ -41,34 +40,27 @@ void C4Network2Address::CompileFunc(StdCompiler *pComp)
|
|||
{ "UDP", P_UDP },
|
||||
{ "TCP", P_TCP },
|
||||
|
||||
{ nullptr, P_NONE },
|
||||
{ nullptr, P_NONE },
|
||||
};
|
||||
pComp->Value(mkEnumAdaptT<uint8_t>(eProtocol, Protocols));
|
||||
pComp->Separator(StdCompiler::SEP_PART2); // ':'
|
||||
|
||||
// Write IP (no IP = 0.0.0.0)
|
||||
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);
|
||||
pComp->Value(mkDefaultAdapt(addr, C4NetIO::addr_t()));
|
||||
}
|
||||
|
||||
StdStrBuf C4Network2Address::toString() const
|
||||
{
|
||||
switch (eProtocol)
|
||||
{
|
||||
case P_UDP: return FormatString("UDP:%s:%d", inet_ntoa(addr.sin_addr), htons(addr.sin_port));
|
||||
case P_TCP: return FormatString("TCP:%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", addr.ToString().getData());
|
||||
default: return StdStrBuf("INVALID");
|
||||
}
|
||||
}
|
||||
|
||||
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:
|
||||
C4Network2Address()
|
||||
: eProtocol(P_NONE)
|
||||
{ ZeroMem(&addr, sizeof(addr)); }
|
||||
{ }
|
||||
|
||||
C4Network2Address(C4NetIO::addr_t addr, C4Network2IOProtocol eProtocol)
|
||||
: addr(addr), eProtocol(eProtocol)
|
||||
|
@ -45,16 +45,18 @@ protected:
|
|||
|
||||
public:
|
||||
const C4NetIO::addr_t &getAddr() const { return addr; }
|
||||
in_addr getIPAddr() const { return addr.sin_addr; }
|
||||
bool isIPNull() const { return !addr.sin_addr.s_addr; }
|
||||
uint16_t getPort() const { return htons(addr.sin_port); }
|
||||
C4NetIO::addr_t &getAddr() { return addr; }
|
||||
//in_addr getIPAddr() const { return addr.sin_addr; }
|
||||
bool isIPNull() const { return addr.IsNull(); }
|
||||
uint16_t getPort() const { return addr.GetPort(); }
|
||||
C4Network2IOProtocol getProtocol() const { return eProtocol; }
|
||||
|
||||
StdStrBuf toString() const;
|
||||
|
||||
void SetAddr(C4NetIO::addr_t naddr) { addr = naddr; }
|
||||
void SetIP(in_addr ip) { addr.sin_addr = ip; }
|
||||
void SetPort(uint16_t iPort) { addr.sin_port = htons(iPort); }
|
||||
//void SetIP(in_addr ip) { addr.SetAddress(ip); }
|
||||
void SetIP(C4NetIO::addr_t ip) { addr.SetAddress(ip); }
|
||||
void SetPort(uint16_t iPort) { addr.SetPort(iPort); }
|
||||
void SetProtocol(C4Network2IOProtocol enProtocol) { eProtocol = enProtocol; }
|
||||
|
||||
void CompileFunc(StdCompiler *pComp);
|
||||
|
|
|
@ -25,7 +25,10 @@
|
|||
#include "game/C4Game.h"
|
||||
#include "player/C4PlayerList.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <iphlpapi.h>
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <ifaddrs.h>
|
||||
|
@ -185,30 +188,55 @@ bool C4Network2Client::AddAddr(const C4Network2Address &addr, bool fAnnounce)
|
|||
void C4Network2Client::AddLocalAddrs(int16_t iPortTCP, int16_t iPortUDP)
|
||||
{
|
||||
// set up address struct
|
||||
sockaddr_in addr; ZeroMem(&addr, sizeof addr);
|
||||
addr.sin_family = AF_INET;
|
||||
C4NetIO::addr_t addr;
|
||||
|
||||
// get local address(es)
|
||||
in_addr **ppAddr = nullptr;
|
||||
#ifdef HAVE_WINSOCK
|
||||
bool fGotWinSock = AcquireWinSock();
|
||||
if (fGotWinSock)
|
||||
const size_t BUFFER_SIZE = 16000;
|
||||
PIP_ADAPTER_ADDRESSES addresses = nullptr;
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
// get local host name
|
||||
char szLocalHostName[128+1]; *szLocalHostName = '\0';
|
||||
::gethostname(szLocalHostName, 128);
|
||||
// get hostent-struct
|
||||
hostent *ph = ::gethostbyname(szLocalHostName);
|
||||
// check type, get addr list
|
||||
if (ph)
|
||||
addresses = (PIP_ADAPTER_ADDRESSES) realloc(addresses, BUFFER_SIZE * (i+1));
|
||||
if (!addresses)
|
||||
// allocation failed
|
||||
return;
|
||||
ULONG bufsz = BUFFER_SIZE * (i+1);
|
||||
DWORD rv = GetAdaptersAddresses(AF_UNSPEC,
|
||||
GAA_FLAG_SKIP_ANYCAST|GAA_FLAG_SKIP_MULTICAST|GAA_FLAG_SKIP_DNS_SERVER|GAA_FLAG_SKIP_FRIENDLY_NAME,
|
||||
nullptr, addresses, &bufsz);
|
||||
if (rv == ERROR_BUFFER_OVERFLOW)
|
||||
// too little space, try again
|
||||
continue;
|
||||
if (rv != NO_ERROR)
|
||||
{
|
||||
if (ph->h_addrtype != AF_INET)
|
||||
ph = nullptr;
|
||||
else
|
||||
ppAddr = reinterpret_cast<in_addr **>(ph->h_addr_list);
|
||||
// Something else happened
|
||||
free(addresses);
|
||||
return;
|
||||
}
|
||||
// All okay, add addresses
|
||||
for (PIP_ADAPTER_ADDRESSES address = addresses; address; address = address->Next)
|
||||
{
|
||||
for (PIP_ADAPTER_UNICAST_ADDRESS unicast = address->FirstUnicastAddress; unicast; unicast = unicast->Next)
|
||||
{
|
||||
addr.SetHost(unicast->Address.lpSockaddr);
|
||||
if (addr.IsLoopback())
|
||||
continue;
|
||||
if (iPortTCP)
|
||||
{
|
||||
addr.SetPort(iPortTCP);
|
||||
AddAddr(C4Network2Address(addr, P_TCP), false);
|
||||
}
|
||||
if (iPortUDP)
|
||||
{
|
||||
addr.SetPort(iPortUDP);
|
||||
AddAddr(C4Network2Address(addr, P_UDP), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
free(addresses);
|
||||
#else
|
||||
in_addr **ppAddr = NULL;
|
||||
std::vector<in_addr*> addr_vec;
|
||||
struct ifaddrs* addrs;
|
||||
getifaddrs(&addrs);
|
||||
|
@ -223,29 +251,24 @@ void C4Network2Client::AddLocalAddrs(int16_t iPortTCP, int16_t iPortUDP)
|
|||
|
||||
addr_vec.push_back(nullptr);
|
||||
ppAddr = &addr_vec[0];
|
||||
#endif
|
||||
|
||||
// add address(es)
|
||||
for (;;)
|
||||
{
|
||||
if (iPortTCP >= 0)
|
||||
{
|
||||
addr.sin_port = htons(iPortTCP);
|
||||
addr.SetPort(iPortTCP);
|
||||
AddAddr(C4Network2Address(addr, P_TCP), false);
|
||||
}
|
||||
if (iPortUDP >= 0)
|
||||
{
|
||||
addr.sin_port = htons(iPortUDP);
|
||||
addr.SetPort(iPortUDP);
|
||||
AddAddr(C4Network2Address(addr, P_UDP), false);
|
||||
}
|
||||
// get next
|
||||
if (!ppAddr || !*ppAddr) break;
|
||||
addr.sin_addr = **ppAddr++;
|
||||
addr.SetHost(C4NetIO::HostAddress((**ppAddr++).s_addr));
|
||||
}
|
||||
|
||||
#ifdef HAVE_WINSOCK
|
||||
if (fGotWinSock) ReleaseWinSock();
|
||||
#else
|
||||
if(addrs) freeifaddrs(addrs);
|
||||
#endif
|
||||
}
|
||||
|
@ -255,7 +278,11 @@ void C4Network2Client::SendAddresses(C4Network2IOConnection *pConn)
|
|||
// send all addresses
|
||||
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)
|
||||
pConn->Send(Pkt);
|
||||
else
|
||||
|
@ -534,7 +561,9 @@ void C4Network2ClientList::HandlePacket(char cStatus, const C4PacketBase *pBaseP
|
|||
C4Network2Address addr = rPkt.getAddr();
|
||||
// IP zero? Set to IP from where the packet came
|
||||
if (addr.isIPNull())
|
||||
addr.SetIP(pConn->getPeerAddr().sin_addr);
|
||||
{
|
||||
addr.SetIP(pConn->getPeerAddr());
|
||||
}
|
||||
// add (no announce)
|
||||
if (pClient->AddAddr(addr, true))
|
||||
// new address? Try to connect
|
||||
|
|
|
@ -96,14 +96,12 @@ void C4Network2ClientDlg::UpdateText()
|
|||
AddLineFmt(LoadResStr("IDS_NET_CLIENT_INFO_CONNECTIONS"),
|
||||
pNetClient->getMsgConn() == pNetClient->getDataConn() ? "Msg/Data" : "Msg",
|
||||
::Network.NetIO.getNetIOName(pNetClient->getMsgConn()->getNetClass()),
|
||||
inet_ntoa(pNetClient->getMsgConn()->getPeerAddr().sin_addr),
|
||||
htons(pNetClient->getMsgConn()->getPeerAddr().sin_port),
|
||||
pNetClient->getMsgConn()->getPeerAddr().ToString().getData(),
|
||||
pNetClient->getMsgConn()->getPingTime());
|
||||
if (pNetClient->getMsgConn() != pNetClient->getDataConn())
|
||||
AddLineFmt(LoadResStr("IDS_NET_CLIENT_INFO_CONNDATA"),
|
||||
::Network.NetIO.getNetIOName(pNetClient->getDataConn()->getNetClass()),
|
||||
inet_ntoa(pNetClient->getDataConn()->getPeerAddr().sin_addr),
|
||||
htons(pNetClient->getDataConn()->getPeerAddr().sin_port),
|
||||
pNetClient->getDataConn()->getPeerAddr().ToString().getData(),
|
||||
pNetClient->getDataConn()->getPingTime());
|
||||
}
|
||||
else
|
||||
|
@ -386,11 +384,10 @@ void C4Network2ClientListBox::ConnectionListItem::Update()
|
|||
else
|
||||
szConnType = "Data";
|
||||
// display info
|
||||
pDesc->SetText(FormatString("%s: %s (%s:%d l%d)",
|
||||
pDesc->SetText(FormatString("%s: %s (%s l%d)",
|
||||
szConnType,
|
||||
::Network.NetIO.getNetIOName(pConn->getNetClass()),
|
||||
inet_ntoa(pConn->getPeerAddr().sin_addr),
|
||||
htons(pConn->getPeerAddr().sin_port),
|
||||
pConn->getPeerAddr().ToString().getData(),
|
||||
pConn->getPacketLoss()).getData());
|
||||
}
|
||||
|
||||
|
|
|
@ -41,10 +41,8 @@ bool C4Network2IODiscover::Init(uint16_t iPort)
|
|||
// Set callback
|
||||
C4NetIOSimpleUDP::SetCallback(this);
|
||||
// Build broadcast address
|
||||
DiscoveryAddr.sin_addr.s_addr = C4NetDiscoveryAddress;
|
||||
DiscoveryAddr.sin_port = htons(iPort);
|
||||
DiscoveryAddr.sin_family = AF_INET;
|
||||
ZeroMem(DiscoveryAddr.sin_zero, sizeof(DiscoveryAddr.sin_zero));
|
||||
DiscoveryAddr.SetAddress(C4NetDiscoveryAddress);
|
||||
DiscoveryAddr.SetPort(iPort);
|
||||
// Initialize broadcast
|
||||
if (!C4NetIOSimpleUDP::InitBroadcast(&DiscoveryAddr))
|
||||
return false;
|
||||
|
@ -71,7 +69,7 @@ void C4Network2IODiscoverClient::OnPacket(const class C4NetIOPacket &rPacket, C4
|
|||
{
|
||||
const C4Network2IODiscoverReply *pReply = reinterpret_cast<const C4Network2IODiscoverReply *>(rPacket.getData());
|
||||
Discovers[iDiscoverCount] = rPacket.getAddr();
|
||||
Discovers[iDiscoverCount].sin_port = pReply->Port;
|
||||
Discovers[iDiscoverCount].SetPort(pReply->Port);
|
||||
iDiscoverCount++;
|
||||
}
|
||||
}
|
||||
|
@ -87,10 +85,8 @@ bool C4Network2IODiscoverClient::Init(uint16_t iPort)
|
|||
// Set callback
|
||||
C4NetIOSimpleUDP::SetCallback(this);
|
||||
// Build broadcast address
|
||||
DiscoveryAddr.sin_addr.s_addr = C4NetDiscoveryAddress;
|
||||
DiscoveryAddr.sin_port = htons(iPort);
|
||||
DiscoveryAddr.sin_family = AF_INET;
|
||||
ZeroMem(DiscoveryAddr.sin_zero, sizeof(DiscoveryAddr.sin_zero));
|
||||
DiscoveryAddr.SetAddress(C4NetDiscoveryAddress);
|
||||
DiscoveryAddr.SetPort(iPort);
|
||||
// Initialize broadcast
|
||||
if (!C4NetIOSimpleUDP::InitBroadcast(&DiscoveryAddr))
|
||||
return false;
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
const int C4NetMaxDiscover = 64;
|
||||
|
||||
const unsigned long C4NetDiscoveryAddress = 0xef; // 239.0.0.0
|
||||
const C4NetIO::HostAddress C4NetDiscoveryAddress = C4NetIO::HostAddress(0xef000000); // 239.0.0.0
|
||||
|
||||
class C4Network2IODiscover : public C4NetIOSimpleUDP, private C4NetIO::CBClass
|
||||
{
|
||||
|
@ -34,12 +34,12 @@ protected:
|
|||
virtual void OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO);
|
||||
|
||||
public:
|
||||
bool Init(uint16_t iPort = P_NONE);
|
||||
bool Init(uint16_t iPort = C4NetIO::addr_t::IPPORT_NONE);
|
||||
void SetDiscoverable(bool fnEnabled) { fEnabled = fnEnabled; }
|
||||
bool Announce();
|
||||
|
||||
private:
|
||||
sockaddr_in DiscoveryAddr;
|
||||
C4NetIO::addr_t DiscoveryAddr;
|
||||
|
||||
uint16_t iRefServerPort;
|
||||
bool fEnabled;
|
||||
|
@ -61,7 +61,7 @@ public:
|
|||
const C4NetIO::addr_t &getDiscover(int i) { return Discovers[i]; }
|
||||
|
||||
void Clear() { iDiscoverCount = 0; }
|
||||
bool Init(uint16_t iPort = P_NONE);
|
||||
bool Init(uint16_t iPort = C4NetIO::addr_t::IPPORT_NONE);
|
||||
bool StartDiscovery();
|
||||
bool PopDiscover(C4NetIO::addr_t &Discover);
|
||||
|
||||
|
|
|
@ -56,7 +56,6 @@ C4Network2IO::C4Network2IO()
|
|||
iTCPIRate(0), iTCPORate(0), iTCPBCRate(0),
|
||||
iUDPIRate(0), iUDPORate(0), iUDPBCRate(0)
|
||||
{
|
||||
ZeroMem(&PuncherAddr, sizeof(PuncherAddr));
|
||||
}
|
||||
|
||||
C4Network2IO::~C4Network2IO()
|
||||
|
@ -253,7 +252,7 @@ bool C4Network2IO::Connect(const C4NetIO::addr_t &addr, C4Network2IOProtocol ePr
|
|||
if (GetConnectionByConnAddr(addr, pNetIO)) return true;
|
||||
// assign new connection ID, peer address isn't known yet
|
||||
uint32_t iConnID = iNextConnID++;
|
||||
C4NetIO::addr_t paddr; ZeroMem(&paddr, sizeof paddr);
|
||||
C4NetIO::addr_t paddr;
|
||||
// create connection object and add to list
|
||||
C4Network2IOConnection *pConn = new C4Network2IOConnection();
|
||||
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())
|
||||
{
|
||||
// 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() : "");
|
||||
pNetIO->ResetError();
|
||||
// remove class
|
||||
|
@ -474,7 +473,7 @@ void C4Network2IO::Punch(const C4NetIO::addr_t &punchee_addr) {
|
|||
}
|
||||
|
||||
void C4Network2IO::SendPuncherPacket(const C4NetpuncherPacket& p) {
|
||||
if (!pNetIO_UDP || !PuncherAddr.sin_addr.s_addr) return;
|
||||
if (!pNetIO_UDP || PuncherAddr.IsNull()) return;
|
||||
pNetIO_UDP->Send(p.PackTo(PuncherAddr));
|
||||
}
|
||||
|
||||
|
@ -482,7 +481,7 @@ void C4Network2IO::SendPuncherPacket(const C4NetpuncherPacket& p) {
|
|||
bool C4Network2IO::OnConn(const C4NetIO::addr_t &PeerAddr, const C4NetIO::addr_t &ConnectAddr, const C4NetIO::addr_t *pOwnAddr, C4NetIO *pNetIO)
|
||||
{
|
||||
// puncher answer?
|
||||
if (pNetIO == pNetIO_UDP && PuncherAddr.sin_addr.s_addr && AddrEqual(PuncherAddr, ConnectAddr))
|
||||
if (pNetIO == pNetIO_UDP && !PuncherAddr.IsNull() && PuncherAddr == ConnectAddr)
|
||||
{
|
||||
// got an address?
|
||||
if (pOwnAddr)
|
||||
|
@ -497,7 +496,7 @@ bool C4Network2IO::OnConn(const C4NetIO::addr_t &PeerAddr, const C4NetIO::addr_t
|
|||
#endif
|
||||
// search connection
|
||||
C4Network2IOConnection *pConn = nullptr;
|
||||
if (ConnectAddr.sin_addr.s_addr)
|
||||
if (!ConnectAddr.IsNull())
|
||||
pConn = GetConnectionByConnAddr(ConnectAddr, pNetIO);
|
||||
// not found?
|
||||
if (!pConn)
|
||||
|
@ -527,7 +526,7 @@ bool C4Network2IO::OnConn(const C4NetIO::addr_t &PeerAddr, const C4NetIO::addr_t
|
|||
SendConnPackets();
|
||||
#if(C4NET2IO_DUMP_LEVEL > 0)
|
||||
// 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
|
||||
// do event (disabled - unused)
|
||||
// pConn->AddRef(); PushNetEv(NE_Conn, pConn);
|
||||
|
@ -538,9 +537,9 @@ bool C4Network2IO::OnConn(const C4NetIO::addr_t &PeerAddr, const C4NetIO::addr_t
|
|||
void C4Network2IO::OnDisconn(const C4NetIO::addr_t &addr, C4NetIO *pNetIO, const char *szReason)
|
||||
{
|
||||
// punch?
|
||||
if (pNetIO == pNetIO_UDP && PuncherAddr.sin_addr.s_addr && AddrEqual(PuncherAddr, addr))
|
||||
if (pNetIO == pNetIO_UDP && !PuncherAddr.IsNull() && PuncherAddr == addr)
|
||||
{
|
||||
ZeroMem(&PuncherAddr, sizeof(PuncherAddr));
|
||||
PuncherAddr.Clear();
|
||||
return;
|
||||
}
|
||||
#if(C4NET2IO_DUMP_LEVEL > 1)
|
||||
|
@ -554,8 +553,8 @@ void C4Network2IO::OnDisconn(const C4NetIO::addr_t &addr, C4NetIO *pNetIO, const
|
|||
if (!pConn) return;
|
||||
#if(C4NET2IO_DUMP_LEVEL > 0)
|
||||
// log
|
||||
Application.InteractiveThread.ThreadLogS("Network: %s connection to %s:%d %s (%s)",
|
||||
getNetIOName(pNetIO), inet_ntoa(addr.sin_addr), htons(addr.sin_port), pConn->isConnecting() ? "failed" : "closed" , szReason);
|
||||
Application.InteractiveThread.ThreadLogS("Network: %s connection to %s %s (%s)",
|
||||
getNetIOName(pNetIO), addr.ToString().getData(), pConn->isConnecting() ? "failed" : "closed" , szReason);
|
||||
#endif
|
||||
// already closed? ignore
|
||||
if (!pConn->isClosed())
|
||||
|
@ -580,7 +579,7 @@ void C4Network2IO::OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO)
|
|||
C4TimeMilliseconds::Now().AsString().getData(),
|
||||
rPacket.getStatus(), getNetIOName(pNetIO));
|
||||
#endif
|
||||
if (pNetIO == pNetIO_UDP && PuncherAddr.sin_addr.s_addr && AddrEqual(PuncherAddr, rPacket.getAddr()))
|
||||
if (pNetIO == pNetIO_UDP && !PuncherAddr.IsNull() && PuncherAddr == rPacket.getAddr())
|
||||
{
|
||||
HandlePuncherPacket(rPacket);
|
||||
return;
|
||||
|
@ -588,7 +587,7 @@ void C4Network2IO::OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO)
|
|||
if (!rPacket.getSize()) return;
|
||||
// find connection
|
||||
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 packet from %s!", rPacket.getAddr().ToString().getData()); return; }
|
||||
#if(C4NET2IO_DUMP_LEVEL > 2)
|
||||
uint32_t iFindConnectionBlocked = C4TimeMilliseconds::Now() - tTime;
|
||||
if (iFindConnectionBlocked > 100)
|
||||
|
@ -748,7 +747,7 @@ C4Network2IOConnection *C4Network2IO::GetConnection(const C4NetIO::addr_t &addr,
|
|||
CStdLock ConnListLock(&ConnListCSec);
|
||||
// search
|
||||
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 nullptr;
|
||||
}
|
||||
|
@ -758,7 +757,7 @@ C4Network2IOConnection *C4Network2IO::GetConnectionByConnAddr(const C4NetIO::add
|
|||
CStdLock ConnListLock(&ConnListCSec);
|
||||
// search
|
||||
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 nullptr;
|
||||
}
|
||||
|
@ -798,7 +797,7 @@ bool C4Network2IO::doAutoAccept(const C4ClientCore &CCore, const C4Network2IOCon
|
|||
for (C4Network2IOConnection *pConn = pConnList; pConn; pConn = pConn->pNext)
|
||||
if (pConn->isAccepted() &&
|
||||
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;
|
||||
// not found or IP matches? Let pass
|
||||
return true;
|
||||
|
@ -837,9 +836,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)
|
||||
{
|
||||
// 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(),
|
||||
inet_ntoa(pConn->getPeerAddr().sin_addr), htons(pConn->getPeerAddr().sin_port),
|
||||
pConn->getPeerAddr().ToString().getData(),
|
||||
static_cast<unsigned long>(rPacket.getSize()), pConn->getInPacketCounter());
|
||||
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.
|
||||
|
@ -1172,7 +1171,7 @@ void C4Network2IO::CheckTimeout()
|
|||
if (!pConn->isClosed() && !pConn->isAccepted())
|
||||
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();
|
||||
}
|
||||
// ping timeout
|
||||
|
@ -1181,7 +1180,7 @@ void C4Network2IO::CheckTimeout()
|
|||
> C4NetPingTimeout)
|
||||
{
|
||||
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();
|
||||
}
|
||||
// delayed connection removal
|
||||
|
@ -1266,13 +1265,9 @@ void C4Network2IO::SendConnPackets()
|
|||
void C4Network2IO::OnPuncherConnect(C4NetIO::addr_t addr)
|
||||
{
|
||||
// Sanity check
|
||||
assert (addr.sin_family == AF_INET);
|
||||
if (addr.sin_family != AF_INET)
|
||||
if (addr.GetFamily() != C4NetIO::HostAddress::IPv4)
|
||||
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));
|
||||
Application.InteractiveThread.ThreadLogS("Adding address from puncher: %s", addr.ToString().getData());
|
||||
// Add for local client
|
||||
C4Network2Client *pLocal = ::Network.Clients.GetLocal();
|
||||
if (pLocal)
|
||||
|
|
|
@ -261,7 +261,7 @@ protected:
|
|||
public:
|
||||
C4NetIO *getNetClass() const { return pNetClass; }
|
||||
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; }
|
||||
uint32_t getID() const { return iID; }
|
||||
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)
|
||||
{
|
||||
// Security checks
|
||||
if (!fConnecting || fConnected || !AddrEqual(AddrConnect, ServerAddr)) return false;
|
||||
if (!fConnecting || fConnected || AddrConnect != ServerAddr) return false;
|
||||
CStdLock Lock(&CSec);
|
||||
// Save connection data
|
||||
fConnected = true;
|
||||
|
|
|
@ -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++)
|
||||
if (Addrs[i].isIPNull())
|
||||
Addrs[i].SetIP(ip);
|
||||
source = ip;
|
||||
if (iAddrCnt < C4ClientMaxAddr)
|
||||
Addrs[++iAddrCnt].SetAddr(ip);
|
||||
}
|
||||
|
||||
void C4Network2Reference::InitLocal()
|
||||
|
@ -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)
|
||||
{
|
||||
// Make sure we're actually waiting for this connection
|
||||
if (!AddrEqual(AddrConnect, ServerAddr))
|
||||
if (AddrConnect != ServerAddr)
|
||||
return false;
|
||||
// Save pack peer address
|
||||
PeerAddr = AddrPeer;
|
||||
// Send the request
|
||||
Send(C4NetIOPacket(Request, AddrPeer));
|
||||
if (!Send(C4NetIOPacket(Request, AddrPeer)))
|
||||
{
|
||||
Error.Format("Unable to send HTTP request: %s", Error.getData());
|
||||
}
|
||||
Request.Clear();
|
||||
fConnected = true;
|
||||
return true;
|
||||
|
@ -557,11 +560,16 @@ bool C4Network2HTTPClient::SetServer(const char *szServerAddress)
|
|||
RequestPath = "/";
|
||||
}
|
||||
// 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());
|
||||
return false;
|
||||
}
|
||||
if (ServerAddr.GetPort() == C4NetIO::EndpointAddress::IPPORT_NONE)
|
||||
{
|
||||
ServerAddr.SetPort(GetDefaultPort());
|
||||
}
|
||||
// Remove port
|
||||
const char *pColon = strchr(Server.getData(), ':');
|
||||
if (pColon)
|
||||
|
@ -657,7 +665,7 @@ bool C4Network2RefClient::GetReferences(C4Network2Reference **&rpReferences, int
|
|||
}
|
||||
// Set source ip
|
||||
for (int i = 0; i < rRefCount; i++)
|
||||
rpReferences[i]->SetSourceIP(getServerAddress().sin_addr);
|
||||
rpReferences[i]->SetSourceAddress(getServerAddress());
|
||||
// Done
|
||||
ResetError();
|
||||
return true;
|
||||
|
|
|
@ -60,9 +60,11 @@ private:
|
|||
// Network addresses
|
||||
uint8_t iAddrCnt;
|
||||
C4Network2Address Addrs[C4ClientMaxAddr];
|
||||
C4NetIO::EndpointAddress source;
|
||||
|
||||
public:
|
||||
const C4Network2Address &getAddr(int i) const { return Addrs[i]; }
|
||||
C4Network2Address &getAddr(int i) { return Addrs[i]; }
|
||||
int getAddrCnt() const { return iAddrCnt; }
|
||||
const char *getTitle() const { return Title.getData(); }
|
||||
int32_t getIcon() const { return Icon; }
|
||||
|
@ -80,7 +82,8 @@ public:
|
|||
C4NetpuncherID_t getNetpuncherGameID() const { return NetpuncherGameID; }
|
||||
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();
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
C4AulDebug::C4AulDebug()
|
||||
: fInit(false), fConnected(false)
|
||||
{
|
||||
ZeroMem(&PeerAddr, sizeof PeerAddr);
|
||||
}
|
||||
|
||||
C4AulDebug::~C4AulDebug()
|
||||
|
@ -125,15 +124,15 @@ bool C4AulDebug::OnConn(const C4NetIO::addr_t &AddrPeer, const C4NetIO::addr_t &
|
|||
// Already have a connection?
|
||||
if (fConnected) return false;
|
||||
// Check address
|
||||
if (AllowedAddr.sin_addr.s_addr)
|
||||
if (AllowedAddr.sin_addr.s_addr != AddrPeer.sin_addr.s_addr ||
|
||||
(AllowedAddr.sin_port && AllowedAddr.sin_port != AddrPeer.sin_port))
|
||||
if (!AllowedAddr.IsNull())
|
||||
if (AllowedAddr.GetHost() != AddrPeer.GetHost() ||
|
||||
(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;
|
||||
}
|
||||
// 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
|
||||
PeerAddr = AddrPeer;
|
||||
return true;
|
||||
|
@ -144,7 +143,7 @@ void C4AulDebug::OnDisconn(const C4NetIO::addr_t &AddrPeer, C4NetIO *pNetIO, con
|
|||
LogF("C4AulDebug lost connection (%s)", szReason);
|
||||
fConnected = false;
|
||||
eState = DS_Go;
|
||||
ZeroMem(&PeerAddr, sizeof PeerAddr);
|
||||
PeerAddr.Clear();
|
||||
}
|
||||
|
||||
void C4AulDebug::OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO)
|
||||
|
@ -155,7 +154,7 @@ void C4AulDebug::OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO)
|
|||
bool C4AulDebug::SetAllowed(const char *szHost)
|
||||
{
|
||||
// Clear
|
||||
ZeroMem(&AllowedAddr, sizeof(AllowedAddr));
|
||||
AllowedAddr.Clear();
|
||||
// No host?
|
||||
if (!szHost || !*szHost) return true;
|
||||
// Resolve the address
|
||||
|
@ -165,7 +164,7 @@ bool C4AulDebug::SetAllowed(const char *szHost)
|
|||
bool C4AulDebug::Init(uint16_t iPort)
|
||||
{
|
||||
if (fInit) Close();
|
||||
if (iPort == P_NONE) return false;
|
||||
if (iPort == EndpointAddress::IPPORT_NONE) return false;
|
||||
|
||||
// Register self as callback for network events
|
||||
C4NetIOTCP::SetCallback(this);
|
||||
|
|
Loading…
Reference in New Issue