struct __attribute__()

in net/socket.h [45:153]


    struct __attribute__ ((packed)) IPAddr {
    public:
        union {
            in6_addr addr = {};
            // all data is in network byte order
            struct { uint16_t _1, _2, _3, _4, _5, _6; uint8_t a, b, c, d; };
        } __attribute__((packed));
        // For compatibility, the default constructor is still 0.0.0.0 (IPv4)
        IPAddr() {
            map_v4(htonl(INADDR_ANY));
        }
        // V6 constructor (Internet Address)
        explicit IPAddr(in6_addr internet_addr) {
            addr = internet_addr;
        }
        // V6 constructor (Network byte order)
        IPAddr(uint32_t nl1, uint32_t nl2, uint32_t nl3, uint32_t nl4) {
            addr._in_addr_field[0] = nl1;
            addr._in_addr_field[1] = nl2;
            addr._in_addr_field[2] = nl3;
            addr._in_addr_field[3] = nl4;
        }
        // V4 constructor (Internet Address)
        explicit IPAddr(in_addr internet_addr) {
            map_v4(internet_addr);
        }
        // V4 constructor (Network byte order)
        explicit IPAddr(uint32_t nl) {
            map_v4(nl);
        }
        // String constructor
        explicit IPAddr(const char* s) {
            if (inet_pton(AF_INET6, s, &addr) > 0) {
                return;
            }
            in_addr v4_addr;
            if (inet_pton(AF_INET, s, &v4_addr) > 0) {
                map_v4(v4_addr);
                return;
            }
            // Invalid string, make it a default value
            *this = IPAddr();
        }
        // Check if it's actually an IPv4 address mapped in IPV6
        bool is_ipv4() const {
            return addr._in_addr_field[0] == 0 &&
                   addr._in_addr_field[1] == 0 &&
                   addr._in_addr_field[2] == htonl(0x0000ffff);
        }
        bool is_ipv6() const {
            return !is_ipv4();
        }
        // We regard the default IPv4 0.0.0.0 as undefined
        bool undefined() const {
            return mem_equal(V4Any());
        }
        void reset() { *this = IPAddr(); }
        void clear() { reset(); }
        // Should ONLY be used for IPv4 address
        uint32_t to_nl() const {
            assert(is_ipv4());
            return addr._in_addr_field[3];
        }
        bool is_loopback() const {
            return is_ipv4() ? mem_equal(V4Loopback()) : mem_equal(V6Loopback());
        }
        bool is_localhost() const {
            return is_loopback();
        }
        bool is_broadcast() const {
            // IPv6 does not support broadcast
            return is_ipv4() && mem_equal(V4Broadcast());
        }
        bool is_link_local() const {
            if (is_ipv4()) {
                return (to_nl() & htonl(0xffff0000)) == htonl(0xa9fe0000);
            } else {
                return (addr._in_addr_field[0] & htonl(0xffc00000)) == htonl(0xfe800000);
            }
        }
        bool operator==(const IPAddr& rhs) const {
            return mem_equal(rhs);
        }
        bool operator!=(const IPAddr& rhs) const {
            return !(*this == rhs);
        }
        static IPAddr V6None() {
            return IPAddr(htonl(0xffffffff), htonl(0xffffffff), htonl(0xffffffff), htonl(0xffffffff));
        }
        static IPAddr V6Any() { return IPAddr(in6addr_any); }
        static IPAddr V6Loopback() { return IPAddr(in6addr_loopback); }
        static IPAddr V4Broadcast() { return IPAddr(htonl(INADDR_BROADCAST)); }
        static IPAddr V4Any() { return IPAddr(htonl(INADDR_ANY)); }
        static IPAddr V4Loopback() { return IPAddr(htonl(INADDR_LOOPBACK)); }
        static IPAddr Localhost() { return V4Loopback(); }
    private:
        bool mem_equal(const IPAddr& rhs) const {
            return memcmp(this, &rhs, sizeof(rhs)) == 0;
        }
        void map_v4(in_addr addr_) {
            map_v4(addr_.s_addr);
        }
        void map_v4(uint32_t nl) {
            addr._in_addr_field[0] = 0x00000000;
            addr._in_addr_field[1] = 0x00000000;
            addr._in_addr_field[2] = htonl(0xffff);
            addr._in_addr_field[3] = nl;
        }
    };