diff options
author | Max Kellermann <max@musicpd.org> | 2017-08-11 08:41:58 +0200 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2017-08-11 09:09:04 +0200 |
commit | d705a92e437234e385a0cf5bed1009409b223541 (patch) | |
tree | a9281f4d66144224991e2e4ff64178fdcfc0abd6 | |
parent | 614b3634d49b98748866fe9ad024eb98133ea4fb (diff) |
net/IPv4Address: new class
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | src/event/ServerSocket.cxx | 10 | ||||
-rw-r--r-- | src/net/IPv4Address.cxx | 46 | ||||
-rw-r--r-- | src/net/IPv4Address.hxx | 147 | ||||
-rw-r--r-- | src/system/EventPipe.cxx | 12 |
5 files changed, 200 insertions, 16 deletions
diff --git a/Makefile.am b/Makefile.am index 494302210..6920bf35e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -482,6 +482,7 @@ libnet_a_SOURCES = \ src/net/Resolver.cxx src/net/Resolver.hxx \ src/net/StaticSocketAddress.cxx src/net/StaticSocketAddress.hxx \ src/net/AllocatedSocketAddress.cxx src/net/AllocatedSocketAddress.hxx \ + src/net/IPv4Address.cxx src/net/IPv4Address.hxx \ src/net/SocketAddress.cxx src/net/SocketAddress.hxx \ src/net/SocketUtil.cxx src/net/SocketUtil.hxx \ src/net/SocketDescriptor.cxx src/net/SocketDescriptor.hxx \ diff --git a/src/event/ServerSocket.cxx b/src/event/ServerSocket.cxx index 55000318f..375daf511 100644 --- a/src/event/ServerSocket.cxx +++ b/src/event/ServerSocket.cxx @@ -19,6 +19,7 @@ #include "config.h" #include "ServerSocket.hxx" +#include "net/IPv4Address.hxx" #include "net/StaticSocketAddress.hxx" #include "net/AllocatedSocketAddress.hxx" #include "net/SocketAddress.hxx" @@ -48,7 +49,6 @@ #include <ws2tcpip.h> #include <winsock.h> #else -#include <netinet/in.h> #include <sys/socket.h> #include <netdb.h> #endif @@ -310,13 +310,7 @@ ServerSocket::AddFD(int _fd) inline void ServerSocket::AddPortIPv4(unsigned port) { - struct sockaddr_in sin; - memset(&sin, 0, sizeof(sin)); - sin.sin_port = htons(port); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = INADDR_ANY; - - AddAddress({(const sockaddr *)&sin, sizeof(sin)}); + AddAddress(IPv4Address(port)); } #ifdef HAVE_IPV6 diff --git a/src/net/IPv4Address.cxx b/src/net/IPv4Address.cxx new file mode 100644 index 000000000..354886896 --- /dev/null +++ b/src/net/IPv4Address.cxx @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2012-2017 Max Kellermann <max.kellermann@gmail.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "IPv4Address.hxx" + +#include <assert.h> + +static const struct sockaddr_in * +CastToIPv4(const struct sockaddr *p) +{ + assert(p->sa_family == AF_INET); + + /* cast through void to work around the bogus alignment warning */ + const void *q = reinterpret_cast<const void *>(p); + return reinterpret_cast<const struct sockaddr_in *>(q); +} + +IPv4Address::IPv4Address(SocketAddress src) + :address(*CastToIPv4(src.GetAddress())) {} diff --git a/src/net/IPv4Address.hxx b/src/net/IPv4Address.hxx new file mode 100644 index 000000000..4107ab44f --- /dev/null +++ b/src/net/IPv4Address.hxx @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2012-2017 Max Kellermann <max.kellermann@gmail.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef IPV4_ADDRESS_HXX +#define IPV4_ADDRESS_HXX + +#include "SocketAddress.hxx" +#include "system/ByteOrder.hxx" + +#include <stdint.h> + +#ifdef _WIN32 +#include <winsock2.h> +#include <ws2tcpip.h> +#else +#include <netinet/in.h> +#endif + +/** + * An OO wrapper for struct sockaddr_in. + */ +class IPv4Address { + struct sockaddr_in address; + +#ifdef WIN32 + static constexpr struct in_addr ConstructInAddr(uint8_t a, uint8_t b, + uint8_t c, uint8_t d) { + return {{{ a, b, c, d }}}; + } + + static constexpr struct in_addr ConstructInAddr(uint32_t x) { + return ConstructInAddr(x >> 24, x >> 16, x >> 8, x); + } +#else + +#ifdef __BIONIC__ + typedef uint32_t in_addr_t; +#endif + + static constexpr in_addr_t ConstructInAddrT(uint8_t a, uint8_t b, + uint8_t c, uint8_t d) { + return ToBE32((a << 24) | (b << 16) | (c << 8) | d); + } + + static constexpr struct in_addr ConstructInAddr(uint32_t x) { + return { ToBE32(x) }; + } + + static constexpr struct in_addr ConstructInAddr(uint8_t a, uint8_t b, + uint8_t c, uint8_t d) { + return { ConstructInAddrT(a, b, c, d) }; + } +#endif + + static constexpr struct sockaddr_in Construct(struct in_addr address, + uint16_t port) { + return { +#if defined(__APPLE__) + sizeof(struct sockaddr_in), +#endif + AF_INET, + ToBE16(port), + address, + {}, + }; + } + + static constexpr struct sockaddr_in Construct(uint32_t address, + uint16_t port) { + return Construct(ConstructInAddr(address), port); + } + +public: + IPv4Address() = default; + + constexpr IPv4Address(struct in_addr _address, uint16_t port) + :address(Construct(_address, port)) {} + + constexpr IPv4Address(uint8_t a, uint8_t b, uint8_t c, + uint8_t d, uint16_t port) + :IPv4Address(ConstructInAddr(a, b, c, d), port) {} + + constexpr explicit IPv4Address(uint16_t port) + :IPv4Address(ConstructInAddr(INADDR_ANY), port) {} + + /** + * Convert a #SocketAddress to a #IPv4Address. Its address family must be AF_INET. + */ + explicit IPv4Address(SocketAddress src); + + static constexpr struct in_addr Loopback() { + return ConstructInAddr(INADDR_LOOPBACK); + } + + operator SocketAddress() const { + return SocketAddress(reinterpret_cast<const struct sockaddr *>(&address), + sizeof(address)); + } + + SocketAddress::size_type GetSize() { + return sizeof(address); + } + + constexpr bool IsDefined() const { + return address.sin_family != AF_UNSPEC; + } + + constexpr uint16_t GetPort() const { + return FromBE16(address.sin_port); + } + + void SetPort(uint16_t port) { + address.sin_port = ToBE16(port); + } + + constexpr const struct in_addr &GetAddress() const { + return address.sin_addr; + } +}; + +#endif diff --git a/src/system/EventPipe.cxx b/src/system/EventPipe.cxx index 7ccb9493c..420db26db 100644 --- a/src/system/EventPipe.cxx +++ b/src/system/EventPipe.cxx @@ -28,9 +28,9 @@ #include <unistd.h> #ifdef WIN32 -#include <ws2tcpip.h> +#include "net/IPv4Address.hxx" + #include <winsock2.h> -#include <cstring> /* for memset() */ #endif #ifdef WIN32 @@ -112,14 +112,10 @@ static bool PoorSocketPair(int fd[2]) closesocket(listen_socket); }; - sockaddr_in address; - std::memset(&address, 0, sizeof(address)); - address.sin_family = AF_INET; - address.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + IPv4Address address(IPv4Address::Loopback(), 0); int ret = bind(listen_socket, - reinterpret_cast<sockaddr*>(&address), - sizeof(address)); + SocketAddress(address).GetAddress(), sizeof(address)); if (ret < 0) return false; |