summaryrefslogtreecommitdiff
path: root/node/Dictionary.hpp
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2016-06-16 12:28:43 -0700
committerAdam Ierymenko <adam.ierymenko@gmail.com>2016-06-16 12:28:43 -0700
commite09c1a1c11522c11c6ea81dcb1c52a4e8a2f5c6c (patch)
treeba6d0381aa472ec1811bd9f16627e10f48f2d203 /node/Dictionary.hpp
parentb104bb4762a07dcb0a950b33c7419b298c2b6267 (diff)
downloadinfinitytier-e09c1a1c11522c11c6ea81dcb1c52a4e8a2f5c6c.tar.gz
infinitytier-e09c1a1c11522c11c6ea81dcb1c52a4e8a2f5c6c.zip
Big refactor mostly builds. We now have a uniform backward compatible netconf.
Diffstat (limited to 'node/Dictionary.hpp')
-rw-r--r--node/Dictionary.hpp120
1 files changed, 90 insertions, 30 deletions
diff --git a/node/Dictionary.hpp b/node/Dictionary.hpp
index 66072952..ccca00c8 100644
--- a/node/Dictionary.hpp
+++ b/node/Dictionary.hpp
@@ -21,11 +21,12 @@
#include "Constants.hpp"
#include "Utils.hpp"
+#include "Buffer.hpp"
+#include "Address.hpp"
#include <stdint.h>
-#include <string>
-
+// Can be increased if it's ever needed, but not too much.
#define ZT_DICTIONARY_MAX_SIZE 16384
namespace ZeroTier {
@@ -45,7 +46,8 @@ namespace ZeroTier {
* Keys cannot contain binary data, CR/LF, nulls, or the equals (=) sign.
* Adding such a key will result in an invalid entry (but isn't dangerous).
*
- * There is code to test and fuzz this in selftest.cpp.
+ * There is code to test and fuzz this in selftest.cpp. Fuzzing a blob of
+ * pointer tricks like this is important after any modifications.
*/
class Dictionary
{
@@ -60,9 +62,32 @@ public:
Utils::scopy(_d,sizeof(_d),s);
}
- inline void load(const char *s)
+ Dictionary(const char *s,unsigned int len)
{
- Utils::scopy(_d,sizeof(_d),s);
+ memcpy(_d,s,(len > ZT_DICTIONARY_MAX_SIZE) ? (unsigned int)ZT_DICTIONARY_MAX_SIZE : len);
+ _d[ZT_DICTIONARY_MAX_SIZE-1] = (char)0;
+ }
+
+ Dictionary(const Dictionary &d)
+ {
+ Utils::scopy(_d,sizeof(_d),d._d);
+ }
+
+ inline Dictionary &operator=(const Dictionary &d)
+ {
+ Utils::scopy(_d,sizeof(_d),d._d);
+ return *this;
+ }
+
+ /**
+ * Load a dictionary from a C-string
+ *
+ * @param s Dictionary in string form
+ * @return False if 's' was longer than ZT_DICTIONARY_MAX_SIZE
+ */
+ inline bool load(const char *s)
+ {
+ return Utils::scopy(_d,sizeof(_d),s);
}
/**
@@ -103,9 +128,7 @@ public:
inline int get(const char *key,char *dest,unsigned int destlen) const
{
const char *p = _d;
- const char *const eof = p + ZT_DICTIONARY_MAX_SIZE;
const char *k,*s;
- unsigned int dptr = 0;
bool esc;
int j;
@@ -185,34 +208,48 @@ public:
}
/**
+ * Get the contents of a key into a buffer
+ *
+ * @param key Key to get
+ * @param dest Destination buffer
+ * @return True if key was found (if false, dest will be empty)
+ */
+ template<unsigned int C>
+ inline bool get(const char *key,Buffer<C> &dest) const
+ {
+ const int r = this->get(key,const_cast<char *>(reinterpret_cast<const char *>(dest.data())),C);
+ if (r >= 0) {
+ dest.setSize((unsigned int)r);
+ return true;
+ } else {
+ dest.clear();
+ return false;
+ }
+ }
+
+ /**
+ * Get a boolean value
+ *
* @param key Key to look up
- * @param dfl Default value if not found in dictionary (a key with an empty value is considered not found)
+ * @param dfl Default value if not found in dictionary
* @return Boolean value of key or 'dfl' if not found
*/
- bool getBoolean(const char *key,bool dfl = false) const
+ bool getB(const char *key,bool dfl = false) const
{
- char tmp[128];
- if (this->get(key,tmp,sizeof(tmp)) >= 1) {
- switch(tmp[0]) {
- case '1':
- case 't':
- case 'T':
- case 'y':
- case 'Y':
- return true;
- default:
- return false;
- }
- }
+ char tmp[4];
+ if (this->get(key,tmp,sizeof(tmp)) >= 0)
+ return ((*tmp == '1')||(*tmp == 't')||(*tmp == 'T'));
return dfl;
}
/**
+ * Get an unsigned int64 stored as hex in the dictionary
+ *
* @param key Key to look up
* @param dfl Default value or 0 if unspecified
* @return Decoded hex UInt value or 'dfl' if not found
*/
- inline uint64_t getHexUInt(const char *key,uint64_t dfl = 0) const
+ inline uint64_t getUI(const char *key,uint64_t dfl = 0) const
{
char tmp[128];
if (this->get(key,tmp,sizeof(tmp)) >= 1)
@@ -227,6 +264,8 @@ public:
* will always be returned by get(). There is no erase(). This is designed
* to be generated and shipped, not as an editable data structure.
*
+ * Use the vlen parameter to add binary values. Nulls will be escaped.
+ *
* @param key Key -- nulls, CR/LF, and equals (=) are illegal characters
* @param value Value to set
* @param vlen Length of value in bytes or -1 to treat value[] as a C-string and look for terminating 0
@@ -249,20 +288,22 @@ public:
int k = 0;
while ((*p)&&((vlen < 0)||(k < vlen))) {
switch(*p) {
+ case 0:
case '\r':
case '\n':
- case '\0':
case '\t':
+ case '\\':
_d[j++] = '\\';
if (j == ZT_DICTIONARY_MAX_SIZE) {
_d[i] = (char)0;
return false;
}
switch(*p) {
+ case 0: _d[j++] = '0'; break;
case '\r': _d[j++] = 'r'; break;
case '\n': _d[j++] = 'n'; break;
- case '\0': _d[j++] = '0'; break;
case '\t': _d[j++] = 't'; break;
+ case '\\': _d[j++] = '\\'; break;
}
if (j == ZT_DICTIONARY_MAX_SIZE) {
_d[i] = (char)0;
@@ -290,19 +331,38 @@ public:
/**
* Add a boolean as a '1' or a '0'
*/
- inline void add(const char *key,bool value)
+ inline bool add(const char *key,bool value)
{
- this->add(key,(value) ? "1" : "0",1);
+ return this->add(key,(value) ? "1" : "0",1);
}
/**
* Add a 64-bit integer (unsigned) as a hex value
*/
- inline void add(const char *key,uint64_t value)
+ inline bool add(const char *key,uint64_t value)
{
- char tmp[128];
+ char tmp[32];
Utils::snprintf(tmp,sizeof(tmp),"%llx",(unsigned long long)value);
- this->add(key,tmp,-1);
+ return this->add(key,tmp,-1);
+ }
+
+ /**
+ * Add a 64-bit integer (unsigned) as a hex value
+ */
+ inline bool add(const char *key,const Address &a)
+ {
+ char tmp[32];
+ Utils::snprintf(tmp,sizeof(tmp),"%.10llx",(unsigned long long)a.toInt());
+ return this->add(key,tmp,-1);
+ }
+
+ /**
+ * Add a binary buffer
+ */
+ template<unsigned int C>
+ inline bool add(const char *key,const Buffer<C> &value)
+ {
+ return this->add(key,(const char *)value.data(),(int)value.size());
}
/**