aboutsummaryrefslogtreecommitdiff
path: root/include/ricochet/net/sys/address.hh
blob: 39c95530ef4b22ada71645c7aaa23f792cd001c0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/**
 * ---------------------------------------------------------------------------
 * @notice This file was adapted from the Minnow networking framework,
 * originally developed for Stanford University's CS144 course.
 * It has been incorporated into the Ricochet project as foundational
 * system utility code.
 * ---------------------------------------------------------------------------
 */

#pragma once

#include <cstddef>
#include <cstdint>
#include <netdb.h>
#include <string>
#include <sys/socket.h>
#include <utility>

//! Wrapper around [IPv4 addresses](@ref man7::ip) and DNS operations.
class Address
{
public:
  //! \brief Wrapper around [sockaddr_storage](@ref man7::socket).
  //! \details A `sockaddr_storage` is enough space to store any socket address (IPv4 or IPv6).
  class Raw
  {
  public:
    sockaddr_storage storage {}; //!< The wrapped struct itself.
    // NOLINTBEGIN (*-explicit-*)
    operator sockaddr*();
    operator const sockaddr*() const;
    // NOLINTEND (*-explicit-*)
  };

private:
  socklen_t size_; //!< Size of the wrapped address.
  Raw address_ {}; //!< A wrapped [sockaddr_storage](@ref man7::socket) containing the address.

  //! Constructor from ip/host, service/port, and hints to the resolver.
  Address( const std::string& node, const std::string& service, const addrinfo& hints );

public:
  //! Construct by resolving a hostname and servicename.
  Address( const std::string& hostname, const std::string& service );

  //! Construct from dotted-quad string ("18.243.0.1") and numeric port.
  explicit Address( const std::string& ip, std::uint16_t port = 0 );

  //! Construct from a [sockaddr *](@ref man7::socket).
  Address( const sockaddr* addr, std::size_t size );

  //! Default constructor
  Address() : Address( nullptr, 0 ) {}

  //! Equality comparison.
  bool operator==( const Address& other ) const;
  bool operator!=( const Address& other ) const { return not operator==( other ); }

  //! \name Conversions
  //!@{

  //! Dotted-quad IP address string ("18.243.0.1") and numeric port.
  std::pair<std::string, uint16_t> ip_port() const;
  //! Dotted-quad IP address string ("18.243.0.1").
  std::string ip() const { return ip_port().first; }
  //! Numeric port (host byte order).
  uint16_t port() const { return ip_port().second; }
  //! Numeric IP address as an integer (i.e., in [host byte order](\ref man3::byteorder)).
  uint32_t ipv4_numeric() const;
  //! Create an Address from a 32-bit raw numeric IP address
  static Address from_ipv4_numeric( uint32_t ip_address );
  //! Human-readable string, e.g., "8.8.8.8:53".
  std::string to_string() const;
  //!@}

  //! \name Low-level operations
  //!@{

  //! Size of the underlying address storage.
  socklen_t size() const { return size_; }
  //! Const pointer to the underlying socket address storage.
  const sockaddr* raw() const { return static_cast<const sockaddr*>( address_ ); }
  //! Safely convert to underlying sockaddr type
  template<typename sockaddr_type>
  const sockaddr_type* as() const;

  //!@}
};