mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-26 08:57:26 +02:00
214 lines
5.8 KiB
C++
214 lines
5.8 KiB
C++
/*
|
|
* Copyright (c)2013-2020 ZeroTier, Inc.
|
|
*
|
|
* Use of this software is governed by the Business Source License included
|
|
* in the LICENSE.TXT file in the project's root directory.
|
|
*
|
|
* Change Date: 2024-01-01
|
|
*
|
|
* On the date above, in accordance with the Business Source License, use
|
|
* of this software will be governed by version 2.0 of the Apache License.
|
|
*/
|
|
/****/
|
|
|
|
#ifndef ZT_ENDPOINT_HPP
|
|
#define ZT_ENDPOINT_HPP
|
|
|
|
#include "Constants.hpp"
|
|
#include "InetAddress.hpp"
|
|
#include "Address.hpp"
|
|
#include "Utils.hpp"
|
|
#include "TriviallyCopyable.hpp"
|
|
#include "Fingerprint.hpp"
|
|
#include "MAC.hpp"
|
|
|
|
#define ZT_ENDPOINT_STRING_SIZE_MAX 256
|
|
#define ZT_ENDPOINT_MARSHAL_SIZE_MAX 192
|
|
|
|
namespace ZeroTier {
|
|
|
|
static_assert((ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > ZT_INETADDRESS_MARSHAL_SIZE_MAX, "ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
|
|
static_assert((ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > sizeof(ZT_Fingerprint), "ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
|
|
static_assert((ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > sizeof(InetAddress), "ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
|
|
static_assert((ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > sizeof(MAC), "ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
|
|
static_assert((ZT_ENDPOINT_MARSHAL_SIZE_MAX - 1) > sizeof(Fingerprint), "ZT_ENDPOINT_MARSHAL_SIZE_MAX not large enough");
|
|
|
|
/**
|
|
* Endpoint variant specifying some form of network endpoint.
|
|
*
|
|
* This is sort of a superset of InetAddress and for the standard UDP
|
|
* protocol marshals and unmarshals to a compatible format. This makes
|
|
* it backward compatible with older node versions' protocol fields
|
|
* where InetAddress was used as long as only the UDP type is exchanged
|
|
* with those nodes.
|
|
*/
|
|
class Endpoint : public ZT_Endpoint, public TriviallyCopyable
|
|
{
|
|
public:
|
|
/**
|
|
* Create a NIL/empty endpoint
|
|
*/
|
|
ZT_INLINE Endpoint() noexcept
|
|
{ memoryZero(this); }
|
|
|
|
ZT_INLINE Endpoint(const ZT_Endpoint &ep) noexcept
|
|
{ *this = ep; }
|
|
|
|
/**
|
|
* Create an endpoint for a type that uses an IP
|
|
*
|
|
* @param a IP/port
|
|
* @param et Endpoint type (default: IP_UDP)
|
|
*/
|
|
ZT_INLINE Endpoint(const InetAddress &inaddr, const ZT_EndpointType et = ZT_ENDPOINT_TYPE_IP_UDP) noexcept
|
|
{
|
|
if (inaddr) {
|
|
this->type = et;
|
|
Utils::copy<sizeof(struct sockaddr_storage)>(&(this->value.ss), &(inaddr.as.ss));
|
|
} else {
|
|
memoryZero(this);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create an endpoint for ZeroTier relaying (ZEROTIER type)
|
|
*
|
|
* @param zt_ ZeroTier identity fingerprint
|
|
*/
|
|
ZT_INLINE Endpoint(const Fingerprint &zt_) noexcept
|
|
{
|
|
if (zt_) {
|
|
this->type = ZT_ENDPOINT_TYPE_ZEROTIER;
|
|
this->value.fp = zt_;
|
|
} else {
|
|
memoryZero(this);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create an endpoint for a type that uses a MAC address
|
|
*
|
|
* @param eth_ Ethernet address
|
|
* @param et Endpoint type (default: ETHERNET)
|
|
*/
|
|
ZT_INLINE Endpoint(const MAC ð_, const ZT_EndpointType et = ZT_ENDPOINT_TYPE_ETHERNET) noexcept
|
|
{
|
|
if (eth_) {
|
|
this->type = et;
|
|
this->value.mac = eth_.toInt();
|
|
} else {
|
|
memoryZero(this);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return True if endpoint type isn't NIL
|
|
*/
|
|
ZT_INLINE operator bool() const noexcept
|
|
{ return this->type != ZT_ENDPOINT_TYPE_NIL; }
|
|
|
|
/**
|
|
* @return True if this endpoint type has an InetAddress address type and thus ip() is valid
|
|
*/
|
|
ZT_INLINE bool isInetAddr() const noexcept
|
|
{
|
|
switch (this->type) {
|
|
case ZT_ENDPOINT_TYPE_IP:
|
|
case ZT_ENDPOINT_TYPE_IP_UDP:
|
|
case ZT_ENDPOINT_TYPE_IP_TCP:
|
|
case ZT_ENDPOINT_TYPE_IP_HTTP2:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check whether this endpoint's address is the same as another.
|
|
*
|
|
* Right now this checks whether IPs are equal if both are IP based endpoints.
|
|
* Otherwise it checks for simple equality.
|
|
*
|
|
* @param ep Endpoint to check
|
|
* @return True if endpoints seem to refer to the same address/host
|
|
*/
|
|
ZT_INLINE bool isSameAddress(const Endpoint &ep) const noexcept
|
|
{
|
|
switch (this->type) {
|
|
case ZT_ENDPOINT_TYPE_IP:
|
|
case ZT_ENDPOINT_TYPE_IP_UDP:
|
|
case ZT_ENDPOINT_TYPE_IP_TCP:
|
|
case ZT_ENDPOINT_TYPE_IP_HTTP:
|
|
switch(ep.type) {
|
|
case ZT_ENDPOINT_TYPE_IP:
|
|
case ZT_ENDPOINT_TYPE_IP_UDP:
|
|
case ZT_ENDPOINT_TYPE_IP_TCP:
|
|
case ZT_ENDPOINT_TYPE_IP_HTTP:
|
|
return ip().ipsEqual(ep.ip());
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return (*this) == ep;
|
|
}
|
|
|
|
/**
|
|
* Get InetAddress if this type uses IPv4 or IPv6 addresses (undefined otherwise)
|
|
*
|
|
* @return InetAddress instance
|
|
*/
|
|
ZT_INLINE const InetAddress &ip() const noexcept
|
|
{ return asInetAddress(this->value.ss); }
|
|
|
|
/**
|
|
* Get MAC if this is an Ethernet, WiFi direct, or Bluetooth type (undefined otherwise)
|
|
*
|
|
* @return Ethernet MAC
|
|
*/
|
|
ZT_INLINE MAC eth() const noexcept
|
|
{ return MAC(this->value.mac); }
|
|
|
|
/**
|
|
* Get fingerprint if this is a ZeroTier endpoint type (undefined otherwise)
|
|
*
|
|
* @return ZeroTier fingerprint
|
|
*/
|
|
ZT_INLINE Fingerprint zt() const noexcept
|
|
{ return Fingerprint(this->value.fp); }
|
|
|
|
char *toString(char s[ZT_ENDPOINT_STRING_SIZE_MAX]) const noexcept;
|
|
|
|
ZT_INLINE String toString() const { char tmp[ZT_ENDPOINT_STRING_SIZE_MAX]; return String(toString(tmp)); }
|
|
|
|
bool fromString(const char *s) noexcept;
|
|
|
|
static constexpr int marshalSizeMax() noexcept
|
|
{ return ZT_ENDPOINT_MARSHAL_SIZE_MAX; }
|
|
|
|
int marshal(uint8_t data[ZT_ENDPOINT_MARSHAL_SIZE_MAX]) const noexcept;
|
|
|
|
int unmarshal(const uint8_t *restrict data, int len) noexcept;
|
|
|
|
bool operator==(const Endpoint &ep) const noexcept;
|
|
|
|
ZT_INLINE bool operator!=(const Endpoint &ep) const noexcept
|
|
{ return !((*this) == ep); }
|
|
|
|
bool operator<(const Endpoint &ep) const noexcept;
|
|
|
|
ZT_INLINE bool operator>(const Endpoint &ep) const noexcept
|
|
{ return (ep < *this); }
|
|
|
|
ZT_INLINE bool operator<=(const Endpoint &ep) const noexcept
|
|
{ return !(ep < *this); }
|
|
|
|
ZT_INLINE bool operator>=(const Endpoint &ep) const noexcept
|
|
{ return !(*this < ep); }
|
|
};
|
|
|
|
} // namespace ZeroTier
|
|
|
|
#endif
|