From 0defce43c97145172f10a5c114281e704820f95c Mon Sep 17 00:00:00 2001
From: wangzhengquan <wangzhengquan85@126.com>
Date: 星期六, 13 六月 2020 13:53:38 +0800
Subject: [PATCH] update

---
 include/nng/protocol/pair0/pair.h         |   34 
 include/jsoncpp/json/autolink.h           |   25 
 include/nng/protocol/reqrep0/req.h        |   39 
 include/nng/compat/nanomsg/survey.h       |   36 
 include/nng/compat/nanomsg/pair.h         |   39 
 include/nng/protocol/pair1/pair.h         |   40 
 include/nng/supplemental/tls/tls.h        |  142 +
 include/nng/protocol/pipeline0/pull.h     |   33 
 include/nng/protocol/pipeline0/push.h     |   33 
 include/nng/supplemental/tls/engine.h     |  207 ++
 service/test_queue                        |    0 
 include/nng/transport/ipc/ipc.h           |   29 
 include/nng/protocol/bus0/bus.h           |   34 
 include/nng/compat/nanomsg/pubsub.h       |   36 
 include/jsoncpp/json/reader.h             |  404 ++++
 include/nng/supplemental/util/options.h   |   48 
 include/jsoncpp/json/features.h           |   57 
 include/jsoncpp/json/forwards.h           |   37 
 lib/nng/libnng.a                          |    0 
 include/jsoncpp/json/assertions.h         |   54 
 include/nng/transport/ws/websocket.h      |   34 
 include/jsoncpp/json/value.h              |  865 +++++++++
 include/nng/protocol/pubsub0/pub.h        |   33 
 lib/jsoncpp/libjsoncpp.a                  |    0 
 include/nng/compat/nanomsg/nn.h           |  284 ++
 service/Makefile                          |   16 
 include/nng/transport/tcp/tcp.h           |   28 
 lib/jsoncpp/libjsoncpp.so                 |    1 
 include/nng/protocol/reqrep0/rep.h        |   38 
 service/netdisk_service                   |    0 
 include/nng/protocol/pubsub0/sub.h        |   39 
 include/nng/transport/zerotier/zerotier.h |  159 +
 include/nng/compat/nanomsg/tcp.h          |   33 
 include/nng/protocol/survey0/respond.h    |   38 
 include/jsoncpp/json/allocator.h          |   94 
 service/test_client                       |    0 
 include/nng/nng.h                         | 1266 +++++++++++++
 lib/jsoncpp/libjsoncpp.so.1               |    0 
 include/nng/compat/nanomsg/ws.h           |   41 
 include/nng/protocol/survey0/survey.h     |   40 
 include/nng/compat/nanomsg/reqrep.h       |   35 
 include/nng/transport/inproc/inproc.h     |   28 
 include/jsoncpp/json/json.h               |   15 
 include/nng/compat/nanomsg/bus.h          |   33 
 include/nng/compat/nanomsg/pipeline.h     |   34 
 service/test_properties                   |    0 
 include/nng/compat/nanomsg/inproc.h       |   31 
 include/nng/compat/nanomsg/ipc.h          |   39 
 include/nng/transport/tls/tls.h           |   28 
 include/jsoncpp/json/config.h             |  173 +
 include/jsoncpp/json/version.h            |   20 
 include/nng/supplemental/http/http.h      |  539 +++++
 include/nng/supplemental/util/platform.h  |  106 +
 include/jsoncpp/json/writer.h             |  331 +++
 service/test                              |    0 
 55 files changed, 5,743 insertions(+), 5 deletions(-)

