summaryrefslogblamecommitdiff
path: root/src/net/ip.hpp
blob: 7508c08fd7f75fc413b15ab277c2dd3c36e42e66 (plain) (tree)
1
            


















                                                                           
                  
 
                       
 

                  
 

                 


              




























                                                     










                                                                         

























































































                                                                
                                               
                                            
                                                         
                   
#pragma once
//    ip.hpp - classes to deal with IP addresses.
//
//    Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com>
//
//    This file is part of The Mana World (Athena server)
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.

#include "fwd.hpp"

#include <netinet/in.h>

#include <cstddef>
#include <cstdint>

#include <vector>


namespace tmwa
{
// TODO - in the long run ports belong here also
// and of course, IPv6 stuff.
// But what about unix socket addresses?

/// Helper function
template<class T, size_t n>
constexpr
bool _ce_a_lt(T (&a)[n], T (&b)[n], size_t i=0)
{
    return (i != n
            && (a[i] < b[i]
                || (a[i] == b[i]
                    && _ce_a_lt(a, b, i + 1))));
}

/// A 32-bit Ipv4 address. Does not include a port.
/// Guaranteed to be laid out like the network wants.
class IP4Address
{
    uint8_t _addr[4];
public:
    constexpr
    IP4Address()
    : _addr{}
    {}
    constexpr explicit
    IP4Address(const uint8_t (&a)[4])
    : _addr{a[0], a[1], a[2], a[3]}
    {}
    explicit
    IP4Address(struct in_addr addr)
    {
        static_assert(sizeof(addr) == sizeof(_addr), "4 bytes");
        *this = IP4Address(reinterpret_cast<const uint8_t (&)[4]>(addr));
    }
    explicit
    operator struct in_addr() const
    {
        return reinterpret_cast<const struct in_addr&>(_addr);
    }

    constexpr friend
    IP4Address operator & (IP4Address l, IP4Address r)
    {
        return IP4Address({
                static_cast<uint8_t>(l._addr[0] & r._addr[0]),
                static_cast<uint8_t>(l._addr[1] & r._addr[1]),
                static_cast<uint8_t>(l._addr[2] & r._addr[2]),
                static_cast<uint8_t>(l._addr[3] & r._addr[3]),
        });
    }

    IP4Address& operator &= (IP4Address m)
    { return *this = *this & m; }

    const uint8_t *bytes() const
    { return _addr; }

    constexpr friend
    bool operator < (IP4Address l, IP4Address r)
    {
        return _ce_a_lt(l._addr, r._addr);
    }

    constexpr friend
    bool operator > (IP4Address l, IP4Address r)
    {
        return _ce_a_lt(r._addr, l._addr);
    }

    constexpr friend
    bool operator >= (IP4Address l, IP4Address r)
    {
        return !_ce_a_lt(l._addr, r._addr);
    }

    constexpr friend
    bool operator <= (IP4Address l, IP4Address r)
    {
        return !_ce_a_lt(r._addr, l._addr);
    }

    constexpr friend
    bool operator == (IP4Address l, IP4Address r)
    {
        return !(l < r || r < l);
    }

    constexpr friend
    bool operator != (IP4Address l, IP4Address r)
    {
        return (l < r || r < l);
    }
};

class IP4Mask
{
    IP4Address _addr, _mask;
public:
    constexpr
    IP4Mask() : _addr(), _mask()
    {}
    constexpr
    IP4Mask(IP4Address a, IP4Address m) : _addr(a & m), _mask(m)
    {}

    constexpr
    IP4Address addr() const
    { return _addr; }
    constexpr
    IP4Address mask() const
    { return _mask; }

    constexpr
    bool covers(IP4Address a) const
    {
        return (a & _mask) == _addr;
    }
};


constexpr
IP4Address IP4_LOCALHOST({127, 0, 0, 1});
constexpr
IP4Address IP4_BROADCAST({255, 255, 255, 255});


VString<15> convert_for_printf(IP4Address a);
VString<31> convert_for_printf(IP4Mask m);

bool impl_extract(XString str, IP4Address *iv);
bool impl_extract(XString str, IP4Mask *iv);
bool impl_extract(XString str, std::vector<IP4Mask> *iv);
} // namespace tmwa