Spicy
address.h
1 // Copyright (c) 2020-2021 by the Zeek Project. See LICENSE for details.
2 
3 #pragma once
4 
5 #include <arpa/inet.h>
6 #include <netinet/in.h>
7 
8 #include <string>
9 #include <tuple>
10 
11 #include <hilti/rt/extension-points.h>
12 #include <hilti/rt/result.h>
13 #include <hilti/rt/types/bytes.h>
14 #include <hilti/rt/types/stream.h>
15 #include <hilti/rt/util.h>
16 
17 namespace hilti::rt {
18 
19 HILTI_RT_ENUM(AddressFamily, Undef, IPv4, IPv6);
20 
25 class Address {
26 public:
34  explicit Address(const std::string& addr) { _parse(addr); }
35 
37  explicit Address(struct in_addr addr4) { _init(addr4); }
38 
42  explicit Address(struct in6_addr addr6) { _init(addr6); }
43 
49  explicit Address(uint32_t addr4) : Address(0, addr4, AddressFamily::IPv4) {} // addr4 in host byte order
50 
57  explicit Address(uint64_t addr6a, uint64_t addr6b, AddressFamily family = AddressFamily::IPv6)
58  : _a1(addr6a), _a2(addr6b), _family(family) {}
59 
60  Address() noexcept = default;
61  Address(const Address&) = default;
62  Address(Address&&) noexcept = default;
63  ~Address() = default;
64 
65  Address& operator=(const Address&) = default;
66  Address& operator=(Address&&) noexcept = default;
67 
72  AddressFamily family() const;
73 
79  Address mask(unsigned int width) const;
80 
85  std::variant<struct in_addr, struct in6_addr> asInAddr() const;
86 
87  bool operator==(const Address& other) const;
88  bool operator!=(const Address& other) const { return ! (*this == other); }
89  bool operator<(const Address& other) const {
90  return std::tie(_a1, _a2, _family) < std::tie(other._a1, other._a2, other._family);
91  };
92 
99  operator std::string() const;
100 
101  Bytes pack(ByteOrder fmt) const;
102 
103 private:
104  void _init(struct in_addr addr);
105  void _init(struct in6_addr addr);
106 
107  // Throws ``InvalidArgument`` if it cannot parse the address.
108  void _parse(const std::string& addr);
109 
110  uint64_t _a1 = 0; // The 8 more significant bytes.
111  uint64_t _a2 = 0; // The 8 less significant bytes.
112 
113  AddressFamily _family = AddressFamily::Undef;
114 };
115 
116 namespace address {
118 inline Bytes pack(const Address& addr, ByteOrder fmt) { return addr.pack(fmt); }
119 
121 extern Result<std::tuple<Address, Bytes>> unpack(const Bytes& data, AddressFamily family, ByteOrder fmt);
122 
124 extern Result<std::tuple<Address, stream::View>> unpack(const stream::View& data, AddressFamily family, ByteOrder fmt);
125 
133 inline Address parse(const Bytes& data) { return Address(data.str()); }
134 
142 inline Address parse(const std::string& data) { return Address(data); }
143 
144 } // namespace address
145 
146 namespace detail::adl {
147 extern std::string to_string(const AddressFamily& x, adl::tag /*unused*/);
148 inline std::string to_string(const Address& x, adl::tag /*unused*/) { return x; }
149 } // namespace detail::adl
150 
151 inline std::ostream& operator<<(std::ostream& out, const Address& x) {
152  out << to_string(x);
153  return out;
154 }
155 
156 inline std::ostream& operator<<(std::ostream& out, const AddressFamily& family) { return out << to_string(family); }
157 
158 } // namespace hilti::rt
std::string to_string(T &&x)
Definition: extension-points.h:26
Definition: any.h:7
Address(uint32_t addr4)
Definition: address.h:49
Address(struct in_addr addr4)
Definition: address.h:37
std::variant< struct in_addr, struct in6_addr > asInAddr() const
Definition: address.cc:75
Definition: bytes.h:157
Address(uint64_t addr6a, uint64_t addr6b, AddressFamily family=AddressFamily::IPv6)
Definition: address.h:57
Definition: stream.h:984
const std::string & str() const &
Definition: bytes.h:223
Address mask(unsigned int width) const
Definition: address.cc:55
Address(struct in6_addr addr6)
Definition: address.h:42
Definition: address.h:25
AddressFamily family() const
Definition: address.cc:53
Address(const std::string &addr)
Definition: address.h:34
Definition: result.h:67
std::string fmt(const char *fmt, const Args &... args)
Definition: fmt.h:13