diff options
Diffstat (limited to 'node/Address.hpp')
-rw-r--r-- | node/Address.hpp | 186 |
1 files changed, 132 insertions, 54 deletions
diff --git a/node/Address.hpp b/node/Address.hpp index 4c912540..fce4f20c 100644 --- a/node/Address.hpp +++ b/node/Address.hpp @@ -28,72 +28,156 @@ #ifndef _ZT_ADDRESS_HPP #define _ZT_ADDRESS_HPP +#include <stdio.h> +#include <stdlib.h> #include <stdint.h> +#include <string.h> #include <string> #include "Utils.hpp" #include "MAC.hpp" #include "Constants.hpp" +#include "Buffer.hpp" namespace ZeroTier { /** - * ZeroTier address, which doubles as the last 5 octets of the MAC on taps - * - * Natural sort order will differ on big vs. little endian machines, but that - * won't matter when it's used as a local map/set key. + * A ZeroTier address */ class Address { -private: - union { - unsigned char o[ZT_ADDRESS_LENGTH]; - uint64_t v; - } _a; - public: Address() - throw() + throw() : + _a(0) { - _a.v = 0; } Address(const Address &a) + throw() : + _a(a._a) + { + } + + Address(uint64_t a) + throw() : + _a(a & 0xffffffffffULL) + { + } + + Address(const char *s) throw() { - _a.v = a._a.v; + unsigned char foo[ZT_ADDRESS_LENGTH]; + setTo(foo,Utils::unhex(s,foo,ZT_ADDRESS_LENGTH)); } - /** - * Create from a ZeroTier MAC - * - * @param m MAC (assumed to be a ZeroTier MAC) - */ - Address(const MAC &m) + Address(const std::string &s) throw() { - _a.v = 0; - for(int i=0;i<ZT_ADDRESS_LENGTH;++i) - _a.o[i] = m.data[i + 1]; + unsigned char foo[ZT_ADDRESS_LENGTH]; + setTo(foo,Utils::unhex(s.c_str(),foo,ZT_ADDRESS_LENGTH)); } /** - * @param bits Raw address -- 5 bytes in length + * @param bits Raw address -- 5 bytes, big-endian byte order + * @param len Length of array */ - Address(const void *bits) + Address(const void *bits,unsigned int len) throw() { - _a.v = 0; - for(int i=0;i<ZT_ADDRESS_LENGTH;++i) - _a.o[i] = ((const unsigned char *)bits)[i]; + setTo(bits,len); } inline Address &operator=(const Address &a) throw() { - _a.v = a._a.v; + _a = a._a; return *this; } + inline Address &operator=(const uint64_t a) + throw() + { + _a = (a & 0xffffffffffULL); + return *this; + } + + /** + * @param bits Raw address -- 5 bytes, big-endian byte order + * @param len Length of array + */ + inline void setTo(const void *bits,unsigned int len) + throw() + { + if (len < ZT_ADDRESS_LENGTH) { + _a = 0; + return; + } + const unsigned char *b = (const unsigned char *)bits; + uint64_t a = ((uint64_t)*b++) << 32; + a |= ((uint64_t)*b++) << 24; + a |= ((uint64_t)*b++) << 16; + a |= ((uint64_t)*b++) << 8; + a |= ((uint64_t)*b); + _a = a; + } + + /** + * @param bits Buffer to hold 5-byte address in big-endian byte order + * @param len Length of array + */ + inline void copyTo(void *bits,unsigned int len) const + throw() + { + if (len < ZT_ADDRESS_LENGTH) + return; + unsigned char *b = (unsigned char *)bits; + *(b++) = (unsigned char)((_a >> 32) & 0xff); + *(b++) = (unsigned char)((_a >> 24) & 0xff); + *(b++) = (unsigned char)((_a >> 16) & 0xff); + *(b++) = (unsigned char)((_a >> 8) & 0xff); + *b = (unsigned char)(_a & 0xff); + } + + /** + * Append to a buffer in big-endian byte order + * + * @param b Buffer to append to + */ + template<unsigned int C> + inline void appendTo(Buffer<C> &b) const + throw(std::out_of_range) + { + b.append((unsigned char)((_a >> 32) & 0xff)); + b.append((unsigned char)((_a >> 24) & 0xff)); + b.append((unsigned char)((_a >> 16) & 0xff)); + b.append((unsigned char)((_a >> 8) & 0xff)); + b.append((unsigned char)(_a & 0xff)); + } + + /** + * @return String containing address as 5 binary bytes + */ + inline std::string toBinaryString() const + { + std::string b; + b.push_back((char)((_a >> 32) & 0xff)); + b.push_back((char)((_a >> 24) & 0xff)); + b.push_back((char)((_a >> 16) & 0xff)); + b.push_back((char)((_a >> 8) & 0xff)); + b.push_back((char)(_a & 0xff)); + return b; + } + + /** + * @return Integer containing address (0 to 2^40) + */ + inline uint64_t toInt() const + throw() + { + return _a; + } + /** * Derive a MAC whose first octet is the ZeroTier LAN standard * @@ -104,8 +188,7 @@ public: { MAC m; m.data[0] = ZT_MAC_FIRST_OCTET; - for(int i=1;i<6;++i) - m.data[i] = _a.o[i - 1]; + copyTo(m.data + 1,ZT_ADDRESS_LENGTH); return m; } @@ -114,18 +197,15 @@ public: */ inline std::string toString() const { - return Utils::hex(_a.o,ZT_ADDRESS_LENGTH); + char buf[16]; + sprintf(buf,"%.10llx",(unsigned long long)_a); + return std::string(buf); }; /** - * Set address to zero - */ - inline void zero() throw() { _a.v = 0; } - - /** * @return True if this address is not zero */ - inline operator bool() const throw() { return (_a.v); } + inline operator bool() const throw() { return (_a); } /** * @return Sum of all bytes in address @@ -133,10 +213,7 @@ public: inline unsigned int sum() const throw() { - unsigned int s = 0; - for(unsigned int i=0;i<ZT_ADDRESS_LENGTH;++i) - s += _a.o[i]; - return s; + return (unsigned int)(((_a >> 32) & 0xff) + ((_a >> 24) & 0xff) + ((_a >> 16) & 0xff) + ((_a >> 8) & 0xff) + (_a & 0xff)); } /** @@ -151,23 +228,24 @@ public: inline bool isReserved() const throw() { - return ((!_a.v)||(_a.o[0] == ZT_ADDRESS_RESERVED_PREFIX)); + return ((!_a)||((_a >> 32) == ZT_ADDRESS_RESERVED_PREFIX)); } - inline unsigned char *data() throw() { return _a.o; } - inline const unsigned char *data() const throw() { return _a.o; } - - inline unsigned int size() const throw() { return ZT_ADDRESS_LENGTH; } + /** + * @param i Value from 0 to 4 (inclusive) + * @return Byte at said position (address interpreted in big-endian order) + */ + inline unsigned char operator[](unsigned int i) const throw() { return (unsigned char)((_a >> (32 - (i * 8))) & 0xff); } - inline unsigned char &operator[](unsigned int i) throw() { return _a.o[i]; } - inline unsigned char operator[](unsigned int i) const throw() { return _a.o[i]; } + inline bool operator==(const Address &a) const throw() { return (_a == a._a); } + inline bool operator!=(const Address &a) const throw() { return (_a != a._a); } + inline bool operator>(const Address &a) const throw() { return (_a > a._a); } + inline bool operator<(const Address &a) const throw() { return (_a < a._a); } + inline bool operator>=(const Address &a) const throw() { return (_a >= a._a); } + inline bool operator<=(const Address &a) const throw() { return (_a <= a._a); } - inline bool operator==(const Address &a) const throw() { return (_a.v == a._a.v); } - inline bool operator!=(const Address &a) const throw() { return (_a.v != a._a.v); } - inline bool operator<(const Address &a) const throw() { return (_a.v < a._a.v); } - inline bool operator>(const Address &a) const throw() { return (_a.v > a._a.v); } - inline bool operator<=(const Address &a) const throw() { return (_a.v <= a._a.v); } - inline bool operator>=(const Address &a) const throw() { return (_a.v >= a._a.v); } +private: + uint64_t _a; }; } // namespace ZeroTier |