Mercurial > code
view C++/modules/Socket/SocketAddress.h @ 388:131ecc6ce7b5
Socket: fix kqueue with new names
author | David Demelier <markand@malikania.fr> |
---|---|
date | Tue, 30 Jun 2015 13:53:40 +0200 |
parents | 743b3a1c71c8 |
children | d5ec1174b707 |
line wrap: on
line source
/* * SocketAddress.h -- socket addresses management * * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _SOCKET_ADDRESS_NG_H_ #define _SOCKET_ADDRESS_NG_H_ /** * @file SocketAddress.h * @brief Describe addresses * * User may set the following variables before compiling these files: * * SOCKET_HAVE_SUN_LEN - (bool) Some systems do not have SUN_LEN which is the preferred way to * compute the address size for a Unix address. Otherwise, sizeof is used. * * Addresses are used in many places such as bind, recvfrom, accept and such. They describe different * parameters depending on the families. * * For example, when using IPv4, one should use Ipv4 class. * * All addresses are used directly as template parameter for a stronger type security. To be compatible * with the sockets classes, an address must have the following requirements: * * - Default constructible * - Copyable or Moveable * * Constructors: * * # With a storage address * * @code * Address(const sockaddr_storage &ss, socklen_t size); * @endcode * * The address is free to use the storage. * * Member functions: * * # Address * * @code * inline const sockaddr &address() const noexcept * @endcode * * Return the address converted to the C sockaddr structure. * * # Length * * @code * inline socklen_t length() const noexcept * @endcode * * Return the length of an address. * * # Info * * @code * SocketAddressInfo info() const * @endcode * * Return an information table about the address. */ #include <memory> #include <string> #include <unordered_map> #if defined(_WIN32) # include <Winsock2.h> # include <Ws2tcpip.h> #else # include <sys/socket.h> # include <sys/un.h> # include <arpa/inet.h> # include <netinet/in.h> #endif /** * Generic information table for an address. */ using SocketAddressInfo = std::unordered_map<std::string, std::string>; /** * @class SocketAddressAbstract * @brief Generic base class for addresses */ class SocketAddressAbstract { public: /** * Get the address as base type. * * @return the base address reference */ virtual const sockaddr &address() const noexcept = 0; /** * Get the address length. * * @return the length */ virtual socklen_t length() const noexcept = 0; }; /** * Compare two socket addresses, std::equal is used. * * @param addr1 the first address * @param addr2 the second address * @return true if equals */ bool operator==(const SocketAddressAbstract &addr1, const SocketAddressAbstract &addr2) noexcept; /** * Compare two socket addresses, std::lexicographical_compare is used. * * @param addr1 the first address * @param addr2 the second address * @return true if addr1 < addr2 */ bool operator<(const SocketAddressAbstract &addr1, const SocketAddressAbstract &addr2) noexcept; /** * @brief Predefined addresses. */ namespace address { /** * @class Ip * @brief Generic internet protocol address * * Create a connect address for internet protocol, * using getaddrinfo(3). * * @see Ipv4 * @see Ipv6 */ class Ip : public SocketAddressAbstract { private: union { sockaddr_in m_sin; sockaddr_in6 m_sin6; }; int m_domain{AF_INET}; public: /** * Default constructor. */ Ip(); /** * Create an IPv4 or IPV6 end point. * * @param host the hostname * @param port the port * @param domain AF_INET or AF_INET6 * @throw SocketError on error */ Ip(const std::string &host, unsigned port, int domain); /** * Construct an internet address from a storage address. * * @param ss the storage * @param length the length */ Ip(const sockaddr_storage &ss, socklen_t length); /** * @copydoc SocketAddress::address */ const sockaddr &address() const noexcept override { // Can't get a ternary operator to work here. if (m_domain == AF_INET6) return reinterpret_cast<const sockaddr &>(m_sin6); return reinterpret_cast<const sockaddr &>(m_sin); } /** * @copydoc SocketAddress::length */ socklen_t length() const noexcept override { return (m_domain == AF_INET6) ? sizeof (sockaddr_in6) : sizeof (sockaddr_in); } /** * @copydoc SocketAddress::info */ SocketAddressInfo info() const; }; /** * @class Ipv6 * @brief Convenient helper for IPv6 protocol */ class Ipv6 : public Ip { public: /** * Default constructor. */ Ipv6() = default; /** * Construct an IPv6 address from storage. * * @param ss the storage * @param length the length */ inline Ipv6(const sockaddr_storage &ss, socklen_t length) : Ip(ss, length) { } /** * Construct an IPv6 address. * * @param host the host * @param port the port * @throw SocketError on error */ inline Ipv6(const std::string &host, unsigned port) : Ip(host, port, AF_INET6) { } }; /** * @class Ipv4 * @brief Convenient helper for IPv4 protocol */ class Ipv4 : public Ip { public: /** * Default constructor. */ Ipv4() = default; /** * Construct an IPv4 address from storage. * * @param ss the storage * @param length the length */ inline Ipv4(const sockaddr_storage &ss, socklen_t length) : Ip(ss, length) { } /** * Construct an IPv4 address. * * @param host the host * @param port the port * @throw SocketError on error */ inline Ipv4(const std::string &host, unsigned port) : Ip(host, port, AF_INET) { } }; #if !defined(_WIN32) /** * @class Unix * @brief unix family sockets * * Create an address to a specific path. Only available on Unix. */ class Unix : public SocketAddressAbstract { private: sockaddr_un m_sun; std::string m_path; public: /** * Default constructor. */ Unix() = default; /** * Construct an address to a path. * * @param path the path * @param rm remove the file before (default: false) */ Unix(std::string path, bool rm = false); /** * Construct an unix address from a storage address. * * @param ss the storage * @param length the length */ Unix(const sockaddr_storage &ss, socklen_t length); /** * @copydoc SocketAddress::address */ inline const sockaddr &address() const noexcept override { return reinterpret_cast<const sockaddr &>(m_sun); } /** * @copydoc SocketAddress::length */ inline socklen_t length() const noexcept override { #if defined(SOCKET_HAVE_SUN_LEN) return SUN_LEN(&m_sun); #else return sizeof (m_sun); #endif } /** * @copydoc SocketAddress::info */ SocketAddressInfo info() const; }; #endif // !_WIN32 } // !address #endif // !_SOCKET_ADDRESS_NG_H_