Skip to content

Commit 0ea8df4

Browse files
authoredDec 29, 2021
Socket-related cleanups
Improve error handling on Windows and reduce the size of the `Address` class
1 parent 05573d6 commit 0ea8df4

File tree

8 files changed

+113
-155
lines changed

8 files changed

+113
-155
lines changed
 

Diff for: ‎src/client/game.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -1444,7 +1444,6 @@ bool Game::connectToServer(const GameStartData &start_data,
14441444
connect_address.Resolve(start_data.address.c_str());
14451445

14461446
if (connect_address.isZero()) { // i.e. INADDR_ANY, IN6ADDR_ANY
1447-
//connect_address.Resolve("localhost");
14481447
if (connect_address.isIPv6()) {
14491448
IPv6AddressBytes addr_bytes;
14501449
addr_bytes.bytes[15] = 1;

Diff for: ‎src/filesys.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ namespace fs
4141
* Windows *
4242
***********/
4343

44+
#ifndef _WIN32_WINNT
4445
#define _WIN32_WINNT 0x0501
46+
#endif
4547
#include <windows.h>
4648
#include <shlwapi.h>
4749
#include <io.h>

Diff for: ‎src/network/address.cpp

+44-75
Original file line numberDiff line numberDiff line change
@@ -87,48 +87,38 @@ Address::Address(const IPv6AddressBytes *ipv6_bytes, u16 port)
8787
setPort(port);
8888
}
8989

90-
// Equality (address family, address and port must be equal)
91-
bool Address::operator==(const Address &address)
90+
// Equality (address family, IP and port must be equal)
91+
bool Address::operator==(const Address &other)
9292
{
93-
if (address.m_addr_family != m_addr_family || address.m_port != m_port)
93+
if (other.m_addr_family != m_addr_family || other.m_port != m_port)
9494
return false;
9595

9696
if (m_addr_family == AF_INET) {
97-
return m_address.ipv4.sin_addr.s_addr ==
98-
address.m_address.ipv4.sin_addr.s_addr;
97+
return m_address.ipv4.s_addr == other.m_address.ipv4.s_addr;
9998
}
10099

101100
if (m_addr_family == AF_INET6) {
102-
return memcmp(m_address.ipv6.sin6_addr.s6_addr,
103-
address.m_address.ipv6.sin6_addr.s6_addr, 16) == 0;
101+
return memcmp(m_address.ipv6.s6_addr,
102+
other.m_address.ipv6.s6_addr, 16) == 0;
104103
}
105104

106105
return false;
107106
}
108107

109-
bool Address::operator!=(const Address &address)
110-
{
111-
return !(*this == address);
112-
}
113-
114108
void Address::Resolve(const char *name)
115109
{
116110
if (!name || name[0] == 0) {
117-
if (m_addr_family == AF_INET) {
118-
setAddress((u32)0);
119-
} else if (m_addr_family == AF_INET6) {
120-
setAddress((IPv6AddressBytes *)0);
121-
}
111+
if (m_addr_family == AF_INET)
112+
setAddress(static_cast<u32>(0));
113+
else if (m_addr_family == AF_INET6)
114+
setAddress(static_cast<IPv6AddressBytes*>(nullptr));
122115
return;
123116
}
124117

125118
struct addrinfo *resolved, hints;
126119
memset(&hints, 0, sizeof(hints));
127120

128121
// Setup hints
129-
hints.ai_socktype = 0;
130-
hints.ai_protocol = 0;
131-
hints.ai_flags = 0;
132122
if (g_settings->getBool("enable_ipv6")) {
133123
// AF_UNSPEC allows both IPv6 and IPv4 addresses to be returned
134124
hints.ai_family = AF_UNSPEC;
@@ -145,14 +135,13 @@ void Address::Resolve(const char *name)
145135
if (resolved->ai_family == AF_INET) {
146136
struct sockaddr_in *t = (struct sockaddr_in *)resolved->ai_addr;
147137
m_addr_family = AF_INET;
148-
m_address.ipv4 = *t;
138+
m_address.ipv4 = t->sin_addr;
149139
} else if (resolved->ai_family == AF_INET6) {
150140
struct sockaddr_in6 *t = (struct sockaddr_in6 *)resolved->ai_addr;
151141
m_addr_family = AF_INET6;
152-
m_address.ipv6 = *t;
142+
m_address.ipv6 = t->sin6_addr;
153143
} else {
154-
freeaddrinfo(resolved);
155-
throw ResolveError("");
144+
m_addr_family = 0;
156145
}
157146
freeaddrinfo(resolved);
158147
}
@@ -163,100 +152,77 @@ std::string Address::serializeString() const
163152
// windows XP doesnt have inet_ntop, maybe use better func
164153
#ifdef _WIN32
165154
if (m_addr_family == AF_INET) {
166-
u8 a, b, c, d;
167-
u32 addr;
168-
addr = ntohl(m_address.ipv4.sin_addr.s_addr);
169-
a = (addr & 0xFF000000) >> 24;
170-
b = (addr & 0x00FF0000) >> 16;
171-
c = (addr & 0x0000FF00) >> 8;
172-
d = (addr & 0x000000FF);
173-
return itos(a) + "." + itos(b) + "." + itos(c) + "." + itos(d);
155+
return inet_ntoa(m_address.ipv4);
174156
} else if (m_addr_family == AF_INET6) {
175157
std::ostringstream os;
158+
os << std::hex;
176159
for (int i = 0; i < 16; i += 2) {
177-
u16 section = (m_address.ipv6.sin6_addr.s6_addr[i] << 8) |
178-
(m_address.ipv6.sin6_addr.s6_addr[i + 1]);
179-
os << std::hex << section;
160+
u16 section = (m_address.ipv6.s6_addr[i] << 8) |
161+
(m_address.ipv6.s6_addr[i + 1]);
162+
os << section;
180163
if (i < 14)
181164
os << ":";
182165
}
183166
return os.str();
184-
} else
185-
return std::string("");
167+
} else {
168+
return "";
169+
}
186170
#else
187171
char str[INET6_ADDRSTRLEN];
188-
if (inet_ntop(m_addr_family,
189-
(m_addr_family == AF_INET)
190-
? (void *)&(m_address.ipv4.sin_addr)
191-
: (void *)&(m_address.ipv6.sin6_addr),
192-
str, INET6_ADDRSTRLEN) == NULL) {
193-
return std::string("");
194-
}
195-
return std::string(str);
172+
if (inet_ntop(m_addr_family, (void*) &m_address, str, sizeof(str)) == nullptr)
173+
return "";
174+
return str;
196175
#endif
197176
}
198177

199-
struct sockaddr_in Address::getAddress() const
178+
struct in_addr Address::getAddress() const
200179
{
201-
return m_address.ipv4; // NOTE: NO PORT INCLUDED, use getPort()
180+
return m_address.ipv4;
202181
}
203182

204-
struct sockaddr_in6 Address::getAddress6() const
183+
struct in6_addr Address::getAddress6() const
205184
{
206-
return m_address.ipv6; // NOTE: NO PORT INCLUDED, use getPort()
185+
return m_address.ipv6;
207186
}
208187

209188
u16 Address::getPort() const
210189
{
211190
return m_port;
212191
}
213192

214-
int Address::getFamily() const
215-
{
216-
return m_addr_family;
217-
}
218-
219-
bool Address::isIPv6() const
220-
{
221-
return m_addr_family == AF_INET6;
222-
}
223-
224193
bool Address::isZero() const
225194
{
226195
if (m_addr_family == AF_INET) {
227-
return m_address.ipv4.sin_addr.s_addr == 0;
196+
return m_address.ipv4.s_addr == 0;
228197
}
229198

230199
if (m_addr_family == AF_INET6) {
231200
static const char zero[16] = {0};
232-
return memcmp(m_address.ipv6.sin6_addr.s6_addr, zero, 16) == 0;
201+
return memcmp(m_address.ipv6.s6_addr, zero, 16) == 0;
233202
}
203+
234204
return false;
235205
}
236206

237207
void Address::setAddress(u32 address)
238208
{
239209
m_addr_family = AF_INET;
240-
m_address.ipv4.sin_family = AF_INET;
241-
m_address.ipv4.sin_addr.s_addr = htonl(address);
210+
m_address.ipv4.s_addr = htonl(address);
242211
}
243212

244213
void Address::setAddress(u8 a, u8 b, u8 c, u8 d)
245214
{
246-
m_addr_family = AF_INET;
247-
m_address.ipv4.sin_family = AF_INET;
248-
u32 addr = htonl((a << 24) | (b << 16) | (c << 8) | d);
249-
m_address.ipv4.sin_addr.s_addr = addr;
215+
u32 addr = (a << 24) | (b << 16) | (c << 8) | d;
216+
setAddress(addr);
250217
}
251218

252219
void Address::setAddress(const IPv6AddressBytes *ipv6_bytes)
253220
{
254221
m_addr_family = AF_INET6;
255-
m_address.ipv6.sin6_family = AF_INET6;
256222
if (ipv6_bytes)
257-
memcpy(m_address.ipv6.sin6_addr.s6_addr, ipv6_bytes->bytes, 16);
223+
memcpy(m_address.ipv6.s6_addr, ipv6_bytes->bytes, 16);
258224
else
259-
memset(m_address.ipv6.sin6_addr.s6_addr, 0, 16);
225+
memset(m_address.ipv6.s6_addr, 0, 16);
260226
}
261227

262228
void Address::setPort(u16 port)
@@ -268,23 +234,26 @@ void Address::print(std::ostream *s) const
268234
{
269235
if (m_addr_family == AF_INET6)
270236
*s << "[" << serializeString() << "]:" << m_port;
271-
else
237+
else if (m_addr_family == AF_INET)
272238
*s << serializeString() << ":" << m_port;
239+
else
240+
*s << "(undefined)";
273241
}
274242

275243
bool Address::isLocalhost() const
276244
{
277245
if (isIPv6()) {
278-
static const unsigned char localhost_bytes[] = {
246+
static const u8 localhost_bytes[] = {
279247
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
280-
static const unsigned char mapped_ipv4_localhost[] = {
248+
static const u8 mapped_ipv4_localhost[] = {
281249
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x7f, 0, 0, 0};
282250

283-
auto addr = m_address.ipv6.sin6_addr.s6_addr;
251+
auto addr = m_address.ipv6.s6_addr;
284252

285253
return memcmp(addr, localhost_bytes, 16) == 0 ||
286254
memcmp(addr, mapped_ipv4_localhost, 13) == 0;
287255
}
288256

289-
return (m_address.ipv4.sin_addr.s_addr & 0xFF) == 0x7f;
257+
auto addr = ntohl(m_address.ipv4.s_addr);
258+
return (addr >> 24) == 0x7f;
290259
}

Diff for: ‎src/network/address.h

+19-16
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
3636
#include "irrlichttypes.h"
3737
#include "networkexceptions.h"
3838

39-
class IPv6AddressBytes
39+
struct IPv6AddressBytes
4040
{
41-
public:
4241
u8 bytes[16];
4342
IPv6AddressBytes() { memset(bytes, 0, 16); }
4443
};
@@ -50,30 +49,34 @@ class Address
5049
Address(u32 address, u16 port);
5150
Address(u8 a, u8 b, u8 c, u8 d, u16 port);
5251
Address(const IPv6AddressBytes *ipv6_bytes, u16 port);
52+
5353
bool operator==(const Address &address);
54-
bool operator!=(const Address &address);
54+
bool operator!=(const Address &address) { return !(*this == address); }
55+
56+
struct in_addr getAddress() const;
57+
struct in6_addr getAddress6() const;
58+
u16 getPort() const;
59+
int getFamily() const { return m_addr_family; }
60+
bool isIPv6() const { return m_addr_family == AF_INET6; }
61+
bool isZero() const;
62+
void print(std::ostream *s) const;
63+
std::string serializeString() const;
64+
bool isLocalhost() const;
65+
5566
// Resolve() may throw ResolveError (address is unchanged in this case)
5667
void Resolve(const char *name);
57-
struct sockaddr_in getAddress() const;
58-
unsigned short getPort() const;
68+
5969
void setAddress(u32 address);
6070
void setAddress(u8 a, u8 b, u8 c, u8 d);
6171
void setAddress(const IPv6AddressBytes *ipv6_bytes);
62-
struct sockaddr_in6 getAddress6() const;
63-
int getFamily() const;
64-
bool isIPv6() const;
65-
bool isZero() const;
66-
void setPort(unsigned short port);
67-
void print(std::ostream *s) const;
68-
std::string serializeString() const;
69-
bool isLocalhost() const;
72+
void setPort(u16 port);
7073

7174
private:
72-
unsigned int m_addr_family = 0;
75+
unsigned short m_addr_family = 0;
7376
union
7477
{
75-
struct sockaddr_in ipv4;
76-
struct sockaddr_in6 ipv6;
78+
struct in_addr ipv4;
79+
struct in6_addr ipv6;
7780
} m_address;
7881
u16 m_port = 0; // Port is separate from sockaddr structures
7982
};

0 commit comments

Comments
 (0)
Please sign in to comment.