/* -*- C++ -*- * Copyright (C) 2003 Thiago Macieira * * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef TDESOCKETADDRESS_H #define TDESOCKETADDRESS_H #include #include #include struct sockaddr; struct sockaddr_in; struct sockaddr_in6; struct sockaddr_un; namespace KNetwork { class KIpAddress; class TDESocketAddress; class KInetSocketAddress; class KUnixSocketAddress; /** @class KIpAddress tdesocketaddress.h tdesocketaddress.h * @brief An IP address. * * This class represents one IP address, version 4 or 6. This is only * the address, not including port information or other data. * * It is not a good programming practice to create address from objects * like this. Instead, prefer a more thorough function like * @ref KResolver::resolve, which also handle extra information like scope * ids. * * This is a light-weight class. Most of the member functions are inlined and * there are no virtual functions. This object's size should be less than 20 * bytes. Also note that there is no sharing of data. * * @author Thiago Macieira */ class TDECORE_EXPORT KIpAddress { public: /** * Default constructor. Creates an empty address. * It defaults to IP version 4. */ inline KIpAddress() : m_version(0) { } /** * Copy constructor. Copies the data from the other * object. * * Data is not shared. * * @param other the other */ inline KIpAddress(const KIpAddress& other) { *this = other; } /** * Creates an object from the given string representation. * * The IP version is guessed from the address format. * * @param addr the address */ inline KIpAddress(const TQString& addr) { setAddress(addr); } /** * Creates an object from the given string representation. * * The IP version is guessed from the address format. * * @param addr the address */ inline KIpAddress(const char* addr) { setAddress(addr); } /** * Creates an object from the given raw data and IP version. * * @param addr the raw data * @param version the IP version (4 or 6) */ inline KIpAddress(const void* addr, int version = 4) { setAddress(addr, version); } /** * This is a convenience constructor. Constructs an object * from the given IPv4 address in the form of an integer. * * Note: do not write code to depend on IPv4 addresses being * integer types. Instead, treat them as a special type, like * a KIpAddress or the system's in_addr. * * @param ip4addr the IPv4 address */ inline KIpAddress(TQ_UINT32 ip4addr) { setAddress(&ip4addr, 4); } /** * Destructor. This frees resources associated with this object. * * Note: destructor is non-virtual. The compiler will happily optimise it * out of the way. */ inline ~KIpAddress() { } /** * Copy operator. * * Copies the data from the other object into this one. * * @param other the object to copy */ KIpAddress& operator =(const KIpAddress& other); /** * Returns true if the two addresses match. * This function performs a v4-mapped check. * @see compare */ inline bool operator ==(const KIpAddress& other) const { return compare(other, true); } /** * Compares this address against the other, supplied one and return * true if they match. The @p checkMapped parameter controls whether * a check for an IPv6 v4-mapped address will be performed. * * An IPv6 v4-mapped address is an IPv6 address that is, for all purposes, * equivalent to an IPv4 one. The default behaviour of this function * is to take that into account. If you want a strict matching, * pass @b false to the @p checkMapped parameter. * * @param other the other IP address * @param checkMapped whether v4-mapped addresses will be taken into account */ bool compare(const KIpAddress& other, bool checkMapped = true) const; /** * Retrieves the IP version in this object. * * @returns the version: 4 or 6 */ inline int version() const { return m_version; } /** * Returns true if this is an IPv4 address. */ inline bool isIPv4Addr() const { return version() == 4; } /** * Returns true if this is an IPv6 address. */ inline bool isIPv6Addr() const { return version() == 6; } /** * Sets the address to the given string representation. * * @return true if the address was successfully parsed; otherwise returns * false and leaves the object unchanged. */ bool setAddress(const TQString& address); /** * Sets the address to the given string representation. * * @return true if the address was successfully parsed; otherwise returns * false and leaves the object unchanged. */ bool setAddress(const char* address); /** * Sets the address to the given raw binary representation. * * @param raw a pointer to the raw binary data * @param version the IP version * @return true if the address was successfully parsed; otherwise returns * false and leaves the object unchanged. */ bool setAddress(const void* raw, int version = 4); /** * Returns the address as a string. */ TQString toString() const; /** * Returns a pointer to binary raw data representing the address. */ inline const void *addr() const { return m_data; } /** * This is a convenience function. Returns the IPv4 address in a * 32-bit integer. The result is only valid if @ref isIPv4Addr returns * true. Alternatively, if the contained IPv6 address is a v4-mapped one * and the @p convertMapped parameter is true, the result will also be * valid. The address returned is in network byte order. * * Note: you should not treat IP addresses as integers. Instead, * use types defined for that purpose, such as KIpAddress or the * system's in_addr type. * */ inline TQ_UINT32 IPv4Addr(bool convertMapped = true) const { return (convertMapped && isV4Mapped()) ? m_data[3] : m_data[0]; } /** * This is a convenience function. Returns the IPv4 address in a * 32-bit integer. The result is only valid if @ref isIPv4Addr returns * true. Alternatively, if the contained IPv6 address is a v4-mapped one * and the @p convertMapped parameter is true, the result will also be * valid. The address returned is in host byte order. * */ TQ_UINT32 hostIPv4Addr(bool convertMapped = true) const; public: /*-- tests --*/ /** * Returns true if this is the IPv4 or IPv6 unspecified address. */ inline bool isUnspecified() const { return version() == 0 ? true : (*this == anyhostV4 || *this == anyhostV6); } /** * Returns true if this is either the IPv4 or the IPv6 localhost address. */ inline bool isLocalhost() const { return version() == 0 ? false : (*this == localhostV4 || *this == localhostV6); } /** * This is an alias for @ref isLocalhost. */ inline bool isLoopback() const { return isLocalhost(); } /** * Returns true if this is an IPv4 class A address, i.e., * from 0.0.0.0 to 127.255.255.255. * * This function does not test for v4-mapped addresses. */ inline bool isClassA() const { return version() != 4 ? false : (hostIPv4Addr() & 0x80000000) == 0; } /** * Returns true if this is an IPv4 class B address, i.e., one from * 128.0.0.0 to 191.255.255.255. * * This function does not test for v4-mapped addresses. */ inline bool isClassB() const { return version() != 4 ? false : (hostIPv4Addr() & 0xc0000000) == 0x80000000; } /** * Returns true if this is an IPv4 class C address, i.e., one from * 192.0.0.0 to 223.255.255.255. * * This function does not test for v4-mapped addresses. */ inline bool isClassC() const { return version() != 4 ? false : (hostIPv4Addr() & 0xe0000000) == 0xc0000000; } /** * Returns true if this is an IPv4 class D (a.k.a. multicast) address. * * Note: this function is not the same as @ref isMulticast. isMulticast also * tests for IPv6 multicast addresses. */ inline bool isClassD() const { return version() != 4 ? false : (hostIPv4Addr() & 0xf0000000) == 0xe0000000; } /** * Returns true if this is a multicast address, be it IPv4 or IPv6. */ inline bool isMulticast() const { if (version() == 4) return isClassD(); if (version() == 6) return ((TQ_UINT8*)addr())[0] == 0xff; return false; } /** * Returns true if this is an IPv6 link-local address. */ inline bool isLinkLocal() const { if (version() != 6) return false; TQ_UINT8* addr = (TQ_UINT8*)this->addr(); return (addr[0] & 0xff) == 0xfe && (addr[1] & 0xc0) == 0x80; } /** * Returns true if this is an IPv6 site-local address. */ inline bool isSiteLocal() const { if (version() != 6) return false; TQ_UINT8* addr = (TQ_UINT8*)this->addr(); return (addr[0] & 0xff) == 0xfe && (addr[1] & 0xc0) == 0xc0; } /** * Returns true if this is a global IPv6 address. */ inline bool isGlobal() const { return version() != 6 ? false : !(isMulticast() || isLinkLocal() || isSiteLocal()); } /** * Returns true if this is a v4-mapped IPv6 address. */ inline bool isV4Mapped() const { if (version() != 6) return false; TQ_UINT32* addr = (TQ_UINT32*)this->addr(); return addr[0] == 0 && addr[1] == 0 && ((TQ_UINT16*)&addr[2])[0] == 0 && ((TQ_UINT16*)&addr[2])[1] == 0xffff; } /** * Returns true if this is a v4-compat IPv6 address. */ inline bool isV4Compat() const { if (version() != 6 || isLocalhost()) return false; TQ_UINT32* addr = (TQ_UINT32*)this->addr(); return addr[0] == 0 && addr[1] == 0 && addr[2] == 0 && addr[3] != 0; } /** * Returns true if this is an IPv6 node-local multicast address. */ inline bool isMulticastNodeLocal() const { return version() == 6 && isMulticast() && (((TQ_UINT32*)addr())[0] & 0xf) == 0x1; } /** * Returns true if this is an IPv6 link-local multicast address. */ inline bool isMulticastLinkLocal() const { return version() == 6 && isMulticast() && (((TQ_UINT32*)addr())[0] & 0xf) == 0x2; } /** * Returns true if this is an IPv6 site-local multicast address. */ inline bool isMulticastSiteLocal() const { return version() == 6 && isMulticast() && (((TQ_UINT32*)addr())[0] & 0xf) == 0x5; } /** * Returns true if this is an IPv6 organisational-local multicast address. */ inline bool isMulticastOrgLocal() const { return version() == 6 && isMulticast() && (((TQ_UINT32*)addr())[0] & 0xf) == 0x8; } /** * Returns true if this is an IPv6 global multicast address. */ inline bool isMulticastGlobal() const { return version() == 6 && isMulticast() && (((TQ_UINT32*)addr())[0] & 0xf) == 0xe; } protected: TQ_UINT32 m_data[4]; // 16 bytes, needed for an IPv6 address char m_version; public: /// localhost in IPv4 (127.0.0.1) static const KIpAddress localhostV4; /// the any host or undefined address in IPv4 (0.0.0.0) static const KIpAddress anyhostV4; /// localhost in IPv6 (::1) static const KIpAddress localhostV6; /// the any host or undefined address in IPv6 (::) static const KIpAddress anyhostV6; }; class TDESocketAddressData; /** @class TDESocketAddress tdesocketaddress.h tdesocketaddress.h * @brief A generic socket address. * * This class holds one generic socket address. * * @author Thiago Macieira */ class TDECORE_EXPORT TDESocketAddress { public: /** * Default constructor. * * Creates an empty object */ TDESocketAddress(); /** * Creates this object with the given data. * The raw socket address is copied into this object. * * @param sa the socket address structure * @param len the socket address length */ TDESocketAddress(const sockaddr* sa, TQ_UINT16 len); /** * Copy constructor. This creates a copy of the other * object. * * Data is not shared. * * @param other the object to copy from */ TDESocketAddress(const TDESocketAddress& other); /** * Destructor. Frees any associated resources. */ virtual ~TDESocketAddress(); /** * Performs a shallow copy of the other object into this one. * Data will be copied. * * @param other the object to copy from */ TDESocketAddress& operator =(const TDESocketAddress& other); /** * Returns the socket address structure, to be passed down to * low level functions. * * Note that this function returns NULL for invalid or empty sockets, * so you may use to to test for validity. */ const sockaddr* address() const; /** * Returns the socket address structure, to be passed down to * low level functions. * * Note that this function returns NULL for invalid or empty sockets, * so you may use to to test for validity. * * The returned value, if not NULL, is an internal buffer which is guaranteed * to be at least @ref length() bytes long. */ sockaddr* address(); /** * Sets the address to the given address. * The raw socket address is copied into this object. * * @param sa the socket address structure * @param len the socket address length */ TDESocketAddress& setAddress(const sockaddr *sa, TQ_UINT16 len); /** * Returns the socket address structure, to be passed down to * low level functions. */ inline operator const sockaddr*() const { return address(); } /** * Returns the length of this socket address structure. */ TQ_UINT16 length() const; /** * Sets the length of this socket structure. * * Use this function with care. It allows you to resize the internal * buffer to fit needs. This function should not be used except for handling * unknown socket address structures. * * Also note that this function may invalidate the socket if a known * family is set (Internet or Unix socket) and the new length would be * too small to hold the system's sockaddr_* structure. If unsure, reset * the family: * * \code * TDESocketAddress qsa; * [...] * qsa.setFamily(AF_UNSPEC).setLength(newlen); * \endcode * * @param len the new length */ TDESocketAddress& setLength(TQ_UINT16 len); /** * Returns the family of this address. * @return the family of this address, AF_UNSPEC if it's undefined */ int family() const; /** * Sets the family of this object. * * Note: setting the family will probably invalidate any address data * contained in this object. Use this function with care. * * @param family the new family to set */ virtual TDESocketAddress& setFamily(int family); /** * Returns the IANA family number of this address. * @return the IANA family number of this address (1 for AF_INET. * 2 for AF_INET6, otherwise 0) */ inline int ianaFamily() const { return ianaFamily(family()); } /** * Returns true if this equals the other socket. * * Socket addresses are considered matching if and only if all data is the same. * * @param other the other socket * @return true if both sockets are equal */ bool operator ==(const TDESocketAddress& other) const; /** * Returns the node name of this socket. * * In the case of Internet sockets, this is string representation of the IP address. * The default implementation returns TQString::null. * * @return the node name, can be TQString::null * @bug use KResolver to resolve unknown families */ virtual TQString nodeName() const; /** * Returns the service name for this socket. * * In the case of Internet sockets, this is the port number. * The default implementation returns TQString::null. * * @return the service name, can be TQString::null * @bug use KResolver to resolve unknown families */ virtual TQString serviceName() const; /** * Returns this socket address as a string suitable for * printing. Family, node and service are part of this address. * * @bug use KResolver to resolve unknown families */ virtual TQString toString() const; /** * Returns an object reference that can be used to manipulate this socket * as an Internet socket address. Both objects share the same data. */ KInetSocketAddress& asInet(); /** * Returns an object is equal to this object's data, but they don't share it. */ KInetSocketAddress asInet() const; /** * Returns an object reference that can be used to manipulate this socket * as a Unix socket address. Both objects share the same data. */ KUnixSocketAddress& asUnix(); /** * Returns an object is equal to this object's data, but they don't share it. */ KUnixSocketAddress asUnix() const; protected: /// @internal /// private data TDESocketAddressData *d; /// @internal /// extra constructor TDESocketAddress(TDESocketAddressData* d); public: // static /** * Returns the IANA family number of the given address family. * Returns 0 if there is no corresponding IANA family number. * @param af the address family, in AF_* constants * @return the IANA family number of this address (1 for AF_INET. * 2 for AF_INET6, otherwise 0) */ static int ianaFamily(int af); /** * Returns the address family of the given IANA family number. * @return the address family, AF_UNSPEC for unknown IANA family numbers */ static int fromIanaFamily(int iana); }; /** @class KInetSocketAddress tdesocketaddress.h tdesocketaddress.h * @brief an Internet socket address * * An Inet (IPv4 or IPv6) socket address * * This is an IPv4 or IPv6 address of the Internet. * * @author Thiago Macieira */ class TDECORE_EXPORT KInetSocketAddress: public TDESocketAddress { friend class TDESocketAddress; public: /** * Public constructor. Creates an empty object. */ KInetSocketAddress(); /** * Creates an object from raw data. * * Note: if the socket address @p sa does not contain a valid Internet * socket (IPv4 or IPv6), this object will be empty. * * @param sa the sockaddr structure * @param len the structure's length */ KInetSocketAddress(const sockaddr* sa, TQ_UINT16 len); /** * Creates an object from an IP address and port. * * @param host the IP address * @param port the port number */ KInetSocketAddress(const KIpAddress& host, TQ_UINT16 port); /** * Copy constructor. * * Data is not shared. * * @param other the other object */ KInetSocketAddress(const KInetSocketAddress& other); /** * Copy constructor. * * If the other, generic socket address contains an Internet address, * it will be copied. Otherwise, this object will be empty. * * @param other the other object */ KInetSocketAddress(const TDESocketAddress& other); /** * Destroys this object. */ virtual ~KInetSocketAddress(); /** * Copy operator. * * Copies the other object into this one. * * @param other the other object */ KInetSocketAddress& operator =(const KInetSocketAddress& other); /** * Cast operator to sockaddr_in. */ inline operator const sockaddr_in*() const { return (const sockaddr_in*)address(); } /** * Cast operator to sockaddr_in6. */ inline operator const sockaddr_in6*() const { return (const sockaddr_in6*)address(); } /** * Returns the IP version of the address this object holds. * * @return 4 or 6, if IPv4 or IPv6, respectively; 0 if this object is empty */ int ipVersion() const; /** * Returns the IP address component. */ KIpAddress ipAddress() const; /** * Sets the IP address to the given raw address. * * This call will preserve port numbers accross IP versions, but will lose * IPv6 specific data if the address is set to IPv4. * * @param addr the address to set to * @return a reference to itself */ KInetSocketAddress& setHost(const KIpAddress& addr); /** * Retrieves the port number stored in this object. * * @return a port number in the range 0 to 65535, inclusive. An empty or * invalid object will have a port number of 0. */ TQ_UINT16 port() const; /** * Sets the port number. If this object is empty, this function will default to * creating an IPv4 address. * * @param port the port number to set * @return a reference to itself */ KInetSocketAddress& setPort(TQ_UINT16 port); /** * Converts this object to an IPv4 socket address. It has no effect if the object * is already an IPv4 socket address. * * If this object is an IPv6 address, the port number is preserved. All other information * is lost. * * @return a reference to itself */ KInetSocketAddress& makeIPv4(); /** * Converts this object to an IPv6 socket address. It has no effect if the object * is already an IPv6 socket address. * * If this object is an IPv4 address, the port number is preserved. * * @return a reference to itself */ KInetSocketAddress& makeIPv6(); /** * Returns the flowinfo information from the IPv6 socket address. * * @return the flowinfo information or 0 if this object is empty or IPv4 */ TQ_UINT32 flowinfo() const; /** * Sets the flowinfo information for an IPv6 socket address. If this is not * an IPv6 socket address, this function converts it to one. See makeIPv6. * * @param flowinfo the flowinfo to set * @return a reference to itself */ KInetSocketAddress& setFlowinfo(TQ_UINT32 flowinfo); /** * Returns the scope id this IPv6 socket is bound to. * * @return the scope id, or 0 if this is not an IPv6 object */ int scopeId() const; /** * Sets the scope id for this IPv6 object. If this is not an IPv6 socket * address, this function converts it to one. See makeIPv6 * * @param scopeid the scopeid to set * @return a reference to itself */ KInetSocketAddress& setScopeId(int scopeid); protected: /// @internal /// extra constructor KInetSocketAddress(TDESocketAddressData* d); private: void update(); }; /* * External definition */ /** @class KUnixSocketAddress tdesocketaddress.h tdesocketaddress.h * @brief A Unix (local) socket address. * * This is a Unix socket address. * * Note that this class uses QStrings to represent filenames, which means * the proper encoding is used to translate into valid filesystem file names. * * @author Thiago Macieira */ class TDECORE_EXPORT KUnixSocketAddress: public TDESocketAddress { friend class TDESocketAddress; public: /** * Default constructor. Creates an empty object. */ KUnixSocketAddress(); /** * Creates this object with the given raw data. If * the sockaddr structure does not contain a Local namespace * (Unix) socket, this object will be created empty. * * @param sa the socket address structure * @param len the structure's length */ KUnixSocketAddress(const sockaddr* sa, TQ_UINT16 len); /** * Copy constructor. Creates a copy of the other object, * sharing the data explicitly. * * @param other the other object */ KUnixSocketAddress(const KUnixSocketAddress& other); /** * Constructs an object from the given pathname. */ KUnixSocketAddress(const TQString& pathname); /** * Destructor. */ virtual ~KUnixSocketAddress(); /** * Copy operator. Copies the contents of the other object into * this one. Data is explicitly shared. * * @param other the other */ KUnixSocketAddress& operator =(const KUnixSocketAddress& other); /** * Cast operator to sockaddr_un. */ inline operator const sockaddr_un*() const { return (const sockaddr_un*)address(); } /** * Returns the pathname associated with this object. Will return * TQString::null if this object is empty. */ TQString pathname() const; /** * Sets the pathname for the object. * * @return a reference to itself */ KUnixSocketAddress& setPathname(const TQString& path); protected: /// @internal /// extra constructor KUnixSocketAddress(TDESocketAddressData* d); }; } // namespace KNetwork #endif