Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/bitcoin/network/config/address.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ class BCT_API address
address(const messages::address_item& item) NOEXCEPT;
address(const messages::address_item::cptr& message) NOEXCEPT;

/// If endpoint is a DNS name (not numeric) default address is returned.
address(const asio::endpoint& uri) NOEXCEPT;

// Methods.
// ------------------------------------------------------------------------
// All values are denormalized (IPv6 or IPv4).
Expand Down
71 changes: 9 additions & 62 deletions include/bitcoin/network/config/authority.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
#define LIBBITCOIN_NETWORK_CONFIG_AUTHORITY_HPP

#include <memory>
#include <bitcoin/network/async/async.hpp>
#include <bitcoin/network/config/address.hpp>
#include <bitcoin/network/define.hpp>
#include <bitcoin/network/messages/messages.hpp>
Expand All @@ -29,86 +28,34 @@ namespace libbitcoin {
namespace network {
namespace config {

/// Container for an [ip-address, port, CIDR] tuple.
/// Subnet matching is employed when nonzero CIDR suffix is present.
/// Internal storage always denormalized to native IPv4/IPv6 (no mapped IPv6).
/// Provided for connection management (not p2p network messaging).
/// Add message address types to base authority configuration class.
/// Message addresses are 16 byte ipv6 encoding with ipv4 addresses mapped.
class BCT_API authority
: public system::config::authority
{
public:
typedef std::shared_ptr<authority> ptr;

DEFAULT_COPY_MOVE_DESTRUCT(authority);

authority() NOEXCEPT;
/// Use base class constructors.
using system::config::authority::authority;

/// Deserialize [IPv6]|IPv4[:port][/cidr] (IPv6 [literal]).
authority(const std::string& authority) THROWS;
authority(const asio::address& ip, uint16_t port, uint8_t cidr=0) NOEXCEPT;
authority(const messages::address_item& item) NOEXCEPT;
authority(const asio::endpoint& endpoint) NOEXCEPT;
authority(const config::address& address) NOEXCEPT;

/// Properties.
/// -----------------------------------------------------------------------

/// The IPv4 or IPv6 address, denormalized (no mapped IPv6).
const asio::address& ip() const NOEXCEPT;

/// The ip port of the authority.
uint16_t port() const NOEXCEPT;

/// The ip subnet mask in cidr format (zero implies none).
uint8_t cidr() const NOEXCEPT;

/// Methods.
/// -----------------------------------------------------------------------
/// All serializations are denormalized (IPv6 or IPv4).

/// The IPv4 or IPv6 address and port as an asio endpoint.
asio::endpoint to_endpoint() const NOEXCEPT;

/// IPv6|IPv4
std::string to_host() const NOEXCEPT;

/// [IPv6]|IPv4
std::string to_literal() const NOEXCEPT;

/// Serialize [IPv6]|IPv4[:port][/cidr] (IPv6 [literal]).
std::string to_string() const NOEXCEPT;

/// Authority converted to messages::ip_address or messages::address_item.
/// Message addresses are 16 byte ipv6 encoding with ipv4 addresses mapped.
/// Authority converted to messages::ip_address.
messages::ip_address to_ip_address() const NOEXCEPT;

/// Authority converted to messages::address_item.
messages::address_item to_address_item() const NOEXCEPT;
messages::address_item to_address_item(uint32_t timestamp,
uint64_t services) const NOEXCEPT;

/// Operators.
/// -----------------------------------------------------------------------

/// False if ip address is unspecified or port is zero.
operator bool() const NOEXCEPT;

/// Equality treats zero port as * and non-zero CIDR as subnet identifier.
/// Equality is subnet containment when one subnet identifier is present.
/// Distinct subnets are usequal even if intersecting, same subnets equal.
bool operator==(const authority& other) const NOEXCEPT;
bool operator!=(const authority& other) const NOEXCEPT;
/// Distinct subnets are unequal even if intersecting, same subnets equal.
bool operator==(const messages::address_item& other) const NOEXCEPT;
bool operator!=(const messages::address_item& other) const NOEXCEPT;

/// Same format as construct(string) and to_string().
friend std::istream& operator>>(std::istream& input,
authority& argument) THROWS;
friend std::ostream& operator<<(std::ostream& output,
const authority& argument) NOEXCEPT;

private:
// These are not thread safe.
asio::address ip_;
uint16_t port_;
uint8_t cidr_;
};

typedef std::vector<authority> authorities;
Expand Down
72 changes: 7 additions & 65 deletions include/bitcoin/network/config/endpoint.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,95 +21,37 @@

#include <memory>
#include <bitcoin/system.hpp>
#include <bitcoin/network/async/async.hpp>
#include <bitcoin/network/config/address.hpp>
#include <bitcoin/network/config/authority.hpp>
#include <bitcoin/network/define.hpp>

namespace libbitcoin {
namespace network {
namespace config {

/// Container for a [scheme, host, port] tuple.
/// IPv6 URIs encoded with literal host (en.wikipedia.org/wiki/IPv6_address).
/// Provided for serialization of network endpoints in URI format.

/// Add message address types to base endpoint configuration class.
class BCT_API endpoint
: public system::config::endpoint
{
public:
typedef std::shared_ptr<endpoint> ptr;

DEFAULT_COPY_MOVE_DESTRUCT(endpoint);

endpoint() NOEXCEPT;

/// The scheme and port may be undefined, in which case the port is
/// reported as zero and the scheme is reported as an empty string.
/// The value is of the form: [scheme://]host[:port] (dns name or ip).
endpoint(const std::string& uri) THROWS;
endpoint(const std::string& host, uint16_t port) NOEXCEPT;
endpoint(const std::string& scheme, const std::string& host,
uint16_t port) NOEXCEPT;
endpoint(const asio::endpoint& uri) NOEXCEPT;
endpoint(const asio::address& ip, uint16_t port) NOEXCEPT;
endpoint(const config::authority& authority) NOEXCEPT;

/// Properties.
/// -----------------------------------------------------------------------

/// The scheme of the endpoint or empty string.
const std::string& scheme() const NOEXCEPT;

/// The host name or ip address of the endpoint.
const std::string& host() const NOEXCEPT;

/// The tcp port of the endpoint.
uint16_t port() const NOEXCEPT;

/// Methods.
/// -----------------------------------------------------------------------

/// An empty scheme and/or empty (zero) port is omitted.
/// The endpoint is of the form: [scheme://]host[:port]
std::string to_uri() const NOEXCEPT;
using system::config::endpoint::endpoint;

/// Return a new endpoint that replaces host instances of "*" with
/// "localhost". This is intended for clients that wish to connect
/// to a service that has been configured to bind to all interfaces.
endpoint to_local() const NOEXCEPT;

/// IP address object if host is numeric, otherwise unspecified.
address to_address() const NOEXCEPT;

/// Operators.
/// -----------------------------------------------------------------------

/// Cast to IP address object if host is numeric, otherwise unspecified.
/// If endpoint is a DNS name (not numeric) default address is returned.
operator const address() const NOEXCEPT;

/// False if the endpoint is not initialized.
operator bool() const NOEXCEPT;
operator const authority() const NOEXCEPT;

/// Equality considers all properties (scheme, host, port).
/// Non-numeric and invalid endpoints will match the default address_item.
bool operator==(const endpoint& other) const NOEXCEPT;
bool operator!=(const endpoint& other) const NOEXCEPT;
bool operator==(const messages::address_item& other) const NOEXCEPT;
bool operator!=(const messages::address_item& other) const NOEXCEPT;

friend std::istream& operator>>(std::istream& input,
endpoint& argument) THROWS;
friend std::ostream& operator<<(std::ostream& output,
const endpoint& argument) NOEXCEPT;

protected:
std::string to_authority() const NOEXCEPT;
address to_address() const NOEXCEPT;
messages::address_item to_address_item() const NOEXCEPT;

private:
// These are not thread safe.
std::string scheme_;
std::string host_;
uint16_t port_;
};

typedef std::vector<endpoint> endpoints;
Expand Down
46 changes: 2 additions & 44 deletions include/bitcoin/network/config/utilities.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,43 +19,19 @@
#ifndef LIBBITCOIN_NETWORK_CONFIG_UTILITIES_HPP
#define LIBBITCOIN_NETWORK_CONFIG_UTILITIES_HPP

#include <algorithm>
#include <bitcoin/system.hpp>
#include <bitcoin/network/async/async.hpp>
#include <bitcoin/network/define.hpp>
#include <bitcoin/network/messages/messages.hpp>
#include <bitcoin/system.hpp>

namespace libbitcoin {
namespace network {
namespace config {

/// IPv6 supports embedding of an IPv4 address (4 bytes) into IPv6 encodings
/// (16 bytes). The two formats, "compatible" and "mapped" embed the same
/// address differently, with the distinction being the level of support of the
/// device. This is problematic for addresses, as they are device independent.
/// P2P protocol is 16 bytes and allows for either encoding, however the
/// "compatible" concoding is deprecated, so we produce only mapped encoding
/// for P2P serialization. However, as both formats are send via P2P we decode
/// from all three IPv6 encodings (native, compatible, mapped). For human
/// readability we serialize addresses as text, for both logging and shutdown
/// persistence. We refer to this format as denormalized, as it supports only
/// native IPv4 and native IPv6 serialization. IPv6 host names are "bracketed".
/// This provides distinction from the port number (otherwise conflating ":").
/// This form is referred to as "literal" IPv6 encoding (from IPv6 URIs). All
/// text addresses are literal encodings, and all host names are serialized as
/// non-literal, and deserialized as either literal or non-literal.

/// datatracker.ietf.org/doc/html/rfc4291
constexpr size_t ipv4_size = 4;
constexpr size_t ipv6_size = 16;
static constexpr system::data_array<ipv6_size - ipv4_size> ip_map_prefix
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff
};

/// True if ip_address starts with the ip map prefix (maps to a v4 address).
constexpr bool is_v4(const messages::ip_address& ip) NOEXCEPT
{
using namespace system::config;
return std::equal(ip_map_prefix.begin(), ip_map_prefix.end(), ip.begin());
}

Expand All @@ -64,28 +40,10 @@ constexpr bool is_v6(const messages::ip_address& ip) NOEXCEPT
return !is_v4(ip);
}

/// Member if subnet addresses contain host.
BCT_API bool is_member(const asio::address& ip, const asio::address& subnet,
uint8_t cidr) NOEXCEPT;

/// Unmap IPv6-mapped addresses.
BCT_API asio::address denormalize(const asio::address& ip) NOEXCEPT;

/// Denormalizes to IPv4 (unmapped), literal emits unbracketed.
BCT_API std::string to_host(const asio::address& ip) NOEXCEPT;
BCT_API std::string to_literal(const asio::address& ip) NOEXCEPT;
BCT_API asio::address from_host(const std::string& host) THROWS;

/// Not denormalizing.
BCT_API messages::ip_address to_address(const asio::address& ip) NOEXCEPT;
BCT_API asio::address from_address(const messages::ip_address& address) NOEXCEPT;

/// Parsers.
BCT_API bool parse_authority(asio::address& ip, uint16_t& port,
uint8_t& cidr, const std::string& value) NOEXCEPT;
BCT_API bool parse_endpoint(std::string& scheme, std::string& host,
uint16_t& port, const std::string& value) NOEXCEPT;

} // namespace config
} // namespace network
} // namespace libbitcoin
Expand Down
10 changes: 8 additions & 2 deletions src/config/address.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <sstream>
#include <utility>
#include <bitcoin/network/config/authority.hpp>
#include <bitcoin/network/config/endpoint.hpp>
#include <bitcoin/network/config/utilities.hpp>
#include <bitcoin/system.hpp>

Expand Down Expand Up @@ -57,17 +58,22 @@ address::address(const messages::address_item::cptr& message) NOEXCEPT
{
}

address::address(const asio::endpoint& uri) NOEXCEPT
: address(endpoint{ uri })
{
}

// Methods.
// ----------------------------------------------------------------------------

asio::address address::to_ip() const NOEXCEPT
{
return config::denormalize(from_address(address_->ip));
return system::config::denormalize(from_address(address_->ip));
}

std::string address::to_host() const NOEXCEPT
{
return config::to_host(to_ip());
return system::config::to_host(to_ip());
}

std::string address::to_string() const NOEXCEPT
Expand Down
Loading
Loading