3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include "network/networkexceptions.h"
30 #include "util/string.h"
31 #include "util/numeric.h"
32 #include "constants.h"
38 // Without this some of the network functions are not found on mingw
40 #define _WIN32_WINNT 0x0501
45 #define LAST_SOCKET_ERR() WSAGetLastError()
46 typedef SOCKET socket_t;
47 typedef int socklen_t;
49 #include <sys/types.h>
50 #include <sys/socket.h>
51 #include <netinet/in.h>
55 #include <arpa/inet.h>
56 #define LAST_SOCKET_ERR() (errno)
66 memset(&m_address, 0, sizeof(m_address));
69 Address::Address(u32 address, u16 port)
71 memset(&m_address, 0, sizeof(m_address));
76 Address::Address(u8 a, u8 b, u8 c, u8 d, u16 port)
78 memset(&m_address, 0, sizeof(m_address));
79 setAddress(a, b, c, d);
83 Address::Address(const IPv6AddressBytes *ipv6_bytes, u16 port)
85 memset(&m_address, 0, sizeof(m_address));
86 setAddress(ipv6_bytes);
90 // Equality (address family, address and port must be equal)
91 bool Address::operator==(const Address &address)
93 if (address.m_addr_family != m_addr_family || address.m_port != m_port)
96 if (m_addr_family == AF_INET) {
97 return m_address.ipv4.sin_addr.s_addr ==
98 address.m_address.ipv4.sin_addr.s_addr;
101 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;
109 bool Address::operator!=(const Address &address)
111 return !(*this == address);
114 void Address::Resolve(const char *name)
116 if (!name || name[0] == 0) {
117 if (m_addr_family == AF_INET) {
119 } else if (m_addr_family == AF_INET6) {
120 setAddress((IPv6AddressBytes *)0);
125 struct addrinfo *resolved, hints;
126 memset(&hints, 0, sizeof(hints));
129 hints.ai_socktype = 0;
130 hints.ai_protocol = 0;
132 if (g_settings->getBool("enable_ipv6")) {
133 // AF_UNSPEC allows both IPv6 and IPv4 addresses to be returned
134 hints.ai_family = AF_UNSPEC;
136 hints.ai_family = AF_INET;
140 int e = getaddrinfo(name, NULL, &hints, &resolved);
142 throw ResolveError(gai_strerror(e));
145 if (resolved->ai_family == AF_INET) {
146 struct sockaddr_in *t = (struct sockaddr_in *)resolved->ai_addr;
147 m_addr_family = AF_INET;
149 } else if (resolved->ai_family == AF_INET6) {
150 struct sockaddr_in6 *t = (struct sockaddr_in6 *)resolved->ai_addr;
151 m_addr_family = AF_INET6;
154 freeaddrinfo(resolved);
155 throw ResolveError("");
157 freeaddrinfo(resolved);
160 // IP address -> textual representation
161 std::string Address::serializeString() const
163 // windows XP doesnt have inet_ntop, maybe use better func
165 if (m_addr_family == AF_INET) {
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);
174 } else if (m_addr_family == AF_INET6) {
175 std::ostringstream os;
176 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;
185 return std::string("");
187 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("");
195 return std::string(str);
199 struct sockaddr_in Address::getAddress() const
201 return m_address.ipv4; // NOTE: NO PORT INCLUDED, use getPort()
204 struct sockaddr_in6 Address::getAddress6() const
206 return m_address.ipv6; // NOTE: NO PORT INCLUDED, use getPort()
209 u16 Address::getPort() const
214 int Address::getFamily() const
216 return m_addr_family;
219 bool Address::isIPv6() const
221 return m_addr_family == AF_INET6;
224 bool Address::isZero() const
226 if (m_addr_family == AF_INET) {
227 return m_address.ipv4.sin_addr.s_addr == 0;
230 if (m_addr_family == AF_INET6) {
231 static const char zero[16] = {0};
232 return memcmp(m_address.ipv6.sin6_addr.s6_addr, zero, 16) == 0;
237 void Address::setAddress(u32 address)
239 m_addr_family = AF_INET;
240 m_address.ipv4.sin_family = AF_INET;
241 m_address.ipv4.sin_addr.s_addr = htonl(address);
244 void Address::setAddress(u8 a, u8 b, u8 c, u8 d)
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;
252 void Address::setAddress(const IPv6AddressBytes *ipv6_bytes)
254 m_addr_family = AF_INET6;
255 m_address.ipv6.sin6_family = AF_INET6;
257 memcpy(m_address.ipv6.sin6_addr.s6_addr, ipv6_bytes->bytes, 16);
259 memset(m_address.ipv6.sin6_addr.s6_addr, 0, 16);
262 void Address::setPort(u16 port)
267 void Address::print(std::ostream *s) const
269 if (m_addr_family == AF_INET6)
270 *s << "[" << serializeString() << "]:" << m_port;
272 *s << serializeString() << ":" << m_port;