Back to Site
Loading...
Searching...
No Matches
address.h
Go to the documentation of this file.
1#pragma once
2
18#include <cstdint>
19#include <functional>
20#include <optional>
21#include <string>
22#include <string_view>
23
24namespace librats {
25
26struct Address {
27 std::string ip;
28 uint16_t port = 0;
29
30 Address() = default;
31 Address(std::string ip, uint16_t port) : ip(std::move(ip)), port(port) {}
32
36 static std::optional<Address> parse(std::string_view text) {
37 if (!text.empty() && text.front() == '[') {
38 // Bracketed IPv6: [ip]:port
39 const auto close = text.find(']');
40 if (close == std::string_view::npos || close + 1 >= text.size() || text[close + 1] != ':')
41 return std::nullopt;
42 const auto host = text.substr(1, close - 1);
43 if (host.empty()) return std::nullopt;
44 const auto port = parse_port(text.substr(close + 2));
45 if (!port) return std::nullopt;
46 return Address{std::string(host), *port};
47 }
48 const auto colon = text.rfind(':');
49 if (colon == std::string_view::npos || colon == 0 || colon + 1 == text.size())
50 return std::nullopt;
51 const auto host = text.substr(0, colon);
52 // A bare IPv6 literal carries its own colons; without brackets the port is
53 // ambiguous, so reject it rather than guess.
54 if (host.find(':') != std::string_view::npos) return std::nullopt;
55 const auto port = parse_port(text.substr(colon + 1));
56 if (!port) return std::nullopt;
57 return Address{std::string(host), *port};
58 }
59
61 std::string to_string() const {
62 if (ip.find(':') != std::string::npos)
63 return "[" + ip + "]:" + std::to_string(port);
64 return ip + ":" + std::to_string(port);
65 }
66
67 bool operator==(const Address& o) const { return ip == o.ip && port == o.port; }
68 bool operator!=(const Address& o) const { return !(*this == o); }
69
70private:
72 static std::optional<uint16_t> parse_port(std::string_view text) {
73 if (text.empty()) return std::nullopt;
74 unsigned long port = 0;
75 for (char c : text) {
76 if (c < '0' || c > '9') return std::nullopt;
77 port = port * 10 + static_cast<unsigned>(c - '0');
78 if (port > 65535) return std::nullopt;
79 }
80 if (port == 0) return std::nullopt;
81 return static_cast<uint16_t>(port);
82 }
83};
84
85} // namespace librats
86
87namespace std {
88template<>
89struct hash<librats::Address> {
90 std::size_t operator()(const librats::Address& a) const noexcept {
91 return std::hash<std::string>{}(a.ip + ":" + std::to_string(a.port));
92 }
93};
94} // namespace std
Definition node.h:65
STL namespace.
std::string ip
Definition address.h:27
bool operator!=(const Address &o) const
Definition address.h:68
bool operator==(const Address &o) const
Definition address.h:67
Address(std::string ip, uint16_t port)
Definition address.h:31
std::string to_string() const
IPv6 literals (any ip containing ':') serialise bracketed; everything else plain.
Definition address.h:61
Address()=default
static std::optional< Address > parse(std::string_view text)
Parse "host:port" or "[ipv6]:port".
Definition address.h:36
uint16_t port
Definition address.h:28