llarp/net/sock_addr.hpp

Namespaces

Name
llarp
[crypto.hpp]
std
STL namespace.

Classes

Name
struct llarp::SockAddr
A simple SockAddr wrapper which provides a sockaddr_in (IPv4).

Source code

#pragma once

#include <netinet/in.h>
#include <arpa/inet.h>

#include <string_view>
#include <string>
#include "net_int.hpp"
#include <oxenc/variant.h>
#include <llarp/util/formattable.hpp>

namespace llarp
{
  struct AddressInfo;

  struct SockAddr
  {
    SockAddr();
    // IPv4 constructors:
    SockAddr(uint8_t a, uint8_t b, uint8_t c, uint8_t d, huint16_t port = {0});
    SockAddr(nuint32_t ip, nuint16_t port = {0});
    SockAddr(huint32_t ip, huint16_t port = {0});

    // IPv6 (or IPv4 if given a special IPv4-mapped IPv6 addr) in host order (including port).
    SockAddr(huint128_t ip, huint16_t port = {0});
    // IPv6 (or IPv4 if given a special IPv4-mapped IPv6 addr) in network order.  NB: port is also
    // in network order!
    SockAddr(nuint128_t ip, nuint16_t port = {0});

    // String ctors
    SockAddr(std::string_view addr);
    SockAddr(std::string_view addr, huint16_t port);  // port is in native (host) order

    SockAddr(const AddressInfo&);

    SockAddr(const SockAddr&);
    SockAddr&
    operator=(const SockAddr&);

    SockAddr(const sockaddr& addr);
    SockAddr&
    operator=(const sockaddr& addr);

    SockAddr(const sockaddr_in& addr);
    SockAddr&
    operator=(const sockaddr_in& addr);

    SockAddr(const sockaddr_in6& addr);
    SockAddr&
    operator=(const sockaddr_in6& addr);

    SockAddr(const in6_addr& addr);
    SockAddr&
    operator=(const in6_addr& addr);

    explicit
    operator const sockaddr*() const;
    explicit
    operator const sockaddr_in*() const;
    explicit
    operator const sockaddr_in6*() const;

    size_t
    sockaddr_len() const;

    bool
    operator<(const SockAddr& other) const;

    bool
    operator==(const SockAddr& other) const;

    bool
    operator!=(const SockAddr& other) const
    {
      return not(*this == other);
    };

    void
    fromString(std::string_view str, bool allow_port = true);

    std::string
    ToString() const;

    std::string
    hostString(bool ipv6_brackets = true) const;

    inline int
    Family() const
    {
      if (isIPv6())
        return AF_INET6;
      return AF_INET;
    }

    bool
    isEmpty() const;

    void
    setIPv4(uint8_t a, uint8_t b, uint8_t c, uint8_t d);

    inline void
    setIP(std::variant<nuint32_t, nuint128_t> ip)
    {
      if (auto* v4 = std::get_if<nuint32_t>(&ip))
        setIPv4(*v4);
      if (auto* v6 = std::get_if<nuint128_t>(&ip))
        setIPv6(*v6);
    }

    void
    setIPv4(nuint32_t ip);

    void
    setIPv4(huint32_t ip);

    void
    setIPv6(huint128_t ip);

    void
    setIPv6(nuint128_t ip);

    void
    setPort(huint16_t port);

    void
    setPort(nuint16_t port);

    // Port is a native (host) value
    void
    setPort(uint16_t port)
    {
      setPort(huint16_t{port});
    }

    net::port_t
    port() const;

    inline uint16_t
    getPort() const
    {
      return ToHost(port()).h;
    }

    bool
    isIPv6() const;

    bool
    isIPv4() const;

    nuint128_t
    getIPv6() const;
    nuint32_t
    getIPv4() const;

    std::variant<nuint32_t, nuint128_t>
    getIP() const;

   private:
    bool m_empty = true;
    sockaddr_in6 m_addr;
    sockaddr_in m_addr4;

    void
    init();

    void
    applyIPv4MapBytes();
  };

  template <>
  inline constexpr bool IsToStringFormattable<SockAddr> = true;

}  // namespace llarp

namespace std
{
  template <>
  struct hash<llarp::SockAddr>
  {
    size_t
    operator()(const llarp::SockAddr& addr) const noexcept
    {
      const std::hash<uint16_t> port{};
      const std::hash<llarp::net::ipv6addr_t> ip{};
      return (port(addr.getPort()) << 3) ^ ip(addr.getIPv6());
    }
  };
}  // namespace std

Updated on 2026-01-10 at 22:49:45 +0000