Implement IPv6 support to C4NetIO

ipv6
Nicolas Hake 2013-02-18 15:30:00 +01:00 committed by Lukas Werling
parent 3fe83986ce
commit 102047f537
22 changed files with 714 additions and 232 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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