diff --git a/include/jsoncpp/json/allocator.h b/include/jsoncpp/json/allocator.h
new file mode 100644
index 0000000..9d8b9fc
--- /dev/null
+++ b/include/jsoncpp/json/allocator.h
@@ -0,0 +1,94 @@
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef CPPTL_JSON_ALLOCATOR_H_INCLUDED
+#define CPPTL_JSON_ALLOCATOR_H_INCLUDED
+
+#include <cstring>
+#include <memory>
+
+namespace Json {
+template<typename T>
+class SecureAllocator {
+	public:
+		// Type definitions
+		using value_type      = T;
+		using pointer         = T*;
+		using const_pointer   = const T*;
+		using reference       = T&;
+		using const_reference = const T&;
+		using size_type       = std::size_t;
+		using difference_type = std::ptrdiff_t;
+
+		/**
+		 * Allocate memory for N items using the standard allocator.
+		 */
+		pointer allocate(size_type n) {
+			// allocate using "global operator new"
+			return static_cast<pointer>(::operator new(n * sizeof(T)));
+		}
+
+		/**
+		 * Release memory which was allocated for N items at pointer P.
+		 *
+		 * The memory block is filled with zeroes before being released.
+		 * The pointer argument is tagged as "volatile" to prevent the
+		 * compiler optimizing out this critical step.
+		 */
+		void deallocate(volatile pointer p, size_type n) {
+			std::memset(p, 0, n * sizeof(T));
+			// free using "global operator delete"
+			::operator delete(p);
+		}
+
+		/**
+		 * Construct an item in-place at pointer P.
+		 */
+		template<typename... Args>
+		void construct(pointer p, Args&&... args) {
+			// construct using "placement new" and "perfect forwarding"
+			::new (static_cast<void*>(p)) T(std::forward<Args>(args)...);
+		}
+
+		size_type max_size() const {
+			return size_t(-1) / sizeof(T);
+		}
+
+		pointer address( reference x ) const {
+			return std::addressof(x);
+		}
+
+		const_pointer address( const_reference x ) const {
+			return std::addressof(x);
+		}
+
+		/**
+		 * Destroy an item in-place at pointer P.
+		 */
+		void destroy(pointer p) {
+			// destroy using "explicit destructor"
+			p->~T();
+		}
+
+		// Boilerplate
+		SecureAllocator() {}
+		template<typename U> SecureAllocator(const SecureAllocator<U>&) {}
+		template<typename U> struct rebind { using other = SecureAllocator<U>; };
+};
+
+
+template<typename T, typename U>
+bool operator==(const SecureAllocator<T>&, const SecureAllocator<U>&) {
+	return true;
+}
+
+template<typename T, typename U>
+bool operator!=(const SecureAllocator<T>&, const SecureAllocator<U>&) {
+	return false;
+}
+
+} //namespace Json
+
+#endif // CPPTL_JSON_ALLOCATOR_H_INCLUDED
diff --git a/include/jsoncpp/json/assertions.h b/include/jsoncpp/json/assertions.h
new file mode 100644
index 0000000..9c5f8bc
--- /dev/null
+++ b/include/jsoncpp/json/assertions.h
@@ -0,0 +1,54 @@
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED
+#define CPPTL_JSON_ASSERTIONS_H_INCLUDED
+
+#include <stdlib.h>
+#include <sstream>
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "config.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+/** It should not be possible for a maliciously designed file to
+ *  cause an abort() or seg-fault, so these macros are used only
+ *  for pre-condition violations and internal logic errors.
+ */
+#if JSON_USE_EXCEPTION
+
+// @todo <= add detail about condition in exception
+# define JSON_ASSERT(condition)                                                \
+  {if (!(condition)) {Json::throwLogicError( "assert json failed" );}}
+
+# define JSON_FAIL_MESSAGE(message)                                            \
+  {                                                                            \
+    JSONCPP_OSTRINGSTREAM oss; oss << message;                                    \
+    Json::throwLogicError(oss.str());                                          \
+    abort();                                                                   \
+  }
+
+#else // JSON_USE_EXCEPTION
+
+# define JSON_ASSERT(condition) assert(condition)
+
+// The call to assert() will show the failure message in debug builds. In
+// release builds we abort, for a core-dump or debugger.
+# define JSON_FAIL_MESSAGE(message)                                            \
+  {                                                                            \
+    JSONCPP_OSTRINGSTREAM oss; oss << message;                                    \
+    assert(false && oss.str().c_str());                                        \
+    abort();                                                                   \
+  }
+
+
+#endif
+
+#define JSON_ASSERT_MESSAGE(condition, message)                                \
+  if (!(condition)) {                                                          \
+    JSON_FAIL_MESSAGE(message);                                                \
+  }
+
+#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED
diff --git a/include/jsoncpp/json/autolink.h b/include/jsoncpp/json/autolink.h
new file mode 100644
index 0000000..6fcc8af
--- /dev/null
+++ b/include/jsoncpp/json/autolink.h
@@ -0,0 +1,25 @@
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_AUTOLINK_H_INCLUDED
+#define JSON_AUTOLINK_H_INCLUDED
+
+#include "config.h"
+
+#ifdef JSON_IN_CPPTL
+#include <cpptl/cpptl_autolink.h>
+#endif
+
+#if !defined(JSON_NO_AUTOLINK) && !defined(JSON_DLL_BUILD) &&                  \
+    !defined(JSON_IN_CPPTL)
+#define CPPTL_AUTOLINK_NAME "json"
+#undef CPPTL_AUTOLINK_DLL
+#ifdef JSON_DLL
+#define CPPTL_AUTOLINK_DLL
+#endif
+#include "autolink.h"
+#endif
+
+#endif // JSON_AUTOLINK_H_INCLUDED
diff --git a/include/jsoncpp/json/config.h b/include/jsoncpp/json/config.h
new file mode 100644
index 0000000..fc841b4
--- /dev/null
+++ b/include/jsoncpp/json/config.h
@@ -0,0 +1,173 @@
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_CONFIG_H_INCLUDED
+#define JSON_CONFIG_H_INCLUDED
+#include <stddef.h>
+#include <string> //typdef String
+
+/// If defined, indicates that json library is embedded in CppTL library.
+//# define JSON_IN_CPPTL 1
+
+/// If defined, indicates that json may leverage CppTL library
+//#  define JSON_USE_CPPTL 1
+/// If defined, indicates that cpptl vector based map should be used instead of
+/// std::map
+/// as Value container.
+//#  define JSON_USE_CPPTL_SMALLMAP 1
+
+// If non-zero, the library uses exceptions to report bad input instead of C
+// assertion macros. The default is to use exceptions.
+#ifndef JSON_USE_EXCEPTION
+#define JSON_USE_EXCEPTION 1
+#endif
+
+/// If defined, indicates that the source file is amalgated
+/// to prevent private header inclusion.
+/// Remarks: it is automatically defined in the generated amalgated header.
+// #define JSON_IS_AMALGAMATION
+
+#ifdef JSON_IN_CPPTL
+#include <cpptl/config.h>
+#ifndef JSON_USE_CPPTL
+#define JSON_USE_CPPTL 1
+#endif
+#endif
+
+#ifdef JSON_IN_CPPTL
+#define JSON_API CPPTL_API
+#elif defined(JSON_DLL_BUILD)
+#if defined(_MSC_VER) || defined(__MINGW32__)
+#define JSON_API __declspec(dllexport)
+#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
+#endif // if defined(_MSC_VER)
+#elif defined(JSON_DLL)
+#if defined(_MSC_VER) || defined(__MINGW32__)
+#define JSON_API __declspec(dllimport)
+#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
+#endif // if defined(_MSC_VER)
+#endif // ifdef JSON_IN_CPPTL
+#if !defined(JSON_API)
+#define JSON_API
+#endif
+
+// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for
+// integer
+// Storages, and 64 bits integer support is disabled.
+// #define JSON_NO_INT64 1
+
+#if defined(_MSC_VER) // MSVC
+#  if _MSC_VER <= 1200 // MSVC 6
+    // Microsoft Visual Studio 6 only support conversion from __int64 to double
+    // (no conversion from unsigned __int64).
+#    define JSON_USE_INT64_DOUBLE_CONVERSION 1
+    // Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255'
+    // characters in the debug information)
+    // All projects I've ever seen with VS6 were using this globally (not bothering
+    // with pragma push/pop).
+#    pragma warning(disable : 4786)
+#  endif // MSVC 6
+
+#  if _MSC_VER >= 1500 // MSVC 2008
+    /// Indicates that the following function is deprecated.
+#    define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
+#  endif
+
+#endif // defined(_MSC_VER)
+
+#if defined(_MSC_VER) && _MSC_VER <= 1600 // MSVC <= 2010
+# define JSONCPP_OVERRIDE
+#else
+# define JSONCPP_OVERRIDE override
+#endif // MSVC <= 2010
+
+
+#ifndef JSON_HAS_RVALUE_REFERENCES
+
+#if defined(_MSC_VER) && _MSC_VER >= 1600 // MSVC >= 2010
+#define JSON_HAS_RVALUE_REFERENCES 1
+#endif // MSVC >= 2010
+
+#ifdef __clang__
+#if __has_feature(cxx_rvalue_references)
+#define JSON_HAS_RVALUE_REFERENCES 1
+#endif  // has_feature
+
+#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
+#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
+#define JSON_HAS_RVALUE_REFERENCES 1
+#endif  // GXX_EXPERIMENTAL
+
+#endif // __clang__ || __GNUC__
+
+#endif // not defined JSON_HAS_RVALUE_REFERENCES
+
+#ifndef JSON_HAS_RVALUE_REFERENCES
+#define JSON_HAS_RVALUE_REFERENCES 0
+#endif
+
+#ifdef __clang__
+#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
+#  if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
+#    define JSONCPP_DEPRECATED(message)  __attribute__ ((deprecated(message)))
+#  elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+#    define JSONCPP_DEPRECATED(message)  __attribute__((__deprecated__))
+#  endif  // GNUC version
+#endif // __clang__ || __GNUC__
+
+#if !defined(JSONCPP_DEPRECATED)
+#define JSONCPP_DEPRECATED(message)
+#endif // if !defined(JSONCPP_DEPRECATED)
+
+#if __GNUC__ >= 6
+#  define JSON_USE_INT64_DOUBLE_CONVERSION 1
+#endif
+
+#if !defined(JSON_IS_AMALGAMATION)
+
+# include "version.h"
+
+# if JSONCPP_USING_SECURE_MEMORY
+#  include "allocator.h" //typedef Allocator
+# endif
+
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+namespace Json {
+typedef int Int;
+typedef unsigned int UInt;
+#if defined(JSON_NO_INT64)
+typedef int LargestInt;
+typedef unsigned int LargestUInt;
+#undef JSON_HAS_INT64
+#else                 // if defined(JSON_NO_INT64)
+// For Microsoft Visual use specific types as long long is not supported
+#if defined(_MSC_VER) // Microsoft Visual Studio
+typedef __int64 Int64;
+typedef unsigned __int64 UInt64;
+#else                 // if defined(_MSC_VER) // Other platforms, use long long
+typedef long long int Int64;
+typedef unsigned long long int UInt64;
+#endif // if defined(_MSC_VER)
+typedef Int64 LargestInt;
+typedef UInt64 LargestUInt;
+#define JSON_HAS_INT64
+#endif // if defined(JSON_NO_INT64)
+#if JSONCPP_USING_SECURE_MEMORY
+#define JSONCPP_STRING        std::basic_string<char, std::char_traits<char>, Json::SecureAllocator<char> >
+#define JSONCPP_OSTRINGSTREAM std::basic_ostringstream<char, std::char_traits<char>, Json::SecureAllocator<char> >
+#define JSONCPP_OSTREAM       std::basic_ostream<char, std::char_traits<char>>
+#define JSONCPP_ISTRINGSTREAM std::basic_istringstream<char, std::char_traits<char>, Json::SecureAllocator<char> >
+#define JSONCPP_ISTREAM       std::istream
+#else
+#define JSONCPP_STRING        std::string
+#define JSONCPP_OSTRINGSTREAM std::ostringstream
+#define JSONCPP_OSTREAM       std::ostream
+#define JSONCPP_ISTRINGSTREAM std::istringstream
+#define JSONCPP_ISTREAM       std::istream
+#endif // if JSONCPP_USING_SECURE_MEMORY
+} // end namespace Json
+
+#endif // JSON_CONFIG_H_INCLUDED
diff --git a/include/jsoncpp/json/features.h b/include/jsoncpp/json/features.h
new file mode 100644
index 0000000..1bb7bb6
--- /dev/null
+++ b/include/jsoncpp/json/features.h
@@ -0,0 +1,57 @@
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef CPPTL_JSON_FEATURES_H_INCLUDED
+#define CPPTL_JSON_FEATURES_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "forwards.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+namespace Json {
+
+/** \brief Configuration passed to reader and writer.
+ * This configuration object can be used to force the Reader or Writer
+ * to behave in a standard conforming way.
+ */
+class JSON_API Features {
+public:
+  /** \brief A configuration that allows all features and assumes all strings
+   * are UTF-8.
+   * - C & C++ comments are allowed
+   * - Root object can be any JSON value
+   * - Assumes Value strings are encoded in UTF-8
+   */
+  static Features all();
+
+  /** \brief A configuration that is strictly compatible with the JSON
+   * specification.
+   * - Comments are forbidden.
+   * - Root object must be either an array or an object value.
+   * - Assumes Value strings are encoded in UTF-8
+   */
+  static Features strictMode();
+
+  /** \brief Initialize the configuration like JsonConfig::allFeatures;
+   */
+  Features();
+
+  /// \c true if comments are allowed. Default: \c true.
+  bool allowComments_;
+
+  /// \c true if root must be either an array or an object value. Default: \c
+  /// false.
+  bool strictRoot_;
+
+  /// \c true if dropped null placeholders are allowed. Default: \c false.
+  bool allowDroppedNullPlaceholders_;
+
+  /// \c true if numeric object key are allowed. Default: \c false.
+  bool allowNumericKeys_;
+};
+
+} // namespace Json
+
+#endif // CPPTL_JSON_FEATURES_H_INCLUDED
diff --git a/include/jsoncpp/json/forwards.h b/include/jsoncpp/json/forwards.h
new file mode 100644
index 0000000..ccfe09a
--- /dev/null
+++ b/include/jsoncpp/json/forwards.h
@@ -0,0 +1,37 @@
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_FORWARDS_H_INCLUDED
+#define JSON_FORWARDS_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "config.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+namespace Json {
+
+// writer.h
+class FastWriter;
+class StyledWriter;
+
+// reader.h
+class Reader;
+
+// features.h
+class Features;
+
+// value.h
+typedef unsigned int ArrayIndex;
+class StaticString;
+class Path;
+class PathArgument;
+class Value;
+class ValueIteratorBase;
+class ValueIterator;
+class ValueConstIterator;
+
+} // namespace Json
+
+#endif // JSON_FORWARDS_H_INCLUDED
diff --git a/include/jsoncpp/json/json.h b/include/jsoncpp/json/json.h
new file mode 100644
index 0000000..8f10ac2
--- /dev/null
+++ b/include/jsoncpp/json/json.h
@@ -0,0 +1,15 @@
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_JSON_H_INCLUDED
+#define JSON_JSON_H_INCLUDED
+
+#include "autolink.h"
+#include "value.h"
+#include "reader.h"
+#include "writer.h"
+#include "features.h"
+
+#endif // JSON_JSON_H_INCLUDED
diff --git a/include/jsoncpp/json/reader.h b/include/jsoncpp/json/reader.h
new file mode 100644
index 0000000..caf8727
--- /dev/null
+++ b/include/jsoncpp/json/reader.h
@@ -0,0 +1,404 @@
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef CPPTL_JSON_READER_H_INCLUDED
+#define CPPTL_JSON_READER_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "features.h"
+#include "value.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <deque>
+#include <iosfwd>
+#include <stack>
+#include <string>
+#include <istream>
+
+// Disable warning C4251: <data member>: <type> needs to have dll-interface to
+// be used by...
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(push)
+#pragma warning(disable : 4251)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+namespace Json {
+
+/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a
+ *Value.
+ *
+ * \deprecated Use CharReader and CharReaderBuilder.
+ */
+class JSON_API Reader {
+public:
+  typedef char Char;
+  typedef const Char* Location;
+
+  /** \brief An error tagged with where in the JSON text it was encountered.
+   *
+   * The offsets give the [start, limit) range of bytes within the text. Note
+   * that this is bytes, not codepoints.
+   *
+   */
+  struct StructuredError {
+    ptrdiff_t offset_start;
+    ptrdiff_t offset_limit;
+    JSONCPP_STRING message;
+  };
+
+  /** \brief Constructs a Reader allowing all features
+   * for parsing.
+   */
+  Reader();
+
+  /** \brief Constructs a Reader allowing the specified feature set
+   * for parsing.
+   */
+  Reader(const Features& features);
+
+  /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
+   * document.
+   * \param document UTF-8 encoded string containing the document to read.
+   * \param root [out] Contains the root value of the document if it was
+   *             successfully parsed.
+   * \param collectComments \c true to collect comment and allow writing them
+   * back during
+   *                        serialization, \c false to discard comments.
+   *                        This parameter is ignored if
+   * Features::allowComments_
+   *                        is \c false.
+   * \return \c true if the document was successfully parsed, \c false if an
+   * error occurred.
+   */
+  bool
+  parse(const std::string& document, Value& root, bool collectComments = true);
+
+  /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
+   document.
+   * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the
+   document to read.
+   * \param endDoc Pointer on the end of the UTF-8 encoded string of the
+   document to read.
+   *               Must be >= beginDoc.
+   * \param root [out] Contains the root value of the document if it was
+   *             successfully parsed.
+   * \param collectComments \c true to collect comment and allow writing them
+   back during
+   *                        serialization, \c false to discard comments.
+   *                        This parameter is ignored if
+   Features::allowComments_
+   *                        is \c false.
+   * \return \c true if the document was successfully parsed, \c false if an
+   error occurred.
+   */
+  bool parse(const char* beginDoc,
+             const char* endDoc,
+             Value& root,
+             bool collectComments = true);
+
+  /// \brief Parse from input stream.
+  /// \see Json::operator>>(std::istream&, Json::Value&).
+  bool parse(JSONCPP_ISTREAM& is, Value& root, bool collectComments = true);
+
+  /** \brief Returns a user friendly string that list errors in the parsed
+   * document.
+   * \return Formatted error message with the list of errors with their location
+   * in
+   *         the parsed document. An empty string is returned if no error
+   * occurred
+   *         during parsing.
+   * \deprecated Use getFormattedErrorMessages() instead (typo fix).
+   */
+  JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.")
+  JSONCPP_STRING getFormatedErrorMessages() const;
+
+  /** \brief Returns a user friendly string that list errors in the parsed
+   * document.
+   * \return Formatted error message with the list of errors with their location
+   * in
+   *         the parsed document. An empty string is returned if no error
+   * occurred
+   *         during parsing.
+   */
+  JSONCPP_STRING getFormattedErrorMessages() const;
+
+  /** \brief Returns a vector of structured erros encounted while parsing.
+   * \return A (possibly empty) vector of StructuredError objects. Currently
+   *         only one error can be returned, but the caller should tolerate
+   * multiple
+   *         errors.  This can occur if the parser recovers from a non-fatal
+   *         parse error and then encounters additional errors.
+   */
+  std::vector<StructuredError> getStructuredErrors() const;
+
+  /** \brief Add a semantic error message.
+   * \param value JSON Value location associated with the error
+   * \param message The error message.
+   * \return \c true if the error was successfully added, \c false if the
+   * Value offset exceeds the document size.
+   */
+  bool pushError(const Value& value, const JSONCPP_STRING& message);
+
+  /** \brief Add a semantic error message with extra context.
+   * \param value JSON Value location associated with the error
+   * \param message The error message.
+   * \param extra Additional JSON Value location to contextualize the error
+   * \return \c true if the error was successfully added, \c false if either
+   * Value offset exceeds the document size.
+   */
+  bool pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra);
+
+  /** \brief Return whether there are any errors.
+   * \return \c true if there are no errors to report \c false if
+   * errors have occurred.
+   */
+  bool good() const;
+
+private:
+  enum TokenType {
+    tokenEndOfStream = 0,
+    tokenObjectBegin,
+    tokenObjectEnd,
+    tokenArrayBegin,
+    tokenArrayEnd,
+    tokenString,
+    tokenNumber,
+    tokenTrue,
+    tokenFalse,
+    tokenNull,
+    tokenArraySeparator,
+    tokenMemberSeparator,
+    tokenComment,
+    tokenError
+  };
+
+  class Token {
+  public:
+    TokenType type_;
+    Location start_;
+    Location end_;
+  };
+
+  class ErrorInfo {
+  public:
+    Token token_;
+    JSONCPP_STRING message_;
+    Location extra_;
+  };
+
+  typedef std::deque<ErrorInfo> Errors;
+
+  bool readToken(Token& token);
+  void skipSpaces();
+  bool match(Location pattern, int patternLength);
+  bool readComment();
+  bool readCStyleComment();
+  bool readCppStyleComment();
+  bool readString();
+  void readNumber();
+  bool readValue();
+  bool readObject(Token& token);
+  bool readArray(Token& token);
+  bool decodeNumber(Token& token);
+  bool decodeNumber(Token& token, Value& decoded);
+  bool decodeString(Token& token);
+  bool decodeString(Token& token, JSONCPP_STRING& decoded);
+  bool decodeDouble(Token& token);
+  bool decodeDouble(Token& token, Value& decoded);
+  bool decodeUnicodeCodePoint(Token& token,
+                              Location& current,
+                              Location end,
+                              unsigned int& unicode);
+  bool decodeUnicodeEscapeSequence(Token& token,
+                                   Location& current,
+                                   Location end,
+                                   unsigned int& unicode);
+  bool addError(const JSONCPP_STRING& message, Token& token, Location extra = 0);
+  bool recoverFromError(TokenType skipUntilToken);
+  bool addErrorAndRecover(const JSONCPP_STRING& message,
+                          Token& token,
+                          TokenType skipUntilToken);
+  void skipUntilSpace();
+  Value& currentValue();
+  Char getNextChar();
+  void
+  getLocationLineAndColumn(Location location, int& line, int& column) const;
+  JSONCPP_STRING getLocationLineAndColumn(Location location) const;
+  void addComment(Location begin, Location end, CommentPlacement placement);
+  void skipCommentTokens(Token& token);
+
+  typedef std::stack<Value*> Nodes;
+  Nodes nodes_;
+  Errors errors_;
+  JSONCPP_STRING document_;
+  Location begin_;
+  Location end_;
+  Location current_;
+  Location lastValueEnd_;
+  Value* lastValue_;
+  JSONCPP_STRING commentsBefore_;
+  Features features_;
+  bool collectComments_;
+};  // Reader
+
+/** Interface for reading JSON from a char array.
+ */
+class JSON_API CharReader {
+public:
+  virtual ~CharReader() {}
+  /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
+   document.
+   * The document must be a UTF-8 encoded string containing the document to read.
+   *
+   * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the
+   document to read.
+   * \param endDoc Pointer on the end of the UTF-8 encoded string of the
+   document to read.
+   *        Must be >= beginDoc.
+   * \param root [out] Contains the root value of the document if it was
+   *             successfully parsed.
+   * \param errs [out] Formatted error messages (if not NULL)
+   *        a user friendly string that lists errors in the parsed
+   * document.
+   * \return \c true if the document was successfully parsed, \c false if an
+   error occurred.
+   */
+  virtual bool parse(
+      char const* beginDoc, char const* endDoc,
+      Value* root, JSONCPP_STRING* errs) = 0;
+
+  class JSON_API Factory {
+  public:
+    virtual ~Factory() {}
+    /** \brief Allocate a CharReader via operator new().
+     * \throw std::exception if something goes wrong (e.g. invalid settings)
+     */
+    virtual CharReader* newCharReader() const = 0;
+  };  // Factory
+};  // CharReader
+
+/** \brief Build a CharReader implementation.
+
+Usage:
+\code
+  using namespace Json;
+  CharReaderBuilder builder;
+  builder["collectComments"] = false;
+  Value value;
+  JSONCPP_STRING errs;
+  bool ok = parseFromStream(builder, std::cin, &value, &errs);
+\endcode
+*/
+class JSON_API CharReaderBuilder : public CharReader::Factory {
+public:
+  // Note: We use a Json::Value so that we can add data-members to this class
+  // without a major version bump.
+  /** Configuration of this builder.
+    These are case-sensitive.
+    Available settings (case-sensitive):
+    - `"collectComments": false or true`
+      - true to collect comment and allow writing them
+        back during serialization, false to discard comments.
+        This parameter is ignored if allowComments is false.
+    - `"allowComments": false or true`
+      - true if comments are allowed.
+    - `"strictRoot": false or true`
+      - true if root must be either an array or an object value
+    - `"allowDroppedNullPlaceholders": false or true`
+      - true if dropped null placeholders are allowed. (See StreamWriterBuilder.)
+    - `"allowNumericKeys": false or true`
+      - true if numeric object keys are allowed.
+    - `"allowSingleQuotes": false or true`
+      - true if '' are allowed for strings (both keys and values)
+    - `"stackLimit": integer`
+      - Exceeding stackLimit (recursive depth of `readValue()`) will
+        cause an exception.
+      - This is a security issue (seg-faults caused by deeply nested JSON),
+        so the default is low.
+    - `"failIfExtra": false or true`
+      - If true, `parse()` returns false when extra non-whitespace trails
+        the JSON value in the input string.
+    - `"rejectDupKeys": false or true`
+      - If true, `parse()` returns false when a key is duplicated within an object.
+    - `"allowSpecialFloats": false or true`
+      - If true, special float values (NaNs and infinities) are allowed 
+        and their values are lossfree restorable.
+
+    You can examine 'settings_` yourself
+    to see the defaults. You can also write and read them just like any
+    JSON Value.
+    \sa setDefaults()
+    */
+  Json::Value settings_;
+
+  CharReaderBuilder();
+  ~CharReaderBuilder() JSONCPP_OVERRIDE;
+
+  CharReader* newCharReader() const JSONCPP_OVERRIDE;
+
+  /** \return true if 'settings' are legal and consistent;
+   *   otherwise, indicate bad settings via 'invalid'.
+   */
+  bool validate(Json::Value* invalid) const;
+
+  /** A simple way to update a specific setting.
+   */
+  Value& operator[](JSONCPP_STRING key);
+
+  /** Called by ctor, but you can use this to reset settings_.
+   * \pre 'settings' != NULL (but Json::null is fine)
+   * \remark Defaults:
+   * \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults
+   */
+  static void setDefaults(Json::Value* settings);
+  /** Same as old Features::strictMode().
+   * \pre 'settings' != NULL (but Json::null is fine)
+   * \remark Defaults:
+   * \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
+   */
+  static void strictMode(Json::Value* settings);
+};
+
+/** Consume entire stream and use its begin/end.
+  * Someday we might have a real StreamReader, but for now this
+  * is convenient.
+  */
+bool JSON_API parseFromStream(
+    CharReader::Factory const&,
+    JSONCPP_ISTREAM&,
+    Value* root, std::string* errs);
+
+/** \brief Read from 'sin' into 'root'.
+
+ Always keep comments from the input JSON.
+
+ This can be used to read a file into a particular sub-object.
+ For example:
+ \code
+ Json::Value root;
+ cin >> root["dir"]["file"];
+ cout << root;
+ \endcode
+ Result:
+ \verbatim
+ {
+ "dir": {
+     "file": {
+     // The input stream JSON would be nested here.
+     }
+ }
+ }
+ \endverbatim
+ \throw std::exception on parse error.
+ \see Json::operator<<()
+*/
+JSON_API JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM&, Value&);
+
+} // namespace Json
+
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(pop)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+#endif // CPPTL_JSON_READER_H_INCLUDED
diff --git a/include/jsoncpp/json/value.h b/include/jsoncpp/json/value.h
new file mode 100644
index 0000000..4c29382
--- /dev/null
+++ b/include/jsoncpp/json/value.h
@@ -0,0 +1,865 @@
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef CPPTL_JSON_H_INCLUDED
+#define CPPTL_JSON_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "forwards.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <string>
+#include <vector>
+#include <exception>
+
+#ifndef JSON_USE_CPPTL_SMALLMAP
+#include <map>
+#else
+#include <cpptl/smallmap.h>
+#endif
+#ifdef JSON_USE_CPPTL
+#include <cpptl/forwards.h>
+#endif
+
+//Conditional NORETURN attribute on the throw functions would:
+// a) suppress false positives from static code analysis 
+// b) possibly improve optimization opportunities.
+#if !defined(JSONCPP_NORETURN)
+#  if defined(_MSC_VER)
+#    define JSONCPP_NORETURN __declspec(noreturn)
+#  elif defined(__GNUC__)
+#    define JSONCPP_NORETURN __attribute__ ((__noreturn__))
+#  else
+#    define JSONCPP_NORETURN
+#  endif
+#endif
+
+// Disable warning C4251: <data member>: <type> needs to have dll-interface to
+// be used by...
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(push)
+#pragma warning(disable : 4251)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+/** \brief JSON (JavaScript Object Notation).
+ */
+namespace Json {
+
+/** Base class for all exceptions we throw.
+ *
+ * We use nothing but these internally. Of course, STL can throw others.
+ */
+class JSON_API Exception : public std::exception {
+public:
+  Exception(JSONCPP_STRING const& msg);
+  ~Exception() throw() JSONCPP_OVERRIDE;
+  char const* what() const throw() JSONCPP_OVERRIDE;
+protected:
+  JSONCPP_STRING msg_;
+};
+
+/** Exceptions which the user cannot easily avoid.
+ *
+ * E.g. out-of-memory (when we use malloc), stack-overflow, malicious input
+ * 
+ * \remark derived from Json::Exception
+ */
+class JSON_API RuntimeError : public Exception {
+public:
+  RuntimeError(JSONCPP_STRING const& msg);
+};
+
+/** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros.
+ *
+ * These are precondition-violations (user bugs) and internal errors (our bugs).
+ * 
+ * \remark derived from Json::Exception
+ */
+class JSON_API LogicError : public Exception {
+public:
+  LogicError(JSONCPP_STRING const& msg);
+};
+
+/// used internally
+JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const& msg);
+/// used internally
+JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg);
+
+/** \brief Type of the value held by a Value object.
+ */
+enum ValueType {
+  nullValue = 0, ///< 'null' value
+  intValue,      ///< signed integer value
+  uintValue,     ///< unsigned integer value
+  realValue,     ///< double value
+  stringValue,   ///< UTF-8 string value
+  booleanValue,  ///< bool value
+  arrayValue,    ///< array value (ordered list)
+  objectValue    ///< object value (collection of name/value pairs).
+};
+
+enum CommentPlacement {
+  commentBefore = 0,      ///< a comment placed on the line before a value
+  commentAfterOnSameLine, ///< a comment just after a value on the same line
+  commentAfter, ///< a comment on the line after a value (only make sense for
+  /// root value)
+  numberOfCommentPlacement
+};
+
+//# ifdef JSON_USE_CPPTL
+//   typedef CppTL::AnyEnumerator<const char *> EnumMemberNames;
+//   typedef CppTL::AnyEnumerator<const Value &> EnumValues;
+//# endif
+
+/** \brief Lightweight wrapper to tag static string.
+ *
+ * Value constructor and objectValue member assignement takes advantage of the
+ * StaticString and avoid the cost of string duplication when storing the
+ * string or the member name.
+ *
+ * Example of usage:
+ * \code
+ * Json::Value aValue( StaticString("some text") );
+ * Json::Value object;
+ * static const StaticString code("code");
+ * object[code] = 1234;
+ * \endcode
+ */
+class JSON_API StaticString {
+public:
+  explicit StaticString(const char* czstring) : c_str_(czstring) {}
+
+  operator const char*() const { return c_str_; }
+
+  const char* c_str() const { return c_str_; }
+
+private:
+  const char* c_str_;
+};
+
+/** \brief Represents a <a HREF="http://www.json.org">JSON</a> value.
+ *
+ * This class is a discriminated union wrapper that can represents a:
+ * - signed integer [range: Value::minInt - Value::maxInt]
+ * - unsigned integer (range: 0 - Value::maxUInt)
+ * - double
+ * - UTF-8 string
+ * - boolean
+ * - 'null'
+ * - an ordered list of Value
+ * - collection of name/value pairs (javascript object)
+ *
+ * The type of the held value is represented by a #ValueType and
+ * can be obtained using type().
+ *
+ * Values of an #objectValue or #arrayValue can be accessed using operator[]()
+ * methods.
+ * Non-const methods will automatically create the a #nullValue element
+ * if it does not exist.
+ * The sequence of an #arrayValue will be automatically resized and initialized
+ * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue.
+ *
+ * The get() methods can be used to obtain default value in the case the
+ * required element does not exist.
+ *
+ * It is possible to iterate over the list of a #objectValue values using
+ * the getMemberNames() method.
+ *
+ * \note #Value string-length fit in size_t, but keys must be < 2^30.
+ * (The reason is an implementation detail.) A #CharReader will raise an
+ * exception if a bound is exceeded to avoid security holes in your app,
+ * but the Value API does *not* check bounds. That is the responsibility
+ * of the caller.
+ */
+class JSON_API Value {
+  friend class ValueIteratorBase;
+public:
+  typedef std::vector<JSONCPP_STRING> Members;
+  typedef ValueIterator iterator;
+  typedef ValueConstIterator const_iterator;
+  typedef Json::UInt UInt;
+  typedef Json::Int Int;
+#if defined(JSON_HAS_INT64)
+  typedef Json::UInt64 UInt64;
+  typedef Json::Int64 Int64;
+#endif // defined(JSON_HAS_INT64)
+  typedef Json::LargestInt LargestInt;
+  typedef Json::LargestUInt LargestUInt;
+  typedef Json::ArrayIndex ArrayIndex;
+
+  static const Value& null;  ///< We regret this reference to a global instance; prefer the simpler Value().
+  static const Value& nullRef;  ///< just a kludge for binary-compatibility; same as null
+  /// Minimum signed integer value that can be stored in a Json::Value.
+  static const LargestInt minLargestInt;
+  /// Maximum signed integer value that can be stored in a Json::Value.
+  static const LargestInt maxLargestInt;
+  /// Maximum unsigned integer value that can be stored in a Json::Value.
+  static const LargestUInt maxLargestUInt;
+
+  /// Minimum signed int value that can be stored in a Json::Value.
+  static const Int minInt;
+  /// Maximum signed int value that can be stored in a Json::Value.
+  static const Int maxInt;
+  /// Maximum unsigned int value that can be stored in a Json::Value.
+  static const UInt maxUInt;
+
+#if defined(JSON_HAS_INT64)
+  /// Minimum signed 64 bits int value that can be stored in a Json::Value.
+  static const Int64 minInt64;
+  /// Maximum signed 64 bits int value that can be stored in a Json::Value.
+  static const Int64 maxInt64;
+  /// Maximum unsigned 64 bits int value that can be stored in a Json::Value.
+  static const UInt64 maxUInt64;
+#endif // defined(JSON_HAS_INT64)
+
+private:
+#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+  class CZString {
+  public:
+    enum DuplicationPolicy {
+      noDuplication = 0,
+      duplicate,
+      duplicateOnCopy
+    };
+    CZString(ArrayIndex index);
+    CZString(char const* str, unsigned length, DuplicationPolicy allocate);
+    CZString(CZString const& other);
+#if JSON_HAS_RVALUE_REFERENCES
+    CZString(CZString&& other);
+#endif
+    ~CZString();
+    CZString& operator=(CZString other);
+    bool operator<(CZString const& other) const;
+    bool operator==(CZString const& other) const;
+    ArrayIndex index() const;
+    //const char* c_str() const; ///< \deprecated
+    char const* data() const;
+    unsigned length() const;
+    bool isStaticString() const;
+
+  private:
+    void swap(CZString& other);
+
+    struct StringStorage {
+      unsigned policy_: 2;
+      unsigned length_: 30; // 1GB max
+    };
+
+    char const* cstr_;  // actually, a prefixed string, unless policy is noDup
+    union {
+      ArrayIndex index_;
+      StringStorage storage_;
+    };
+  };
+
+public:
+#ifndef JSON_USE_CPPTL_SMALLMAP
+  typedef std::map<CZString, Value> ObjectValues;
+#else
+  typedef CppTL::SmallMap<CZString, Value> ObjectValues;
+#endif // ifndef JSON_USE_CPPTL_SMALLMAP
+#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+public:
+  /** \brief Create a default Value of the given type.
+
+    This is a very useful constructor.
+    To create an empty array, pass arrayValue.
+    To create an empty object, pass objectValue.
+    Another Value can then be set to this one by assignment.
+This is useful since clear() and resize() will not alter types.
+
+    Examples:
+\code
+Json::Value null_value; // null
+Json::Value arr_value(Json::arrayValue); // []
+Json::Value obj_value(Json::objectValue); // {}
+\endcode
+  */
+  Value(ValueType type = nullValue);
+  Value(Int value);
+  Value(UInt value);
+#if defined(JSON_HAS_INT64)
+  Value(Int64 value);
+  Value(UInt64 value);
+#endif // if defined(JSON_HAS_INT64)
+  Value(double value);
+  Value(const char* value); ///< Copy til first 0. (NULL causes to seg-fault.)
+  Value(const char* begin, const char* end); ///< Copy all, incl zeroes.
+  /** \brief Constructs a value from a static string.
+
+   * Like other value string constructor but do not duplicate the string for
+   * internal storage. The given string must remain alive after the call to this
+   * constructor.
+   * \note This works only for null-terminated strings. (We cannot change the
+   *   size of this class, so we have nowhere to store the length,
+   *   which might be computed later for various operations.)
+   *
+   * Example of usage:
+   * \code
+   * static StaticString foo("some text");
+   * Json::Value aValue(foo);
+   * \endcode
+   */
+  Value(const StaticString& value);
+  Value(const JSONCPP_STRING& value); ///< Copy data() til size(). Embedded zeroes too.
+#ifdef JSON_USE_CPPTL
+  Value(const CppTL::ConstString& value);
+#endif
+  Value(bool value);
+  /// Deep copy.
+  Value(const Value& other);
+#if JSON_HAS_RVALUE_REFERENCES
+  /// Move constructor
+  Value(Value&& other);
+#endif
+  ~Value();
+
+  /// Deep copy, then swap(other).
+  /// \note Over-write existing comments. To preserve comments, use #swapPayload().
+  Value& operator=(Value other);
+  /// Swap everything.
+  void swap(Value& other);
+  /// Swap values but leave comments and source offsets in place.
+  void swapPayload(Value& other);
+
+  ValueType type() const;
+
+  /// Compare payload only, not comments etc.
+  bool operator<(const Value& other) const;
+  bool operator<=(const Value& other) const;
+  bool operator>=(const Value& other) const;
+  bool operator>(const Value& other) const;
+  bool operator==(const Value& other) const;
+  bool operator!=(const Value& other) const;
+  int compare(const Value& other) const;
+
+  const char* asCString() const; ///< Embedded zeroes could cause you trouble!
+#if JSONCPP_USING_SECURE_MEMORY
+  unsigned getCStringLength() const; //Allows you to understand the length of the CString
+#endif
+  JSONCPP_STRING asString() const; ///< Embedded zeroes are possible.
+  /** Get raw char* of string-value.
+   *  \return false if !string. (Seg-fault if str or end are NULL.)
+   */
+  bool getString(
+      char const** begin, char const** end) const;
+#ifdef JSON_USE_CPPTL
+  CppTL::ConstString asConstString() const;
+#endif
+  Int asInt() const;
+  UInt asUInt() const;
+#if defined(JSON_HAS_INT64)
+  Int64 asInt64() const;
+  UInt64 asUInt64() const;
+#endif // if defined(JSON_HAS_INT64)
+  LargestInt asLargestInt() const;
+  LargestUInt asLargestUInt() const;
+  float asFloat() const;
+  double asDouble() const;
+  bool asBool() const;
+
+  bool isNull() const;
+  bool isBool() const;
+  bool isInt() const;
+  bool isInt64() const;
+  bool isUInt() const;
+  bool isUInt64() const;
+  bool isIntegral() const;
+  bool isDouble() const;
+  bool isNumeric() const;
+  bool isString() const;
+  bool isArray() const;
+  bool isObject() const;
+
+  bool isConvertibleTo(ValueType other) const;
+
+  /// Number of values in array or object
+  ArrayIndex size() const;
+
+  /// \brief Return true if empty array, empty object, or null;
+  /// otherwise, false.
+  bool empty() const;
+
+  /// Return isNull()
+  bool operator!() const;
+
+  /// Remove all object members and array elements.
+  /// \pre type() is arrayValue, objectValue, or nullValue
+  /// \post type() is unchanged
+  void clear();
+
+  /// Resize the array to size elements.
+  /// New elements are initialized to null.
+  /// May only be called on nullValue or arrayValue.
+  /// \pre type() is arrayValue or nullValue
+  /// \post type() is arrayValue
+  void resize(ArrayIndex size);
+
+  /// Access an array element (zero based index ).
+  /// If the array contains less than index element, then null value are
+  /// inserted
+  /// in the array so that its size is index+1.
+  /// (You may need to say 'value[0u]' to get your compiler to distinguish
+  ///  this from the operator[] which takes a string.)
+  Value& operator[](ArrayIndex index);
+
+  /// Access an array element (zero based index ).
+  /// If the array contains less than index element, then null value are
+  /// inserted
+  /// in the array so that its size is index+1.
+  /// (You may need to say 'value[0u]' to get your compiler to distinguish
+  ///  this from the operator[] which takes a string.)
+  Value& operator[](int index);
+
+  /// Access an array element (zero based index )
+  /// (You may need to say 'value[0u]' to get your compiler to distinguish
+  ///  this from the operator[] which takes a string.)
+  const Value& operator[](ArrayIndex index) const;
+
+  /// Access an array element (zero based index )
+  /// (You may need to say 'value[0u]' to get your compiler to distinguish
+  ///  this from the operator[] which takes a string.)
+  const Value& operator[](int index) const;
+
+  /// If the array contains at least index+1 elements, returns the element
+  /// value,
+  /// otherwise returns defaultValue.
+  Value get(ArrayIndex index, const Value& defaultValue) const;
+  /// Return true if index < size().
+  bool isValidIndex(ArrayIndex index) const;
+  /// \brief Append value to array at the end.
+  ///
+  /// Equivalent to jsonvalue[jsonvalue.size()] = value;
+  Value& append(const Value& value);
+
+  /// Access an object value by name, create a null member if it does not exist.
+  /// \note Because of our implementation, keys are limited to 2^30 -1 chars.
+  ///  Exceeding that will cause an exception.
+  Value& operator[](const char* key);
+  /// Access an object value by name, returns null if there is no member with
+  /// that name.
+  const Value& operator[](const char* key) const;
+  /// Access an object value by name, create a null member if it does not exist.
+  /// \param key may contain embedded nulls.
+  Value& operator[](const JSONCPP_STRING& key);
+  /// Access an object value by name, returns null if there is no member with
+  /// that name.
+  /// \param key may contain embedded nulls.
+  const Value& operator[](const JSONCPP_STRING& key) const;
+  /** \brief Access an object value by name, create a null member if it does not
+   exist.
+
+   * If the object has no entry for that name, then the member name used to store
+   * the new entry is not duplicated.
+   * Example of use:
+   * \code
+   * Json::Value object;
+   * static const StaticString code("code");
+   * object[code] = 1234;
+   * \endcode
+   */
+  Value& operator[](const StaticString& key);
+#ifdef JSON_USE_CPPTL
+  /// Access an object value by name, create a null member if it does not exist.
+  Value& operator[](const CppTL::ConstString& key);
+  /// Access an object value by name, returns null if there is no member with
+  /// that name.
+  const Value& operator[](const CppTL::ConstString& key) const;
+#endif
+  /// Return the member named key if it exist, defaultValue otherwise.
+  /// \note deep copy
+  Value get(const char* key, const Value& defaultValue) const;
+  /// Return the member named key if it exist, defaultValue otherwise.
+  /// \note deep copy
+  /// \note key may contain embedded nulls.
+  Value get(const char* begin, const char* end, const Value& defaultValue) const;
+  /// Return the member named key if it exist, defaultValue otherwise.
+  /// \note deep copy
+  /// \param key may contain embedded nulls.
+  Value get(const JSONCPP_STRING& key, const Value& defaultValue) const;
+#ifdef JSON_USE_CPPTL
+  /// Return the member named key if it exist, defaultValue otherwise.
+  /// \note deep copy
+  Value get(const CppTL::ConstString& key, const Value& defaultValue) const;
+#endif
+  /// Most general and efficient version of isMember()const, get()const,
+  /// and operator[]const
+  /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
+  Value const* find(char const* begin, char const* end) const;
+  /// Most general and efficient version of object-mutators.
+  /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
+  /// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue.
+  Value const* demand(char const* begin, char const* end);
+  /// \brief Remove and return the named member.
+  ///
+  /// Do nothing if it did not exist.
+  /// \return the removed Value, or null.
+  /// \pre type() is objectValue or nullValue
+  /// \post type() is unchanged
+  /// \deprecated
+  Value removeMember(const char* key);
+  /// Same as removeMember(const char*)
+  /// \param key may contain embedded nulls.
+  /// \deprecated
+  Value removeMember(const JSONCPP_STRING& key);
+  /// Same as removeMember(const char* begin, const char* end, Value* removed),
+  /// but 'key' is null-terminated.
+  bool removeMember(const char* key, Value* removed);
+  /** \brief Remove the named map member.
+
+      Update 'removed' iff removed.
+      \param key may contain embedded nulls.
+      \return true iff removed (no exceptions)
+  */
+  bool removeMember(JSONCPP_STRING const& key, Value* removed);
+  /// Same as removeMember(JSONCPP_STRING const& key, Value* removed)
+  bool removeMember(const char* begin, const char* end, Value* removed);
+  /** \brief Remove the indexed array element.
+
+      O(n) expensive operations.
+      Update 'removed' iff removed.
+      \return true iff removed (no exceptions)
+  */
+  bool removeIndex(ArrayIndex i, Value* removed);
+
+  /// Return true if the object has a member named key.
+  /// \note 'key' must be null-terminated.
+  bool isMember(const char* key) const;
+  /// Return true if the object has a member named key.
+  /// \param key may contain embedded nulls.
+  bool isMember(const JSONCPP_STRING& key) const;
+  /// Same as isMember(JSONCPP_STRING const& key)const
+  bool isMember(const char* begin, const char* end) const;
+#ifdef JSON_USE_CPPTL
+  /// Return true if the object has a member named key.
+  bool isMember(const CppTL::ConstString& key) const;
+#endif
+
+  /// \brief Return a list of the member names.
+  ///
+  /// If null, return an empty list.
+  /// \pre type() is objectValue or nullValue
+  /// \post if type() was nullValue, it remains nullValue
+  Members getMemberNames() const;
+
+  //# ifdef JSON_USE_CPPTL
+  //      EnumMemberNames enumMemberNames() const;
+  //      EnumValues enumValues() const;
+  //# endif
+
+  /// \deprecated Always pass len.
+  JSONCPP_DEPRECATED("Use setComment(JSONCPP_STRING const&) instead.")
+  void setComment(const char* comment, CommentPlacement placement);
+  /// Comments must be //... or /* ... */
+  void setComment(const char* comment, size_t len, CommentPlacement placement);
+  /// Comments must be //... or /* ... */
+  void setComment(const JSONCPP_STRING& comment, CommentPlacement placement);
+  bool hasComment(CommentPlacement placement) const;
+  /// Include delimiters and embedded newlines.
+  JSONCPP_STRING getComment(CommentPlacement placement) const;
+
+  JSONCPP_STRING toStyledString() const;
+
+  const_iterator begin() const;
+  const_iterator end() const;
+
+  iterator begin();
+  iterator end();
+
+  // Accessors for the [start, limit) range of bytes within the JSON text from
+  // which this value was parsed, if any.
+  void setOffsetStart(ptrdiff_t start);
+  void setOffsetLimit(ptrdiff_t limit);
+  ptrdiff_t getOffsetStart() const;
+  ptrdiff_t getOffsetLimit() const;
+
+private:
+  void initBasic(ValueType type, bool allocated = false);
+
+  Value& resolveReference(const char* key);
+  Value& resolveReference(const char* key, const char* end);
+
+  struct CommentInfo {
+    CommentInfo();
+    ~CommentInfo();
+
+    void setComment(const char* text, size_t len);
+
+    char* comment_;
+  };
+
+  // struct MemberNamesTransform
+  //{
+  //   typedef const char *result_type;
+  //   const char *operator()( const CZString &name ) const
+  //   {
+  //      return name.c_str();
+  //   }
+  //};
+
+  union ValueHolder {
+    LargestInt int_;
+    LargestUInt uint_;
+    double real_;
+    bool bool_;
+    char* string_;  // actually ptr to unsigned, followed by str, unless !allocated_
+    ObjectValues* map_;
+  } value_;
+  ValueType type_ : 8;
+  unsigned int allocated_ : 1; // Notes: if declared as bool, bitfield is useless.
+                               // If not allocated_, string_ must be null-terminated.
+  CommentInfo* comments_;
+
+  // [start, limit) byte offsets in the source JSON text from which this Value
+  // was extracted.
+  ptrdiff_t start_;
+  ptrdiff_t limit_;
+};
+
+/** \brief Experimental and untested: represents an element of the "path" to
+ * access a node.
+ */
+class JSON_API PathArgument {
+public:
+  friend class Path;
+
+  PathArgument();
+  PathArgument(ArrayIndex index);
+  PathArgument(const char* key);
+  PathArgument(const JSONCPP_STRING& key);
+
+private:
+  enum Kind {
+    kindNone = 0,
+    kindIndex,
+    kindKey
+  };
+  JSONCPP_STRING key_;
+  ArrayIndex index_;
+  Kind kind_;
+};
+
+/** \brief Experimental and untested: represents a "path" to access a node.
+ *
+ * Syntax:
+ * - "." => root node
+ * - ".[n]" => elements at index 'n' of root node (an array value)
+ * - ".name" => member named 'name' of root node (an object value)
+ * - ".name1.name2.name3"
+ * - ".[0][1][2].name1[3]"
+ * - ".%" => member name is provided as parameter
+ * - ".[%]" => index is provied as parameter
+ */
+class JSON_API Path {
+public:
+  Path(const JSONCPP_STRING& path,
+       const PathArgument& a1 = PathArgument(),
+       const PathArgument& a2 = PathArgument(),
+       const PathArgument& a3 = PathArgument(),
+       const PathArgument& a4 = PathArgument(),
+       const PathArgument& a5 = PathArgument());
+
+  const Value& resolve(const Value& root) const;
+  Value resolve(const Value& root, const Value& defaultValue) const;
+  /// Creates the "path" to access the specified node and returns a reference on
+  /// the node.
+  Value& make(Value& root) const;
+
+private:
+  typedef std::vector<const PathArgument*> InArgs;
+  typedef std::vector<PathArgument> Args;
+
+  void makePath(const JSONCPP_STRING& path, const InArgs& in);
+  void addPathInArg(const JSONCPP_STRING& path,
+                    const InArgs& in,
+                    InArgs::const_iterator& itInArg,
+                    PathArgument::Kind kind);
+  void invalidPath(const JSONCPP_STRING& path, int location);
+
+  Args args_;
+};
+
+/** \brief base class for Value iterators.
+ *
+ */
+class JSON_API ValueIteratorBase {
+public:
+  typedef std::bidirectional_iterator_tag iterator_category;
+  typedef unsigned int size_t;
+  typedef int difference_type;
+  typedef ValueIteratorBase SelfType;
+
+  bool operator==(const SelfType& other) const { return isEqual(other); }
+
+  bool operator!=(const SelfType& other) const { return !isEqual(other); }
+
+  difference_type operator-(const SelfType& other) const {
+    return other.computeDistance(*this);
+  }
+
+  /// Return either the index or the member name of the referenced value as a
+  /// Value.
+  Value key() const;
+
+  /// Return the index of the referenced Value, or -1 if it is not an arrayValue.
+  UInt index() const;
+
+  /// Return the member name of the referenced Value, or "" if it is not an
+  /// objectValue.
+  /// \note Avoid `c_str()` on result, as embedded zeroes are possible.
+  JSONCPP_STRING name() const;
+
+  /// Return the member name of the referenced Value. "" if it is not an
+  /// objectValue.
+  /// \deprecated This cannot be used for UTF-8 strings, since there can be embedded nulls.
+  JSONCPP_DEPRECATED("Use `key = name();` instead.")
+  char const* memberName() const;
+  /// Return the member name of the referenced Value, or NULL if it is not an
+  /// objectValue.
+  /// \note Better version than memberName(). Allows embedded nulls.
+  char const* memberName(char const** end) const;
+
+protected:
+  Value& deref() const;
+
+  void increment();
+
+  void decrement();
+
+  difference_type computeDistance(const SelfType& other) const;
+
+  bool isEqual(const SelfType& other) const;
+
+  void copy(const SelfType& other);
+
+private:
+  Value::ObjectValues::iterator current_;
+  // Indicates that iterator is for a null value.
+  bool isNull_;
+
+public:
+  // For some reason, BORLAND needs these at the end, rather
+  // than earlier. No idea why.
+  ValueIteratorBase();
+  explicit ValueIteratorBase(const Value::ObjectValues::iterator& current);
+};
+
+/** \brief const iterator for object and array value.
+ *
+ */
+class JSON_API ValueConstIterator : public ValueIteratorBase {
+  friend class Value;
+
+public:
+  typedef const Value value_type;
+  //typedef unsigned int size_t;
+  //typedef int difference_type;
+  typedef const Value& reference;
+  typedef const Value* pointer;
+  typedef ValueConstIterator SelfType;
+
+  ValueConstIterator();
+  ValueConstIterator(ValueIterator const& other);
+
+private:
+/*! \internal Use by Value to create an iterator.
+ */
+  explicit ValueConstIterator(const Value::ObjectValues::iterator& current);
+public:
+  SelfType& operator=(const ValueIteratorBase& other);
+
+  SelfType operator++(int) {
+    SelfType temp(*this);
+    ++*this;
+    return temp;
+  }
+
+  SelfType operator--(int) {
+    SelfType temp(*this);
+    --*this;
+    return temp;
+  }
+
+  SelfType& operator--() {
+    decrement();
+    return *this;
+  }
+
+  SelfType& operator++() {
+    increment();
+    return *this;
+  }
+
+  reference operator*() const { return deref(); }
+
+  pointer operator->() const { return &deref(); }
+};
+
+/** \brief Iterator for object and array value.
+ */
+class JSON_API ValueIterator : public ValueIteratorBase {
+  friend class Value;
+
+public:
+  typedef Value value_type;
+  typedef unsigned int size_t;
+  typedef int difference_type;
+  typedef Value& reference;
+  typedef Value* pointer;
+  typedef ValueIterator SelfType;
+
+  ValueIterator();
+  explicit ValueIterator(const ValueConstIterator& other);
+  ValueIterator(const ValueIterator& other);
+
+private:
+/*! \internal Use by Value to create an iterator.
+ */
+  explicit ValueIterator(const Value::ObjectValues::iterator& current);
+public:
+  SelfType& operator=(const SelfType& other);
+
+  SelfType operator++(int) {
+    SelfType temp(*this);
+    ++*this;
+    return temp;
+  }
+
+  SelfType operator--(int) {
+    SelfType temp(*this);
+    --*this;
+    return temp;
+  }
+
+  SelfType& operator--() {
+    decrement();
+    return *this;
+  }
+
+  SelfType& operator++() {
+    increment();
+    return *this;
+  }
+
+  reference operator*() const { return deref(); }
+
+  pointer operator->() const { return &deref(); }
+};
+
+} // namespace Json
+
+
+namespace std {
+/// Specialize std::swap() for Json::Value.
+template<>
+inline void swap(Json::Value& a, Json::Value& b) { a.swap(b); }
+}
+
+
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(pop)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+#endif // CPPTL_JSON_H_INCLUDED
diff --git a/include/jsoncpp/json/version.h b/include/jsoncpp/json/version.h
new file mode 100644
index 0000000..18ce358
--- /dev/null
+++ b/include/jsoncpp/json/version.h
@@ -0,0 +1,20 @@
+// DO NOT EDIT. This file (and "version") is generated by CMake.
+// Run CMake configure step to update it.
+#ifndef JSON_VERSION_H_INCLUDED
+# define JSON_VERSION_H_INCLUDED
+
+# define JSONCPP_VERSION_STRING "1.7.2"
+# define JSONCPP_VERSION_MAJOR 1
+# define JSONCPP_VERSION_MINOR 7
+# define JSONCPP_VERSION_PATCH 2
+# define JSONCPP_VERSION_QUALIFIER
+# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))
+
+#ifdef JSONCPP_USING_SECURE_MEMORY
+#undef JSONCPP_USING_SECURE_MEMORY
+#endif
+#define JSONCPP_USING_SECURE_MEMORY 0
+// If non-zero, the library zeroes any memory that it has allocated before
+// it frees its memory.
+
+#endif // JSON_VERSION_H_INCLUDED
diff --git a/include/jsoncpp/json/writer.h b/include/jsoncpp/json/writer.h
new file mode 100644
index 0000000..2c1e65b
--- /dev/null
+++ b/include/jsoncpp/json/writer.h
@@ -0,0 +1,331 @@
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_WRITER_H_INCLUDED
+#define JSON_WRITER_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "value.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <vector>
+#include <string>
+#include <ostream>
+
+// Disable warning C4251: <data member>: <type> needs to have dll-interface to
+// be used by...
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(push)
+#pragma warning(disable : 4251)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+namespace Json {
+
+class Value;
+
+/**
+
+Usage:
+\code
+  using namespace Json;
+  void writeToStdout(StreamWriter::Factory const& factory, Value const& value) {
+    std::unique_ptr<StreamWriter> const writer(
+      factory.newStreamWriter());
+    writer->write(value, &std::cout);
+    std::cout << std::endl;  // add lf and flush
+  }
+\endcode
+*/
+class JSON_API StreamWriter {
+protected:
+  JSONCPP_OSTREAM* sout_;  // not owned; will not delete
+public:
+  StreamWriter();
+  virtual ~StreamWriter();
+  /** Write Value into document as configured in sub-class.
+      Do not take ownership of sout, but maintain a reference during function.
+      \pre sout != NULL
+      \return zero on success (For now, we always return zero, so check the stream instead.)
+      \throw std::exception possibly, depending on configuration
+   */
+  virtual int write(Value const& root, JSONCPP_OSTREAM* sout) = 0;
+
+  /** \brief A simple abstract factory.
+   */
+  class JSON_API Factory {
+  public:
+    virtual ~Factory();
+    /** \brief Allocate a CharReader via operator new().
+     * \throw std::exception if something goes wrong (e.g. invalid settings)
+     */
+    virtual StreamWriter* newStreamWriter() const = 0;
+  };  // Factory
+};  // StreamWriter
+
+/** \brief Write into stringstream, then return string, for convenience.
+ * A StreamWriter will be created from the factory, used, and then deleted.
+ */
+JSONCPP_STRING JSON_API writeString(StreamWriter::Factory const& factory, Value const& root);
+
+
+/** \brief Build a StreamWriter implementation.
+
+Usage:
+\code
+  using namespace Json;
+  Value value = ...;
+  StreamWriterBuilder builder;
+  builder["commentStyle"] = "None";
+  builder["indentation"] = "   ";  // or whatever you like
+  std::unique_ptr<Json::StreamWriter> writer(
+      builder.newStreamWriter());
+  writer->write(value, &std::cout);
+  std::cout << std::endl;  // add lf and flush
+\endcode
+*/
+class JSON_API StreamWriterBuilder : public StreamWriter::Factory {
+public:
+  // Note: We use a Json::Value so that we can add data-members to this class
+  // without a major version bump.
+  /** Configuration of this builder.
+    Available settings (case-sensitive):
+    - "commentStyle": "None" or "All"
+    - "indentation":  "<anything>"
+    - "enableYAMLCompatibility": false or true
+      - slightly change the whitespace around colons
+    - "dropNullPlaceholders": false or true
+      - Drop the "null" string from the writer's output for nullValues.
+        Strictly speaking, this is not valid JSON. But when the output is being
+        fed to a browser's Javascript, it makes for smaller output and the
+        browser can handle the output just fine.
+    - "useSpecialFloats": false or true
+      - If true, outputs non-finite floating point values in the following way:
+        NaN values as "NaN", positive infinity as "Infinity", and negative infinity
+        as "-Infinity".
+
+    You can examine 'settings_` yourself
+    to see the defaults. You can also write and read them just like any
+    JSON Value.
+    \sa setDefaults()
+    */
+  Json::Value settings_;
+
+  StreamWriterBuilder();
+  ~StreamWriterBuilder() JSONCPP_OVERRIDE;
+
+  /**
+   * \throw std::exception if something goes wrong (e.g. invalid settings)
+   */
+  StreamWriter* newStreamWriter() const JSONCPP_OVERRIDE;
+
+  /** \return true if 'settings' are legal and consistent;
+   *   otherwise, indicate bad settings via 'invalid'.
+   */
+  bool validate(Json::Value* invalid) const;
+  /** A simple way to update a specific setting.
+   */
+  Value& operator[](JSONCPP_STRING key);
+
+  /** Called by ctor, but you can use this to reset settings_.
+   * \pre 'settings' != NULL (but Json::null is fine)
+   * \remark Defaults:
+   * \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults
+   */
+  static void setDefaults(Json::Value* settings);
+};
+
+/** \brief Abstract class for writers.
+ * \deprecated Use StreamWriter. (And really, this is an implementation detail.)
+ */
+class JSON_API Writer {
+public:
+  virtual ~Writer();
+
+  virtual JSONCPP_STRING write(const Value& root) = 0;
+};
+
+/** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format
+ *without formatting (not human friendly).
+ *
+ * The JSON document is written in a single line. It is not intended for 'human'
+ *consumption,
+ * but may be usefull to support feature such as RPC where bandwith is limited.
+ * \sa Reader, Value
+ * \deprecated Use StreamWriterBuilder.
+ */
+class JSON_API FastWriter : public Writer {
+
+public:
+  FastWriter();
+  ~FastWriter() JSONCPP_OVERRIDE {}
+
+  void enableYAMLCompatibility();
+
+  /** \brief Drop the "null" string from the writer's output for nullValues.
+   * Strictly speaking, this is not valid JSON. But when the output is being
+   * fed to a browser's Javascript, it makes for smaller output and the
+   * browser can handle the output just fine.
+   */
+  void dropNullPlaceholders();
+
+  void omitEndingLineFeed();
+
+public: // overridden from Writer
+  JSONCPP_STRING write(const Value& root) JSONCPP_OVERRIDE;
+
+private:
+  void writeValue(const Value& value);
+
+  JSONCPP_STRING document_;
+  bool yamlCompatiblityEnabled_;
+  bool dropNullPlaceholders_;
+  bool omitEndingLineFeed_;
+};
+
+/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
+ *human friendly way.
+ *
+ * The rules for line break and indent are as follow:
+ * - Object value:
+ *     - if empty then print {} without indent and line break
+ *     - if not empty the print '{', line break & indent, print one value per
+ *line
+ *       and then unindent and line break and print '}'.
+ * - Array value:
+ *     - if empty then print [] without indent and line break
+ *     - if the array contains no object value, empty array or some other value
+ *types,
+ *       and all the values fit on one lines, then print the array on a single
+ *line.
+ *     - otherwise, it the values do not fit on one line, or the array contains
+ *       object or non empty array, then print one value per line.
+ *
+ * If the Value have comments then they are outputed according to their
+ *#CommentPlacement.
+ *
+ * \sa Reader, Value, Value::setComment()
+ * \deprecated Use StreamWriterBuilder.
+ */
+class JSON_API StyledWriter : public Writer {
+public:
+  StyledWriter();
+  ~StyledWriter() JSONCPP_OVERRIDE {}
+
+public: // overridden from Writer
+  /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
+   * \param root Value to serialize.
+   * \return String containing the JSON document that represents the root value.
+   */
+  JSONCPP_STRING write(const Value& root) JSONCPP_OVERRIDE;
+
+private:
+  void writeValue(const Value& value);
+  void writeArrayValue(const Value& value);
+  bool isMultineArray(const Value& value);
+  void pushValue(const JSONCPP_STRING& value);
+  void writeIndent();
+  void writeWithIndent(const JSONCPP_STRING& value);
+  void indent();
+  void unindent();
+  void writeCommentBeforeValue(const Value& root);
+  void writeCommentAfterValueOnSameLine(const Value& root);
+  bool hasCommentForValue(const Value& value);
+  static JSONCPP_STRING normalizeEOL(const JSONCPP_STRING& text);
+
+  typedef std::vector<JSONCPP_STRING> ChildValues;
+
+  ChildValues childValues_;
+  JSONCPP_STRING document_;
+  JSONCPP_STRING indentString_;
+  unsigned int rightMargin_;
+  unsigned int indentSize_;
+  bool addChildValues_;
+};
+
+/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
+ human friendly way,
+     to a stream rather than to a string.
+ *
+ * The rules for line break and indent are as follow:
+ * - Object value:
+ *     - if empty then print {} without indent and line break
+ *     - if not empty the print '{', line break & indent, print one value per
+ line
+ *       and then unindent and line break and print '}'.
+ * - Array value:
+ *     - if empty then print [] without indent and line break
+ *     - if the array contains no object value, empty array or some other value
+ types,
+ *       and all the values fit on one lines, then print the array on a single
+ line.
+ *     - otherwise, it the values do not fit on one line, or the array contains
+ *       object or non empty array, then print one value per line.
+ *
+ * If the Value have comments then they are outputed according to their
+ #CommentPlacement.
+ *
+ * \param indentation Each level will be indented by this amount extra.
+ * \sa Reader, Value, Value::setComment()
+ * \deprecated Use StreamWriterBuilder.
+ */
+class JSON_API StyledStreamWriter {
+public:
+  StyledStreamWriter(JSONCPP_STRING indentation = "\t");
+  ~StyledStreamWriter() {}
+
+public:
+  /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
+   * \param out Stream to write to. (Can be ostringstream, e.g.)
+   * \param root Value to serialize.
+   * \note There is no point in deriving from Writer, since write() should not
+   * return a value.
+   */
+  void write(JSONCPP_OSTREAM& out, const Value& root);
+
+private:
+  void writeValue(const Value& value);
+  void writeArrayValue(const Value& value);
+  bool isMultineArray(const Value& value);
+  void pushValue(const JSONCPP_STRING& value);
+  void writeIndent();
+  void writeWithIndent(const JSONCPP_STRING& value);
+  void indent();
+  void unindent();
+  void writeCommentBeforeValue(const Value& root);
+  void writeCommentAfterValueOnSameLine(const Value& root);
+  bool hasCommentForValue(const Value& value);
+  static JSONCPP_STRING normalizeEOL(const JSONCPP_STRING& text);
+
+  typedef std::vector<JSONCPP_STRING> ChildValues;
+
+  ChildValues childValues_;
+  JSONCPP_OSTREAM* document_;
+  JSONCPP_STRING indentString_;
+  unsigned int rightMargin_;
+  JSONCPP_STRING indentation_;
+  bool addChildValues_ : 1;
+  bool indented_ : 1;
+};
+
+#if defined(JSON_HAS_INT64)
+JSONCPP_STRING JSON_API valueToString(Int value);
+JSONCPP_STRING JSON_API valueToString(UInt value);
+#endif // if defined(JSON_HAS_INT64)
+JSONCPP_STRING JSON_API valueToString(LargestInt value);
+JSONCPP_STRING JSON_API valueToString(LargestUInt value);
+JSONCPP_STRING JSON_API valueToString(double value);
+JSONCPP_STRING JSON_API valueToString(bool value);
+JSONCPP_STRING JSON_API valueToQuotedString(const char* value);
+
+/// \brief Output using the StyledStreamWriter.
+/// \see Json::operator>>()
+JSON_API JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM&, const Value& root);
+
+} // namespace Json
+
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(pop)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+#endif // JSON_WRITER_H_INCLUDED
diff --git a/include/nng/compat/nanomsg/bus.h b/include/nng/compat/nanomsg/bus.h
new file mode 100644
index 0000000..004a9ac
--- /dev/null
+++ b/include/nng/compat/nanomsg/bus.h
@@ -0,0 +1,33 @@
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_COMPAT_BUS_H
+#define NNG_COMPAT_BUS_H
+
+// This header contains interfaces that are intended to offer compatibility
+// with nanomsg v1.0.  These are not the "preferred" interfaces for nng,
+// and consumers should only use these if they are porting software that
+// previously used nanomsg.  New programs should use the nng native APIs.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// BUS sockopt level.
+#define NN_PROTO_BUS 7
+#define NN_BUS (NN_PROTO_BUS * 16 + 0)
+
+// BUS has no options.
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_COMPAT_BUS_H
diff --git a/include/nng/compat/nanomsg/inproc.h b/include/nng/compat/nanomsg/inproc.h
new file mode 100644
index 0000000..9c71a1e
--- /dev/null
+++ b/include/nng/compat/nanomsg/inproc.h
@@ -0,0 +1,31 @@
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_COMPAT_INPROC_H
+#define NNG_COMPAT_INPROC_H
+
+// This header contains interfaces that are intended to offer compatibility
+// with nanomsg v1.0.  These are not the "preferred" interfaces for nng,
+// and consumers should only use these if they are porting software that
+// previously used nanomsg.  New programs should use the nng native APIs.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// inproc sockopt level.
+// There are no inproc tunables.
+#define NN_INPROC (-1)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_COMPAT_INPROC_H
diff --git a/include/nng/compat/nanomsg/ipc.h b/include/nng/compat/nanomsg/ipc.h
new file mode 100644
index 0000000..fad520d
--- /dev/null
+++ b/include/nng/compat/nanomsg/ipc.h
@@ -0,0 +1,39 @@
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_COMPAT_IPC_H
+#define NNG_COMPAT_IPC_H
+
+// This header contains interfaces that are intended to offer compatibility
+// with nanomsg v1.0.  These are not the "preferred" interfaces for nng,
+// and consumers should only use these if they are porting software that
+// previously used nanomsg.  New programs should use the nng native APIs.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// IPC sockopt level.
+#define NN_IPC (-2)
+
+// IPC options.  Note that these are not currently supported.
+// IPC_SEC_ATTR works quite differently in NNG, and must be
+// configured using the new API.  The buffer sizing options are
+// not supported at all.  None of these were ever documented, and
+// are offered here only for source compatibility.
+#define NN_IPC_SEC_ATTR 1
+#define NN_IPC_OUTBUFSZ 2
+#define NN_IPC_INBUFSZ 3
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_COMPAT_IPC_H
diff --git a/include/nng/compat/nanomsg/nn.h b/include/nng/compat/nanomsg/nn.h
new file mode 100644
index 0000000..60c33c6
--- /dev/null
+++ b/include/nng/compat/nanomsg/nn.h
@@ -0,0 +1,284 @@
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_COMPAT_NN_H
+#define NNG_COMPAT_NN_H
+
+// This header contains interfaces that are intended to offer compatibility
+// with nanomsg v1.0.  These are not the "preferred" interfaces for nng,
+// and consumers should only use these if they are porting software that
+// previously used nanomsg.  New programs should use the nng native APIs.
+
+// Note that compatibility promises are limited to public portions of the
+// nanomsg API, and specifically do NOT extend to the ABI.  Furthermore,
+// there may be other limitations around less commonly used portions of the
+// API; for example only SP headers may be transported in control data for
+// messages, there is almost no compatibility offered for statistics.
+// Error values may differ from those returned by nanomsg as well; the nng
+// error reporting facility expresses only a subset of the possibilities of
+// nanomsg.
+
+// Note that unlike nanomsg, nng does not aggressively recycle socket or
+// endpoint IDs, which means applications which made assumptions that these
+// would be relatively small integers (e.g. to use them as array indices)
+// may break.  (No promise about values was ever made.)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdint.h>
+
+// clang-format gets in the way of most of this file.
+// We turn it off, at least until it gets smarter about aligning
+// macro definitions or we adopt enums or somesuch.
+// clang-format off
+
+// NNG_DECL is used on declarations to deal with scope.
+// For building Windows DLLs, it should be the appropriate __declspec().
+// For shared libraries with platforms that support hidden visibility,
+// it should evaluate to __attribute__((visibility("default"))).
+#ifndef NN_DECL
+#if defined(_WIN32) && !defined(NNG_STATIC_LIB)
+#if defined(NNG_SHARED_LIB)
+#define NN_DECL		__declspec(dllexport)
+#else
+#define NN_DECL		__declspec(dllimport)
+#endif // NNG_SHARED_LIB
+#else
+#if defined(NNG_SHARED_LIB) && defined(NNG_HIDDEN_VISIBILITY)
+#define NN_DECL __attribute__((visibility("default")))
+#else
+#define NN_DECL extern
+#endif
+#endif // _WIN32 && !NNG_STATIC_LIB
+#endif  // NN_DECL
+
+#define AF_SP			1
+#define AF_SP_RAW		2
+
+#define NN_SOCKADDR_MAX		128
+#define NN_SOL_SOCKET		0
+
+// Flag for send/recv (nonblocking)
+#define NN_DONTWAIT		1
+
+// CMSG data type
+#define PROTO_SP		1
+#define SP_HDR			1
+
+// Errnos.  Legacy nanomsg uses posix errnos where possible.
+// If a define is not set, use add NN_ERRBASE.  nng does not
+// return all of these values, so there may be some loss of
+// of information for edge cases, but we don't expect that to be
+// a problem really.
+#define NN_ERRBASE		(0x10000000)
+#ifndef ENOTSUP
+#define ENOTSUP			(NN_ERRBASE+1)
+#endif
+#ifndef EPROTONOSUPPORT
+#define EPROTONOSUPPORT		(NN_ERRBASE+2)
+#endif
+#ifndef ENOBUFS
+#define ENOBUFS			(NN_ERRBASE+3)
+#endif
+#ifndef ENETDOWN
+#define ENETDOWN		(NN_ERRBASE+4)
+#endif
+#ifndef EADDRINUSE
+#define EADDRINUSE		(NN_ERRBASE+5)
+#endif
+#ifndef EADDRNOTAVAIL
+#define EADDRNOTAVAIL		(NN_ERRBASE+6)
+#endif
+#ifndef ENOTSOCK
+#define ENOTSOCK		(NN_ERRBASE+7)
+#endif
+#ifndef EAGAIN
+#define EAGAIN			(NN_ERRBASE+8)
+#endif
+#ifndef EBADF
+#define EBADF			(NN_ERRBASE+9)
+#endif
+#ifndef EINVAL
+#define EINVAL			(NN_ERRBASE+10)
+#endif
+#ifndef EMFILE
+#define EMFILE			(NN_ERRBASE+11)
+#endif
+#ifndef EFAULT
+#define EFAULT			(NN_ERRBASE+12)
+#endif
+#ifndef EACCES
+#define EACCES			(NN_ERRBASE+13)
+#endif
+#ifndef ENETRESET
+#define ENETRESET		(NN_ERRBASE+14)
+#endif
+#ifndef ENETUNREACH
+#define ENETUNREACH		(NN_ERRBASE+15)
+#endif
+#ifndef EHOSTUNREACH
+#define EHOSTUNREACH		(NN_ERRBASE+16)
+#endif
+#ifndef EAFNOSUPPORT
+#define EAFNOSUPPORT		(NN_ERRBASE+17)
+#endif
+#ifndef EINPROGRESS
+#define EINPROGRESS		(NN_ERRBASE+18)
+#endif
+#ifndef EPROTO
+#define EPROTO			(NN_ERRBASE+19)
+#endif
+#ifndef ECONNREFUSED
+#define ECONNREFUSED		(NN_ERRBASE+20)
+#endif
+#ifndef ENOTCONN
+#define ENOTCONN		(NN_ERRBASE+21)
+#endif
+#ifndef EMSGSIZE
+#define EMSGSIZE		(NN_ERRBASE+22)
+#endif
+#ifndef ETIMEDOUT
+#define ETIMEDOUT		(NN_ERRBASE+23)
+#endif
+#ifndef ECONNABORTED
+#define ECONNABORTED		(NN_ERRBASE+24)
+#endif
+#ifndef ECONNRESET
+#define ECONNRESET		(NN_ERRBASE+25)
+#endif
+#ifndef ENOPROTOOPT
+#define ENOPROTOOPT		(NN_ERRBASE+26)
+#endif
+#ifndef EISCONN
+#define EISCONN			(NN_ERRBASE+27)
+#endif
+#ifndef ESOCKNOSUPPORT
+#define ESOCKNOSPPORT		(NN_ERRBASE+28)
+#endif
+#ifndef ETERM
+#define ETERM			(NN_ERRBASE+29)
+#endif
+#ifndef EFSM
+#define EFSM			(NN_ERRBASE+30)
+#endif
+#ifndef ENOENT
+#define ENOENT			(NN_ERRBASE+31)
+#endif
+#ifndef EIO
+#define EIO			(NN_ERRBASE+32)
+#endif
+#ifndef EEXIST
+#define EEXIST			(NN_ERRBASE+33)
+#endif
+#ifndef ENOSPC
+#define ENOSPC			(NN_ERRBASE+34)
+#endif
+
+
+// Socket options
+#define NN_LINGER		1
+#define NN_SNDBUF		2
+#define NN_RCVBUF		3
+#define NN_SNDTIMEO		4
+#define NN_RCVTIMEO		5
+#define NN_RECONNECT_IVL	6
+#define NN_RECONNECT_IVL_MAX	7
+#define NN_SNDPRIO		8
+#define NN_RCVPRIO		9
+#define NN_SNDFD		10
+#define NN_RCVFD		11
+#define NN_DOMAIN		12
+#define NN_PROTOCOL		13
+#define NN_IPV4ONLY		14
+#define NN_SOCKET_NAME		15
+#define NN_RCVMAXSIZE		16
+#define NN_MAXTTL		17
+
+// from this point on formatting is fine
+// clang-format on
+
+// Poll stuff
+#define NN_POLLIN 1
+#define NN_POLLOUT 2
+struct nn_pollfd {
+	int      fd;
+	uint16_t events;
+	uint16_t revents;
+};
+
+// Magical size for allocation
+#define NN_MSG ((size_t) -1)
+
+struct nn_iovec {
+	void * iov_base;
+	size_t iov_len;
+};
+
+struct nn_msghdr {
+	struct nn_iovec *msg_iov;
+	int              msg_iovlen;
+	void *           msg_control;
+	size_t           msg_controllen;
+};
+
+struct nn_cmsghdr {
+	size_t cmsg_len;
+	int    cmsg_level;
+	int    cmsg_type;
+};
+
+#define NN_CMSG_ALIGN(len) \
+	(((len) + sizeof(size_t) - 1) & (size_t) ~(sizeof(size_t) - 1))
+
+// Unlike old nanomsg, we explicitly only support the SP header as attached
+// cmsg data.  It turns out that old nanomsg didn't really store anything
+// useful otherwise anyway.  (One specific exception was that it stored the
+// message type of text or binary for the websocket transport.  We don't think
+// anyone used that in practice though.)
+#define NN_CMSG_FIRSTHDR(mh) nn_cmsg_next((struct nn_msghdr *) (mh), NULL)
+#define NN_CMSG_NXTHDR(mh, ch) \
+	nn_cmsg_next((struct nn_msghdr *) (mh), (struct nn_cmsghdr *) ch)
+#define NN_CMSG_DATA(ch) ((unsigned char *) (((struct nn_cmsghdr *) (ch)) + 1))
+#define NN_CMSG_SPACE(len) \
+	(NN_CMSG_ALIGN(len) + NN_CMSG_ALIGN(sizeof(struct nn_cmsghdr)))
+#define NN_CMSG_LEN(len) (NN_CMSG_ALIGN(sizeof(struct nn_cmsghdr)) + (len))
+
+NN_DECL struct nn_cmsghdr *nn_cmsg_next(
+    struct nn_msghdr *, struct nn_cmsghdr *);
+NN_DECL int nn_socket(int, int);
+NN_DECL int nn_setsockopt(int, int, int, const void *, size_t);
+NN_DECL int nn_getsockopt(int, int, int, void *, size_t *);
+NN_DECL int nn_bind(int, const char *);
+NN_DECL int nn_connect(int, const char *);
+NN_DECL int nn_shutdown(int, int);
+NN_DECL int nn_send(int, const void *, size_t, int);
+NN_DECL int nn_recv(int, void *, size_t, int);
+NN_DECL int nn_sendmsg(int, const struct nn_msghdr *, int);
+NN_DECL int nn_recvmsg(int, struct nn_msghdr *, int);
+NN_DECL int nn_close(int);
+NN_DECL int nn_poll(struct nn_pollfd *, int, int);
+NN_DECL int nn_device(int, int);
+NN_DECL uint64_t    nn_get_statistic(int, int);
+NN_DECL void *      nn_allocmsg(size_t, int);
+NN_DECL void *      nn_reallocmsg(void *, size_t);
+NN_DECL int         nn_freemsg(void *);
+NN_DECL int         nn_errno(void);
+NN_DECL const char *nn_strerror(int);
+NN_DECL void        nn_term(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_COMPAT_NN_H
diff --git a/include/nng/compat/nanomsg/pair.h b/include/nng/compat/nanomsg/pair.h
new file mode 100644
index 0000000..458aac8
--- /dev/null
+++ b/include/nng/compat/nanomsg/pair.h
@@ -0,0 +1,39 @@
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_COMPAT_PAIR_H
+#define NNG_COMPAT_PAIR_H
+
+// This header contains interfaces that are intended to offer compatibility
+// with nanomsg v1.0.  These are not the "preferred" interfaces for nng,
+// and consumers should only use these if they are porting software that
+// previously used nanomsg.  New programs should use the nng native APIs.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// PAIR sockopt level.
+#define NN_PROTO_PAIR 1
+#define NN_PAIR (NN_PROTO_PAIR * 16 + 0)
+
+// These are technically "new", and not available in nanomsg, but
+// offered here as a transition aid.  If you want to use the advanced
+// PAIRv1 options (POLYAMOROUS mode) you still need to use the new API.
+#define NN_PAIR_v0 (NN_PROTO_PAIR * 16 + 0)
+#define NN_PAIR_V1 (NN_PROTO_PAIR * 16 + 1)
+
+// PAIR has no options.
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_COMPAT_PAIR_H
diff --git a/include/nng/compat/nanomsg/pipeline.h b/include/nng/compat/nanomsg/pipeline.h
new file mode 100644
index 0000000..187a4b4
--- /dev/null
+++ b/include/nng/compat/nanomsg/pipeline.h
@@ -0,0 +1,34 @@
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_COMPAT_PIPELINE_H
+#define NNG_COMPAT_PIPELINE_H
+
+// This header contains interfaces that are intended to offer compatibility
+// with nanomsg v1.0.  These are not the "preferred" interfaces for nng,
+// and consumers should only use these if they are porting software that
+// previously used nanomsg.  New programs should use the nng native APIs.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// PUSH and PULL sockopt level.
+#define NN_PROTO_PIPELINE 5
+#define NN_PUSH (NN_PROTO_PIPELINE * 16 + 0)
+#define NN_PULL (NN_PROTO_PIPELINE * 16 + 1)
+
+// PUSH and PULL have no options.
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_COMPAT_PIPELINE_H
diff --git a/include/nng/compat/nanomsg/pubsub.h b/include/nng/compat/nanomsg/pubsub.h
new file mode 100644
index 0000000..43118f6
--- /dev/null
+++ b/include/nng/compat/nanomsg/pubsub.h
@@ -0,0 +1,36 @@
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_COMPAT_PUBSUB_H
+#define NNG_COMPAT_PUBSUB_H
+
+// This header contains interfaces that are intended to offer compatibility
+// with nanomsg v1.0.  These are not the "preferred" interfaces for nng,
+// and consumers should only use these if they are porting software that
+// previously used nanomsg.  New programs should use the nng native APIs.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// PUB and SUB sockopt level.
+#define NN_PROTO_PUBSUB 2
+#define NN_PUB (NN_PROTO_PUBSUB * 16 + 0)
+#define NN_SUB (NN_PROTO_PUBSUB * 16 + 1)
+
+// SUB options.  (PUB has none.)
+#define NN_SUB_SUBSCRIBE (NN_SUB * 16 + 1)
+#define NN_SUB_UNSUBSCRIBE (NN_SUB * 16 + 2)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_COMPAT_PUBSUB_H
diff --git a/include/nng/compat/nanomsg/reqrep.h b/include/nng/compat/nanomsg/reqrep.h
new file mode 100644
index 0000000..9490a8f
--- /dev/null
+++ b/include/nng/compat/nanomsg/reqrep.h
@@ -0,0 +1,35 @@
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_COMPAT_REQREP_H
+#define NNG_COMPAT_REQREP_H
+
+// This header contains interfaces that are intended to offer compatibility
+// with nanomsg v1.0.  These are not the "preferred" interfaces for nng,
+// and consumers should only use these if they are porting software that
+// previously used nanomsg.  New programs should use the nng native APIs.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// REQ and REP sockopt level.
+#define NN_PROTO_REQREP 3
+#define NN_REQ (NN_PROTO_REQREP * 16 + 0)
+#define NN_REP (NN_PROTO_REQREP * 16 + 1)
+
+// REQ options.  (REP has none.)
+#define NN_REQ_RESEND_IVL (NN_REQ * 16 + 1)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_COMPAT_REQREP_H
diff --git a/include/nng/compat/nanomsg/survey.h b/include/nng/compat/nanomsg/survey.h
new file mode 100644
index 0000000..fdef10c
--- /dev/null
+++ b/include/nng/compat/nanomsg/survey.h
@@ -0,0 +1,36 @@
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_COMPAT_SURVEY_H
+#define NNG_COMPAT_SURVEY_H
+
+// This header contains interfaces that are intended to offer compatibility
+// with nanomsg v1.0.  These are not the "preferred" interfaces for nng,
+// and consumers should only use these if they are porting software that
+// previously used nanomsg.  New programs should use the nng native APIs.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// SURVEYOR and RESPONDENT sockopt level.
+#define NN_PROTO_SURVEY 6
+#define NN_SURVEYOR (NN_PROTO_SURVEY * 16 + 2)
+#define NN_RESPONDENT (NN_PROTO_SURVEY * 16 + 3)
+
+// SURVEYOR options.  (RESPONDENT has none.)
+
+#define NN_SURVEYOR_DEADLINE (NN_SURVEYOR * 16 + 1)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_COMPAT_SURVEY_H
diff --git a/include/nng/compat/nanomsg/tcp.h b/include/nng/compat/nanomsg/tcp.h
new file mode 100644
index 0000000..5a305c4
--- /dev/null
+++ b/include/nng/compat/nanomsg/tcp.h
@@ -0,0 +1,33 @@
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_COMPAT_TCP_H
+#define NNG_COMPAT_TCP_H
+
+// This header contains interfaces that are intended to offer compatibility
+// with nanomsg v1.0.  These are not the "preferred" interfaces for nng,
+// and consumers should only use these if they are porting software that
+// previously used nanomsg.  New programs should use the nng native APIs.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// TCP sockopt level.
+#define NN_TCP (-3)
+
+// TCP options.
+#define NN_TCP_NODELAY 1
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_COMPAT_TCP_H
diff --git a/include/nng/compat/nanomsg/ws.h b/include/nng/compat/nanomsg/ws.h
new file mode 100644
index 0000000..3072a3b
--- /dev/null
+++ b/include/nng/compat/nanomsg/ws.h
@@ -0,0 +1,41 @@
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_COMPAT_WS_H
+#define NNG_COMPAT_WS_H
+
+// This header contains interfaces that are intended to offer compatibility
+// with nanomsg v1.0.  These are not the "preferred" interfaces for nng,
+// and consumers should only use these if they are porting software that
+// previously used nanomsg.  New programs should use the nng native APIs.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// WS sockopt level.
+#define NN_WS (-4)
+
+// WS options.
+
+// Note that while legacy libnanomsg had *some* support for text messages,
+// NNG only supports binary.  Binary types are required to pass protocol
+// headers with NNG and nanomsg in any event.  This means that the NNG
+// WebSocket support will not be compatible with some very old browsers.
+#define NN_WS_MSG_TYPE 1
+
+#define NN_WS_MSG_TYPE_TEXT 0x1
+#define NN_WS_MSG_TYPE_BINARY 0x2
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_COMPAT_WS_H
diff --git a/include/nng/nng.h b/include/nng/nng.h
new file mode 100644
index 0000000..c26cb5b
--- /dev/null
+++ b/include/nng/nng.h
@@ -0,0 +1,1266 @@
+//
+// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_NNG_H
+#define NNG_NNG_H
+
+// NNG (nanomsg-next-gen) is an improved implementation of the SP protocols.
+// The APIs have changed, and there is no attempt to provide API compatibility
+// with legacy libnanomsg. This file defines the library consumer-facing
+// Public API. Use of definitions or declarations not found in this header
+// file is specifically unsupported and strongly discouraged.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+// NNG_DECL is used on declarations to deal with scope.
+// For building Windows DLLs, it should be the appropriate __declspec().
+// For shared libraries with platforms that support hidden visibility,
+// it should evaluate to __attribute__((visibility("default"))).
+#ifndef NNG_DECL
+#if defined(_WIN32) && !defined(NNG_STATIC_LIB)
+#if defined(NNG_SHARED_LIB)
+#define NNG_DECL __declspec(dllexport)
+#else
+#define NNG_DECL __declspec(dllimport)
+#endif // NNG_SHARED_LIB
+#else
+#if defined(NNG_SHARED_LIB) && defined(NNG_HIDDEN_VISIBILITY)
+#define NNG_DECL __attribute__((visibility("default")))
+#else
+#define NNG_DECL extern
+#endif
+#endif // _WIN32 && !NNG_STATIC_LIB
+#endif // NNG_DECL
+
+// NNG Library & API version.
+// We use SemVer, and these versions are about the API, and
+// may not necessarily match the ABI versions. Right now at
+// version 0, you should not be making any forward compatibility
+// assumptions.
+#define NNG_MAJOR_VERSION 1
+#define NNG_MINOR_VERSION 3
+#define NNG_PATCH_VERSION 0
+#define NNG_RELEASE_SUFFIX "" // if non-empty, this is a pre-release
+
+// Maximum length of a socket address. This includes the terminating NUL.
+// This limit is built into other implementations, so do not change it.
+// Note that some transports are quite happy to let you use addresses
+// in excess of this, but if you do you may not be able to communicate
+// with other implementations.
+#define NNG_MAXADDRLEN (128)
+
+// NNG_PROTOCOL_NUMBER is used by protocol headers to calculate their
+// protocol number from a major and minor number.  Applications should
+// probably not need to use this.
+#define NNG_PROTOCOL_NUMBER(maj, min) (((x) *16) + (y))
+
+// Types common to nng.
+
+// Identifiers are wrapped in a structure to improve compiler validation
+// of incorrect passing.  This gives us strong type checking.  Modern
+// compilers compile passing these by value to identical code as passing
+// the integer type (at least with optimization applied).  Please do not
+// access the ID member directly.
+
+typedef struct nng_ctx_s {
+	uint32_t id;
+} nng_ctx;
+
+typedef struct nng_dialer_s {
+	uint32_t id;
+} nng_dialer;
+
+typedef struct nng_listener_s {
+	uint32_t id;
+} nng_listener;
+
+typedef struct nng_pipe_s {
+	uint32_t id;
+} nng_pipe;
+
+typedef struct nng_socket_s {
+	uint32_t id;
+} nng_socket;
+
+typedef int32_t         nng_duration; // in milliseconds
+typedef struct nng_msg  nng_msg;
+typedef struct nng_stat nng_stat;
+typedef struct nng_aio  nng_aio;
+
+// Initializers.
+// clang-format off
+#define NNG_PIPE_INITIALIZER { 0 }
+#define NNG_SOCKET_INITIALIZER { 0 }
+#define NNG_DIALER_INITIALIZER { 0 }
+#define NNG_LISTENER_INITIALIZER { 0 }
+#define NNG_CTX_INITIALIZER { 0 }
+// clang-format on
+
+// Some address details. This is in some ways like a traditional sockets
+// sockaddr, but we have our own to cope with our unique families, etc.
+// The details of this structure are directly exposed to applications.
+// These structures can be obtained via property lookups, etc.
+struct nng_sockaddr_inproc {
+	uint16_t sa_family;
+	char     sa_name[NNG_MAXADDRLEN];
+};
+typedef struct nng_sockaddr_inproc nng_sockaddr_inproc;
+
+struct nng_sockaddr_path {
+	uint16_t sa_family;
+	char     sa_path[NNG_MAXADDRLEN];
+};
+typedef struct nng_sockaddr_path nng_sockaddr_path;
+typedef struct nng_sockaddr_path nng_sockaddr_ipc;
+
+struct nng_sockaddr_in6 {
+	uint16_t sa_family;
+	uint16_t sa_port;
+	uint8_t  sa_addr[16];
+};
+typedef struct nng_sockaddr_in6 nng_sockaddr_in6;
+typedef struct nng_sockaddr_in6 nng_sockaddr_udp6;
+typedef struct nng_sockaddr_in6 nng_sockaddr_tcp6;
+
+struct nng_sockaddr_in {
+	uint16_t sa_family;
+	uint16_t sa_port;
+	uint32_t sa_addr;
+};
+
+struct nng_sockaddr_zt {
+	uint16_t sa_family;
+	uint64_t sa_nwid;
+	uint64_t sa_nodeid;
+	uint32_t sa_port;
+};
+
+typedef struct nng_sockaddr_in nng_sockaddr_in;
+typedef struct nng_sockaddr_in nng_sockaddr_udp;
+typedef struct nng_sockaddr_in nng_sockaddr_tcp;
+typedef struct nng_sockaddr_zt nng_sockaddr_zt;
+
+typedef union nng_sockaddr {
+	uint16_t            s_family;
+	nng_sockaddr_ipc    s_ipc;
+	nng_sockaddr_inproc s_inproc;
+	nng_sockaddr_in6    s_in6;
+	nng_sockaddr_in     s_in;
+	nng_sockaddr_zt     s_zt;
+} nng_sockaddr;
+
+enum nng_sockaddr_family {
+	NNG_AF_UNSPEC = 0,
+	NNG_AF_INPROC = 1,
+	NNG_AF_IPC    = 2,
+	NNG_AF_INET   = 3,
+	NNG_AF_INET6  = 4,
+	NNG_AF_ZT     = 5 // ZeroTier
+};
+
+// Scatter/gather I/O.
+typedef struct nng_iov {
+	void * iov_buf;
+	size_t iov_len;
+} nng_iov;
+
+// Some definitions for durations used with timeouts.
+#define NNG_DURATION_INFINITE (-1)
+#define NNG_DURATION_DEFAULT (-2)
+#define NNG_DURATION_ZERO (0)
+
+// nng_fini is used to terminate the library, freeing certain global resources.
+// This should only be called during atexit() or just before dlclose().
+// THIS FUNCTION MUST NOT BE CALLED CONCURRENTLY WITH ANY OTHER FUNCTION
+// IN THIS LIBRARY; IT IS NOT REENTRANT OR THREADSAFE.
+//
+// For most cases, this call is unnecessary, but it is provided to assist
+// when debugging with memory checkers (e.g. valgrind).  Calling this
+// function prevents global library resources from being reported incorrectly
+// as memory leaks.  In those cases, we recommend doing this with atexit().
+NNG_DECL void nng_fini(void);
+
+// nng_close closes the socket, terminating all activity and
+// closing any underlying connections and releasing any associated
+// resources.
+NNG_DECL int nng_close(nng_socket);
+
+// nng_socket_id returns the positive socket id for the socket, or -1
+// if the socket is not valid.
+NNG_DECL int nng_socket_id(nng_socket);
+
+// nng_closeall closes all open sockets. Do not call this from
+// a library; it will affect all sockets.
+NNG_DECL void nng_closeall(void);
+
+// nng_setopt sets an option for a specific socket.
+NNG_DECL int nng_setopt(nng_socket, const char *, const void *, size_t);
+NNG_DECL int nng_setopt_bool(nng_socket, const char *, bool);
+NNG_DECL int nng_setopt_int(nng_socket, const char *, int);
+NNG_DECL int nng_setopt_ms(nng_socket, const char *, nng_duration);
+NNG_DECL int nng_setopt_size(nng_socket, const char *, size_t);
+NNG_DECL int nng_setopt_uint64(nng_socket, const char *, uint64_t);
+NNG_DECL int nng_setopt_string(nng_socket, const char *, const char *);
+NNG_DECL int nng_setopt_ptr(nng_socket, const char *, void *);
+
+// nng_socket_getopt obtains the option for a socket.
+NNG_DECL int nng_getopt(nng_socket, const char *, void *, size_t *);
+NNG_DECL int nng_getopt_bool(nng_socket, const char *, bool *);
+NNG_DECL int nng_getopt_int(nng_socket, const char *, int *);
+NNG_DECL int nng_getopt_ms(nng_socket, const char *, nng_duration *);
+NNG_DECL int nng_getopt_size(nng_socket, const char *, size_t *);
+NNG_DECL int nng_getopt_uint64(nng_socket, const char *, uint64_t *);
+NNG_DECL int nng_getopt_ptr(nng_socket, const char *, void **);
+
+// nng_getopt_string is special -- it allocates a string to hold the
+// resulting string, which should be freed with nng_strfree when it is
+// no logner needed.
+NNG_DECL int nng_getopt_string(nng_socket, const char *, char **);
+
+NNG_DECL int nng_socket_set(nng_socket, const char *, const void *, size_t);
+NNG_DECL int nng_socket_set_bool(nng_socket, const char *, bool);
+NNG_DECL int nng_socket_set_int(nng_socket, const char *, int);
+NNG_DECL int nng_socket_set_size(nng_socket, const char *, size_t);
+NNG_DECL int nng_socket_set_uint64(nng_socket, const char *, uint64_t);
+NNG_DECL int nng_socket_set_string(nng_socket, const char *, const char *);
+NNG_DECL int nng_socket_set_ptr(nng_socket, const char *, void *);
+NNG_DECL int nng_socket_set_ms(nng_socket, const char *, nng_duration);
+NNG_DECL int nng_socket_set_addr(
+    nng_socket, const char *, const nng_sockaddr *);
+
+NNG_DECL int nng_socket_get(nng_socket, const char *, void *, size_t *);
+NNG_DECL int nng_socket_get_bool(nng_socket, const char *, bool *);
+NNG_DECL int nng_socket_get_int(nng_socket, const char *, int *);
+NNG_DECL int nng_socket_get_size(nng_socket, const char *, size_t *);
+NNG_DECL int nng_socket_get_uint64(nng_socket, const char *, uint64_t *);
+NNG_DECL int nng_socket_get_string(nng_socket, const char *, char **);
+NNG_DECL int nng_socket_get_ptr(nng_socket, const char *, void **);
+NNG_DECL int nng_socket_get_ms(nng_socket, const char *, nng_duration *);
+NNG_DECL int nng_socket_get_addr(nng_socket, const char *, nng_sockaddr *);
+
+// Arguably the pipe callback functions could be handled as an option,
+// but with the need to specify an argument, we find it best to unify
+// this as a separate function to pass in the argument and the callback.
+// Only one callback can be set on a given socket, and there is no way
+// to retrieve the old value.
+typedef enum {
+	NNG_PIPE_EV_ADD_PRE,  // Called just before pipe added to socket
+	NNG_PIPE_EV_ADD_POST, // Called just after pipe added to socket
+	NNG_PIPE_EV_REM_POST, // Called just after pipe removed from socket
+	NNG_PIPE_EV_NUM,      // Used internally, must be last.
+} nng_pipe_ev;
+
+typedef void (*nng_pipe_cb)(nng_pipe, nng_pipe_ev, void *);
+
+// nng_pipe_notify registers a callback to be executed when the
+// given event is triggered.  To watch for different events, register
+// multiple times.  Each event can have at most one callback registered.
+NNG_DECL int nng_pipe_notify(nng_socket, nng_pipe_ev, nng_pipe_cb, void *);
+
+// nng_listen creates a listening endpoint with no special options,
+// and starts it listening.  It is functionally equivalent to the legacy
+// nn_bind(). The underlying endpoint is returned back to the caller in the
+// endpoint pointer, if it is not NULL.  The flags are ignored at present.
+NNG_DECL int nng_listen(nng_socket, const char *, nng_listener *, int);
+
+// nng_dial creates a dialing endpoint, with no special options, and
+// starts it dialing.  Dialers have at most one active connection at a time
+// This is similar to the legacy nn_connect().  The underlying endpoint
+// is returned back to the caller in the endpoint pointer, if it is not NULL.
+// The flags may be NNG_FLAG_NONBLOCK to indicate that the first attempt to
+// dial will be made in the background, returning control to the caller
+// immediately.  In this case, if the connection fails, the function will
+// keep retrying in the background.  (If the connection is dropped in either
+// case, it will still be reconnected in the background -- only the initial
+// connection attempt is normally synchronous.)
+NNG_DECL int nng_dial(nng_socket, const char *, nng_dialer *, int);
+
+// nng_dialer_create creates a new dialer, that is not yet started.
+NNG_DECL int nng_dialer_create(nng_dialer *, nng_socket, const char *);
+
+// nng_listener_create creates a new listener, that is not yet started.
+NNG_DECL int nng_listener_create(nng_listener *, nng_socket, const char *);
+
+// nng_dialer_start starts the endpoint dialing.  This is only possible if
+// the dialer is not already dialing.
+NNG_DECL int nng_dialer_start(nng_dialer, int);
+
+// nng_listener_start starts the endpoint listening.  This is only possible if
+// the listener is not already listening.
+NNG_DECL int nng_listener_start(nng_listener, int);
+
+// nng_dialer_close closes the dialer, shutting down all underlying
+// connections and releasing all associated resources.
+NNG_DECL int nng_dialer_close(nng_dialer);
+
+// nng_listener_close closes the listener, shutting down all underlying
+// connections and releasing all associated resources.
+NNG_DECL int nng_listener_close(nng_listener);
+
+// nng_dialer_id returns the positive dialer ID, or -1 if the dialer is
+// invalid.
+NNG_DECL int nng_dialer_id(nng_dialer);
+
+// nng_listener_id returns the positive listener ID, or -1 if the listener is
+// invalid.
+NNG_DECL int nng_listener_id(nng_listener);
+
+// nng_dialer_setopt sets an option for a specific dialer.  Note
+// dialer options may not be altered on a running dialer.
+NNG_DECL int nng_dialer_setopt(nng_dialer, const char *, const void *, size_t);
+NNG_DECL int nng_dialer_setopt_bool(nng_dialer, const char *, bool);
+NNG_DECL int nng_dialer_setopt_int(nng_dialer, const char *, int);
+NNG_DECL int nng_dialer_setopt_ms(nng_dialer, const char *, nng_duration);
+NNG_DECL int nng_dialer_setopt_size(nng_dialer, const char *, size_t);
+NNG_DECL int nng_dialer_setopt_uint64(nng_dialer, const char *, uint64_t);
+NNG_DECL int nng_dialer_setopt_ptr(nng_dialer, const char *, void *);
+NNG_DECL int nng_dialer_setopt_string(nng_dialer, const char *, const char *);
+
+// nng_dialer_getopt obtains the option for a dialer. This will
+// fail for options that a particular dialer is not interested in,
+// even if they were set on the socket.
+NNG_DECL int nng_dialer_getopt(nng_dialer, const char *, void *, size_t *);
+NNG_DECL int nng_dialer_getopt_bool(nng_dialer, const char *, bool *);
+NNG_DECL int nng_dialer_getopt_int(nng_dialer, const char *, int *);
+NNG_DECL int nng_dialer_getopt_ms(nng_dialer, const char *, nng_duration *);
+NNG_DECL int nng_dialer_getopt_size(nng_dialer, const char *, size_t *);
+NNG_DECL int nng_dialer_getopt_sockaddr(
+    nng_dialer, const char *, nng_sockaddr *);
+NNG_DECL int nng_dialer_getopt_uint64(nng_dialer, const char *, uint64_t *);
+NNG_DECL int nng_dialer_getopt_ptr(nng_dialer, const char *, void **);
+
+// nng_dialer_getopt_string is special -- it allocates a string to hold the
+// resulting string, which should be freed with nng_strfree when it is
+// no logner needed.
+NNG_DECL int nng_dialer_getopt_string(nng_dialer, const char *, char **);
+
+NNG_DECL int nng_dialer_set(nng_dialer, const char *, const void *, size_t);
+NNG_DECL int nng_dialer_set_bool(nng_dialer, const char *, bool);
+NNG_DECL int nng_dialer_set_int(nng_dialer, const char *, int);
+NNG_DECL int nng_dialer_set_size(nng_dialer, const char *, size_t);
+NNG_DECL int nng_dialer_set_uint64(nng_dialer, const char *, uint64_t);
+NNG_DECL int nng_dialer_set_string(nng_dialer, const char *, const char *);
+NNG_DECL int nng_dialer_set_ptr(nng_dialer, const char *, void *);
+NNG_DECL int nng_dialer_set_ms(nng_dialer, const char *, nng_duration);
+NNG_DECL int nng_dialer_set_addr(
+    nng_dialer, const char *, const nng_sockaddr *);
+
+NNG_DECL int nng_dialer_get(nng_dialer, const char *, void *, size_t *);
+NNG_DECL int nng_dialer_get_bool(nng_dialer, const char *, bool *);
+NNG_DECL int nng_dialer_get_int(nng_dialer, const char *, int *);
+NNG_DECL int nng_dialer_get_size(nng_dialer, const char *, size_t *);
+NNG_DECL int nng_dialer_get_uint64(nng_dialer, const char *, uint64_t *);
+NNG_DECL int nng_dialer_get_string(nng_dialer, const char *, char **);
+NNG_DECL int nng_dialer_get_ptr(nng_dialer, const char *, void **);
+NNG_DECL int nng_dialer_get_ms(nng_dialer, const char *, nng_duration *);
+NNG_DECL int nng_dialer_get_addr(nng_dialer, const char *, nng_sockaddr *);
+
+// nng_listener_setopt sets an option for a dialer.  This value is
+// not stored in the socket.  Subsequent setopts on the socket may
+// override these value however.  Note listener options may not be altered
+// on a running listener.
+NNG_DECL int nng_listener_setopt(
+    nng_listener, const char *, const void *, size_t);
+NNG_DECL int nng_listener_setopt_bool(nng_listener, const char *, bool);
+NNG_DECL int nng_listener_setopt_int(nng_listener, const char *, int);
+NNG_DECL int nng_listener_setopt_ms(nng_listener, const char *, nng_duration);
+NNG_DECL int nng_listener_setopt_size(nng_listener, const char *, size_t);
+NNG_DECL int nng_listener_setopt_uint64(nng_listener, const char *, uint64_t);
+NNG_DECL int nng_listener_setopt_ptr(nng_listener, const char *, void *);
+NNG_DECL int nng_listener_setopt_string(
+    nng_listener, const char *, const char *);
+
+// nng_listener_getopt obtains the option for a listener.  This will
+// fail for options that a particular listener is not interested in,
+// even if they were set on the socket.
+NNG_DECL int nng_listener_getopt(nng_listener, const char *, void *, size_t *);
+NNG_DECL int nng_listener_getopt_bool(nng_listener, const char *, bool *);
+NNG_DECL int nng_listener_getopt_int(nng_listener, const char *, int *);
+NNG_DECL int nng_listener_getopt_ms(
+    nng_listener, const char *, nng_duration *);
+NNG_DECL int nng_listener_getopt_size(nng_listener, const char *, size_t *);
+NNG_DECL int nng_listener_getopt_sockaddr(
+    nng_listener, const char *, nng_sockaddr *);
+NNG_DECL int nng_listener_getopt_uint64(
+    nng_listener, const char *, uint64_t *);
+NNG_DECL int nng_listener_getopt_ptr(nng_listener, const char *, void **);
+
+// nng_listener_getopt_string is special -- it allocates a string to hold the
+// resulting string, which should be freed with nng_strfree when it is
+// no logner needed.
+NNG_DECL int nng_listener_getopt_string(nng_listener, const char *, char **);
+
+NNG_DECL int nng_listener_set(
+    nng_listener, const char *, const void *, size_t);
+NNG_DECL int nng_listener_set_bool(nng_listener, const char *, bool);
+NNG_DECL int nng_listener_set_int(nng_listener, const char *, int);
+NNG_DECL int nng_listener_set_size(nng_listener, const char *, size_t);
+NNG_DECL int nng_listener_set_uint64(nng_listener, const char *, uint64_t);
+NNG_DECL int nng_listener_set_string(nng_listener, const char *, const char *);
+NNG_DECL int nng_listener_set_ptr(nng_listener, const char *, void *);
+NNG_DECL int nng_listener_set_ms(nng_listener, const char *, nng_duration);
+NNG_DECL int nng_listener_set_addr(
+    nng_listener, const char *, const nng_sockaddr *);
+
+NNG_DECL int nng_listener_get(nng_listener, const char *, void *, size_t *);
+NNG_DECL int nng_listener_get_bool(nng_listener, const char *, bool *);
+NNG_DECL int nng_listener_get_int(nng_listener, const char *, int *);
+NNG_DECL int nng_listener_get_size(nng_listener, const char *, size_t *);
+NNG_DECL int nng_listener_get_uint64(nng_listener, const char *, uint64_t *);
+NNG_DECL int nng_listener_get_string(nng_listener, const char *, char **);
+NNG_DECL int nng_listener_get_ptr(nng_listener, const char *, void **);
+NNG_DECL int nng_listener_get_ms(nng_listener, const char *, nng_duration *);
+NNG_DECL int nng_listener_get_addr(nng_listener, const char *, nng_sockaddr *);
+
+// nng_strerror returns a human readable string associated with the error
+// code supplied.
+NNG_DECL const char *nng_strerror(int);
+
+// nng_send sends (or arranges to send) the data on the socket.  Note that
+// this function may (will!) return before any receiver has actually
+// received the data.  The return value will be zero to indicate that the
+// socket has accepted the entire data for send, or an errno to indicate
+// failure.  The flags may include NNG_FLAG_NONBLOCK or NNG_FLAG_ALLOC.
+// If the flag includes NNG_FLAG_ALLOC, then the function will call
+// nng_free() on the supplied pointer & size on success. (If the call
+// fails then the memory is not freed.)
+NNG_DECL int nng_send(nng_socket, void *, size_t, int);
+
+// nng_recv receives message data into the socket, up to the supplied size.
+// The actual size of the message data will be written to the value pointed
+// to by size.  The flags may include NNG_FLAG_NONBLOCK and NNG_FLAG_ALLOC.
+// If NNG_FLAG_ALLOC is supplied then the library will allocate memory for
+// the caller.  In that case the pointer to the allocated will be stored
+// instead of the data itself.  The caller is responsible for freeing the
+// associated memory with nng_free().
+NNG_DECL int nng_recv(nng_socket, void *, size_t *, int);
+
+// nng_sendmsg is like nng_send, but offers up a message structure, which
+// gives the ability to provide more control over the message, including
+// providing backtrace information.  It also can take a message that was
+// obtain via nn_recvmsg, allowing for zero copy forwarding.
+NNG_DECL int nng_sendmsg(nng_socket, nng_msg *, int);
+
+// nng_recvmsg is like nng_recv, but is used to obtain a message structure
+// as well as the data buffer.  This can be used to obtain more information
+// about where the message came from, access raw headers, etc.  It also
+// can be passed off directly to nng_sendmsg.
+NNG_DECL int nng_recvmsg(nng_socket, nng_msg **, int);
+
+// nng_send_aio sends data on the socket asynchronously.  As with nng_send,
+// the completion may be executed before the data has actually been delivered,
+// but only when it is accepted for delivery.  The supplied AIO must have
+// been initialized, and have an associated message.  The message will be
+// "owned" by the socket if the operation completes successfully.  Otherwise
+// the caller is responsible for freeing it.
+NNG_DECL void nng_send_aio(nng_socket, nng_aio *);
+
+// nng_recv_aio receives data on the socket asynchronously.  On a successful
+// result, the AIO will have an associated message, that can be obtained
+// with nng_aio_get_msg().  The caller takes ownership of the message at
+// this point.
+NNG_DECL void nng_recv_aio(nng_socket, nng_aio *);
+
+// Context support.  User contexts are not supported by all protocols,
+// but for those that do, they give a way to create multiple contexts
+// on a single socket, each of which runs the protocol's state machinery
+// independently, offering a way to achieve concurrent protocol support
+// without resorting to raw mode sockets.  See the protocol specific
+// documentation for further details.  (Note that at this time, only
+// asynchronous send/recv are supported for contexts, but its easy enough
+// to make synchronous versions with nng_aio_wait().)  Note that nng_close
+// of the parent socket will *block* as long as any contexts are open.
+
+// nng_ctx_open creates a context.  This returns NNG_ENOTSUP if the
+// protocol implementation does not support separate contexts.
+NNG_DECL int nng_ctx_open(nng_ctx *, nng_socket);
+
+// nng_ctx_close closes the context.
+NNG_DECL int nng_ctx_close(nng_ctx);
+
+// nng_ctx_id returns the numeric id for the context; this will be
+// a positive value for a valid context, or < 0 for an invalid context.
+// A valid context is not necessarily an *open* context.
+NNG_DECL int nng_ctx_id(nng_ctx);
+
+// nng_ctx_recv receives asynchronously.  It works like nng_recv_aio, but
+// uses a local context instead of the socket global context.
+NNG_DECL void nng_ctx_recv(nng_ctx, nng_aio *);
+
+// nng_ctx_send sends asynchronously. It works like nng_send_aio, but
+// uses a local context instead of the socket global context.
+NNG_DECL void nng_ctx_send(nng_ctx, nng_aio *);
+
+// nng_ctx_getopt is used to retrieve a context-specific option.  This
+// can only be used for those options that relate to specific context
+// tunables (which does include NNG_OPT_SENDTIMEO and NNG_OPT_RECVTIMEO);
+// see the protocol documentation for more details.
+NNG_DECL int nng_ctx_getopt(nng_ctx, const char *, void *, size_t *);
+NNG_DECL int nng_ctx_getopt_bool(nng_ctx, const char *, bool *);
+NNG_DECL int nng_ctx_getopt_int(nng_ctx, const char *, int *);
+NNG_DECL int nng_ctx_getopt_ms(nng_ctx, const char *, nng_duration *);
+NNG_DECL int nng_ctx_getopt_size(nng_ctx, const char *, size_t *);
+
+// nng_ctx_setopt is used to set a context-specific option.  This
+// can only be used for those options that relate to specific context
+// tunables (which does include NNG_OPT_SENDTIMEO and NNG_OPT_RECVTIMEO);
+// see the protocol documentation for more details.
+NNG_DECL int nng_ctx_setopt(nng_ctx, const char *, const void *, size_t);
+NNG_DECL int nng_ctx_setopt_bool(nng_ctx, const char *, bool);
+NNG_DECL int nng_ctx_setopt_int(nng_ctx, const char *, int);
+NNG_DECL int nng_ctx_setopt_ms(nng_ctx, const char *, nng_duration);
+NNG_DECL int nng_ctx_setopt_size(nng_ctx, const char *, size_t);
+
+NNG_DECL int nng_ctx_get(nng_ctx, const char *, void *, size_t *);
+NNG_DECL int nng_ctx_get_bool(nng_ctx, const char *, bool *);
+NNG_DECL int nng_ctx_get_int(nng_ctx, const char *, int *);
+NNG_DECL int nng_ctx_get_size(nng_ctx, const char *, size_t *);
+NNG_DECL int nng_ctx_get_uint64(nng_ctx, const char *, uint64_t *);
+NNG_DECL int nng_ctx_get_string(nng_ctx, const char *, char **);
+NNG_DECL int nng_ctx_get_ptr(nng_ctx, const char *, void **);
+NNG_DECL int nng_ctx_get_ms(nng_ctx, const char *, nng_duration *);
+NNG_DECL int nng_ctx_get_addr(nng_ctx, const char *, nng_sockaddr *);
+
+NNG_DECL int nng_ctx_set(nng_ctx, const char *, const void *, size_t);
+NNG_DECL int nng_ctx_set_bool(nng_ctx, const char *, bool);
+NNG_DECL int nng_ctx_set_int(nng_ctx, const char *, int);
+NNG_DECL int nng_ctx_set_size(nng_ctx, const char *, size_t);
+NNG_DECL int nng_ctx_set_uint64(nng_ctx, const char *, uint64_t);
+NNG_DECL int nng_ctx_set_string(nng_ctx, const char *, const char *);
+NNG_DECL int nng_ctx_set_ptr(nng_ctx, const char *, void *);
+NNG_DECL int nng_ctx_set_ms(nng_ctx, const char *, nng_duration);
+NNG_DECL int nng_ctx_set_addr(nng_ctx, const char *, const nng_sockaddr *);
+
+// nng_alloc is used to allocate memory.  It's intended purpose is for
+// allocating memory suitable for message buffers with nng_send().
+// Applications that need memory for other purposes should use their platform
+// specific API.
+NNG_DECL void *nng_alloc(size_t);
+
+// nng_free is used to free memory allocated with nng_alloc, which includes
+// memory allocated by nng_recv() when the NNG_FLAG_ALLOC message is supplied.
+// As the application is required to keep track of the size of memory, this
+// is probably less convenient for general uses than the C library malloc and
+// calloc.
+NNG_DECL void nng_free(void *, size_t);
+
+// nng_strdup duplicates the source string, using nng_alloc. The result
+// should be freed with nng_strfree (or nng_free(strlen(s)+1)).
+NNG_DECL char *nng_strdup(const char *);
+
+// nng_strfree is equivalent to nng_free(strlen(s)+1).
+NNG_DECL void nng_strfree(char *);
+
+// Async IO API.  AIO structures can be thought of as "handles" to
+// support asynchronous operations.  They contain the completion callback, and
+// a pointer to consumer data.  This is similar to how overlapped I/O
+// works in Windows, when used with a completion callback.
+//
+// AIO structures can carry up to 4 distinct input values, and up to
+// 4 distinct output values, and up to 4 distinct "private state" values.
+// The meaning of the inputs and the outputs are determined by the
+// I/O functions being called.
+
+// nng_aio_alloc allocates a new AIO, and associated the completion
+// callback and its opaque argument.  If NULL is supplied for the
+// callback, then the caller must use nng_aio_wait() to wait for the
+// operation to complete.  If the completion callback is not NULL, then
+// when a submitted operation completes (or is canceled or fails) the
+// callback will be executed, generally in a different thread, with no
+// locks held.
+NNG_DECL int nng_aio_alloc(nng_aio **, void (*)(void *), void *);
+
+// nng_aio_free frees the AIO and any associated resources.
+// It *must not* be in use at the time it is freed.
+NNG_DECL void nng_aio_free(nng_aio *);
+
+// nng_aio_stop stops any outstanding operation, and waits for the
+// AIO to be free, including for the callback to have completed
+// execution.  Therefore the caller must NOT hold any locks that
+// are acquired in the callback, or deadlock will occur.
+NNG_DECL void nng_aio_stop(nng_aio *);
+
+// nng_aio_result returns the status/result of the operation. This
+// will be zero on successful completion, or an nng error code on
+// failure.
+NNG_DECL int nng_aio_result(nng_aio *);
+
+// nng_aio_count returns the number of bytes transferred for certain
+// I/O operations.  This is meaningless for other operations (e.g.
+// DNS lookups or TCP connection setup).
+NNG_DECL size_t nng_aio_count(nng_aio *);
+
+// nng_aio_cancel attempts to cancel any in-progress I/O operation.
+// The AIO callback will still be executed, but if the cancellation is
+// successful then the status will be NNG_ECANCELED.
+NNG_DECL void nng_aio_cancel(nng_aio *);
+
+// nng_aio_abort is like nng_aio_cancel, but allows for a different
+// error result to be returned.
+NNG_DECL void nng_aio_abort(nng_aio *, int);
+
+// nng_aio_wait waits synchronously for any pending operation to complete.
+// It also waits for the callback to have completed execution.  Therefore,
+// the caller of this function must not hold any locks acquired by the
+// callback or deadlock may occur.
+NNG_DECL void nng_aio_wait(nng_aio *);
+
+// nng_aio_set_msg sets the message structure to use for asynchronous
+// message send operations.
+NNG_DECL void nng_aio_set_msg(nng_aio *, nng_msg *);
+
+// nng_aio_get_msg returns the message structure associated with a completed
+// receive operation.
+NNG_DECL nng_msg *nng_aio_get_msg(nng_aio *);
+
+// nng_aio_set_input sets an input parameter at the given index.
+NNG_DECL int nng_aio_set_input(nng_aio *, unsigned, void *);
+
+// nng_aio_get_input retrieves the input parameter at the given index.
+NNG_DECL void *nng_aio_get_input(nng_aio *, unsigned);
+
+// nng_aio_set_output sets an output result at the given index.
+NNG_DECL int nng_aio_set_output(nng_aio *, unsigned, void *);
+
+// nng_aio_get_output retrieves the output result at the given index.
+NNG_DECL void *nng_aio_get_output(nng_aio *, unsigned);
+
+// nng_aio_set_timeout sets a timeout on the AIO.  This should be called for
+// operations that should time out after a period.  The timeout should be
+// either a positive number of milliseconds, or NNG_DURATION_INFINITE to
+// indicate that the operation has no timeout.  A poll may be done by
+// specifying NNG_DURATION_ZERO.  The value NNG_DURATION_DEFAULT indicates
+// that any socket specific timeout should be used.
+NNG_DECL void nng_aio_set_timeout(nng_aio *, nng_duration);
+
+// nng_aio_set_iov sets a scatter/gather vector on the aio.  The iov array
+// itself is copied. Data members (the memory regions referenced) *may* be
+// copied as well, depending on the operation.  This operation is guaranteed
+// to succeed if n <= 4, otherwise it may fail due to NNG_ENOMEM.
+NNG_DECL int nng_aio_set_iov(nng_aio *, unsigned, const nng_iov *);
+
+// nng_aio_begin is called by the provider to mark the operation as
+// beginning.  If it returns false, then the provider must take no
+// further action on the aio.
+NNG_DECL bool nng_aio_begin(nng_aio *);
+
+// nng_aio_finish is used to "finish" an asynchronous operation.
+// It should only be called by "providers" (such as HTTP server API users).
+// The argument is the value that nng_aio_result() should return.
+// IMPORTANT: Callers must ensure that this is called EXACTLY ONCE on any
+// given aio.
+NNG_DECL void nng_aio_finish(nng_aio *, int);
+
+// nng_aio_defer is used to register a cancellation routine, and indicate
+// that the operation will be completed asynchronously.  It must only be
+// called once per operation on an aio, and must only be called by providers.
+// If the operation is canceled by the consumer, the cancellation callback
+// will be called.  The provider *must* still ensure that the nng_aio_finish()
+// function is called EXACTLY ONCE.  If the operation cannot be canceled
+// for any reason, the cancellation callback should do nothing.  The
+// final argument is passed to the cancelfn.  The final argument of the
+// cancellation function is the error number (will not be zero) corresponding
+// to the reason for cancellation, e.g. NNG_ETIMEDOUT or NNG_ECANCELED.
+typedef void (*nng_aio_cancelfn)(nng_aio *, void *, int);
+NNG_DECL void nng_aio_defer(nng_aio *, nng_aio_cancelfn, void *);
+
+// nng_aio_sleep does a "sleeping" operation, basically does nothing
+// but wait for the specified number of milliseconds to expire, then
+// calls the callback.  This returns 0, rather than NNG_ETIMEDOUT.
+NNG_DECL void nng_sleep_aio(nng_duration, nng_aio *);
+
+// Message API.
+NNG_DECL int      nng_msg_alloc(nng_msg **, size_t);
+NNG_DECL void     nng_msg_free(nng_msg *);
+NNG_DECL int      nng_msg_realloc(nng_msg *, size_t);
+NNG_DECL void *   nng_msg_header(nng_msg *);
+NNG_DECL size_t   nng_msg_header_len(const nng_msg *);
+NNG_DECL void *   nng_msg_body(nng_msg *);
+NNG_DECL size_t   nng_msg_len(const nng_msg *);
+NNG_DECL int      nng_msg_append(nng_msg *, const void *, size_t);
+NNG_DECL int      nng_msg_insert(nng_msg *, const void *, size_t);
+NNG_DECL int      nng_msg_trim(nng_msg *, size_t);
+NNG_DECL int      nng_msg_chop(nng_msg *, size_t);
+NNG_DECL int      nng_msg_header_append(nng_msg *, const void *, size_t);
+NNG_DECL int      nng_msg_header_insert(nng_msg *, const void *, size_t);
+NNG_DECL int      nng_msg_header_trim(nng_msg *, size_t);
+NNG_DECL int      nng_msg_header_chop(nng_msg *, size_t);
+NNG_DECL int      nng_msg_header_append_u16(nng_msg *, uint16_t);
+NNG_DECL int      nng_msg_header_append_u32(nng_msg *, uint32_t);
+NNG_DECL int      nng_msg_header_append_u64(nng_msg *, uint64_t);
+NNG_DECL int      nng_msg_header_insert_u16(nng_msg *, uint16_t);
+NNG_DECL int      nng_msg_header_insert_u32(nng_msg *, uint32_t);
+NNG_DECL int      nng_msg_header_insert_u64(nng_msg *, uint64_t);
+NNG_DECL int      nng_msg_header_chop_u16(nng_msg *, uint16_t *);
+NNG_DECL int      nng_msg_header_chop_u32(nng_msg *, uint32_t *);
+NNG_DECL int      nng_msg_header_chop_u64(nng_msg *, uint64_t *);
+NNG_DECL int      nng_msg_header_trim_u16(nng_msg *, uint16_t *);
+NNG_DECL int      nng_msg_header_trim_u32(nng_msg *, uint32_t *);
+NNG_DECL int      nng_msg_header_trim_u64(nng_msg *, uint64_t *);
+NNG_DECL int      nng_msg_append_u16(nng_msg *, uint16_t);
+NNG_DECL int      nng_msg_append_u32(nng_msg *, uint32_t);
+NNG_DECL int      nng_msg_append_u64(nng_msg *, uint64_t);
+NNG_DECL int      nng_msg_insert_u16(nng_msg *, uint16_t);
+NNG_DECL int      nng_msg_insert_u32(nng_msg *, uint32_t);
+NNG_DECL int      nng_msg_insert_u64(nng_msg *, uint64_t);
+NNG_DECL int      nng_msg_chop_u16(nng_msg *, uint16_t *);
+NNG_DECL int      nng_msg_chop_u32(nng_msg *, uint32_t *);
+NNG_DECL int      nng_msg_chop_u64(nng_msg *, uint64_t *);
+NNG_DECL int      nng_msg_trim_u16(nng_msg *, uint16_t *);
+NNG_DECL int      nng_msg_trim_u32(nng_msg *, uint32_t *);
+NNG_DECL int      nng_msg_trim_u64(nng_msg *, uint64_t *);
+NNG_DECL int      nng_msg_dup(nng_msg **, const nng_msg *);
+NNG_DECL void     nng_msg_clear(nng_msg *);
+NNG_DECL void     nng_msg_header_clear(nng_msg *);
+NNG_DECL void     nng_msg_set_pipe(nng_msg *, nng_pipe);
+NNG_DECL nng_pipe nng_msg_get_pipe(const nng_msg *);
+
+// nng_msg_getopt is defunct, and should not be used by programs. It
+// always returns NNG_ENOTSUP.
+NNG_DECL int nng_msg_getopt(nng_msg *, int, void *, size_t *);
+
+// Pipe API. Generally pipes are only "observable" to applications, but
+// we do permit an application to close a pipe. This can be useful, for
+// example during a connection notification, to disconnect a pipe that
+// is associated with an invalid or untrusted remote peer.
+NNG_DECL int nng_pipe_getopt(nng_pipe, const char *, void *, size_t *);
+NNG_DECL int nng_pipe_getopt_bool(nng_pipe, const char *, bool *);
+NNG_DECL int nng_pipe_getopt_int(nng_pipe, const char *, int *);
+NNG_DECL int nng_pipe_getopt_ms(nng_pipe, const char *, nng_duration *);
+NNG_DECL int nng_pipe_getopt_size(nng_pipe, const char *, size_t *);
+NNG_DECL int nng_pipe_getopt_sockaddr(nng_pipe, const char *, nng_sockaddr *);
+NNG_DECL int nng_pipe_getopt_uint64(nng_pipe, const char *, uint64_t *);
+NNG_DECL int nng_pipe_getopt_ptr(nng_pipe, const char *, void **);
+NNG_DECL int nng_pipe_getopt_string(nng_pipe, const char *, char **);
+
+NNG_DECL int nng_pipe_get(nng_pipe, const char *, void *, size_t *);
+NNG_DECL int nng_pipe_get_bool(nng_pipe, const char *, bool *);
+NNG_DECL int nng_pipe_get_int(nng_pipe, const char *, int *);
+NNG_DECL int nng_pipe_get_ms(nng_pipe, const char *, nng_duration *);
+NNG_DECL int nng_pipe_get_size(nng_pipe, const char *, size_t *);
+NNG_DECL int nng_pipe_get_uint64(nng_pipe, const char *, uint64_t *);
+NNG_DECL int nng_pipe_get_string(nng_pipe, const char *, char **);
+NNG_DECL int nng_pipe_get_ptr(nng_pipe, const char *, void **);
+NNG_DECL int nng_pipe_get_addr(nng_pipe, const char *, nng_sockaddr *);
+
+NNG_DECL int          nng_pipe_close(nng_pipe);
+NNG_DECL int          nng_pipe_id(nng_pipe);
+NNG_DECL nng_socket   nng_pipe_socket(nng_pipe);
+NNG_DECL nng_dialer   nng_pipe_dialer(nng_pipe);
+NNG_DECL nng_listener nng_pipe_listener(nng_pipe);
+
+// Flags.
+enum nng_flag_enum {
+	NNG_FLAG_ALLOC    = 1, // Recv to allocate receive buffer.
+	NNG_FLAG_NONBLOCK = 2  // Non-blocking operations.
+};
+
+// Options.
+#define NNG_OPT_SOCKNAME "socket-name"
+#define NNG_OPT_RAW "raw"
+#define NNG_OPT_PROTO "protocol"
+#define NNG_OPT_PROTONAME "protocol-name"
+#define NNG_OPT_PEER "peer"
+#define NNG_OPT_PEERNAME "peer-name"
+#define NNG_OPT_RECVBUF "recv-buffer"
+#define NNG_OPT_SENDBUF "send-buffer"
+#define NNG_OPT_RECVFD "recv-fd"
+#define NNG_OPT_SENDFD "send-fd"
+#define NNG_OPT_RECVTIMEO "recv-timeout"
+#define NNG_OPT_SENDTIMEO "send-timeout"
+#define NNG_OPT_LOCADDR "local-address"
+#define NNG_OPT_REMADDR "remote-address"
+#define NNG_OPT_URL "url"
+#define NNG_OPT_MAXTTL "ttl-max"
+#define NNG_OPT_RECVMAXSZ "recv-size-max"
+#define NNG_OPT_RECONNMINT "reconnect-time-min"
+#define NNG_OPT_RECONNMAXT "reconnect-time-max"
+
+// TLS options are only used when the underlying transport supports TLS.
+
+// NNG_OPT_TLS_CONFIG is a pointer to an nng_tls_config object.  Generally
+// this can used with endpoints, although once an endpoint is started, or
+// once a configuration is used, the value becomes read-only. Note that
+// when configuring the object, a hold is placed on the TLS configuration,
+// using a reference count.  When retrieving the object, no such hold is
+// placed, and so the caller must take care not to use the associated object
+// after the endpoint it is associated with is closed.
+#define NNG_OPT_TLS_CONFIG "tls-config"
+
+// NNG_OPT_TLS_AUTH_MODE is a write-only integer (int) option that specifies
+// whether peer authentication is needed.  The option can take one of the
+// values of NNG_TLS_AUTH_MODE_NONE, NNG_TLS_AUTH_MODE_OPTIONAL, or
+// NNG_TLS_AUTH_MODE_REQUIRED.  The default is typically NNG_TLS_AUTH_MODE_NONE
+// for listeners, and NNG_TLS_AUTH_MODE_REQUIRED for dialers. If set to
+// REQUIRED, then connections will be rejected if the peer cannot be verified.
+// If set to OPTIONAL, then a verification step takes place, but the connection
+// is still permitted.  (The result can be checked with NNG_OPT_TLS_VERIFIED).
+#define NNG_OPT_TLS_AUTH_MODE "tls-authmode"
+
+// NNG_OPT_TLS_CERT_KEY_FILE names a single file that contains a certificate
+// and key identifying the endpoint.  This is a write-only value.  This can be
+// set multiple times for times for different keys/certs corresponding to
+// different algorithms on listeners, whereas dialers only support one.  The
+// file must contain both cert and key as PEM blocks, and the key must
+// not be encrypted.  (If more flexibility is needed, use the TLS configuration
+// directly, via NNG_OPT_TLS_CONFIG.)
+#define NNG_OPT_TLS_CERT_KEY_FILE "tls-cert-key-file"
+
+// NNG_OPT_TLS_CA_FILE names a single file that contains certificate(s) for a
+// CA, and optionally CRLs, which are used to validate the peer's certificate.
+// This is a write-only value, but multiple CAs can be loaded by setting this
+// multiple times.
+#define NNG_OPT_TLS_CA_FILE "tls-ca-file"
+
+// NNG_OPT_TLS_SERVER_NAME is a write-only string that can typically be
+// set on dialers to check the CN of the server for a match.  This
+// can also affect SNI (server name indication).  It usually has no effect
+// on listeners.
+#define NNG_OPT_TLS_SERVER_NAME "tls-server-name"
+
+// NNG_OPT_TLS_VERIFIED returns a boolean indicating whether the peer has
+// been verified (true) or not (false). Typically this is read-only, and
+// only available for pipes. This option may return incorrect results if
+// peer authentication is disabled with `NNG_TLS_AUTH_MODE_NONE`.
+#define NNG_OPT_TLS_VERIFIED "tls-verified"
+
+// TCP options.  These may be supported on various transports that use
+// TCP underneath such as TLS, or not.
+
+// TCP nodelay disables the use of Nagle, so that messages are sent
+// as soon as data is available. This tends to reduce latency, but
+// can come at the cost of extra messages being sent, and may have
+// a detrimental effect on performance. For most uses, we recommend
+// enabling this. (Disable it if you are on a very slow network.)
+// This is a boolean.
+#define NNG_OPT_TCP_NODELAY "tcp-nodelay"
+
+// TCP keepalive causes the underlying transport to send keep-alive
+// messages, and keep the session active. Keepalives are zero length
+// messages with the ACK flag turned on. If we don't get an ACK back,
+// then we know the other side is gone. This is useful for detecting
+// dead peers, and is also used to prevent disconnections caused by
+// middle boxes thinking the session has gone idle (e.g. keeping NAT
+// state current). This is a boolean.
+#define NNG_OPT_TCP_KEEPALIVE "tcp-keepalive"
+
+// Local TCP port number.  This is used on a listener, and is intended
+// to be used after starting the listener in combination with a wildcard
+// (0) local port.  This determines the actual ephemeral port that was
+// selected and bound.  The value is provided as an int, but only the
+// low order 16 bits will be set.  This is provided in native byte order,
+// which makes it more convenient than using the NNG_OPT_LOCADDR option.
+#define NNG_OPT_TCP_BOUND_PORT "tcp-bound-port"
+
+// IPC options.  These will largely vary depending on the platform,
+// as POSIX systems have very different options than Windows.
+
+// Security Descriptor.  This option may only be set on listeners
+// on the Windows platform, where the object is a pointer to a
+// a Windows SECURITY_DESCRIPTOR.
+#define NNG_OPT_IPC_SECURITY_DESCRIPTOR "ipc:security-descriptor"
+
+// Permissions bits.  This option is only valid for listeners on
+// POSIX platforms and others that honor UNIX style permission bits.
+// Note that some platforms may not honor the permissions here, although
+// at least Linux and macOS seem to do so.  Check before you rely on
+// this for security.
+#define NNG_OPT_IPC_PERMISSIONS "ipc:permissions"
+
+// Peer UID.  This is only available on POSIX style systems.
+#define NNG_OPT_IPC_PEER_UID "ipc:peer-uid"
+
+// Peer GID (primary group).  This is only available on POSIX style systems.
+#define NNG_OPT_IPC_PEER_GID "ipc:peer-gid"
+
+// Peer process ID.  Available on Windows, Linux, and SunOS.
+// In theory we could obtain this with the first message sent,
+// but we have elected not to do this for now. (Nice RFE for a FreeBSD
+// guru though.)
+#define NNG_OPT_IPC_PEER_PID "ipc:peer-pid"
+
+// Peer Zone ID.  Only on SunOS systems.  (Linux containers have no
+// definable kernel identity; they are a user-land fabrication made up
+// from various pieces of different namespaces. FreeBSD does have
+// something called JailIDs, but it isn't obvious how to determine this,
+// or even if processes can use IPC across jail boundaries.)
+#define NNG_OPT_IPC_PEER_ZONEID "ipc:peer-zoneid"
+
+// WebSocket Options.
+
+// NNG_OPT_WS_REQUEST_HEADERS is a string containing the
+// request headers, formatted as CRLF terminated lines.
+#define NNG_OPT_WS_REQUEST_HEADERS "ws:request-headers"
+
+// NNG_OPT_WS_RESPONSE_HEADERS is a string containing the
+// response headers, formatted as CRLF terminated lines.
+#define NNG_OPT_WS_RESPONSE_HEADERS "ws:response-headers"
+
+// NNG_OPT_WS_REQUEST_HEADER is a prefix, for a dynamic
+// property name.  This allows direct access to any named header.
+// Concatenate this with the name of the property (case is not sensitive).
+// Only the first such header is returned.
+#define NNG_OPT_WS_RESPONSE_HEADER "ws:response-header:"
+
+// NNG_OPT_WS_RESPONSE_HEADER is like NNG_OPT_REQUEST_HEADER, but used for
+// accessing the request headers.
+#define NNG_OPT_WS_REQUEST_HEADER "ws:request-header:"
+
+// NNG_OPT_WS_REQUEST_URI is used to obtain the URI sent by the client.
+// This can be useful when a handler supports an entire directory tree.
+#define NNG_OPT_WS_REQUEST_URI "ws:request-uri"
+
+// NNG_OPT_WS_SENDMAXFRAME is used to configure the fragmentation size
+// used for frames.  This has a default value of 64k.  Large values
+// are good for throughput, but penalize latency.  They also require
+// additional buffering on the peer.  This value must not be larger
+// than what the peer will accept, and unfortunately there is no way
+// to negotiate this.
+#define NNG_OPT_WS_SENDMAXFRAME "ws:txframe-max"
+
+// NNG_OPT_WS_RECVMAXFRAME is the largest frame we will accept.  This should
+// probably not be larger than NNG_OPT_RECVMAXSZ. If the sender attempts
+// to send more data than this in a single message, it will be dropped.
+#define NNG_OPT_WS_RECVMAXFRAME "ws:rxframe-max"
+
+// NNG_OPT_WS_PROTOCOL is the "websocket subprotocol" -- it's a string.
+// This is also known as the Sec-WebSocket-Protocol header. It is treated
+// specially.  This is part of the websocket handshake.
+#define NNG_OPT_WS_PROTOCOL "ws:protocol"
+
+// XXX: TBD: priorities, ipv4only
+
+// Statistics. These are for informational purposes only, and subject
+// to change without notice. The API for accessing these is stable,
+// but the individual statistic names, values, and meanings are all
+// subject to change.
+
+// nng_stats_get takes a snapshot of the entire set of statistics.
+// While the operation can be somewhat expensive (allocations), it
+// is done in a way that minimizes impact to running operations.
+// Note that the statistics are provided as a tree, with parents
+// used for grouping, and with child statistics underneath.  The
+// top stat returned will be of type NNG_STAT_SCOPE with name "".
+// Applications may choose to consider this root scope as "root", if
+// the empty string is not suitable.
+NNG_DECL int nng_stats_get(nng_stat **);
+
+// nng_stats_free frees a previous list of snapshots.  This should only
+// be called on the parent statistic that obtained via nng_stats_get.
+NNG_DECL void nng_stats_free(nng_stat *);
+
+// nng_stats_dump is a debugging function that dumps the entire set of
+// statistics to stdout.
+NNG_DECL void nng_stats_dump(nng_stat *);
+
+// nng_stat_next finds the next sibling for the current stat.  If there
+// are no more siblings, it returns NULL.
+NNG_DECL nng_stat *nng_stat_next(nng_stat *);
+
+// nng_stat_child finds the first child of the current stat.  If no children
+// exist, then NULL is returned.
+NNG_DECL nng_stat *nng_stat_child(nng_stat *);
+
+// nng_stat_name is used to determine the name of the statistic.
+// This is a human readable name.  Statistic names, as well as the presence
+// or absence or semantic of any particular statistic are not part of any
+// stable API, and may be changed without notice in future updates.
+NNG_DECL const char *nng_stat_name(nng_stat *);
+
+// nng_stat_type is used to determine the type of the statistic.
+// Counters generally increment, and therefore changes in the value over
+// time are likely more interesting than the actual level.  Level
+// values reflect some absolute state however, and should be presented to the
+// user as is.
+NNG_DECL int nng_stat_type(nng_stat *);
+
+// nng_stat_find is used to find a specific named statistic within
+// a statistic tree.  NULL is returned if no such statistic exists.
+NNG_DECL nng_stat *nng_stat_find(nng_stat *, const char *);
+
+// nng_stat_find_socket is used to find the stats for the given socket.
+NNG_DECL nng_stat *nng_stat_find_socket(nng_stat *, nng_socket);
+
+// nng_stat_find_dialer is used to find the stats for the given dialer.
+NNG_DECL nng_stat *nng_stat_find_dialer(nng_stat *, nng_dialer);
+
+// nng_stat_find_listener is used to find the stats for the given listener.
+NNG_DECL nng_stat *nng_stat_find_listener(nng_stat *, nng_listener);
+
+enum nng_stat_type_enum {
+	NNG_STAT_SCOPE   = 0, // Stat is for scoping, and carries no value
+	NNG_STAT_LEVEL   = 1, // Numeric "absolute" value, diffs meaningless
+	NNG_STAT_COUNTER = 2, // Incrementing value (diffs are meaningful)
+	NNG_STAT_STRING  = 3, // Value is a string
+	NNG_STAT_BOOLEAN = 4, // Value is a boolean
+	NNG_STAT_ID      = 5, // Value is a numeric ID
+};
+
+// nng_stat_unit provides information about the unit for the statistic,
+// such as NNG_UNIT_BYTES or NNG_UNIT_BYTES.  If no specific unit is
+// applicable, such as a relative priority, then NN_UNIT_NONE is returned.
+NNG_DECL int nng_stat_unit(nng_stat *);
+
+enum nng_unit_enum {
+	NNG_UNIT_NONE     = 0, // No special units
+	NNG_UNIT_BYTES    = 1, // Bytes, e.g. bytes sent, etc.
+	NNG_UNIT_MESSAGES = 2, // Messages, one per message
+	NNG_UNIT_MILLIS   = 3, // Milliseconds
+	NNG_UNIT_EVENTS   = 4  // Some other type of event
+};
+
+// nng_stat_value returns returns the actual value of the statistic.
+// Statistic values reflect their value at the time that the corresponding
+// snapshot was updated, and are undefined until an update is performed.
+NNG_DECL uint64_t nng_stat_value(nng_stat *);
+
+// nng_stat_string returns the string associated with a string statistic,
+// or NULL if the statistic is not part of the string.  The value returned
+// is valid until the associated statistic is freed.
+NNG_DECL const char *nng_stat_string(nng_stat *);
+
+// nng_stat_desc returns a human readable description of the statistic.
+// This may be useful for display in diagnostic interfaces, etc.
+NNG_DECL const char *nng_stat_desc(nng_stat *);
+
+// nng_stat_timestamp returns a timestamp (milliseconds) when the statistic
+// was captured.  The base offset is the same as used by nng_clock().
+// We don't use nng_time though, because that's in the supplemental header.
+NNG_DECL uint64_t nng_stat_timestamp(nng_stat *);
+
+// Device functionality.  This connects two sockets together in a device,
+// which means that messages from one side are forwarded to the other.
+NNG_DECL int nng_device(nng_socket, nng_socket);
+
+// Symbol name and visibility.  TBD.  The only symbols that really should
+// be directly exported to runtimes IMO are the option symbols.  And frankly
+// they have enough special logic around them that it might be best not to
+// automate the promotion of them to other APIs.  This is an area open
+// for discussion.
+
+// Error codes.  These generally have different values from UNIX errnos,
+// so take care about converting them.  The one exception is that 0 is
+// unambiguously "success".
+//
+// NNG_SYSERR is a special code, which allows us to wrap errors from the
+// underlying operating system.  We generally prefer to map errors to one
+// of the above, but if we cannot, then we just encode an error this way.
+// The bit is large enough to accommodate all known UNIX and Win32 error
+// codes.  We try hard to match things semantically to one of our standard
+// errors.  For example, a connection reset or aborted we treat as a
+// closed connection, because that's basically what it means.  (The remote
+// peer closed the connection.)  For certain kinds of resource exhaustion
+// we treat it the same as memory.  But for files, etc. that's OS-specific,
+// and we use the generic below.  Some of the above error codes we use
+// internally, and the application should never see (e.g. NNG_EINTR).
+//
+// NNG_ETRANERR is like ESYSERR, but is used to wrap transport specific
+// errors, from different transports.  It should only be used when none
+// of the other options are available.
+
+enum nng_errno_enum {
+	NNG_EINTR        = 1,
+	NNG_ENOMEM       = 2,
+	NNG_EINVAL       = 3,
+	NNG_EBUSY        = 4,
+	NNG_ETIMEDOUT    = 5,
+	NNG_ECONNREFUSED = 6,
+	NNG_ECLOSED      = 7,
+	NNG_EAGAIN       = 8,
+	NNG_ENOTSUP      = 9,
+	NNG_EADDRINUSE   = 10,
+	NNG_ESTATE       = 11,
+	NNG_ENOENT       = 12,
+	NNG_EPROTO       = 13,
+	NNG_EUNREACHABLE = 14,
+	NNG_EADDRINVAL   = 15,
+	NNG_EPERM        = 16,
+	NNG_EMSGSIZE     = 17,
+	NNG_ECONNABORTED = 18,
+	NNG_ECONNRESET   = 19,
+	NNG_ECANCELED    = 20,
+	NNG_ENOFILES     = 21,
+	NNG_ENOSPC       = 22,
+	NNG_EEXIST       = 23,
+	NNG_EREADONLY    = 24,
+	NNG_EWRITEONLY   = 25,
+	NNG_ECRYPTO      = 26,
+	NNG_EPEERAUTH    = 27,
+	NNG_ENOARG       = 28,
+	NNG_EAMBIGUOUS   = 29,
+	NNG_EBADTYPE     = 30,
+	NNG_ECONNSHUT    = 31,
+	NNG_EINTERNAL    = 1000,
+	NNG_ESYSERR      = 0x10000000,
+	NNG_ETRANERR     = 0x20000000
+};
+
+// URL support.  We frequently want to process a URL, and these methods
+// give us a convenient way of doing so.
+
+typedef struct nng_url {
+	char *u_rawurl;   // never NULL
+	char *u_scheme;   // never NULL
+	char *u_userinfo; // will be NULL if not specified
+	char *u_host;     // including colon and port
+	char *u_hostname; // name only, will be "" if not specified
+	char *u_port;     // port, will be "" if not specified
+	char *u_path;     // path, will be "" if not specified
+	char *u_query;    // without '?', will be NULL if not specified
+	char *u_fragment; // without '#', will be NULL if not specified
+	char *u_requri;   // includes query and fragment, "" if not specified
+} nng_url;
+
+// nng_url_parse parses a URL string into a structured form.
+// Note that the u_port member will be filled out with a numeric
+// port if one isn't specified and a default port is appropriate for
+// the scheme.  The URL structure is allocated, along with individual
+// members.  It can be freed with nng_url_free.
+NNG_DECL int nng_url_parse(nng_url **, const char *);
+
+// nng_url_free frees a URL structure that was created by nng_url_parse().
+NNG_DECL void nng_url_free(nng_url *);
+
+// nng_url_clone clones a URL structure.
+NNG_DECL int nng_url_clone(nng_url **, const nng_url *);
+
+// nng_version returns the library version as a human readable string.
+NNG_DECL const char *nng_version(void);
+
+// nng_stream operations permit direct access to low level streams,
+// which can have a variety of uses.  Internally most of the transports
+// are built on top of these.  Streams are created by other dialers or
+// listeners.  The API for creating dialers and listeners varies.
+
+typedef struct nng_stream          nng_stream;
+typedef struct nng_stream_dialer   nng_stream_dialer;
+typedef struct nng_stream_listener nng_stream_listener;
+
+NNG_DECL void nng_stream_free(nng_stream *);
+NNG_DECL void nng_stream_close(nng_stream *);
+NNG_DECL void nng_stream_send(nng_stream *, nng_aio *);
+NNG_DECL void nng_stream_recv(nng_stream *, nng_aio *);
+NNG_DECL int  nng_stream_get(nng_stream *, const char *, void *, size_t *);
+NNG_DECL int  nng_stream_get_bool(nng_stream *, const char *, bool *);
+NNG_DECL int  nng_stream_get_int(nng_stream *, const char *, int *);
+NNG_DECL int  nng_stream_get_ms(nng_stream *, const char *, nng_duration *);
+NNG_DECL int  nng_stream_get_size(nng_stream *, const char *, size_t *);
+NNG_DECL int  nng_stream_get_uint64(nng_stream *, const char *, uint64_t *);
+NNG_DECL int  nng_stream_get_string(nng_stream *, const char *, char **);
+NNG_DECL int  nng_stream_get_ptr(nng_stream *, const char *, void **);
+NNG_DECL int  nng_stream_get_addr(nng_stream *, const char *, nng_sockaddr *);
+NNG_DECL int  nng_stream_set(nng_stream *, const char *, const void *, size_t);
+NNG_DECL int  nng_stream_set_bool(nng_stream *, const char *, bool);
+NNG_DECL int  nng_stream_set_int(nng_stream *, const char *, int);
+NNG_DECL int  nng_stream_set_ms(nng_stream *, const char *, nng_duration);
+NNG_DECL int  nng_stream_set_size(nng_stream *, const char *, size_t);
+NNG_DECL int  nng_stream_set_uint64(nng_stream *, const char *, uint64_t);
+NNG_DECL int  nng_stream_set_string(nng_stream *, const char *, const char *);
+NNG_DECL int  nng_stream_set_ptr(nng_stream *, const char *, void *);
+NNG_DECL int  nng_stream_set_addr(
+     nng_stream *, const char *, const nng_sockaddr *);
+
+NNG_DECL int nng_stream_dialer_alloc(nng_stream_dialer **, const char *);
+NNG_DECL int nng_stream_dialer_alloc_url(
+    nng_stream_dialer **, const nng_url *);
+NNG_DECL void nng_stream_dialer_free(nng_stream_dialer *);
+NNG_DECL void nng_stream_dialer_close(nng_stream_dialer *);
+NNG_DECL void nng_stream_dialer_dial(nng_stream_dialer *, nng_aio *);
+NNG_DECL int  nng_stream_dialer_set(
+     nng_stream_dialer *, const char *, const void *, size_t);
+NNG_DECL int nng_stream_dialer_get(
+    nng_stream_dialer *, const char *, void *, size_t *);
+NNG_DECL int nng_stream_dialer_get_bool(
+    nng_stream_dialer *, const char *, bool *);
+NNG_DECL int nng_stream_dialer_get_int(
+    nng_stream_dialer *, const char *, int *);
+NNG_DECL int nng_stream_dialer_get_ms(
+    nng_stream_dialer *, const char *, nng_duration *);
+NNG_DECL int nng_stream_dialer_get_size(
+    nng_stream_dialer *, const char *, size_t *);
+NNG_DECL int nng_stream_dialer_get_uint64(
+    nng_stream_dialer *, const char *, uint64_t *);
+NNG_DECL int nng_stream_dialer_get_string(
+    nng_stream_dialer *, const char *, char **);
+NNG_DECL int nng_stream_dialer_get_ptr(
+    nng_stream_dialer *, const char *, void **);
+NNG_DECL int nng_stream_dialer_get_addr(
+    nng_stream_dialer *, const char *, nng_sockaddr *);
+NNG_DECL int nng_stream_dialer_set_bool(
+    nng_stream_dialer *, const char *, bool);
+NNG_DECL int nng_stream_dialer_set_int(nng_stream_dialer *, const char *, int);
+NNG_DECL int nng_stream_dialer_set_ms(
+    nng_stream_dialer *, const char *, nng_duration);
+NNG_DECL int nng_stream_dialer_set_size(
+    nng_stream_dialer *, const char *, size_t);
+NNG_DECL int nng_stream_dialer_set_uint64(
+    nng_stream_dialer *, const char *, uint64_t);
+NNG_DECL int nng_stream_dialer_set_string(
+    nng_stream_dialer *, const char *, const char *);
+NNG_DECL int nng_stream_dialer_set_ptr(
+    nng_stream_dialer *, const char *, void *);
+NNG_DECL int nng_stream_dialer_set_addr(
+    nng_stream_dialer *, const char *, const nng_sockaddr *);
+
+NNG_DECL int nng_stream_listener_alloc(nng_stream_listener **, const char *);
+NNG_DECL int nng_stream_listener_alloc_url(
+    nng_stream_listener **, const nng_url *);
+NNG_DECL void nng_stream_listener_free(nng_stream_listener *);
+NNG_DECL void nng_stream_listener_close(nng_stream_listener *);
+NNG_DECL int  nng_stream_listener_listen(nng_stream_listener *);
+NNG_DECL void nng_stream_listener_accept(nng_stream_listener *, nng_aio *);
+NNG_DECL int  nng_stream_listener_set(
+     nng_stream_listener *, const char *, const void *, size_t);
+NNG_DECL int nng_stream_listener_get(
+    nng_stream_listener *, const char *, void *, size_t *);
+NNG_DECL int nng_stream_listener_get_bool(
+    nng_stream_listener *, const char *, bool *);
+NNG_DECL int nng_stream_listener_get_int(
+    nng_stream_listener *, const char *, int *);
+NNG_DECL int nng_stream_listener_get_ms(
+    nng_stream_listener *, const char *, nng_duration *);
+NNG_DECL int nng_stream_listener_get_size(
+    nng_stream_listener *, const char *, size_t *);
+NNG_DECL int nng_stream_listener_get_uint64(
+    nng_stream_listener *, const char *, uint64_t *);
+NNG_DECL int nng_stream_listener_get_string(
+    nng_stream_listener *, const char *, char **);
+NNG_DECL int nng_stream_listener_get_ptr(
+    nng_stream_listener *, const char *, void **);
+NNG_DECL int nng_stream_listener_get_addr(
+    nng_stream_listener *, const char *, nng_sockaddr *);
+NNG_DECL int nng_stream_listener_set_bool(
+    nng_stream_listener *, const char *, bool);
+NNG_DECL int nng_stream_listener_set_int(
+    nng_stream_listener *, const char *, int);
+NNG_DECL int nng_stream_listener_set_ms(
+    nng_stream_listener *, const char *, nng_duration);
+NNG_DECL int nng_stream_listener_set_size(
+    nng_stream_listener *, const char *, size_t);
+NNG_DECL int nng_stream_listener_set_uint64(
+    nng_stream_listener *, const char *, uint64_t);
+NNG_DECL int nng_stream_listener_set_string(
+    nng_stream_listener *, const char *, const char *);
+NNG_DECL int nng_stream_listener_set_ptr(
+    nng_stream_listener *, const char *, void *);
+NNG_DECL int nng_stream_listener_set_addr(
+    nng_stream_listener *, const char *, const nng_sockaddr *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_NNG_H
diff --git a/include/nng/protocol/bus0/bus.h b/include/nng/protocol/bus0/bus.h
new file mode 100644
index 0000000..c8c23d8
--- /dev/null
+++ b/include/nng/protocol/bus0/bus.h
@@ -0,0 +1,34 @@
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_PROTOCOL_BUS0_BUS_H
+#define NNG_PROTOCOL_BUS0_BUS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+NNG_DECL int nng_bus0_open(nng_socket *);
+
+NNG_DECL int nng_bus0_open_raw(nng_socket *);
+
+#ifndef nng_bus_open
+#define nng_bus_open nng_bus0_open
+#endif
+
+#ifndef nng_bus_open_raw
+#define nng_bus_open_raw nng_bus0_open_raw
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_PROTOCOL_BUS0_BUS_H
diff --git a/include/nng/protocol/pair0/pair.h b/include/nng/protocol/pair0/pair.h
new file mode 100644
index 0000000..1356f1c
--- /dev/null
+++ b/include/nng/protocol/pair0/pair.h
@@ -0,0 +1,34 @@
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_PROTOCOL_PAIR0_PAIR_H
+#define NNG_PROTOCOL_PAIR0_PAIR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+NNG_DECL int nng_pair0_open(nng_socket *);
+
+NNG_DECL int nng_pair0_open_raw(nng_socket *);
+
+#ifndef nng_pair_open
+#define nng_pair_open nng_pair0_open
+#endif
+
+#ifndef nng_pair_open_raw
+#define nng_pair_open_raw nng_pair0_open_raw
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_PROTOCOL_PAIR0_PAIR_H
diff --git a/include/nng/protocol/pair1/pair.h b/include/nng/protocol/pair1/pair.h
new file mode 100644
index 0000000..c48b202
--- /dev/null
+++ b/include/nng/protocol/pair1/pair.h
@@ -0,0 +1,40 @@
+//
+// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_PROTOCOL_PAIR1_PAIR_H
+#define NNG_PROTOCOL_PAIR1_PAIR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+NNG_DECL int nng_pair1_open(nng_socket *);
+NNG_DECL int nng_pair1_open_raw(nng_socket *);
+NNG_DECL int nng_pair1_open_poly(nng_socket *);
+
+#ifndef nng_pair_open
+#define nng_pair_open nng_pair1_open
+#endif
+
+#ifndef nng_pair_open_raw
+#define nng_pair_open_raw nng_pair1_open_raw
+#endif
+
+#define NNG_OPT_PAIR1_POLY "pair1:polyamorous"
+#define NNG_PAIR1_SELF 0x11
+#define NNG_PAIR1_PEER 0x11
+#define NNG_PAIR1_SELF_NAME "pair1"
+#define NNG_PAIR1_PEER_NAME "pair1"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_PROTOCOL_PAIR1_PAIR_H
diff --git a/include/nng/protocol/pipeline0/pull.h b/include/nng/protocol/pipeline0/pull.h
new file mode 100644
index 0000000..1c5d63e
--- /dev/null
+++ b/include/nng/protocol/pipeline0/pull.h
@@ -0,0 +1,33 @@
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_PROTOCOL_PIPELINE0_PULL_H
+#define NNG_PROTOCOL_PIPELINE0_PULL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+NNG_DECL int nng_pull0_open(nng_socket *);
+NNG_DECL int nng_pull0_open_raw(nng_socket *);
+
+#ifndef nng_pull_open
+#define nng_pull_open nng_pull0_open
+#endif
+
+#ifndef nng_pull_open_raw
+#define nng_pull_open_raw nng_pull0_open_raw
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_PROTOCOL_PIPELINE0_PULL_H
diff --git a/include/nng/protocol/pipeline0/push.h b/include/nng/protocol/pipeline0/push.h
new file mode 100644
index 0000000..a1384e0
--- /dev/null
+++ b/include/nng/protocol/pipeline0/push.h
@@ -0,0 +1,33 @@
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_PROTOCOL_PIPELINE0_PUSH_H
+#define NNG_PROTOCOL_PIPELINE0_PUSH_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+NNG_DECL int nng_push0_open(nng_socket *);
+NNG_DECL int nng_push0_open_raw(nng_socket *);
+
+#ifndef nng_push_open
+#define nng_push_open nng_push0_open
+#endif
+
+#ifndef nng_push_open_raw
+#define nng_push_open_raw nng_push0_open_raw
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_PROTOCOL_PIPELINE0_PUSH_H
diff --git a/include/nng/protocol/pubsub0/pub.h b/include/nng/protocol/pubsub0/pub.h
new file mode 100644
index 0000000..877f2f1
--- /dev/null
+++ b/include/nng/protocol/pubsub0/pub.h
@@ -0,0 +1,33 @@
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_PROTOCOL_PUBSUB0_PUB_H
+#define NNG_PROTOCOL_PUBSUB0_PUB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+NNG_DECL int nng_pub0_open(nng_socket *);
+NNG_DECL int nng_pub0_open_raw(nng_socket *);
+
+#ifndef nng_pub_open
+#define nng_pub_open nng_pub0_open
+#endif
+
+#ifndef nng_pub_open_raw
+#define nng_pub_open_raw nng_pub0_open_raw
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_PROTOCOL_PUBSUB0_PUB_H
diff --git a/include/nng/protocol/pubsub0/sub.h b/include/nng/protocol/pubsub0/sub.h
new file mode 100644
index 0000000..81f50a8
--- /dev/null
+++ b/include/nng/protocol/pubsub0/sub.h
@@ -0,0 +1,39 @@
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_PROTOCOL_PUBSUB0_SUB_H
+#define NNG_PROTOCOL_PUBSUB0_SUB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+NNG_DECL int nng_sub0_open(nng_socket *);
+
+NNG_DECL int nng_sub0_open_raw(nng_socket *);
+
+#ifndef nng_sub_open
+#define nng_sub_open nng_sub0_open
+#endif
+
+#ifndef nng_sub_open_raw
+#define nng_sub_open_raw nng_sub0_open_raw
+#endif
+
+#define NNG_OPT_SUB_SUBSCRIBE "sub:subscribe"
+#define NNG_OPT_SUB_UNSUBSCRIBE "sub:unsubscribe"
+
+#define NNG_OPT_SUB_PREFNEW "sub:prefnew"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_PROTOCOL_PUBSUB0_SUB_H
diff --git a/include/nng/protocol/reqrep0/rep.h b/include/nng/protocol/reqrep0/rep.h
new file mode 100644
index 0000000..04fe18b
--- /dev/null
+++ b/include/nng/protocol/reqrep0/rep.h
@@ -0,0 +1,38 @@
+//
+// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_PROTOCOL_REQREP0_REP_H
+#define NNG_PROTOCOL_REQREP0_REP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+NNG_DECL int nng_rep0_open(nng_socket *);
+NNG_DECL int nng_rep0_open_raw(nng_socket *);
+
+#ifndef nng_rep_open
+#define nng_rep_open nng_rep0_open
+#endif
+
+#ifndef nng_rep_open_raw
+#define nng_rep_open_raw nng_rep0_open_raw
+#endif
+
+#define NNG_REP0_SELF 0x31
+#define NNG_REP0_PEER 0x30
+#define NNG_REP0_SELF_NAME "rep"
+#define NNG_REP0_PEER_NAME "req"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_PROTOCOL_REQREP0_REP_H
diff --git a/include/nng/protocol/reqrep0/req.h b/include/nng/protocol/reqrep0/req.h
new file mode 100644
index 0000000..3ed8021
--- /dev/null
+++ b/include/nng/protocol/reqrep0/req.h
@@ -0,0 +1,39 @@
+//
+// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_PROTOCOL_REQREP0_REQ_H
+#define NNG_PROTOCOL_REQREP0_REQ_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+NNG_DECL int nng_req0_open(nng_socket *);
+NNG_DECL int nng_req0_open_raw(nng_socket *);
+
+#ifndef nng_req_open
+#define nng_req_open nng_req0_open
+#endif
+#ifndef nng_req_open_raw
+#define nng_req_open_raw nng_req0_open_raw
+#endif
+
+#define NNG_REQ0_SELF 0x30
+#define NNG_REQ0_PEER 0x31
+#define NNG_REQ0_SELF_NAME "req"
+#define NNG_REQ0_PEER_NAME "rep"
+
+#define NNG_OPT_REQ_RESENDTIME "req:resend-time"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_PROTOCOL_REQREP0_REQ_H
diff --git a/include/nng/protocol/survey0/respond.h b/include/nng/protocol/survey0/respond.h
new file mode 100644
index 0000000..d7dab61
--- /dev/null
+++ b/include/nng/protocol/survey0/respond.h
@@ -0,0 +1,38 @@
+//
+// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_PROTOCOL_SURVEY0_RESPOND_H
+#define NNG_PROTOCOL_SURVEY0_RESPOND_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+NNG_DECL int nng_respondent0_open(nng_socket *);
+NNG_DECL int nng_respondent0_open_raw(nng_socket *);
+
+#ifndef nng_respondent_open
+#define nng_respondent_open nng_respondent0_open
+#endif
+
+#ifndef nng_respondent_open_raw
+#define nng_respondent_open_raw nng_respondent0_open_raw
+#endif
+
+#define NNG_RESPONDENT0_SELF 0x63
+#define NNG_RESPONDENT0_PEER 0x62
+#define NNG_RESPONDENT0_SELF_NAME "respondent"
+#define NNG_RESPONDENT0_PEER_NAME "surveyor"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_PROTOCOL_SURVEY0_RESPOND_H
diff --git a/include/nng/protocol/survey0/survey.h b/include/nng/protocol/survey0/survey.h
new file mode 100644
index 0000000..cea4d58
--- /dev/null
+++ b/include/nng/protocol/survey0/survey.h
@@ -0,0 +1,40 @@
+//
+// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_PROTOCOL_SURVEY0_SURVEY_H
+#define NNG_PROTOCOL_SURVEY0_SURVEY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+NNG_DECL int nng_surveyor0_open(nng_socket *);
+NNG_DECL int nng_surveyor0_open_raw(nng_socket *);
+
+#ifndef nng_surveyor_open
+#define nng_surveyor_open nng_surveyor0_open
+#endif
+
+#ifndef nng_surveyor_open_raw
+#define nng_surveyor_open_raw nng_surveyor0_open_raw
+#endif
+
+#define NNG_SURVEYOR0_SELF 0x62
+#define NNG_SURVEYOR0_PEER 0x63
+#define NNG_SURVEYOR0_SELF_NAME "surveyor"
+#define NNG_SURVEYOR0_PEER_NAME "respondent"
+
+#define NNG_OPT_SURVEYOR_SURVEYTIME "surveyor:survey-time"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_PROTOCOL_SURVEY0_SURVEY_H
diff --git a/include/nng/supplemental/http/http.h b/include/nng/supplemental/http/http.h
new file mode 100644
index 0000000..ff8616c
--- /dev/null
+++ b/include/nng/supplemental/http/http.h
@@ -0,0 +1,539 @@
+//
+// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+// Copyright 2020 Dirac Research <robert.bielik@dirac.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_SUPPLEMENTAL_HTTP_HTTP_H
+#define NNG_SUPPLEMENTAL_HTTP_HTTP_H
+
+// HTTP API.  Only present if HTTP support compiled into the library.
+// Functions will return NNG_ENOTSUP (or NULL or 0 as appropriate)
+// if the library lacks support for HTTP.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+struct nng_tls_config;
+
+// HTTP status codes.  This list is not exhaustive.
+enum nng_http_status {
+	NNG_HTTP_STATUS_CONTINUE                 = 100,
+	NNG_HTTP_STATUS_SWITCHING                = 101,
+	NNG_HTTP_STATUS_PROCESSING               = 102,
+	NNG_HTTP_STATUS_OK                       = 200,
+	NNG_HTTP_STATUS_CREATED                  = 201,
+	NNG_HTTP_STATUS_ACCEPTED                 = 202,
+	NNG_HTTP_STATUS_NOT_AUTHORITATIVE        = 203,
+	NNG_HTTP_STATUS_NO_CONTENT               = 204,
+	NNG_HTTP_STATUS_RESET_CONTENT            = 205,
+	NNG_HTTP_STATUS_PARTIAL_CONTENT          = 206,
+	NNG_HTTP_STATUS_MULTI_STATUS             = 207,
+	NNG_HTTP_STATUS_ALREADY_REPORTED         = 208,
+	NNG_HTTP_STATUS_IM_USED                  = 226,
+	NNG_HTTP_STATUS_MULTIPLE_CHOICES         = 300,
+	NNG_HTTP_STATUS_STATUS_MOVED_PERMANENTLY = 301,
+	NNG_HTTP_STATUS_FOUND                    = 302,
+	NNG_HTTP_STATUS_SEE_OTHER                = 303,
+	NNG_HTTP_STATUS_NOT_MODIFIED             = 304,
+	NNG_HTTP_STATUS_USE_PROXY                = 305,
+	NNG_HTTP_STATUS_TEMPORARY_REDIRECT       = 307,
+	NNG_HTTP_STATUS_PERMANENT_REDIRECT       = 308,
+	NNG_HTTP_STATUS_BAD_REQUEST              = 400,
+	NNG_HTTP_STATUS_UNAUTHORIZED             = 401,
+	NNG_HTTP_STATUS_PAYMENT_REQUIRED         = 402,
+	NNG_HTTP_STATUS_FORBIDDEN                = 403,
+	NNG_HTTP_STATUS_NOT_FOUND                = 404,
+	NNG_HTTP_STATUS_METHOD_NOT_ALLOWED       = 405,
+	NNG_HTTP_STATUS_NOT_ACCEPTABLE           = 406,
+	NNG_HTTP_STATUS_PROXY_AUTH_REQUIRED      = 407,
+	NNG_HTTP_STATUS_REQUEST_TIMEOUT          = 408,
+	NNG_HTTP_STATUS_CONFLICT                 = 409,
+	NNG_HTTP_STATUS_GONE                     = 410,
+	NNG_HTTP_STATUS_LENGTH_REQUIRED          = 411,
+	NNG_HTTP_STATUS_PRECONDITION_FAILED      = 412,
+	NNG_HTTP_STATUS_PAYLOAD_TOO_LARGE        = 413,
+	NNG_HTTP_STATUS_ENTITY_TOO_LONG          = 414,
+	NNG_HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE   = 415,
+	NNG_HTTP_STATUS_RANGE_NOT_SATISFIABLE    = 416,
+	NNG_HTTP_STATUS_EXPECTATION_FAILED       = 417,
+	NNG_HTTP_STATUS_TEAPOT                   = 418,
+	NNG_HTTP_STATUS_UNPROCESSABLE_ENTITY     = 422,
+	NNG_HTTP_STATUS_LOCKED                   = 423,
+	NNG_HTTP_STATUS_FAILED_DEPENDENCY        = 424,
+	NNG_HTTP_STATUS_UPGRADE_REQUIRED         = 426,
+	NNG_HTTP_STATUS_PRECONDITION_REQUIRED    = 428,
+	NNG_HTTP_STATUS_TOO_MANY_REQUESTS        = 429,
+	NNG_HTTP_STATUS_HEADERS_TOO_LARGE        = 431,
+	NNG_HTTP_STATUS_UNAVAIL_LEGAL_REASONS    = 451,
+	NNG_HTTP_STATUS_INTERNAL_SERVER_ERROR    = 500,
+	NNG_HTTP_STATUS_NOT_IMPLEMENTED          = 501,
+	NNG_HTTP_STATUS_BAD_GATEWAY              = 502,
+	NNG_HTTP_STATUS_SERVICE_UNAVAILABLE      = 503,
+	NNG_HTTP_STATUS_GATEWAY_TIMEOUT          = 504,
+	NNG_HTTP_STATUS_HTTP_VERSION_NOT_SUPP    = 505,
+	NNG_HTTP_STATUS_VARIANT_ALSO_NEGOTIATES  = 506,
+	NNG_HTTP_STATUS_INSUFFICIENT_STORAGE     = 507,
+	NNG_HTTP_STATUS_LOOP_DETECTED            = 508,
+	NNG_HTTP_STATUS_NOT_EXTENDED             = 510,
+	NNG_HTTP_STATUS_NETWORK_AUTH_REQUIRED    = 511,
+};
+
+// nng_http_req represents an HTTP request.
+typedef struct nng_http_req nng_http_req;
+
+// nng_http_req_alloc creates a vanilla HTTP request object.  The object is
+// initialized with the given URL object for an HTTP/1.1 GET request by
+// default. It also adds the Host: header required for HTTP/1.1.  If the
+// url is NULL, then the uri and Host: header are uninitialized, and will
+// need to be set explicitly.
+NNG_DECL int nng_http_req_alloc(nng_http_req **, const nng_url *);
+
+// nng_http_req_free frees an HTTP request object.
+NNG_DECL void nng_http_req_free(nng_http_req *);
+
+// nng_http_req_get_method returns the method.
+NNG_DECL const char *nng_http_req_get_method(nng_http_req *);
+
+// nng_http_req_get_version returns the version, usually HTTP/1.1.
+NNG_DECL const char *nng_http_req_get_version(nng_http_req *);
+
+// nng_http_req_get_uri returns the "abs-uri", which is URL without
+// the scheme, host, or port.
+NNG_DECL const char *nng_http_req_get_uri(nng_http_req *);
+
+// nng_http_req_set_header sets an HTTP header, replacing any previous value
+// that might have been present.
+NNG_DECL int nng_http_req_set_header(
+    nng_http_req *, const char *, const char *);
+
+// nng_http_req_add_header adds an HTTP header, without disrupting any other
+// with the same name that might have been present.
+NNG_DECL int nng_http_req_add_header(
+    nng_http_req *, const char *, const char *);
+
+// nng_http_req_del_header deletes all occurrences of a named header.
+NNG_DECL int nng_http_req_del_header(nng_http_req *, const char *);
+
+// nng_http_req_get_header looks up a header with the named, returns NULL
+// if not found.
+NNG_DECL const char *nng_http_req_get_header(nng_http_req *, const char *);
+
+// nng_http_req_set_method is used to change the method of a request.
+// The method should be an upper case HTTP method, like POST, or DELETE.
+// Null sets the default ("GET").
+NNG_DECL int nng_http_req_set_method(nng_http_req *, const char *);
+
+// nng_http_req_set_version is used to change the version of a request.
+// Normally the version is "HTTP/1.1".  Note that the framework does
+// not support HTTP/2 at all.  Null sets the default ("HTTP/1.1").
+NNG_DECL int nng_http_req_set_version(nng_http_req *, const char *);
+
+// nng_http_req_set_uri is used to change the URI of a request.  This
+// should be an "abs-uri", that is a path, plus query and fragment if
+// needed.  The scheme, host, and port don't belong here.  The URI should
+// start with a leading '/' per HTTP.
+NNG_DECL int nng_http_req_set_uri(nng_http_req *, const char *);
+
+// nng_http_req_set_data adds entity data to the request.  The
+// data object must persist (so only really useful for static data).
+// The content-length header is updated as well, but the caller should
+// probably set the content-type header.
+NNG_DECL int nng_http_req_set_data(nng_http_req *, const void *, size_t);
+
+// nng_http_req_copy_data adds entity data to the response. A private
+// copy of the data is made (will be freed with the request).
+// The content-length header is updated as well, but the caller should
+// probably set the content-type header.
+NNG_DECL int nng_http_req_copy_data(nng_http_req *, const void *, size_t);
+
+// nng_http_req_get_data gets the data for the response.
+NNG_DECL void nng_http_req_get_data(nng_http_req *, void **, size_t *);
+
+// nng_http_res represents an HTTP response.
+typedef struct nng_http_res nng_http_res;
+
+// nng_http_res_alloc creates a vanilla HTTP response object.  The object is
+// initialized for an HTTP/1.1 200 OK response by default.
+NNG_DECL int nng_http_res_alloc(nng_http_res **);
+
+// nng_http_res_alloc_error creates an error HTTP response object.  The object
+// is initialized for an HTTP/1.1 response, and contains an associated
+// generic HTML error page.
+NNG_DECL int nng_http_res_alloc_error(nng_http_res **, uint16_t);
+
+// nng_http_res_free frees an HTTP response object.
+NNG_DECL void nng_http_res_free(nng_http_res *);
+
+// nng_http_res_get_status returns the HTTP status code from the server.
+NNG_DECL uint16_t nng_http_res_get_status(nng_http_res *);
+
+// nng_http_res_set_status sets the HTTP status code.
+NNG_DECL int nng_http_res_set_status(nng_http_res *, uint16_t);
+
+// nng_http_res_get_reason returns the human readable status message
+// that the server responds (or responded) with.
+NNG_DECL const char *nng_http_res_get_reason(nng_http_res *);
+
+// nng_http_res_set_reason sets the human readable status message.
+// NULL means that a default reason is used based on the status code.
+NNG_DECL int nng_http_res_set_reason(nng_http_res *, const char *);
+
+// nng_http_res_set_header sets an HTTP header, replacing any previous value
+// that might have been present.
+NNG_DECL int nng_http_res_set_header(
+    nng_http_res *, const char *, const char *);
+
+// nng_http_res_add_header adds an HTTP header, without disrupting any other
+// with the same name that might have been present.
+NNG_DECL int nng_http_res_add_header(
+    nng_http_res *, const char *, const char *);
+
+// nng_http_res_del_header deletes all occurrences of a named header.
+NNG_DECL int nng_http_res_del_header(nng_http_res *, const char *);
+
+// nng_http_res_get_header looks up a header with the named, returns NULL
+// if not found.
+NNG_DECL const char *nng_http_res_get_header(nng_http_res *, const char *);
+
+// nng_http_res_set_version is used to change the version of a response.
+// Normally the version is "HTTP/1.1".  Note that the framework does
+// not support HTTP/2 at all.  NULL sets the default ("HTTP/1.1").
+NNG_DECL int nng_http_res_set_version(nng_http_res *, const char *);
+
+// nng_http_res_get_version returns the version, usually HTTP/1.1.
+NNG_DECL const char *nng_http_res_get_version(nng_http_res *);
+
+// nng_http_res_get_data gets the data for the response.
+NNG_DECL void nng_http_res_get_data(nng_http_res *, void **, size_t *);
+
+// nng_http_res_set_data adds entity data to the response.  The
+// data object must persist (so only really useful for static data).
+// The content-length header is updated as well, but the caller should
+// probably set the content-type header.
+NNG_DECL int nng_http_res_set_data(nng_http_res *, const void *, size_t);
+
+// nng_http_res_copy_data adds entity data to the response. A private
+// copy of the data is made (will be freed with the request).
+// The content-length header is updated as well, but the caller should
+// probably set the content-type header.
+NNG_DECL int nng_http_res_copy_data(nng_http_res *, const void *, size_t);
+
+// An nng_http_conn represents an underlying "connection".  It may be
+// a TCP channel, or a TLS channel, but the main thing is that this is
+// normally only used for exchanging HTTP requests and responses.
+typedef struct nng_http_conn nng_http_conn;
+
+// nng_http_conn_close closes the underlying channel.  Applications should
+// not use this channel after this operation is performed.
+NNG_DECL void nng_http_conn_close(nng_http_conn *);
+
+// nng_http_conn_read attempts to read data from the connection.  This
+// completes as soon as at least one byte is read; it does not wait
+// for the entire aio to be filled.
+NNG_DECL void nng_http_conn_read(nng_http_conn *, nng_aio *);
+
+// nng_http_conn_read_all is like nng_http_conn_read, but it does not
+// finish until either all the requested data is read, or an error occurs.
+NNG_DECL void nng_http_conn_read_all(nng_http_conn *, nng_aio *);
+
+// nng_http_conn_write attempts to write data, but it can write less
+// than the amount requested. (It completes as soon as at least one
+// byte is written.)
+NNG_DECL void nng_http_conn_write(nng_http_conn *, nng_aio *);
+
+// nng_http_conn_write_all is like nng_http_conn_write, but it does not
+// finish until either all the requested data is written, or an error occurs.
+NNG_DECL void nng_http_conn_write_all(nng_http_conn *, nng_aio *);
+
+// nng_http_conn_write_req writes the entire request.  It will also write any
+// data that has been attached.
+NNG_DECL void nng_http_conn_write_req(
+    nng_http_conn *, nng_http_req *, nng_aio *);
+
+// nng_http_conn_write_res writes the entire response.  It will also write any
+// data that has been attached.
+NNG_DECL void nng_http_conn_write_res(
+    nng_http_conn *, nng_http_res *, nng_aio *);
+
+// nng_http_conn_read_req reads an entire request, EXCEPT for any entity
+// data.  The caller is responsible for processing the headers in the request
+// and reading any submitted entity data itself.
+NNG_DECL void nng_http_conn_read_req(
+    nng_http_conn *, nng_http_req *, nng_aio *);
+
+// nng_http_conn_read_res reads an entire response, EXCEPT for any entity
+// data.  The caller is responsible for processing the headers in the response
+// and reading any submitted entity data itself.
+NNG_DECL void nng_http_conn_read_res(
+    nng_http_conn *, nng_http_res *, nng_aio *);
+
+// nng_http_req_reset resets the request to an initially allocated state.
+NNG_DECL void nng_http_req_reset(nng_http_req *);
+
+// nng_http_res_reset resets the response to an initially allocated state.
+NNG_DECL void nng_http_res_reset(nng_http_res *);
+
+// nng_http_handler is a handler used on the server side to handle HTTP
+// requests coming into a specific URL.
+typedef struct nng_http_handler nng_http_handler;
+
+// nng_http_handler_alloc creates a server handler object, for the supplied
+// absolute URI (path only) with the callback.  By default the handler
+// is assumed to handle only GET requests (and implictly HEAD requests
+// as well.)
+//
+// Note that methods which modify a handler cannot be called while the handler
+// is registered with the server, and that a handler can only be registered
+// once per server.
+//
+// The callback function will receive the following arguments (via
+// nng_aio_get_input(): nng_http_request *, nng_http_handler *, and
+// nng_http_conn *.  The first is a request object, for convenience.
+// The second is the handler, from which the callback can obtain any other
+// data it has set.  The final is the http connection, which can be used
+// to hijack the session.
+//
+// Upon completion, the handler should store an nng_http_res * as the
+// first output using nng_aio_set_output.  If it does not do so, or supplies
+// NULL, then it must send a response itself.
+//
+// The callback should complete with a result of 0 in most circumstances.
+// If it completes with an error, then the connection is terminated, after
+// possibly sending a 500 error response to the client.
+NNG_DECL int nng_http_handler_alloc(
+    nng_http_handler **, const char *, void (*)(nng_aio *));
+
+// nng_http_handler_free frees the handler. This actually just drops a
+// reference count on the handler, as it may be in use by an existing
+// server.  The server will also call this when it is destroyed.
+NNG_DECL void nng_http_handler_free(nng_http_handler *);
+
+// nng_http_handler_alloc_file creates a "file" based handler, that
+// serves up static content from the given file path.  The content-type
+// supplied is determined from the file name using a simple built-in map.
+NNG_DECL int nng_http_handler_alloc_file(
+    nng_http_handler **, const char *, const char *);
+
+// nng_http_handler_alloc_static creates a static-content handler.
+// The last argument is the content-type, which may be NULL (in which case
+// "application/octet-stream" is assumed.)
+NNG_DECL int nng_http_handler_alloc_static(
+    nng_http_handler **, const char *, const void *, size_t, const char *);
+
+// nng_http_handler_alloc_redirect creates an HTTP redirect handler.
+// The status is given, along with the new URL.  If the status is 0,
+// then 301 will be used instead.
+NNG_DECL int nng_http_handler_alloc_redirect(
+    nng_http_handler **, const char *, uint16_t, const char *);
+
+// nng_http_handler_alloc_file creates a "directory" based handler, that
+// serves up static content from the given directory tree.  Directories
+// that contain an index.html or index.htm file use that file for the
+// directory content, otherwise a suitable error page is returned (the server
+// does not generate index pages automatically.)  The content-type for
+// files is determined from the file name using a simple built-in map.
+NNG_DECL int nng_http_handler_alloc_directory(
+    nng_http_handler **, const char *, const char *);
+
+// nng_http_handler_set_method sets the method that the handler will be
+// called for.  By default this is GET.  If NULL is supplied for the
+// method, then the handler is executed regardless of method, and must
+// inspect the method itself.
+NNG_DECL int nng_http_handler_set_method(nng_http_handler *, const char *);
+
+// nng_http_handler_set_host sets the Host: that the handler will be
+// called for (to allow for virtual hosts).  If the value is NULL (the
+// default, then the Host: header is not considered when matching the
+// handler.)  Note that the Host: header must match *exactly* (except
+// that case is not considered.)
+NNG_DECL int nng_http_handler_set_host(nng_http_handler *, const char *);
+
+// nng_http_handler_collect_body is used to indicate the server should
+// check for, and process, data sent by the client, which will be attached
+// to the request.  If this is false, then the handler will need to check
+// for and process any content data.  By default the server will accept
+// up to 1MB.  If the client attempts to send more data than requested,
+// then a 400 Bad Request will be sent back to the client.  To set an
+// unlimited value, use (size_t)-1.  To preclude the client from sending
+// *any* data, use 0.  (The static and file handlers use 0 by default.)
+NNG_DECL int nng_http_handler_collect_body(nng_http_handler *, bool, size_t);
+
+// nng_http_handler_set_tree indicates that the handler is being registered
+// for a hierarchical tree, rather than just a single path, so it will be
+// called for all child paths supplied.  By default the handler is only
+// called for an exact path match.
+NNG_DECL int nng_http_handler_set_tree(nng_http_handler *);
+
+// nng_http_handler_set_tree_exclusive indicates that the handler is being
+// registered for a heirarchical tree *exclusively*, rather than just a single
+// path, so it will be called for all child paths supplied. By default the
+// handler is only called for an exact path match. Exclusive means that any
+// other handler on a conflicting path will induce an address conflict error
+// when added to a server.
+NNG_DECL int nng_http_handler_set_tree_exclusive(nng_http_handler *);
+
+// nng_http_handler_set_data is used to store additional data, along with
+// a possible clean up routine.  (The clean up is a custom de-allocator and
+// will be called with the supplied data as an argument, when the handler
+// is being de-allocated.)
+NNG_DECL int nng_http_handler_set_data(
+    nng_http_handler *, void *, void (*)(void *));
+
+// nng_http_handler_get_data returns the data that was previously stored.
+NNG_DECL void *nng_http_handler_get_data(nng_http_handler *);
+
+// nng_http_server is a handle to an HTTP server instance.  Servers
+// only serve a single port / address at this time.
+
+typedef struct nng_http_server nng_http_server;
+
+// nng_http_server_hold gets a server structure, using the address determined
+// from the URL.  If a server already exists, then a hold is placed on it, and
+// that instance is returned.  If no such server exists, then a new instance
+// is created.
+NNG_DECL int nng_http_server_hold(nng_http_server **, const nng_url *);
+
+// nng_http_server_release releases the hold on the server.  If this is the
+// last instance of the server, then it is shutdown and resources are freed.
+NNG_DECL void nng_http_server_release(nng_http_server *);
+
+// nng_http_server_start starts the server handling HTTP.  Once this is
+// called, it will not be possible to change certain parameters (such as
+// any TLS configuration).
+NNG_DECL int nng_http_server_start(nng_http_server *);
+
+// nng_http_server_stop stops the server.  No new client connections are
+// accepted after this returns.  Once a server is stopped fully, the
+// instance will no longer be returned by nng_http_server_hold, as the
+// server may not be reused.
+NNG_DECL void nng_http_server_stop(nng_http_server *);
+
+// nng_http_server_add_handler registers a handler on the server.
+// This function will return NNG_EADDRINUSE if a conflicting handler
+// is already registered (i.e. a handler with the same value for Host,
+// Method, and URL.)
+NNG_DECL int nng_http_server_add_handler(
+    nng_http_server *, nng_http_handler *);
+
+// nni_http_del_handler removes the given handler.  The caller is
+// responsible for finalizing it afterwards.  If the handler was not found
+// (not registered), NNG_ENOENT is returned.  In this case it is unsafe
+// to make assumptions about the validity of the handler.
+NNG_DECL int nng_http_server_del_handler(
+    nng_http_server *, nng_http_handler *);
+
+// nng_http_server_set_tls adds a TLS configuration to the server,
+// and enables the use of it.  This returns NNG_EBUSY if the server is
+// already started.   This wipes out the entire TLS configuration on the
+// server client, so the caller must have configured it reasonably.
+// This API is not recommended unless the caller needs complete control
+// over the TLS configuration.
+NNG_DECL int nng_http_server_set_tls(
+    nng_http_server *, struct nng_tls_config *);
+
+// nng_http_server_get_tls obtains the TLS configuration if one is present,
+// or returns NNG_EINVAL.  The TLS configuration is invalidated if the
+// nng_http_server_set_tls function is called, so be careful.
+NNG_DECL int nng_http_server_get_tls(
+    nng_http_server *, struct nng_tls_config **);
+
+// nng_http_server_get_addr obtains the address with which the server was
+// initialized or returns NNG_EINVAL. Useful for instance when the port has
+// been automatically assigned.
+NNG_DECL int nng_http_server_get_addr(nng_http_server *, nng_sockaddr *);
+
+// nng_http_server_set_error_page sets a custom error page (HTML) content
+// to be sent for the given error code.  This is used when the error is
+// generated internally by the framework, or when the application returns
+// the response back to the server via the handler's aio, and the response
+// was allocated with nng_http_res_alloc_error.  If the response was not
+// allocated this way, or the application writes the response itself instead
+// of letting the server do so, then this setting will be ignored.
+NNG_DECL int nng_http_server_set_error_page(
+    nng_http_server *, uint16_t, const char *);
+
+// nng_http_server_set_error_file works like nng_http_server_error_page,
+// except that the content is loaded from the named file path.  The contents
+// are loaded at the time this function is called, so this function should be
+// called anytime the contents of the named file have changed.
+NNG_DECL int nng_http_server_set_error_file(
+    nng_http_server *, uint16_t, const char *);
+
+// nng_http_server_res_error takes replaces the body of the response with
+// a custom error page previously set for the server, using the status
+// of the response.  The response must have the status set first using
+// nng_http_res_set_status or implicitly via nng_http_res_alloc_error.
+NNG_DECL int nng_http_server_res_error(nng_http_server *, nng_http_res *);
+
+// nng_http_hijack is intended to be called by a handler that wishes to
+// take over the processing of the HTTP session -- usually to change protocols
+// (such as in the case of websocket).  The caller is responsible for the
+// final disposal of the associated nng_http_conn.  Also, this completely
+// disassociates the http session from the server, so the server may be
+// stopped or destroyed without affecting the hijacked session.  Note also
+// that the hijacker will need to issue any HTTP reply itself.  Finally,
+// when a session is hijacked, the caller is also responsible for disposing
+// of the request structure.  (Some hijackers may keep the request for
+// further processing.)
+
+NNG_DECL int nng_http_hijack(nng_http_conn *);
+
+// nng_http_client represents a "client" object.  Clients can be used
+// to create HTTP connections.  At present, connections are not cached
+// or reused, but that could change in the future.
+typedef struct nng_http_client nng_http_client;
+
+// nng_http_client_alloc allocates a client object, associated with
+// the given URL.
+NNG_DECL int nng_http_client_alloc(nng_http_client **, const nng_url *);
+
+// nng_http_client_free frees the client.  Connections created by the
+// the client are not necessarily closed.
+NNG_DECL void nng_http_client_free(nng_http_client *);
+
+// nng_http_client_set_tls sets the TLS configuration.  This wipes out
+// the entire TLS configuration on the client, so the caller must have
+// configured it reasonably.  This API is not recommended unless the
+// caller needs complete control over the TLS configuration.
+NNG_DECL int nng_http_client_set_tls(
+    nng_http_client *, struct nng_tls_config *);
+
+// nng_http_client_get_tls obtains the TLS configuration if one is present,
+// or returns NNG_EINVAL.  The supplied TLS configuration object may
+// be invalidated by any future calls to nni_http_client_set_tls.
+NNG_DECL int nng_http_client_get_tls(
+    nng_http_client *, struct nng_tls_config **);
+
+// nng_http_client_connect establishes a new connection with the server
+// named in the URL used when the client was created.  Once the connection
+// is established, the associated nng_http_conn object pointer is returned
+// in the first (index 0) output for the aio.
+NNG_DECL void nng_http_client_connect(nng_http_client *, nng_aio *);
+
+// nng_http_conn_transact is used to perform a round-trip exchange (i.e. a
+// single HTTP transaction).  It will not automatically close the connection,
+// unless some kind of significant error occurs.  The caller should close
+// the connection if the aio does not complete successfully.
+NNG_DECL void nng_http_conn_transact(
+    nng_http_conn *, nng_http_req *, nng_http_res *, nng_aio *);
+
+// nng_http_client_transact is used to execute a single transaction to a
+// server. The connection is opened, and will be closed when the transaction is
+// complete.
+NNG_DECL void nng_http_client_transact(
+    nng_http_client *, nng_http_req *, nng_http_res *, nng_aio *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_H
diff --git a/include/nng/supplemental/tls/engine.h b/include/nng/supplemental/tls/engine.h
new file mode 100644
index 0000000..81385fb
--- /dev/null
+++ b/include/nng/supplemental/tls/engine.h
@@ -0,0 +1,207 @@
+//
+// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+// This file is used to enable external TLS "engines", so
+// that third party TLS libraries can be plugged in
+
+#ifndef NNG_SUPPLEMENTAL_TLS_ENGINE_H
+#define NNG_SUPPLEMENTAL_TLS_ENGINE_H
+
+#include <nng/supplemental/tls/tls.h>
+
+// Locking theory statement for TLS engines.  The engine is assumed
+// operate only from the context of threads called by the common
+// framework.  That is to say, the callbacks made by the engine
+// should always be on a thread that has context from the framework
+// calling into the engine.  This means that the lower level send
+// and receive functions can assume that they have lock ownership
+// inherited on the stack.
+
+// nng_tls_engine_conn represents the engine-specific private
+// state for a TLS connection.  It is provided here for type
+// safety.  Engine implementations should provide the structure
+// definition locally.
+typedef struct nng_tls_engine_conn nng_tls_engine_conn;
+
+// nng_tls_engine_config represents the engine-specific private
+// state for the TLS configuration.  It is provided here for type
+// safety.  Engine implementations should provide the structure
+// definition locally.
+typedef struct nng_tls_engine_config nng_tls_engine_config;
+
+typedef struct nng_tls_engine_conn_ops_s {
+	// size is the size of the engine's per-connection state.
+	// The framework will allocate this on behalf of the engine.
+	// Typically this will be sizeof (struct nng_tls_engine_conn).
+	size_t size;
+
+	// init is used to initialize a connection object.
+	// The passed in connection state will be aligned naturally,
+	// and zeroed.  On success this returns 0, else an NNG error code.
+	int (*init)(nng_tls_engine_conn *, void *, nng_tls_engine_config *);
+
+	// fini destroys a connection object.  This will
+	// be called only when no other external use of the connection
+	// object exists, and only on fully initialed connection objects.
+	void (*fini)(nng_tls_engine_conn *);
+
+	// close closes the connection object, but should not
+	// deallocate any memory.  It may also issue a TLS close-notify.
+	void (*close)(nng_tls_engine_conn *);
+
+	// handshake attempts to complete the SSL handshake phase.
+	// It returns zero on success, or an error if one occurred.
+	// The value NNG_EAGAIN should be returned if underlying I/O
+	// is required to be completed first.  The framework will
+	// ensure that the handshake completes before sending any data
+	// down.
+	int (*handshake)(nng_tls_engine_conn *);
+
+	// recv attempts to read data (decrypted) from the connection.
+	// It returns 0 on success, otherwise an error.  The implementation
+	// should return NNG_EAGAIN if I/O to the underlying stream is
+	// required to complete the operation.  On success, the count
+	// is updated to reflect the number of bytes actually received.
+	int (*recv)(nng_tls_engine_conn *, uint8_t *, size_t *);
+
+	// send attempts to write data to the underlying connection.
+	// It returns zero on success, otherwise an error. The implementation
+	// should return NNG_EAGAIN if I/O to the underlying stream is
+	// required to complete the operation.  On success, the count
+	// is updated to reflect the number of bytes actually sent.
+	int (*send)(nng_tls_engine_conn *, const uint8_t *, size_t *);
+
+	// verified returns true if the connection is fully
+	// TLS verified, false otherwise.
+	bool (*verified)(nng_tls_engine_conn *);
+} nng_tls_engine_conn_ops;
+
+typedef struct nng_tls_engine_config_ops_s {
+	// size is the size of the engine's configuration object.
+	// The framework will allocate this on behalf of the engine.
+	// Typically this will be sizeof (struct nng_tls_engine_config).
+	size_t size;
+
+	// init prepares the configuration object object.
+	// The mode indicates whether the object should be
+	// initialized for use as a TLS server or client.
+	// The config passed in will be aligned on a 64-bit boundary,
+	// and will be initialized to zero.  On success this returns
+	// 0, else an NNG error code.
+	int (*init)(nng_tls_engine_config *, nng_tls_mode);
+
+	// fini is used to tear down the configuration object.
+	// This will only be called on objects that have been properly
+	// initialized with nte_config_init.
+	void (*fini)(nng_tls_engine_config *);
+
+	// server is used to set the server name.  This can be used in SNI,
+	// and will also be used on the client to validate the identity.
+	// If this is not set, then no verification will be performed.
+	int (*server)(nng_tls_engine_config *, const char *);
+
+	// auth is used to configure the authentication mode.  Values:
+	// NNG_AUTH_MODE_NONE
+	//   No validation of the peer is performed.  Public facing
+	//   servers often use this.
+	// NNG_AUTH_MODE_OPTIONAL
+	//   The peer's identity is validated if a certificate is presented.
+	//   This is typically useful on servers.
+	// NNG_AUTH_MODE_REQUIRED
+	//   The peer's certificate must be present and is verified.
+	//   This is standard for the client, and on servers it is used
+	//   when client (mutual) authentication is needed.
+	int (*auth)(nng_tls_engine_config *, nng_tls_auth_mode);
+
+	// ca_chain sets the configuration authorities that will be
+	// used to validate peers.  An optional CRL is supplied as well.
+	// Both values are C strings (NUL terminated) containing
+	// PEM data.  There may be multiple PEM blocks.  The
+	// CRL may be NULL if not needed.
+	int (*ca_chain)(nng_tls_engine_config *, const char *, const char *);
+
+	// own_cert configures our identity -- the certificate containing
+	// our public key, our private key (which might be encrypted), and
+	// potentially a password used to decrypt the private key.
+	// All of these are C strings.  The cert may actually be a chain
+	// which will be presented to our peer.   This function may be
+	// called multiple times to register different keys with different
+	// parameters on a server.  (For example, once for RSA parameters,
+	// and again later with EC parameters.)  The certificate and the
+	// private key may be presented in the same file.  The implementation
+	// is responsible for parsing out the relevant data.  If the password
+	// is NULL, then the key file should be unencrypted.  The supplied
+	// password may be ignored if the key is not encrypted.  Not all
+	// engine implementations need support encryption of the key.
+	int (*own_cert)(
+	    nng_tls_engine_config *, const char *, const char *, const char *);
+
+	// version configures the minimum and maximum TLS versions.  The
+	// engine should default to supporting TLS1.0 through 1.2, and
+	// optionally 1.3 if it can.  The engine should restrict the
+	// the requested range to what it can support -- if no version
+	// within the range is supported (such as if NNG_TLS_1_3 is
+	// specified for both min and max, and the engine lacks support
+	// for v1.3, then NNG_ENOTSUP should be returned.
+	int (*version)(
+	    nng_tls_engine_config *, nng_tls_version, nng_tls_version);
+} nng_tls_engine_config_ops;
+
+typedef enum nng_tls_engine_version_e {
+	NNG_TLS_ENGINE_V0      = 0,
+	NNG_TLS_ENGINE_V1      = 1,
+	NNG_TLS_ENGINE_VERSION = NNG_TLS_ENGINE_V1,
+} nng_tls_engine_version;
+
+typedef struct nng_tls_engine_s {
+	// _version is the engine version.  This for now must
+	// be NNG_TLS_ENGINE_VERSION.  If the version does not match
+	// then registration of the engine will fail.
+	nng_tls_engine_version version;
+
+	// config_ops is the operations for TLS configuration objects.
+	nng_tls_engine_config_ops *config_ops;
+
+	// conn_ops is the operations for TLS connections (stream-oriented).
+	nng_tls_engine_conn_ops *conn_ops;
+
+	// name contains the name of the engine, for example "wolfSSL".
+	// It is acceptable to append a version number as well.
+	const char *name;
+
+	// description contains a human readable description.  This can
+	// supply information about the backing library, for example
+	// "mbed TLS v2.7"
+	const char *description;
+
+	// fips_mode is true if the engine is in FIPS mode.
+	// It is expected that this will be enabled either at compile
+	// time, or via environment variables at engine initialization.
+	// FIPS mode cannot be changed once the engine is registered.
+	bool fips_mode;
+} nng_tls_engine;
+
+NNG_DECL int nng_tls_engine_register(const nng_tls_engine *);
+
+// nng_tls_engine_send is called by the engine to send data over the
+// underlying connection.  It returns zero on success, NNG_EAGAIN if
+// the operation can't be completed yet (the transport is busy and cannot
+// accept more data yet), or some other error.  On success the count is
+// updated with the number of bytes actually sent.  The first argument
+// is the context structure passed in when starting the engine.
+NNG_DECL int nng_tls_engine_send(void *, const uint8_t *, size_t *);
+
+// nng_tls_engine_recv is called byu the engine to receive data over
+// the underlying connection.  It returns zero on success, NNG_EAGAIN
+// if the operation can't be completed yet (there is no data available
+// for reading), or some other error.  On success the count is updated
+// with the number of bytes actually received.
+NNG_DECL int nng_tls_engine_recv(void *, uint8_t *, size_t *);
+
+#endif // NNG_SUPPLEMENTAL_TLS_ENGINE_H
diff --git a/include/nng/supplemental/tls/tls.h b/include/nng/supplemental/tls/tls.h
new file mode 100644
index 0000000..e547f8e
--- /dev/null
+++ b/include/nng/supplemental/tls/tls.h
@@ -0,0 +1,142 @@
+//
+// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_SUPPLEMENTAL_TLS_TLS_H
+#define NNG_SUPPLEMENTAL_TLS_TLS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+// Note that TLS functions may be stubbed out if TLS is not enabled in
+// the build.
+
+// For some transports, we need TLS configuration, including certificates
+// and so forth.  A TLS configuration cannot be changed once it is in use.
+typedef struct nng_tls_config nng_tls_config;
+
+typedef enum nng_tls_mode {
+	NNG_TLS_MODE_CLIENT = 0,
+	NNG_TLS_MODE_SERVER = 1,
+} nng_tls_mode;
+
+typedef enum nng_tls_auth_mode {
+	NNG_TLS_AUTH_MODE_NONE     = 0, // No verification is performed
+	NNG_TLS_AUTH_MODE_OPTIONAL = 1, // Verify cert if presented
+	NNG_TLS_AUTH_MODE_REQUIRED = 2, // Verify cert, close if invalid
+} nng_tls_auth_mode;
+
+// TLS version numbers.  We encode the major number and minor number
+// as separate byte fields.  No support for SSL 3.0 or earlier -- older
+// versions are known to be insecure and should not be used.
+// When possible applications should restrict themselves to TLS 1.2 or better.
+typedef enum nng_tls_version {
+	NNG_TLS_1_0 = 0x301,
+	NNG_TLS_1_1 = 0x302,
+	NNG_TLS_1_2 = 0x303,
+	NNG_TLS_1_3 = 0x304
+} nng_tls_version;
+
+// nng_tls_config_alloc creates a TLS configuration using
+// reasonable defaults.  This configuration can be shared
+// with multiple pipes or services/servers.
+NNG_DECL int nng_tls_config_alloc(nng_tls_config **, nng_tls_mode);
+
+// nng_tls_config_hold increments the reference count on the TLS
+// configuration object.  The hold can be dropped by calling
+// nng_tls_config_free later.
+NNG_DECL void nng_tls_config_hold(nng_tls_config *);
+
+// nng_tls_config_free drops the reference count on the TLS
+// configuration object, and if zero, deallocates it.
+NNG_DECL void nng_tls_config_free(nng_tls_config *);
+
+// nng_tls_config_server_name sets the server name.  This is
+// called by clients to set the name that the server supplied
+// certificate should be matched against.  This can also cause
+// the SNI to be sent to the server to tell it which cert to
+// use if it supports more than one.
+NNG_DECL int nng_tls_config_server_name(nng_tls_config *, const char *);
+
+// nng_tls_config_ca_cert configures one or more CAs used for validation
+// of peer certificates.  Multiple CAs (and their chains) may be configured
+// by either calling this multiple times, or by specifying a list of
+// certificates as concatenated data.  The final argument is an optional CRL
+// (revocation list) for the CA, also in PEM.  Both PEM strings are ASCIIZ
+// format (except that the CRL may be NULL).
+NNG_DECL int nng_tls_config_ca_chain(
+    nng_tls_config *, const char *, const char *);
+
+// nng_tls_config_own_cert is used to load our own certificate and public
+// key.  For servers, this may be called more than once to configure multiple
+// different keys, for example with different algorithms depending on what
+// the peer supports. On the client, only a single option is available.
+// The first two arguments are the cert (or validation chain) and the
+// key as PEM format ASCIIZ strings.  The final argument is an optional
+// password and may be NULL.
+NNG_DECL int nng_tls_config_own_cert(
+    nng_tls_config *, const char *, const char *, const char *);
+
+// nng_tls_config_key is used to pass our own private key.
+NNG_DECL int nng_tls_config_key(nng_tls_config *, const uint8_t *, size_t);
+
+// nng_tls_config_pass is used to pass a password used to decrypt
+// private keys that are encrypted.
+NNG_DECL int nng_tls_config_pass(nng_tls_config *, const char *);
+
+// nng_tls_config_auth_mode is used to configure the authentication mode use.
+// The default is that servers have this off (i.e. no client authentication)
+// and clients have it on (they verify the server), which matches typical
+// practice.
+NNG_DECL int nng_tls_config_auth_mode(nng_tls_config *, nng_tls_auth_mode);
+
+// nng_tls_config_ca_file is used to pass a CA chain and optional CRL
+// via the filesystem.  If CRL data is present, it must be contained
+// in the file, along with the CA certificate data.  The format is PEM.
+// The path name must be a legal file name.
+NNG_DECL int nng_tls_config_ca_file(nng_tls_config *, const char *);
+
+// nng_tls_config_cert_key_file is used to pass our own certificate and
+// private key data via the filesystem.  Both the key and certificate
+// must be present as PEM blocks in the same file.  A password is used to
+// decrypt the private key if it is encrypted and the password supplied is not
+// NULL. This may be called multiple times on servers, but only once on a
+// client. (Servers can support multiple different certificates and keys for
+// different cryptographic algorithms.  Clients only get one.)
+NNG_DECL int nng_tls_config_cert_key_file(
+    nng_tls_config *, const char *, const char *);
+
+// Configure supported TLS version.  By default we usually restrict
+// ourselves to TLS 1.2 and newer.  We do not support older versions.
+// If the implementation cannot support any version (for example if
+// the minimum requested is 1.3 but the TLS implementation lacks support
+// for TLS 1.3) then NNG_ENOTSUP will be returned.
+NNG_DECL int nng_tls_config_version(
+    nng_tls_config *, nng_tls_version, nng_tls_version);
+
+// nng_tls_engine_name returns the "name" of the TLS engine.  If no
+// TLS engine support is enabled, then "none" is returned.
+NNG_DECL const char *nng_tls_engine_name(void);
+
+// nng_tls_engine_description returns the "description" of the TLS engine.
+// If no TLS engine support is enabled, then an empty string is returned.
+NNG_DECL const char *nng_tls_engine_description(void);
+
+// nng_tls_engine_fips_mode returns true if the engine is in FIPS 140-2 mode.
+NNG_DECL bool nng_tls_engine_fips_mode(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_SUPPLEMENTAL_TLS_TLS_H
diff --git a/include/nng/supplemental/util/options.h b/include/nng/supplemental/util/options.h
new file mode 100644
index 0000000..83969a9
--- /dev/null
+++ b/include/nng/supplemental/util/options.h
@@ -0,0 +1,48 @@
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_SUPPLEMENTAL_UTIL_OPTIONS_H
+#define NNG_SUPPLEMENTAL_UTIL_OPTIONS_H
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// This is a relatively simple "options parsing" library, used to
+// parse command line options.  We would use getopt(3), but there are
+// two problems with getopt(3).  First, it isn't available on all
+// platforms (especially Win32), and second, it doesn't support long
+// options.  We *exclusively* support long options.  POSIX style
+// short option clustering is *NOT* supported.
+
+struct nng_optspec {
+	const char *o_name;  // Long style name (may be NULL for short only)
+	int         o_short; // Short option (no clustering!)
+	int         o_val;   // Value stored on a good parse (>0)
+	bool        o_arg;   // Option takes an argument if true
+};
+
+typedef struct nng_optspec nng_optspec;
+
+// Call with *optidx set to 1 to start parsing for a standard program.
+// The val will store the value of the matched "o_val", optarg will be
+// set to match the option string, and optidx will be increment appropriately.
+// Returns -1 when the end of options is reached, 0 on success, or
+// NNG_EINVAL if the option parse is invalid for any reason.
+NNG_DECL int nng_opts_parse(int argc, char *const *argv,
+    const nng_optspec *opts, int *val, char **optarg, int *optidx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_SUPPLEMENTAL_UTIL_OPTIONS_H
diff --git a/include/nng/supplemental/util/platform.h b/include/nng/supplemental/util/platform.h
new file mode 100644
index 0000000..87e0305
--- /dev/null
+++ b/include/nng/supplemental/util/platform.h
@@ -0,0 +1,106 @@
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_SUPPLEMENTAL_UTIL_PLATFORM_H
+#define NNG_SUPPLEMENTAL_UTIL_PLATFORM_H
+
+// The declarations in this file are provided to assist with application
+// portability.  Conceptually these APIs are based on work we have already
+// done for NNG internals, and we find that they are useful in building
+// portable applications.
+
+// If it is more natural to use native system APIs like pthreads or C11
+// APIs or Windows APIs, then by all means please feel free to simply
+// ignore this.
+
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// nng_time represents an absolute time since some arbitrary point in the
+// past, measured in milliseconds.  The values are always positive.
+typedef uint64_t nng_time;
+
+// Return an absolute time from some arbitrary point.  The value is
+// provided in milliseconds, and is of limited resolution based on the
+// system clock.  (Do not use it for fine grained performance measurements.)
+NNG_DECL nng_time nng_clock(void);
+
+// Sleep for specified msecs.
+NNG_DECL void nng_msleep(nng_duration);
+
+// nng_thread is a handle to a "thread", which may be a real system
+// thread, or a coroutine on some platforms.
+typedef struct nng_thread nng_thread;
+
+// Create and start a thread.  Note that on some platforms, this might
+// actually be a coroutine, with limitations about what system APIs
+// you can call.  Therefore, these threads should only be used with the
+// I/O APIs provided by nng.  The thread runs until completion.
+NNG_DECL int nng_thread_create(nng_thread **, void (*)(void *), void *);
+
+// Destroy a thread (waiting for it to complete.)  When this function
+// returns all resources for the thread are cleaned up.
+NNG_DECL void nng_thread_destroy(nng_thread *);
+
+// nng_mtx represents a mutex, which is a simple, non-reentrant, boolean lock.
+typedef struct nng_mtx nng_mtx;
+
+// nng_mtx_alloc allocates a mutex structure.
+NNG_DECL int nng_mtx_alloc(nng_mtx **);
+
+// nng_mtx_free frees the mutex.  It must not be locked.
+NNG_DECL void nng_mtx_free(nng_mtx *);
+
+// nng_mtx_lock locks the mutex; if it is already locked it will block
+// until it can be locked.  If the caller already holds the lock, the
+// results are undefined (a panic may occur).
+NNG_DECL void nng_mtx_lock(nng_mtx *);
+
+// nng_mtx_unlock unlocks a previously locked mutex.  It is an error to
+// call this on a mutex which is not owned by caller.
+NNG_DECL void nng_mtx_unlock(nng_mtx *);
+
+// nng_cv is a condition variable.  It is always allocated with an
+// associated mutex, which must be held when waiting for it, or
+// when signaling it.
+typedef struct nng_cv nng_cv;
+
+NNG_DECL int nng_cv_alloc(nng_cv **, nng_mtx *);
+
+// nng_cv_free frees the condition variable.
+NNG_DECL void nng_cv_free(nng_cv *);
+
+// nng_cv_wait waits until the condition variable is "signaled".
+NNG_DECL void nng_cv_wait(nng_cv *);
+
+// nng_cv_until waits until either the condition is signaled, or
+// the timeout expires.  It returns NNG_ETIMEDOUT in that case.
+NNG_DECL int nng_cv_until(nng_cv *, nng_time);
+
+// nng_cv_wake wakes all threads waiting on the condition.
+NNG_DECL void nng_cv_wake(nng_cv *);
+
+// nng_cv_wake1 wakes only one thread waiting on the condition.  This may
+// reduce the thundering herd problem, but care must be taken to ensure
+// that no waiter starves forever.
+NNG_DECL void nng_cv_wake1(nng_cv *);
+
+// nng_random returns a "strong" (cryptographic sense) random number.
+NNG_DECL uint32_t nng_random(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_SUPPLEMENTAL_UTIL_PLATFORM_H
diff --git a/include/nng/transport/inproc/inproc.h b/include/nng/transport/inproc/inproc.h
new file mode 100644
index 0000000..80a8388
--- /dev/null
+++ b/include/nng/transport/inproc/inproc.h
@@ -0,0 +1,28 @@
+//
+// Copyright 2019 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2017 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_TRANSPORT_INPROC_INPROC_H
+#define NNG_TRANSPORT_INPROC_INPROC_H
+
+#include <nng/nng.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// inproc transport.  This is used for intra-process communication.
+
+NNG_DECL int nng_inproc_register(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_TRANSPORT_INPROC_INPROC_H
diff --git a/include/nng/transport/ipc/ipc.h b/include/nng/transport/ipc/ipc.h
new file mode 100644
index 0000000..18d2046
--- /dev/null
+++ b/include/nng/transport/ipc/ipc.h
@@ -0,0 +1,29 @@
+//
+// Copyright 2019 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_TRANSPORT_IPC_IPC_H
+#define NNG_TRANSPORT_IPC_IPC_H
+
+#include <nng/nng.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ipc transport.  This is used for inter-process communication on
+// the same host computer.
+
+NNG_DECL int nng_ipc_register(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_TRANSPORT_IPC_IPC_H
diff --git a/include/nng/transport/tcp/tcp.h b/include/nng/transport/tcp/tcp.h
new file mode 100644
index 0000000..2ca40b7
--- /dev/null
+++ b/include/nng/transport/tcp/tcp.h
@@ -0,0 +1,28 @@
+//
+// Copyright 2019 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2017 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_TRANSPORT_TCP_TCP_H
+#define NNG_TRANSPORT_TCP_TCP_H
+
+#include <nng/nng.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// TCP transport.  This is used for communication over TCP/IP.
+
+NNG_DECL int nng_tcp_register(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_TRANSPORT_TCP_TCP_H
diff --git a/include/nng/transport/tls/tls.h b/include/nng/transport/tls/tls.h
new file mode 100644
index 0000000..700d5ff
--- /dev/null
+++ b/include/nng/transport/tls/tls.h
@@ -0,0 +1,28 @@
+//
+// Copyright 2019 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_TRANSPORT_TLS_TLS_H
+#define NNG_TRANSPORT_TLS_TLS_H
+
+#include <nng/nng.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// TLS transport.  This is used for communication via TLS v1.2 over TCP/IP.
+
+NNG_DECL int nng_tls_register(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_TRANSPORT_TLS_TLS_H
diff --git a/include/nng/transport/ws/websocket.h b/include/nng/transport/ws/websocket.h
new file mode 100644
index 0000000..6957710
--- /dev/null
+++ b/include/nng/transport/ws/websocket.h
@@ -0,0 +1,34 @@
+//
+// Copyright 2019 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_TRANSPORT_WS_WEBSOCKET_H
+#define NNG_TRANSPORT_WS_WEBSOCKET_H
+
+#include <nng/nng.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// WebSocket transport.  This is used for communication via WebSocket.
+
+NNG_DECL int nng_ws_register(void);
+
+// These aliases are for WSS naming consistency.
+#define NNG_OPT_WSS_REQUEST_HEADERS NNG_OPT_WS_REQUEST_HEADERS
+#define NNG_OPT_WSS_RESPONSE_HEADERS NNG_OPT_WS_RESPONSE_HEADERS
+
+NNG_DECL int nng_wss_register(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_TRANSPORT_WS_WEBSOCKET_H
diff --git a/include/nng/transport/zerotier/zerotier.h b/include/nng/transport/zerotier/zerotier.h
new file mode 100644
index 0000000..ea73fea
--- /dev/null
+++ b/include/nng/transport/zerotier/zerotier.h
@@ -0,0 +1,159 @@
+//
+// Copyright 2019 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt).  A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#ifndef NNG_TRANSPORT_ZEROTIER_ZEROTIER_H
+#define NNG_TRANSPORT_ZEROTIER_ZEROTIER_H
+
+#include <nng/nng.h>
+
+// ZeroTier Transport.  This sits on the ZeroTier L2 network, which itself
+// is implemented on top of UDP.  This requires the 3rd party
+// libzerotiercore library (which is GPLv3!) and platform specific UDP
+// functionality to be built in.  Note that care must be taken to link
+// dynamically if one wishes to avoid making your entire application GPL3.
+// (Alternatively ZeroTier offers commercial licenses which may prevent
+// this particular problem.)  This implementation does not make use of
+// certain advanced capabilities in ZeroTier such as more sophisticated
+// route management and TCP fallback.  You need to have connectivity
+// to the Internet to use this.  (Or at least to your Planetary root.)
+//
+// The ZeroTier URL format we support is zt://<ztid>.<nwid>:<port> where
+// the <nwid> component represents the 64-bit hexadecimal ZeroTier
+// network ID,the <ztid> represents the 40-bit hexadecimal ZeroTier
+// node (device) ID, and the <port> is a 24-bit (decimal) port number.
+//
+// A listener may replace the <ztid> with a wildcard, to just bind to itself,
+// in which case the format will be zt://*.<nwid>:<port>
+//
+// A listener may also use either 0 or * for the <port> to indicate that
+// a random local ephemeral port should be used.
+//
+// Because ZeroTier takes a while to establish connectivity, it is even
+// more important that applications using the ZeroTier transport not
+// assume that a connection will be immediately available.  It can take
+// quite a few seconds for peer-to-peer connectivity to be established.
+//
+// The ZeroTier transport was funded by Capitar IT Group, BV.
+//
+// The protocol itself is documented online at:
+// http://nanomsg.org/rfcs/sp-zerotier-v0.html
+//
+// This transport is highly experimental.
+
+// ZeroTier transport-specific options.
+
+// NNG_OPT_ZT_HOME is a string containing a directory, where persistent
+// state (key files, etc.) will be stored.  It should be protected from
+// unauthorized viewing and modification.  This option must be set on an
+// endpoint or socket before the endpoint(s) are started.  If the unset,
+// or an empty string, then no persistence is used and an ephemeral node
+// will be created instead.  Note that different endpoints may use different
+// values for this option, and that will lead to each endpoint having a
+// different ZeroTier identity -- however only one ephemeral node will
+// be created for the application.
+#define NNG_OPT_ZT_HOME "zt:home"
+
+// NNG_OPT_ZT_NWID is the 64-bit network ID, represented using a uint64_t in
+// native byte order.  This is a read-only option; it is derived automatically
+// from the URL.
+#define NNG_OPT_ZT_NWID "zt:nwid"
+
+// NNG_OPT_ZT_NODE is the 40-bit node ID, stored in native order in the low
+// 40-bits of a uint64_t, of the node.  This is a read-only option.
+#define NNG_OPT_ZT_NODE "zt:node"
+
+// NNG_OPT_ZT_NETWORK_STATUS represents the status of the ZeroTier virtual
+// network.  The option is a read-only value, stored as an integer, which
+// takes of the nng_zt_network_status_xxx values listed below.
+#define NNG_OPT_ZT_NETWORK_STATUS "zt:network-status"
+
+// NNG_OPT_ZT_NETWORK_NAME is a human-readable name for the ZeroTier virtual
+// network.  This will only be set once the ZeroTier network has come up
+// as the name comes from the network controller.  This is read-only, and
+// is presented as an ASCIIZ string.
+#define NNG_OPT_ZT_NETWORK_NAME "zt:network-name"
+
+// NNG_OPT_ZT_PING_TIME and NNG_OPT_ZT_PING_TRIES are used to send ping
+// requests when a connection appears to be idled.  If a logical session
+// has not received traffic from it's peer for ping-time, then a ping packet
+// is sent.  This will be done up to ping-count times.  If no traffic from
+// the remote peer is seen after all ping requests are sent, then the peer
+// is assumed to be dead or offline, and the session is closed.  The
+// NNG_OPT_ZT_PING_TIME is a duration (msec, stored as an nng_duration, and
+// NNG_OPT_ZT_PING_COUNT is an integer.)  This ping process can be disabled
+// by setting either ping-time or ping-count to zero.
+#define NNG_OPT_ZT_PING_TIME "zt:ping-time"
+#define NNG_OPT_ZT_PING_TRIES "zt:ping-tries"
+
+// NNG_OPT_ZT_CONN_TIME and NNG_OPT_ZT_CONN_TRIES are used to control
+// the interval between connection attempts, and the maximum number of
+// connection attempts to make before assuming that the peer is absent
+// (and returning NNG_ETIMEDOUT).  The NNG_OPT_ZT_CONN_TIME is a duration,
+// the NNG_OPT_ZT_CONN_TRIES is an integer.
+#define NNG_OPT_ZT_CONN_TIME "zt:conn-time"
+#define NNG_OPT_ZT_CONN_TRIES "zt:conn-tries"
+
+// NNG_OPT_ZT_MTU is a read-only size_t and contains the ZeroTier virtual
+// network MTU (i.e. the L2 payload MTU). Messages that are larger than this
+// (including our 20-byte header data) will be fragmented into multiple
+// virtual L2 frames.
+#define NNG_OPT_ZT_MTU "zt:mtu"
+
+// NNG_OPT_ZT_ORBIT is a write-only API to add a "moon" -- this affects the
+// endpoint, and all other endpoints using the same node. The value is
+// a pair of 64-bit integers -- the first is the moon ID, and the second, if
+// non-zero, is the node ID of a server.  Conventionally this is the same
+// as the moon ID.
+#define NNG_OPT_ZT_ORBIT "zt:orbit"
+
+// NNG_OPT_ZT_DEORBIT removes the moon ID from the node, so that it will
+// no longer use that moon.  The argument is a moon ID to remove.  If the
+// node is not already orbiting, then this operation does nothing.
+#define NNG_OPT_ZT_DEORBIT "zt:deorbit"
+
+// NNG_OPT_ZT_ADD_LOCAL_ADDR adds the local address (IP address) as
+// local interface address.  This facilitates the local startup and
+// discovery.  Note that this can be called multiple times to add
+// additional address.  This is optional, and usually not needed.
+// The value is an nng_sockaddr corresponding to an IP (or IPv6) address.
+#define NNG_OPT_ZT_ADD_LOCAL_ADDR "zt:add-local-addr"
+
+// NNG_OPT_ZT_CLEAR_LOCAL_ADDRS clears ZeroTier's notion of all
+// local addresses.  This may be useful when used on a mobile node,
+// to reset the notion of what the local addresses are.  This
+// option takes no argument really.
+#define NNG_OPT_ZT_CLEAR_LOCAL_ADDRS "zt:clear-local-addrs"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Network status values.
+// These values are supplied to help folks checking status.  They are the
+// return values from zt_opt_status.  We avoid hard coding them as defines,
+// to keep applications from baking in values that may change if the
+// underlying ZeroTier transport changes.
+enum nng_zt_status {
+	NNG_ZT_STATUS_UP,
+	NNG_ZT_STATUS_CONFIG,
+	NNG_ZT_STATUS_DENIED,
+	NNG_ZT_STATUS_NOTFOUND,
+	NNG_ZT_STATUS_ERROR,
+	NNG_ZT_STATUS_OBSOLETE,
+	NNG_ZT_STATUS_UNKNOWN,
+};
+
+NNG_DECL int nng_zt_register(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NNG_TRANSPORT_ZEROTIER_ZEROTIER_H
diff --git a/lib/jsoncpp/libjsoncpp.a b/lib/jsoncpp/libjsoncpp.a
new file mode 100644
index 0000000..925609b
--- /dev/null
+++ b/lib/jsoncpp/libjsoncpp.a
Binary files differ
diff --git a/lib/jsoncpp/libjsoncpp.so b/lib/jsoncpp/libjsoncpp.so
new file mode 120000
index 0000000..748700e
--- /dev/null
+++ b/lib/jsoncpp/libjsoncpp.so
@@ -0,0 +1 @@
+libjsoncpp.so.1
\ No newline at end of file
diff --git a/lib/jsoncpp/libjsoncpp.so.1 b/lib/jsoncpp/libjsoncpp.so.1
new file mode 100755
index 0000000..40bc1a8
--- /dev/null
+++ b/lib/jsoncpp/libjsoncpp.so.1
Binary files differ
diff --git a/lib/nng/libnng.a b/lib/nng/libnng.a
new file mode 100644
index 0000000..c77b190
--- /dev/null
+++ b/lib/nng/libnng.a
Binary files differ
diff --git a/service/Makefile b/service/Makefile
index 452d39d..81cb258 100644
--- a/service/Makefile
+++ b/service/Makefile
@@ -2,12 +2,15 @@
 # Makefile for common library.
 #
 ROOT=..
-LDLIBS+=-Wl,-rpath=$(ROOT)/lib/hc:$(ROOT)/lib/hc/HCNetSDKCom:$(ROOT)/common
+LDLIBS+=-Wl,-rpath=$(ROOT)/lib/hc:$(ROOT)/lib/hc/HCNetSDKCom:$(ROOT)/common:$(ROOT)/lib/jsoncpp
 # 娴峰悍鍖呰矾寰�
 LDDIR += -L$(ROOT)/lib/hc -L$(ROOT)/lib/hc/HCNetSDKCom
-LDLIBS +=
+# 寮�婧愬伐鍏峰寘璺緞
+LDDIR += -L$(ROOT)/lib/jsoncpp -L$(ROOT)/lib/nng
+
 # 娴峰悍鍖�
-LDLIBS +=  -lhcnetsdk -lhpr -lHCCore 
+LDLIBS +=  -lhcnetsdk -lhpr -lHCCore
+# 寮�婧愬伐鍏峰寘
 LDLIBS += -ljsoncpp  -lnng  -lpthread
 
 INCLUDE += -I$(ROOT)/device/include
@@ -16,7 +19,10 @@
 PLATFORM=$(shell $(ROOT)/systype.sh)
 include $(ROOT)/Make.defines.$(PLATFORM)
 
-all: netdisk_service test_client test test_queue test_properties
+ 
+PROGS = netdisk_service test_client test test_queue test_properties
+
+all: $(PROGS)
 
 
 netdisk_service: $(ROOT)/device/hcnetdisk.c $(ROOT)/device/netdisk_factory.c login_store.c request_handler.c properties_config.c
@@ -26,7 +32,7 @@
 test_properties: properties_config.c
 
 clean:
-	rm -f test *.o a.out core temp.* *.a *.so
+	rm -f $(TEMPFILES) $(PROGS)
 
 
 include $(ROOT)/Make.common.inc
diff --git a/service/netdisk_service b/service/netdisk_service
index aa7df14..fd9bbc1 100755
--- a/service/netdisk_service
+++ b/service/netdisk_service
Binary files differ
diff --git a/service/test b/service/test
index a400c13..f5f368d 100755
--- a/service/test
+++ b/service/test
Binary files differ
diff --git a/service/test_client b/service/test_client
index b186451..baf8670 100755
--- a/service/test_client
+++ b/service/test_client
Binary files differ
diff --git a/service/test_properties b/service/test_properties
index 8b9c3f1..31584af 100755
--- a/service/test_properties
+++ b/service/test_properties
Binary files differ
diff --git a/service/test_queue b/service/test_queue
index 47f3dd8..e417957 100755
--- a/service/test_queue
+++ b/service/test_queue
Binary files differ

--
Gitblit v1.8.0