summaryrefslogtreecommitdiff
path: root/node/Buffer.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'node/Buffer.hpp')
-rw-r--r--node/Buffer.hpp207
1 files changed, 84 insertions, 123 deletions
diff --git a/node/Buffer.hpp b/node/Buffer.hpp
index 0b171592..bbf4ee37 100644
--- a/node/Buffer.hpp
+++ b/node/Buffer.hpp
@@ -1,6 +1,6 @@
/*
* ZeroTier One - Network Virtualization Everywhere
- * Copyright (C) 2011-2016 ZeroTier, Inc. https://www.zerotier.com/
+ * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -14,6 +14,14 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * --
+ *
+ * You can be released from the requirements of the license by purchasing
+ * a commercial license. Buying such a license is mandatory as soon as you
+ * develop commercial closed-source software that incorporates or links
+ * directly against ZeroTier software without disclosing the source code
+ * of your own application.
*/
#ifndef ZT_BUFFER_HPP
@@ -61,11 +69,11 @@ public:
// STL container idioms
typedef unsigned char value_type;
typedef unsigned char * pointer;
- typedef const unsigned char * const_pointer;
- typedef unsigned char & reference;
- typedef const unsigned char & const_reference;
- typedef unsigned char * iterator;
- typedef const unsigned char * const_iterator;
+ typedef const char * const_pointer;
+ typedef char & reference;
+ typedef const char & const_reference;
+ typedef char * iterator;
+ typedef const char * const_iterator;
typedef unsigned int size_type;
typedef int difference_type;
typedef std::reverse_iterator<iterator> reverse_iterator;
@@ -79,78 +87,61 @@ public:
inline const_reverse_iterator rbegin() const { return const_reverse_iterator(begin()); }
inline const_reverse_iterator rend() const { return const_reverse_iterator(end()); }
- Buffer()
- throw() :
+ Buffer() :
_l(0)
{
}
Buffer(unsigned int l)
- throw(std::out_of_range)
{
if (l > C)
- throw std::out_of_range("Buffer: construct with size larger than capacity");
+ throw ZT_EXCEPTION_OUT_OF_BOUNDS;
_l = l;
}
template<unsigned int C2>
Buffer(const Buffer<C2> &b)
- throw(std::out_of_range)
{
*this = b;
}
Buffer(const void *b,unsigned int l)
- throw(std::out_of_range)
{
copyFrom(b,l);
}
- Buffer(const std::string &s)
- throw(std::out_of_range)
- {
- copyFrom(s.data(),s.length());
- }
-
template<unsigned int C2>
inline Buffer &operator=(const Buffer<C2> &b)
- throw(std::out_of_range)
- {
- if (b._l > C)
- throw std::out_of_range("Buffer: assignment from buffer larger than capacity");
- memcpy(_b,b._b,_l = b._l);
- return *this;
- }
-
- inline Buffer &operator=(const std::string &s)
- throw(std::out_of_range)
{
- copyFrom(s.data(),s.length());
+ if (unlikely(b._l > C))
+ throw ZT_EXCEPTION_OUT_OF_BOUNDS;
+ if (C2 == C) {
+ ZT_FAST_MEMCPY(this,&b,sizeof(Buffer<C>));
+ } else {
+ ZT_FAST_MEMCPY(_b,b._b,_l = b._l);
+ }
return *this;
}
inline void copyFrom(const void *b,unsigned int l)
- throw(std::out_of_range)
{
- if (l > C)
- throw std::out_of_range("Buffer: set from C array larger than capacity");
+ if (unlikely(l > C))
+ throw ZT_EXCEPTION_OUT_OF_BOUNDS;
+ ZT_FAST_MEMCPY(_b,b,l);
_l = l;
- memcpy(_b,b,l);
}
unsigned char operator[](const unsigned int i) const
- throw(std::out_of_range)
{
- if (i >= _l)
- throw std::out_of_range("Buffer: [] beyond end of data");
+ if (unlikely(i >= _l))
+ throw ZT_EXCEPTION_OUT_OF_BOUNDS;
return (unsigned char)_b[i];
}
unsigned char &operator[](const unsigned int i)
- throw(std::out_of_range)
{
- if (i >= _l)
- throw std::out_of_range("Buffer: [] beyond end of data");
+ if (unlikely(i >= _l))
+ throw ZT_EXCEPTION_OUT_OF_BOUNDS;
return ((unsigned char *)_b)[i];
}
@@ -168,17 +159,15 @@ public:
* @throws std::out_of_range Field extends beyond data size
*/
unsigned char *field(unsigned int i,unsigned int l)
- throw(std::out_of_range)
{
- if ((i + l) > _l)
- throw std::out_of_range("Buffer: field() beyond end of data");
+ if (unlikely((i + l) > _l))
+ throw ZT_EXCEPTION_OUT_OF_BOUNDS;
return (unsigned char *)(_b + i);
}
const unsigned char *field(unsigned int i,unsigned int l) const
- throw(std::out_of_range)
{
- if ((i + l) > _l)
- throw std::out_of_range("Buffer: field() beyond end of data");
+ if (unlikely((i + l) > _l))
+ throw ZT_EXCEPTION_OUT_OF_BOUNDS;
return (const unsigned char *)(_b + i);
}
@@ -191,10 +180,9 @@ public:
*/
template<typename T>
inline void setAt(unsigned int i,const T v)
- throw(std::out_of_range)
{
- if ((i + sizeof(T)) > _l)
- throw std::out_of_range("Buffer: setAt() beyond end of data");
+ if (unlikely((i + sizeof(T)) > _l))
+ throw ZT_EXCEPTION_OUT_OF_BOUNDS;
#ifdef ZT_NO_TYPE_PUNNING
uint8_t *p = reinterpret_cast<uint8_t *>(_b + i);
for(unsigned int x=1;x<=sizeof(T);++x)
@@ -214,10 +202,9 @@ public:
*/
template<typename T>
inline T at(unsigned int i) const
- throw(std::out_of_range)
{
- if ((i + sizeof(T)) > _l)
- throw std::out_of_range("Buffer: at() beyond end of data");
+ if (unlikely((i + sizeof(T)) > _l))
+ throw ZT_EXCEPTION_OUT_OF_BOUNDS;
#ifdef ZT_NO_TYPE_PUNNING
T v = 0;
const uint8_t *p = reinterpret_cast<const uint8_t *>(_b + i);
@@ -241,10 +228,9 @@ public:
*/
template<typename T>
inline void append(const T v)
- throw(std::out_of_range)
{
- if ((_l + sizeof(T)) > C)
- throw std::out_of_range("Buffer: append beyond capacity");
+ if (unlikely((_l + sizeof(T)) > C))
+ throw ZT_EXCEPTION_OUT_OF_BOUNDS;
#ifdef ZT_NO_TYPE_PUNNING
uint8_t *p = reinterpret_cast<uint8_t *>(_b + _l);
for(unsigned int x=1;x<=sizeof(T);++x)
@@ -264,40 +250,39 @@ public:
* @throws std::out_of_range Attempt to append beyond capacity
*/
inline void append(unsigned char c,unsigned int n)
- throw(std::out_of_range)
{
- if ((_l + n) > C)
- throw std::out_of_range("Buffer: append beyond capacity");
+ if (unlikely((_l + n) > C))
+ throw ZT_EXCEPTION_OUT_OF_BOUNDS;
for(unsigned int i=0;i<n;++i)
_b[_l++] = (char)c;
}
/**
- * Append a C-array of bytes
+ * Append secure random bytes
*
- * @param b Data
- * @param l Length
- * @throws std::out_of_range Attempt to append beyond capacity
+ * @param n Number of random bytes to append
*/
- inline void append(const void *b,unsigned int l)
- throw(std::out_of_range)
+ inline void appendRandom(unsigned int n)
{
- if ((_l + l) > C)
- throw std::out_of_range("Buffer: append beyond capacity");
- memcpy(_b + _l,b,l);
- _l += l;
+ if (unlikely((_l + n) > C))
+ throw ZT_EXCEPTION_OUT_OF_BOUNDS;
+ Utils::getSecureRandom(_b + _l,n);
+ _l += n;
}
/**
- * Append a string
+ * Append a C-array of bytes
*
- * @param s String to append
+ * @param b Data
+ * @param l Length
* @throws std::out_of_range Attempt to append beyond capacity
*/
- inline void append(const std::string &s)
- throw(std::out_of_range)
+ inline void append(const void *b,unsigned int l)
{
- append(s.data(),(unsigned int)s.length());
+ if (unlikely((_l + l) > C))
+ throw ZT_EXCEPTION_OUT_OF_BOUNDS;
+ ZT_FAST_MEMCPY(_b + _l,b,l);
+ _l += l;
}
/**
@@ -307,11 +292,10 @@ public:
* @throws std::out_of_range Attempt to append beyond capacity
*/
inline void appendCString(const char *s)
- throw(std::out_of_range)
{
for(;;) {
- if (_l >= C)
- throw std::out_of_range("Buffer: append beyond capacity");
+ if (unlikely(_l >= C))
+ throw ZT_EXCEPTION_OUT_OF_BOUNDS;
if (!(_b[_l++] = *(s++)))
break;
}
@@ -326,7 +310,6 @@ public:
*/
template<unsigned int C2>
inline void append(const Buffer<C2> &b)
- throw(std::out_of_range)
{
append(b._b,b._l);
}
@@ -342,10 +325,9 @@ public:
* @return Pointer to beginning of appended field of length 'l'
*/
inline char *appendField(unsigned int l)
- throw(std::out_of_range)
{
- if ((_l + l) > C)
- throw std::out_of_range("Buffer: append beyond capacity");
+ if (unlikely((_l + l) > C))
+ throw ZT_EXCEPTION_OUT_OF_BOUNDS;
char *r = _b + _l;
_l += l;
return r;
@@ -360,10 +342,9 @@ public:
* @throws std::out_of_range Capacity exceeded
*/
inline void addSize(unsigned int i)
- throw(std::out_of_range)
{
- if ((i + _l) > C)
- throw std::out_of_range("Buffer: setSize to larger than capacity");
+ if (unlikely((i + _l) > C))
+ throw ZT_EXCEPTION_OUT_OF_BOUNDS;
_l += i;
}
@@ -376,10 +357,9 @@ public:
* @throws std::out_of_range Size larger than capacity
*/
inline void setSize(const unsigned int i)
- throw(std::out_of_range)
{
- if (i > C)
- throw std::out_of_range("Buffer: setSize to larger than capacity");
+ if (unlikely(i > C))
+ throw ZT_EXCEPTION_OUT_OF_BOUNDS;
_l = i;
}
@@ -387,15 +367,14 @@ public:
* Move everything after 'at' to the buffer's front and truncate
*
* @param at Truncate before this position
- * @throw std::out_of_range Position is beyond size of buffer
+ * @throws std::out_of_range Position is beyond size of buffer
*/
inline void behead(const unsigned int at)
- throw(std::out_of_range)
{
if (!at)
return;
- if (at > _l)
- throw std::out_of_range("Buffer: behead() beyond capacity");
+ if (unlikely(at > _l))
+ throw ZT_EXCEPTION_OUT_OF_BOUNDS;
::memmove(_b,_b + at,_l -= at);
}
@@ -404,14 +383,13 @@ public:
*
* @param start Starting position
* @param length Length of block to erase
- * @throw std::out_of_range Position plus length is beyond size of buffer
+ * @throws std::out_of_range Position plus length is beyond size of buffer
*/
inline void erase(const unsigned int at,const unsigned int length)
- throw(std::out_of_range)
{
const unsigned int endr = at + length;
- if (endr > _l)
- throw std::out_of_range("Buffer: erase() range beyond end of buffer");
+ if (unlikely(endr > _l))
+ throw ZT_EXCEPTION_OUT_OF_BOUNDS;
::memmove(_b + at,_b + endr,_l - endr);
_l -= length;
}
@@ -419,94 +397,77 @@ public:
/**
* Set buffer data length to zero
*/
- inline void clear()
- throw()
- {
- _l = 0;
- }
+ inline void clear() { _l = 0; }
/**
* Zero buffer up to size()
*/
- inline void zero()
- throw()
- {
- memset(_b,0,_l);
- }
+ inline void zero() { memset(_b,0,_l); }
/**
* Zero unused capacity area
*/
- inline void zeroUnused()
- throw()
- {
- memset(_b + _l,0,C - _l);
- }
+ inline void zeroUnused() { memset(_b + _l,0,C - _l); }
/**
* Unconditionally and securely zero buffer's underlying memory
*/
- inline void burn()
- throw()
- {
- Utils::burn(_b,sizeof(_b));
- }
+ inline void burn() { Utils::burn(_b,sizeof(_b)); }
/**
* @return Constant pointer to data in buffer
*/
- inline const void *data() const throw() { return _b; }
+ inline const void *data() const { return _b; }
+
+ /**
+ * @return Non-constant pointer to data in buffer
+ */
+ inline void *unsafeData() { return _b; }
/**
* @return Size of data in buffer
*/
- inline unsigned int size() const throw() { return _l; }
+ inline unsigned int size() const { return _l; }
/**
* @return Capacity of buffer
*/
- inline unsigned int capacity() const throw() { return C; }
+ inline unsigned int capacity() const { return C; }
template<unsigned int C2>
inline bool operator==(const Buffer<C2> &b) const
- throw()
{
return ((_l == b._l)&&(!memcmp(_b,b._b,_l)));
}
template<unsigned int C2>
inline bool operator!=(const Buffer<C2> &b) const
- throw()
{
return ((_l != b._l)||(memcmp(_b,b._b,_l)));
}
template<unsigned int C2>
inline bool operator<(const Buffer<C2> &b) const
- throw()
{
return (memcmp(_b,b._b,std::min(_l,b._l)) < 0);
}
template<unsigned int C2>
inline bool operator>(const Buffer<C2> &b) const
- throw()
{
return (b < *this);
}
template<unsigned int C2>
inline bool operator<=(const Buffer<C2> &b) const
- throw()
{
return !(b < *this);
}
template<unsigned int C2>
inline bool operator>=(const Buffer<C2> &b) const
- throw()
{
return !(*this < b);
}
private:
- unsigned int _l;
char ZT_VAR_MAY_ALIAS _b[C];
+ unsigned int _l;
};
} // namespace ZeroTier