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