diff --git a/.travis.yml b/.travis.yml
index e8ff00f425f..52c15ea5b1b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,7 +11,7 @@ before_install:
- echo "yes" | sudo add-apt-repository ppa:ubuntu-toolchain-r/test
- sudo apt-get -qq update
- sudo apt-get -qq install build-essential libtool gcc-4.8 g++-4.8 make cmake openssl
- - sudo apt-get -qq install libssl-dev libmysqlclient15-dev libmysql++-dev libreadline6-dev zlib1g-dev libbz2-dev
+ - sudo apt-get -qq install libssl-dev libmysqlclient15-dev libmysql++-dev libreadline6-dev zlib1g-dev libbz2-dev libzmq3-dev
- sudo apt-get -qq install libboost1.55-dev libboost-thread1.55-dev libboost-system1.55-dev libboost-program-options1.55-dev
install:
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5e91c7da4ec..905d92996bf 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -56,6 +56,7 @@ set(OPENSSL_EXPECTED_VERSION 1.0.0)
find_package(PCHSupport)
find_package(OpenSSL REQUIRED)
find_package(Threads REQUIRED)
+find_package(ZMQ REQUIRED)
include(ConfigureBoost)
find_package(MySQL REQUIRED)
diff --git a/README.md b/README.md
index 33fea30e36e..540ce485dca 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
#  TrinityCore
-[](https://scan.coverity.com/projects/435)
+[](https://scan.coverity.com/projects/435)
+[](https://www.bountysource.com/trackers/1310-trinity-core?utm_source=1310&utm_medium=shield&utm_campaign=TRACKER_BADGE)
`3.3.5`: [](https://travis-ci.org/TrinityCore/TrinityCore)
`4.3.4`: [](https://travis-ci.org/TrinityCore/TrinityCore)
@@ -21,7 +22,6 @@ make pull requests to our [Github repository](https://github.com/TrinityCore/Tri
For further information on the TrinityCore project, please visit our project
website at [TrinityCore.org](http://www.trinitycore.org).
-
## Requirements
+ Platform: Linux, Windows or Mac
diff --git a/cmake/macros/FindZMQ.cmake b/cmake/macros/FindZMQ.cmake
new file mode 100644
index 00000000000..b0d7c56489f
--- /dev/null
+++ b/cmake/macros/FindZMQ.cmake
@@ -0,0 +1,76 @@
+#
+# Find the ZMQ includes and library
+#
+
+# This module defines
+# ZMQ_INCLUDE_DIR, where to find zmq.h
+# ZMQ_LIBRARY, the library needed to use ZMQ
+# ZMQ_FOUND, if false, you cannot build anything that requires ZMQ.
+
+set(ZMQ_FOUND 0)
+
+if (PLATFORM EQUAL 64)
+ set(ZMQ_REGISTRY_PATH
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ZeroMQ (x64);DisplayIcon]"
+ )
+else()
+ set(ZMQ_REGISTRY_PATH
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ZeroMQ;DisplayIcon]"
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ZeroMQ;DisplayIcon]"
+ )
+endif()
+
+find_path(ZMQ_ROOT_DIR
+ NAMES
+ include/zmq.h
+ HINTS
+ ${ZMQ_REGISTRY_PATH}
+ PATHS
+ /usr
+ /usr/local
+)
+
+find_path(ZMQ_INCLUDE_DIR zmq.h ${ZMQ_ROOT_DIR}/include)
+
+if (MSVC)
+ # Read registry key holding version
+ if (PLATFORM EQUAL 64)
+ get_filename_component(ZMQ_NAME "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ZeroMQ (x64);DisplayVersion]" NAME)
+ else()
+ get_filename_component(ZMQ_NAME "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ZeroMQ;DisplayVersion]" NAME)
+ if (${ZMQ_NAME} MATCHES "registry") # if key was not found, the string "registry" is returned
+ get_filename_component(ZMQ_NAME "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ZeroMQ;DisplayVersion]" NAME)
+ endif()
+ endif()
+
+ # Replace dots with underscores
+ string(REGEX REPLACE "\\." "_" ZMQ_NAME ${ZMQ_NAME})
+
+ # Get Visual studio version number
+ string(REGEX REPLACE "Visual Studio ([0-9]+).*" "\\1" ZMQ_VS_VERSION ${CMAKE_GENERATOR})
+
+ # Format ZMQ library file name
+ set(ZMQ_LIBRARY_NAME "libzmq-v${ZMQ_VS_VERSION}0-mt-${ZMQ_NAME}")
+endif()
+
+find_library(ZMQ_LIBRARY
+ NAMES
+ zmq
+ ${ZMQ_LIBRARY_NAME}
+ PATHS
+ /lib
+ /usr/lib
+ /usr/local/lib
+ "${ZMQ_ROOT_DIR}/lib"
+)
+
+if (ZMQ_INCLUDE_DIR AND ZMQ_LIBRARY)
+ set(ZMQ_FOUND 1)
+ message(STATUS "Found ZMQ library: ${ZMQ_LIBRARY}")
+ message(STATUS "Found ZMQ headers: ${ZMQ_INCLUDE_DIR}")
+else()
+ message(FATAL_ERROR "Could not find ZMQ libraries/headers! Please install ZMQ with libraries and headers")
+endif()
+
+# show the ZMQ_INCLUDE_DIR and ZMQ_LIBRARY variables only in the advanced view
+mark_as_advanced(ZMQ_ROOT_DIR ZMQ_INCLUDE_DIR ZMQ_LIBRARY ZMQ_FOUND)
diff --git a/dep/CMakeLists.txt b/dep/CMakeLists.txt
index b469cb694e2..9d186c796f5 100644
--- a/dep/CMakeLists.txt
+++ b/dep/CMakeLists.txt
@@ -36,6 +36,7 @@ endif()
if(SERVERS)
add_subdirectory(gsoap)
+ add_subdirectory(zmqpp)
endif()
if(TOOLS)
diff --git a/dep/PackageList.txt b/dep/PackageList.txt
index d8cad9038b2..12e0de314f7 100644
--- a/dep/PackageList.txt
+++ b/dep/PackageList.txt
@@ -39,3 +39,8 @@ recastnavigation (Recast is state of the art navigation mesh construction toolse
CascLib (An open-source implementation of library for reading CASC storage from Blizzard games since 2014)
https://github.com/ladislav-zezula/CascLib
Version: d3d17de30a1c5678375049f4cf3301a0a7962780
+
+zmqpp (C++ binding for 0mq/zmq is a 'high-level' library that hides most of the c-style interface core 0mq provides.)
+ https://github.com/zeromq/zmqpp
+ Version: 3.2.0 17e9f6afa98f56ecac1e3f3eecbfc112357a6732
+
diff --git a/dep/zmqpp/CMakeLists.txt b/dep/zmqpp/CMakeLists.txt
new file mode 100644
index 00000000000..6b6bd35b6e7
--- /dev/null
+++ b/dep/zmqpp/CMakeLists.txt
@@ -0,0 +1,31 @@
+# Copyright (C) 2008-2014 TrinityCore
+#
+# This file is free software; as a special exception the author gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+file(GLOB_RECURSE sources_zmqpp zmqpp/*.cpp zmqpp/*.hpp zmqpp/*.h)
+
+set(zmqpp_STAT_SRCS
+ ${sources_zmqpp}
+)
+
+include_directories(${ZMQ_INCLUDE_DIR})
+
+add_library(zmqpp STATIC
+ ${zmqpp_STAT_SRCS}
+)
+
+if (WIN32)
+ add_definitions(-DBUILD_VERSION=\\"3.2.0\\")
+else()
+ add_definitions(-DBUILD_VERSION='"3.2.0"')
+endif()
+
+add_definitions(-DBUILD_VERSION_MAJOR=3)
+add_definitions(-DBUILD_VERSION_MINOR=2)
+add_definitions(-DBUILD_VERSION_REVISION=0)
diff --git a/dep/zmqpp/zmqpp/compatibility.hpp b/dep/zmqpp/zmqpp/compatibility.hpp
new file mode 100644
index 00000000000..103b2c82ebd
--- /dev/null
+++ b/dep/zmqpp/zmqpp/compatibility.hpp
@@ -0,0 +1,97 @@
+/**
+ * \file
+ *
+ * \date 10 Sep 2011
+ * \author ron
+ * \author Ben Gray (\@benjamg)
+ *
+ * A fair number of C++0x (or more accurately C++11) features are used in this
+ * library and as this project is used where I work on older compilers this
+ * file was created to help.
+ *
+ * C++ features and their workaround where not supported:
+ * \li lambda functions - disabled, these are only used in the test anyway.
+ * \li typesafe enums - replaced with enum where comparisons needed.
+ * \li nullptr - defined to null.
+ *
+ * As of the port to version 3.1 (libzmqpp version 1.1.0) this file will also
+ * be used to maintain compatablity with multiple versions of 0mq
+ */
+
+#ifndef ZMQPP_COMPATIBILITY_HPP_
+#define ZMQPP_COMPATIBILITY_HPP_
+
+#include
+#include
+
+// Currently we require at least 0mq version 2.2.x
+#define ZMQPP_REQUIRED_ZMQ_MAJOR 2
+#define ZMQPP_REQUIRED_ZMQ_MINOR 2
+
+#if (ZMQ_VERSION_MAJOR < ZMQPP_REQUIRED_ZMQ_MAJOR) || ((ZMQ_VERSION_MAJOR == ZMQPP_REQUIRED_ZMQ_MAJOR) && (ZMQ_VERSION_MINOR < ZMQPP_REQUIRED_ZMQ_MINOR))
+#error zmqpp requires a later version of 0mq
+#endif
+
+// Experimental feature support
+#if (ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR == 0)
+#define ZMQ_EXPERIMENTAL_LABELS
+#endif
+
+// Deal with older versions of gcc
+#if defined(__GNUC__) && !defined(__clang__)
+#if __GNUC__ == 4
+
+// Deal with older gcc not supporting C++0x typesafe enum class name {} comparison
+#if __GNUC_MINOR__ < 4
+#define ZMQPP_COMPARABLE_ENUM enum
+#endif
+
+#if __GNUC_MINOR__ == 4
+#if __GNUC_PATCHLEVEL__ < 1
+#undef ZMQPP_COMPARABLE_ENUM
+#define ZMQPP_COMPARABLE_ENUM enum
+#endif // if __GNUC_PATCHLEVEL__ < 1
+#endif // if __GNUC_MINOR__ == 4
+
+// Deal with older gcc not supporting C++0x lambda function
+#if __GNUC_MINOR__ < 5
+#define ZMQPP_IGNORE_LAMBDA_FUNCTION_TESTS
+#define ZMQPP_EXPLICITLY_DELETED
+#endif // if __GNUC_MINOR__ < 5
+
+// Deal with older gcc not supporting C++0x nullptr
+#if __GNUC_MINOR__ < 6
+#define nullptr NULL
+#define NOEXCEPT
+#endif // if __GNUC_MINOR__ < 6
+
+#endif // if __GNUC_ == 4
+#endif // if defined(__GNUC__) && !defined(__clang__)
+
+#if defined(_MSC_VER)
+#define NOEXCEPT throw()
+#if _MSC_VER < 1800
+#define ZMQPP_EXPLICITLY_DELETED
+#endif // if _MSC_VER < 1800
+#if _MSC_VER < 1600
+#define nullptr NULL
+#define ZMQPP_IGNORE_LAMBDA_FUNCTION_TESTS
+#define ZMQPP_COMPARABLE_ENUM enum
+#endif // if _MSC_VER < 1600
+#endif // if defined(_MSC_VER)
+
+// Generic state, assume a modern compiler
+#ifndef ZMQPP_COMPARABLE_ENUM
+#define ZMQPP_COMPARABLE_ENUM enum class
+#endif
+
+#ifndef ZMQPP_EXPLICITLY_DELETED
+#define ZMQPP_EXPLICITLY_DELETED = delete
+#endif
+
+#ifndef NOEXCEPT
+#define NOEXCEPT noexcept
+#endif
+
+#endif /* ZMQPP_COMPATIBILITY_HPP_ */
+
diff --git a/dep/zmqpp/zmqpp/context.cpp b/dep/zmqpp/zmqpp/context.cpp
new file mode 100644
index 00000000000..32c657199dc
--- /dev/null
+++ b/dep/zmqpp/zmqpp/context.cpp
@@ -0,0 +1,54 @@
+/**
+ * \file
+ *
+ * \date 9 Aug 2011
+ * \author Ben Gray (\@benjamg)
+ */
+
+#include "context.hpp"
+
+namespace zmqpp
+{
+
+void context::terminate()
+{
+ int result;
+ do
+ {
+#if (ZMQ_VERSION_MAJOR < 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR < 2))
+ result = zmq_term(_context);
+#else
+ result = zmq_ctx_destroy(_context);
+#endif
+ } while (result != 0 && zmq_errno() == EINTR);
+ if (result != 0) { throw zmq_internal_exception(); }
+ _context = nullptr;
+}
+
+#if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 2))
+void context::set(context_option const option, int const value)
+{
+ if (nullptr == _context) { throw invalid_instance("context is invalid"); }
+
+ if (0 != zmq_ctx_set(_context, static_cast(option), value))
+ {
+ throw zmq_internal_exception();
+ }
+}
+
+int context::get(context_option const option)
+{
+ if (nullptr == _context) { throw invalid_instance("context is invalid"); }
+
+ int result = zmq_ctx_get(_context, static_cast(option));
+
+ if (result < 0)
+ {
+ throw zmq_internal_exception();
+ }
+
+ return result;
+}
+#endif
+
+}
diff --git a/dep/zmqpp/zmqpp/context.hpp b/dep/zmqpp/zmqpp/context.hpp
new file mode 100644
index 00000000000..3ffaf791440
--- /dev/null
+++ b/dep/zmqpp/zmqpp/context.hpp
@@ -0,0 +1,184 @@
+/**
+ * \file
+ *
+ * \date 9 Aug 2011
+ * \author Ben Gray (\@benjamg)
+ */
+
+#ifndef ZMQPP_CONTEXT_HPP_
+#define ZMQPP_CONTEXT_HPP_
+
+#include
+
+#include
+
+#include "compatibility.hpp"
+#include "exception.hpp"
+#if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 2))
+#include "context_options.hpp"
+#endif
+
+namespace zmqpp
+{
+
+/*!
+ * The context class represents internal zmq context and io threads.
+ *
+ * By default the context class will create one thread, however this can be
+ * overridden in the constructor.
+ *
+ * The context class is the only object that can be considered thread safe.
+ *
+ * All sockets using endpoints other than inproc require the context to have
+ * at least one thread.
+ *
+ * This class is c++0x move supporting and cannot be copied.
+ */
+class context
+{
+public:
+
+#if (ZMQ_VERSION_MAJOR < 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR < 2))
+ /*!
+ * Initialise the 0mq context.
+ *
+ * If only inproc is used then the context may be created with zero threads.
+ * Any inproc endpoint using sockets must be created using the same context.
+ *
+ * The context is thread safe an may be used anywhere in your application,
+ * however there is no requirement (other than inproc restrictions) for you
+ * to do this.
+ *
+ * \param threads an integer argument for the number of required threads. Defaults to 1.
+ */
+ context(int const& threads = 1)
+#else
+ /*!
+ * Initialise the 0mq context.
+ *
+ * The context is thread safe an may be used anywhere in your application,
+ * however there is no requirement (other than inproc restrictions) for you
+ * to do this.
+ */
+ context()
+#endif
+ : _context(nullptr)
+ {
+#if (ZMQ_VERSION_MAJOR < 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR < 2))
+ _context = zmq_init(threads);
+#else
+ _context = zmq_ctx_new();
+#endif
+
+ if (nullptr == _context)
+ {
+ throw zmq_internal_exception();
+ }
+ }
+
+ /*!
+ * Closes the 0mq context.
+ *
+ * Any blocking calls other than a socket close will return with an error.
+ *
+ * If there are open sockets will block while zmq internal buffers are
+ * processed up to a limit specified by that sockets linger option.
+ */
+ ~context() NOEXCEPT
+ {
+ if (nullptr != _context)
+ {
+ terminate();
+ }
+ }
+
+ /*!
+ * Move supporting constructor.
+ *
+ * Allows zero-copy move semantics to be used with this class.
+ *
+ * \param source a rvalue instance of the object who's internals we wish to steal.
+ */
+ context(context&& source) NOEXCEPT
+ : _context(source._context)
+ {
+ source._context = nullptr;
+ }
+
+ /*!
+ * Move supporting operator.
+ *
+ * Allows zero-copy move semantics to be used with this class.
+ *
+ * \param source an rvalue instance of the context who's internals we wish to steal.
+ */
+ context& operator=(context&& source) NOEXCEPT
+ {
+ std::swap( _context, source._context );
+ return *this;
+ }
+
+ /*!
+ * Terminate the current context.
+ *
+ * Any blocking calls other than a socket close will return with an error.
+ *
+ * If there are open sockets will block while zmq internal buffers are
+ * processed up to a limit specified by that sockets linger option.
+ */
+ void terminate();
+
+#if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 2))
+ /*!
+ * Set the value of an option in the underlaying zmq context.
+ *
+ * \param option a valid ::context_option
+ * \param value to set the option to
+ */
+ void set(context_option const option, int const value);
+
+ /*!
+ * Get a context option from the underlaying zmq context.
+ *
+ * \param option a valid ::context_option
+ * \return context option value
+ */
+ int get(context_option const option);
+#endif
+
+ /*!
+ * Validity checking of the context
+ *
+ * Checks if the underlying 0mq context for this instance is valid.
+ *
+ * Contexts should always be valid unless people are doing 'fun' things with
+ * std::move.
+ *
+ * \return boolean true if the object is valid.
+ */
+ operator bool() const NOEXCEPT
+ {
+ return nullptr != _context;
+ }
+
+ /*!
+ * Access to the raw 0mq context
+ *
+ * \return void pointer to the underlying 0mq context.
+ */
+ operator void*() const NOEXCEPT
+ {
+ return _context;
+ }
+
+private:
+ void* _context;
+
+ // No copy - private and not implemented
+ context(context const&) ZMQPP_EXPLICITLY_DELETED;
+ context& operator=(context const&) NOEXCEPT ZMQPP_EXPLICITLY_DELETED;
+};
+
+}
+
+#endif /* ZMQPP_CONTEXT_HPP_ */
diff --git a/dep/zmqpp/zmqpp/context_options.hpp b/dep/zmqpp/zmqpp/context_options.hpp
new file mode 100644
index 00000000000..b2e2cf4805f
--- /dev/null
+++ b/dep/zmqpp/zmqpp/context_options.hpp
@@ -0,0 +1,26 @@
+/**
+ * \file
+ *
+ * \date 3 Jul 2013
+ * \author Ben Gray (\@benjamg)
+ */
+
+#ifndef ZMQPP_CONTEXT_OPTIONS_HPP_
+#define ZMQPP_CONTEXT_OPTIONS_HPP_
+
+namespace zmqpp
+{
+
+/** \todo Expand the information on the options to make it actually useful. */
+/*!
+ * \brief possible Context options in zmq
+ */
+
+enum class context_option {
+ io_threads = ZMQ_IO_THREADS, /*!< I/O thread count */
+ max_sockets = ZMQ_MAX_SOCKETS, /*!< Maximum supported sockets */
+};
+
+}
+
+#endif /* ZMQPP_CONTEXT_OPTIONS_HPP_ */
diff --git a/dep/zmqpp/zmqpp/exception.hpp b/dep/zmqpp/zmqpp/exception.hpp
new file mode 100644
index 00000000000..a0b234769ce
--- /dev/null
+++ b/dep/zmqpp/zmqpp/exception.hpp
@@ -0,0 +1,87 @@
+/**
+ * \file
+ *
+ * \date 9 Aug 2011
+ * \author Ben Gray (\@benjamg)
+ */
+
+#ifndef ZMQPP_EXCEPTION_HPP_
+#define ZMQPP_EXCEPTION_HPP_
+
+#include
+#include
+
+#include
+
+namespace zmqpp
+{
+
+/** \todo Have a larger variety of exceptions with better state debug information */
+
+/*!
+ * Represents the base zmqpp exception.
+ *
+ * All zmqpp runtime exceptions are children of this class.
+ * The class itself does not provide any special access fields but it only
+ * for convince when catching exceptions.
+ *
+ * The class extends std::runtime_error.
+ *
+ */
+class exception : public std::runtime_error
+{
+public:
+ /*!
+ * Standard exception constructor.
+ *
+ * \param message a string representing the error message.
+ */
+ exception(std::string const& message)
+ : std::runtime_error(message)
+ { }
+};
+
+/*!
+ * Represents an attempt to use an invalid object.
+ *
+ * Objects may be invalid initially or after a shutdown or close.
+ */
+class invalid_instance : public exception
+{
+public:
+ invalid_instance(std::string const& message)
+ : exception(message)
+ { }
+};
+
+/*!
+ * Represents internal zmq errors.
+ *
+ * Any error response from the zmq bindings will be wrapped in this error.
+ *
+ * The class provides access to the zmq error number via zmq_error().
+ */
+class zmq_internal_exception : public exception
+{
+public:
+ /*!
+ * Uses the zmq functions to pull out error messages and numbers.
+ */
+ zmq_internal_exception()
+ : exception(zmq_strerror(zmq_errno()))
+ , _error(zmq_errno())
+ { }
+
+ /*!
+ * Retrieve the zmq error number associated with this exception.
+ * \return zmq error number
+ */
+ int zmq_error() const { return _error; }
+
+private:
+ int _error;
+};
+
+}
+
+#endif /* ZMQPP_EXCEPTION_HPP_ */
diff --git a/dep/zmqpp/zmqpp/frame.cpp b/dep/zmqpp/zmqpp/frame.cpp
new file mode 100644
index 00000000000..4c512ae1010
--- /dev/null
+++ b/dep/zmqpp/zmqpp/frame.cpp
@@ -0,0 +1,95 @@
+/**
+ * \file
+ *
+ * \date 8 Jan 2014
+ * \author Ben Gray (\@benjamg)
+ */
+
+#include
+#include
+
+#include "exception.hpp"
+#include "frame.hpp"
+
+namespace zmqpp {
+
+frame::frame()
+ : _sent( false )
+{
+ if( 0 != zmq_msg_init( &_msg ) )
+ {
+ throw zmq_internal_exception();
+ }
+}
+
+frame::frame(size_t const size)
+ : _sent( false )
+{
+ if( 0 != zmq_msg_init_size( &_msg, size ) )
+ {
+ throw zmq_internal_exception();
+ }
+}
+
+frame::frame(void const* part, size_t const size)
+ : _sent( false )
+{
+ if( 0 != zmq_msg_init_size( &_msg, size ) )
+ {
+ throw zmq_internal_exception();
+ }
+
+ void* msg_data = zmq_msg_data( &_msg );
+ memcpy( msg_data, part, size );
+}
+
+frame::frame(void* part, size_t const size, zmq_free_fn *ffn, void *hint)
+ : _sent( false )
+{
+ if( 0 != zmq_msg_init_data( &_msg, part, size, ffn, hint ) )
+ {
+ throw zmq_internal_exception();
+ }
+}
+
+frame::~frame()
+{
+#ifndef NDEBUG // unused assert variable in release
+ int result = zmq_msg_close( &_msg );
+ assert(0 == result);
+#else
+ zmq_msg_close( &_msg );
+#endif // NDEBUG
+}
+
+frame::frame(frame&& other)
+ : _sent( other._sent )
+{
+ zmq_msg_init( &_msg );
+ zmq_msg_move( &_msg, &other._msg );
+ other._sent = false;
+}
+
+frame& frame::operator=(frame&& other)
+{
+ zmq_msg_init( &_msg );
+ zmq_msg_move( &_msg, &other._msg );
+ std::swap( _sent, other._sent );
+
+ return *this;
+}
+
+frame frame::copy() const
+{
+ frame other( size() );
+ other._sent = _sent;
+
+ if( 0 != zmq_msg_copy( &other._msg, const_cast(&_msg) ) )
+ {
+ throw zmq_internal_exception();
+ }
+
+ return other;
+}
+
+} // namespace zmqpp
diff --git a/dep/zmqpp/zmqpp/frame.hpp b/dep/zmqpp/zmqpp/frame.hpp
new file mode 100644
index 00000000000..c9e4b9b7d82
--- /dev/null
+++ b/dep/zmqpp/zmqpp/frame.hpp
@@ -0,0 +1,58 @@
+/**
+ * \file
+ *
+ * \date 8 Jan 2014
+ * \author Ben Gray (\@benjamg)
+ */
+
+#ifndef ZMQPP_MESSAGE_FRAME_HPP_
+#define ZMQPP_MESSAGE_FRAME_HPP_
+
+#include
+
+#include "compatibility.hpp"
+
+namespace zmqpp {
+
+/*!
+ * \brief an internal frame wrapper for a single zmq message
+ *
+ * This frame wrapper consists of a zmq message and meta data it is used
+ * by the zmqpp message class to keep track of parts in the internal
+ * queue. It is unlikely you need to use this class.
+ */
+class frame
+{
+public:
+ frame();
+ frame(size_t const size);
+ frame(void const* part, size_t const size);
+ frame(void* part, size_t const size, zmq_free_fn *ffn, void *hint);
+
+ ~frame();
+
+ bool is_sent() const { return _sent; }
+ void const* data() const { return zmq_msg_data( const_cast(&_msg) ); }
+ size_t size() const { return zmq_msg_size( const_cast(&_msg) ); }
+
+ void mark_sent() { _sent = true; }
+ zmq_msg_t& msg() { return _msg; }
+
+ // Move operators
+ frame(frame&& other);
+ frame& operator=(frame&& other);
+
+ frame copy() const;
+
+private:
+ bool _sent;
+ zmq_msg_t _msg;
+
+ // Disable implicit copy support, code must request a copy to clone
+ frame(frame const&) NOEXCEPT ZMQPP_EXPLICITLY_DELETED;
+ frame& operator=(frame const&) NOEXCEPT ZMQPP_EXPLICITLY_DELETED;
+};
+
+} // namespace zmqpp
+
+#endif /* ZMQPP_MESSAGE_FRAME_HPP_ */
diff --git a/dep/zmqpp/zmqpp/inet.hpp b/dep/zmqpp/zmqpp/inet.hpp
new file mode 100644
index 00000000000..5245aa4143c
--- /dev/null
+++ b/dep/zmqpp/zmqpp/inet.hpp
@@ -0,0 +1,171 @@
+/**
+ * \file
+ *
+ * \date 10 Aug 2011
+ * \author Ben Gray (\@benjamg)
+ */
+
+#ifndef ZMQPP_INET_HPP_
+#define ZMQPP_INET_HPP_
+
+/** \todo cross-platform version of including headers. */
+// We get htons and htonl from here
+#ifdef _WIN32
+#include
+#else
+#include
+#endif
+
+#include "compatibility.hpp"
+
+namespace zmqpp
+{
+
+/*!
+ * \brief Possible byte order types.
+ *
+ * An enumeration of all the known order types, all two of them.
+ * There is also an entry for unknown which is just used as a default.
+ */
+ZMQPP_COMPARABLE_ENUM order {
+ big_endian, /*!< byte order is big endian */
+ little_endian /*!< byte order is little endian */
+};
+
+/*!
+ * Common code for the 64bit versions of htons/htons and ntohs/ntohl
+ *
+ * As htons and ntohs (or htonl and ntohs) always just do the same thing, ie
+ * swap bytes if the host order differs from network order or otherwise don't
+ * do anything, it seemed silly to type the code twice.
+ *
+ * \note This code assumes network order is always big endian. Which it is.
+ * \note The host endian is only checked once and afterwards assumed to remain
+ * the same.
+ *
+ * \param value_to_check unsigned 64 bit integer to swap
+ * \return swapped (or not) unsigned 64 bit integer
+ */
+inline uint64_t swap_if_needed(uint64_t const value_to_check)
+{
+ static order host_order = (htonl(42) == 42) ? order::big_endian : order::little_endian;
+
+ if (order::big_endian == host_order)
+ {
+ return value_to_check;
+ }
+
+ union {
+ uint64_t integer;
+ uint8_t bytes[8];
+ } value { value_to_check };
+
+ std::swap(value.bytes[0], value.bytes[7]);
+ std::swap(value.bytes[1], value.bytes[6]);
+ std::swap(value.bytes[2], value.bytes[5]);
+ std::swap(value.bytes[3], value.bytes[4]);
+
+ return value.integer;
+}
+
+/*!
+ * 64 bit version of the htons/htonl
+ *
+ * I've used the name htonll to try and keep with the htonl naming scheme.
+ *
+ * \param hostlonglong unsigned 64 bit host order integer
+ * \return unsigned 64 bit network order integer
+ */
+inline uint64_t htonll(uint64_t const hostlonglong)
+{
+ return zmqpp::swap_if_needed(hostlonglong);
+}
+
+/*!
+ * 64 bit version of the ntohs/ntohl
+ *
+ * I've used the name htonll to try and keep with the htonl naming scheme.
+ *
+ * \param networklonglong unsigned 64 bit network order integer
+ * \return unsigned 64 bit host order integer
+ */
+inline uint64_t ntohll(uint64_t const networklonglong)
+{
+ return zmqpp::swap_if_needed(networklonglong);
+}
+
+/*!
+ * floating point version of the htons/htonl
+ *
+ * \param value host order floating point
+ * \returns network order floating point
+ */
+inline float htonf(float value)
+{
+ assert(sizeof(float) == sizeof(uint32_t));
+
+ uint32_t temp;
+ memcpy(&temp, &value, sizeof(uint32_t));
+ temp = htonl( temp );
+ memcpy(&value, &temp, sizeof(uint32_t));
+
+ return value;
+}
+
+/*!
+ * floating point version of the ntohs/ntohl
+ *
+ * \param value network order float
+ * \returns host order float
+ */
+inline float ntohf(float value)
+{
+ assert(sizeof(float) == sizeof(uint32_t));
+
+ uint32_t temp;
+ memcpy(&temp, &value, sizeof(uint32_t));
+ temp = ntohl( temp );
+ memcpy(&value, &temp, sizeof(uint32_t));
+
+ return value;
+}
+
+/*!
+ * double precision floating point version of the htons/htonl
+ *
+ * \param value host order double precision floating point
+ * \returns network order double precision floating point
+ */
+inline double htond(double value)
+{
+ assert(sizeof(double) == sizeof(uint64_t));
+
+ uint64_t temp;
+ memcpy(&temp, &value, sizeof(uint64_t));
+ temp = zmqpp::htonll(temp);
+ memcpy(&value, &temp, sizeof(uint64_t));
+
+ return value;
+}
+
+/*!
+ * double precision floating point version of the ntohs/ntohl
+ *
+ * \param value network order double precision floating point
+ * \returns host order double precision floating point
+ */
+inline double ntohd(double value)
+{
+ assert(sizeof(double) == sizeof(uint64_t));
+
+ uint64_t temp;
+ memcpy(&temp, &value, sizeof(uint64_t));
+ temp = zmqpp::ntohll(temp);
+ memcpy(&value, &temp, sizeof(uint64_t));
+
+ return value;
+}
+
+}
+
+#endif /* INET_HPP_ */
diff --git a/dep/zmqpp/zmqpp/message.cpp b/dep/zmqpp/zmqpp/message.cpp
new file mode 100644
index 00000000000..58587307364
--- /dev/null
+++ b/dep/zmqpp/zmqpp/message.cpp
@@ -0,0 +1,454 @@
+/*
+ * Created on: 9 Aug 2011
+ * Author: Ben Gray (@benjamg)
+ */
+
+#include
+#include
+
+#include "exception.hpp"
+#include "inet.hpp"
+#include "message.hpp"
+
+namespace zmqpp
+{
+
+/*!
+ * \brief internal construct
+ * \internal handles bubbling callback from zmq c style to the c++ functor provided
+ */
+struct callback_releaser
+{
+ message::release_function func;
+};
+
+message::message()
+ : _parts()
+ , _read_cursor(0)
+{
+}
+
+message::~message()
+{
+ _parts.clear();
+}
+
+size_t message::parts() const
+{
+ return _parts.size();
+}
+
+/*
+ * The two const_casts in size and raw_data are a little bit hacky
+ * but neither of these methods called this way actually modify data
+ * so accurately represent the intent of these calls.
+ */
+
+size_t message::size(size_t const part /* = 0 */) const
+{
+ if(part >= _parts.size())
+ {
+ throw exception("attempting to request a message part outside the valid range");
+ }
+
+ return _parts[part].size();
+}
+
+void const* message::raw_data(size_t const part /* = 0 */) const
+{
+ if(part >= _parts.size())
+ {
+ throw exception("attempting to request a message part outside the valid range");
+ }
+
+ return _parts[part].data();
+}
+
+zmq_msg_t& message::raw_msg(size_t const part /* = 0 */)
+{
+ if(part >= _parts.size())
+ {
+ throw exception("attempting to request a message part outside the valid range");
+ }
+
+ return _parts[part].msg();
+}
+
+zmq_msg_t& message::raw_new_msg()
+{
+ _parts.push_back( frame() );
+
+ return _parts.back().msg();
+}
+
+zmq_msg_t& message::raw_new_msg(size_t const reserve_data_size)
+{
+ _parts.push_back( frame(reserve_data_size) );
+
+ return _parts.back().msg();
+}
+
+std::string message::get(size_t const part /* = 0 */) const
+{
+ return std::string(static_cast(raw_data(part)), size(part));
+}
+
+
+// Move operators will take ownership of message parts without copying
+void message::move(void* part, size_t const size, release_function const& release)
+{
+ callback_releaser* hint = new callback_releaser();
+ hint->func = release;
+
+ _parts.push_back( frame( part, size, &message::release_callback, hint ) );
+}
+
+// Stream reader style
+void message::reset_read_cursor()
+{
+ _read_cursor = 0;
+}
+
+void message::get(int8_t& integer, size_t const part) const
+{
+ assert(sizeof(int8_t) == size(part));
+
+ int8_t const* byte = static_cast(raw_data(part));
+ integer = *byte;
+}
+
+void message::get(int16_t& integer, size_t const part) const
+{
+ assert(sizeof(int16_t) == size(part));
+
+ uint16_t const* network_order = static_cast(raw_data(part));
+ integer = static_cast(ntohs(*network_order));
+}
+
+void message::get(int32_t& integer, size_t const part) const
+{
+ assert(sizeof(int32_t) == size(part));
+
+ uint32_t const* network_order = static_cast(raw_data(part));
+ integer = static_cast(htonl(*network_order));
+}
+
+void message::get(int64_t& integer, size_t const part) const
+{
+ assert(sizeof(int64_t) == size(part));
+
+ uint64_t const* network_order = static_cast(raw_data(part));
+ integer = static_cast(zmqpp::htonll(*network_order));
+}
+
+void message::get(uint8_t& unsigned_integer, size_t const part) const
+{
+ assert(sizeof(uint8_t) == size(part));
+
+ uint8_t const* byte = static_cast(raw_data(part));
+ unsigned_integer = *byte;
+}
+
+void message::get(uint16_t& unsigned_integer, size_t const part) const
+{
+ assert(sizeof(uint16_t) == size(part));
+
+ uint16_t const* network_order = static_cast(raw_data(part));
+ unsigned_integer = ntohs(*network_order);
+}
+
+void message::get(uint32_t& unsigned_integer, size_t const part) const
+{
+ assert(sizeof(uint32_t) == size(part));
+
+ uint32_t const* network_order = static_cast(raw_data(part));
+ unsigned_integer = ntohl(*network_order);
+}
+
+void message::get(uint64_t& unsigned_integer, size_t const part) const
+{
+ assert(sizeof(uint64_t) == size(part));
+
+ uint64_t const* network_order = static_cast(raw_data(part));
+ unsigned_integer = zmqpp::ntohll(*network_order);
+}
+
+void message::get(float& floating_point, size_t const part) const
+{
+ assert(sizeof(float) == size(part));
+
+ float const* network_order = static_cast(raw_data(part));
+ floating_point = zmqpp::ntohf(*network_order);
+}
+
+void message::get(double& double_precision, size_t const part) const
+{
+ assert(sizeof(double) == size(part));
+
+ double const* network_order = static_cast(raw_data(part));
+ double_precision = zmqpp::ntohd(*network_order);
+}
+
+void message::get(bool& boolean, size_t const part) const
+{
+ assert(sizeof(uint8_t) == size(part));
+
+ uint8_t const* byte = static_cast(raw_data(part));
+ boolean = (*byte != 0);
+}
+
+void message::get(std::string& string, size_t const part) const
+{
+ string.assign( get(part) );
+}
+
+
+// Stream writer style - these all use copy styles
+message& message::operator<<(int8_t const integer)
+{
+ add(reinterpret_cast(&integer), sizeof(int8_t));
+ return *this;
+}
+
+message& message::operator<<(int16_t const integer)
+{
+ uint16_t network_order = htons(static_cast(integer));
+ add(reinterpret_cast(&network_order), sizeof(uint16_t));
+
+ return *this;
+}
+
+message& message::operator<<(int32_t const integer)
+{
+ uint32_t network_order = htonl(static_cast(integer));
+ add(reinterpret_cast(&network_order), sizeof(uint32_t));
+
+ return *this;
+}
+
+message& message::operator<<(int64_t const integer)
+{
+ uint64_t network_order = zmqpp::htonll(static_cast(integer));
+ add(reinterpret_cast(&network_order), sizeof(uint64_t));
+
+ return *this;
+}
+
+
+message& message::operator<<(uint8_t const unsigned_integer)
+{
+ add(reinterpret_cast(&unsigned_integer), sizeof(uint8_t));
+ return *this;
+}
+
+message& message::operator<<(uint16_t const unsigned_integer)
+{
+ uint16_t network_order = htons(unsigned_integer);
+ add(reinterpret_cast(&network_order), sizeof(uint16_t));
+
+ return *this;
+}
+
+message& message::operator<<(uint32_t const unsigned_integer)
+{
+ uint32_t network_order = htonl(unsigned_integer);
+ add(reinterpret_cast(&network_order), sizeof(uint32_t));
+
+ return *this;
+}
+
+message& message::operator<<(uint64_t const unsigned_integer)
+{
+ uint64_t network_order = zmqpp::htonll(unsigned_integer);
+ add(reinterpret_cast(&network_order), sizeof(uint64_t));
+
+ return *this;
+}
+
+message& message::operator<<(float const floating_point)
+{
+ assert(sizeof(float) == 4);
+
+ float network_order = zmqpp::htonf(floating_point);
+ add(&network_order, sizeof(float));
+
+ return *this;
+}
+
+message& message::operator<<(double const double_precision)
+{
+ assert(sizeof(double) == 8);
+
+ double network_order = zmqpp::htond(double_precision);
+ add(&network_order, sizeof(double));
+
+ return *this;
+}
+
+message& message::operator<<(bool const boolean)
+{
+ uint8_t byte = (boolean) ? 1 : 0;
+ add(reinterpret_cast(&byte), sizeof(uint8_t));
+
+ return *this;
+}
+
+message& message::operator<<(char const* c_string)
+{
+ add(reinterpret_cast(c_string), strlen(c_string));
+ return *this;
+}
+
+message& message::operator<<(std::string const& string)
+{
+ add(reinterpret_cast(string.data()), string.size());
+ return *this;
+}
+
+void message::push_front(void const* part, size_t const size)
+{
+ _parts.emplace( _parts.begin(), part, size );
+}
+
+void message::push_front(int8_t const integer)
+{
+ push_front(&integer, sizeof(int8_t));
+}
+
+void message::push_front(int16_t const integer)
+{
+ uint16_t network_order = htons(static_cast(integer));
+ push_front(&network_order, sizeof(uint16_t));
+}
+
+void message::push_front(int32_t const integer)
+{
+ uint32_t network_order = htonl(static_cast(integer));
+ push_front(&network_order, sizeof(uint32_t));
+}
+
+void message::push_front(int64_t const integer)
+{
+ uint64_t network_order = zmqpp::htonll(static_cast(integer));
+ push_front(&network_order, sizeof(uint64_t));
+}
+
+
+void message::push_front(uint8_t const unsigned_integer)
+{
+ push_front(&unsigned_integer, sizeof(uint8_t));
+}
+
+void message::push_front(uint16_t const unsigned_integer)
+{
+ uint16_t network_order = htons(unsigned_integer);
+ push_front(&network_order, sizeof(uint16_t));
+}
+
+void message::push_front(uint32_t const unsigned_integer)
+{
+ uint32_t network_order = htonl(unsigned_integer);
+ push_front(&network_order, sizeof(uint32_t));
+}
+
+void message::push_front(uint64_t const unsigned_integer)
+{
+ uint64_t network_order = zmqpp::htonll(unsigned_integer);
+ push_front(&network_order, sizeof(uint64_t));
+}
+
+void message::push_front(float const floating_point)
+{
+ assert(sizeof(float) == 4);
+
+ float network_order = zmqpp::htonf(floating_point);
+ push_front(&network_order, sizeof(float));
+}
+
+void message::push_front(double const double_precision)
+{
+ assert(sizeof(double) == 8);
+
+ double network_order = zmqpp::htond(double_precision);
+ push_front(&network_order, sizeof(double));
+}
+
+void message::push_front(bool const boolean)
+{
+ uint8_t byte = (boolean) ? 1 : 0;
+ push_front(&byte, sizeof(uint8_t));
+}
+
+void message::push_front(char const* c_string)
+{
+ push_front(c_string, strlen(c_string));
+}
+
+void message::push_front(std::string const& string)
+{
+ push_front(string.data(), string.size());
+}
+
+void message::pop_front()
+{
+ _parts.erase( _parts.begin() );
+}
+
+void message::pop_back()
+{
+ _parts.pop_back();
+}
+
+message::message(message&& source) NOEXCEPT
+ : _parts()
+ , _read_cursor(0)
+{
+ std::swap(_parts, source._parts);
+}
+
+message& message::operator=(message&& source) NOEXCEPT
+{
+ std::swap(_parts, source._parts);
+ return *this;
+}
+
+message message::copy() const
+{
+ message msg;
+ msg.copy(*this);
+ return msg;
+}
+
+void message::copy(message const& source)
+{
+ _parts.resize( source._parts.size() );
+ for(size_t i = 0; i < source._parts.size(); ++i)
+ {
+ _parts[i] = source._parts[i].copy();
+ }
+
+ // we don't need a copy of the releasers as we did data copies of the internal data,
+ //_releasers = source._releasers;
+ //_strings = source._strings
+}
+
+// Used for internal tracking
+void message::sent(size_t const part)
+{
+ // sanity check
+ assert(!_parts[part].is_sent());
+ _parts[part].mark_sent();
+}
+
+// Note that these releasers are not thread safe, the only safety is provided by
+// the socket class taking ownership so no updates can happen while zmq does it's thing
+// If used in a custom class this has to be dealt with.
+void message::release_callback(void* data, void* hint)
+{
+ callback_releaser* releaser = static_cast(hint);
+ releaser->func(data);
+
+ delete releaser;
+}
+
+}
diff --git a/dep/zmqpp/zmqpp/message.hpp b/dep/zmqpp/zmqpp/message.hpp
new file mode 100644
index 00000000000..2a747bfd1db
--- /dev/null
+++ b/dep/zmqpp/zmqpp/message.hpp
@@ -0,0 +1,254 @@
+/**
+ * \file
+ *
+ * \date 9 Aug 2011
+ * \author Ben Gray (\@benjamg)
+ */
+
+#ifndef ZMQPP_MESSAGE_HPP_
+#define ZMQPP_MESSAGE_HPP_
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include "compatibility.hpp"
+#include "frame.hpp"
+
+namespace zmqpp
+{
+
+/*!
+ * \brief a zmq message with optional multipart support
+ *
+ * A zmq message is made up of one or more parts which are sent together to
+ * the target endpoints. zmq guarantees either the whole message or none
+ * of the message will be delivered.
+ */
+class message
+{
+public:
+ /*!
+ * \brief callback to release user allocated data.
+ *
+ * The release function will be called on any void* moved part.
+ * It must be thread safe to the extent that the callback may occur on
+ * one of the context threads.
+ *
+ * The function called will be passed a single variable which is the
+ * pointer to the memory allocated.
+ */
+ typedef std::function release_function;
+
+ message();
+ ~message();
+
+ template
+ message(T const &part, Args &&...args)
+ : message()
+ {
+ add(part, std::forward(args)...);
+ }
+
+ size_t parts() const;
+ size_t size(size_t const part) const;
+ std::string get(size_t const part) const;
+
+ void get(int8_t& integer, size_t const part) const;
+ void get(int16_t& integer, size_t const part) const;
+ void get(int32_t& integer, size_t const part) const;
+ void get(int64_t& integer, size_t const part) const;
+
+ void get(uint8_t& unsigned_integer, size_t const part) const;
+ void get(uint16_t& unsigned_integer, size_t const part) const;
+ void get(uint32_t& unsigned_integer, size_t const part) const;
+ void get(uint64_t& unsigned_integer, size_t const part) const;
+
+ void get(float& floating_point, size_t const part) const;
+ void get(double& double_precision, size_t const part) const;
+ void get(bool& boolean, size_t const part) const;
+
+ void get(std::string& string, size_t const part) const;
+
+ // Warn: If a pointer type is requested the message (well zmq) still 'owns'
+ // the data and will release it when the message object is freed.
+ template
+ Type get(size_t const part)
+ {
+ Type value;
+ get(value, part);
+ return value;
+ }
+
+ template
+ void extract(T &nextpart, Args &...args)
+ {
+ assert(part < parts());
+ get(nextpart,part);
+ extract(args...);
+ }
+
+ template
+ void extract(T &nextpart)
+ {
+ assert(part < parts());
+ get(nextpart,part);
+ }
+
+ // Raw get data operations, useful with data structures more than anything else
+ // Warn: The message (well zmq) still 'owns' the data and will release it
+ // when the message object is freed.
+ template
+ void get(Type*& value, size_t const part) const
+ {
+ value = static_cast(raw_data(part));
+ }
+
+ // Warn: The message (well zmq) still 'owns' the data and will release it
+ // when the message object is freed.
+ template
+ void get(Type** value, size_t const part) const
+ {
+ *value = static_cast(raw_data(part));
+ }
+
+ // Move operators will take ownership of message parts without copying
+ void move(void* part, size_t const size, release_function const& release);
+
+ // Raw move data operation, useful with data structures more than anything else
+ template
+ void move(Object *part)
+ {
+ move(part, sizeof(Object), &deleter_callback