├── .gitignore ├── README.md ├── Serializer.hpp ├── build-vs2015 ├── bin │ ├── buttonrpc-client.exe │ ├── buttonrpc-server.exe │ └── libzmq.dll ├── buttonrpc-demo │ ├── .vs │ │ └── buttonrpc-demo │ │ │ └── v14 │ │ │ └── .suo │ ├── buttonrpc-client.vcxproj │ ├── buttonrpc-client.vcxproj.filters │ ├── buttonrpc-demo.sln │ ├── buttonrpc-server.vcxproj │ ├── buttonrpc-server.vcxproj.filters │ └── buttonrpc-server.vcxproj.user └── depends │ ├── include │ ├── zmq.h │ └── zmq.hpp │ └── lib │ ├── libzmq.dll │ └── libzmq.lib ├── buttonrpc.hpp └── example ├── main_client.cpp └── main_server.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | build-vs2015/buttonrpc-demo/Release/ 2 | build-vs2015/buttonrpc-demo/buttonrpc-demo.VC.db 3 | *.ipdb 4 | *.pdb 5 | *.iobj 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # buttonrpc - modern rpc framework for C++ 3 | - ZeroMQ 作为网络层 4 | - 使用c++14开发 5 | 6 | ## Features 7 | - 轻量级,跨平台,简单易用 8 | - 服务端可以绑定自由函数,类成员函数,std::function对象 9 | - 服务端可以绑定参数是任意自定义类型的函数 10 | - 客户端与服务端自动重连机制 11 | - 客户端调用超时选项 12 | 13 | ## Example 14 | server: 15 | 16 | ```c++ 17 | #include "buttonrpc.hpp" 18 | 19 | int foo(int age, int mm){ 20 | return age + mm; 21 | } 22 | 23 | int main() 24 | { 25 | buttonrpc server; 26 | server.as_server(5555); 27 | 28 | server.bind("foo", foo); 29 | server.run(); 30 | 31 | return 0; 32 | } 33 | ``` 34 | 35 | client: 36 | 37 | ```c++ 38 | #include 39 | #include "buttonrpc.hpp" 40 | 41 | int main() 42 | { 43 | buttonrpc client; 44 | client.as_client("127.0.0.1", 5555); 45 | int a = client.call("foo", 2, 3).val(); 46 | std::cout << "call foo result: " << a << std::endl; 47 | system("pause"); 48 | return 0; 49 | } 50 | 51 | // output: call foo result: 5 52 | 53 | ``` 54 | 55 | ## Dependences 56 | - [ZeroMQ](http://zguide.zeromq.org/page:all) 57 | 58 | 59 | ## Building 60 | - windows vs2015 或者更高版本, linux 添加编译选项:-std=c++1z 61 | 62 | ## Usage 63 | 64 | - 1: 更多例子在目录 example/ 下 65 | 66 | -------------------------------------------------------------------------------- /Serializer.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * buttonrpc library 4 | * Copyright 2018-04-28 Button 5 | * 6 | */ 7 | 8 | #pragma once 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | using namespace std; 16 | 17 | class StreamBuffer : public vector 18 | { 19 | public: 20 | StreamBuffer(){ m_curpos = 0; } 21 | StreamBuffer(const char* in, size_t len){ 22 | m_curpos = 0; 23 | insert(begin(), in, in+len); 24 | } 25 | ~StreamBuffer(){ } 26 | 27 | void reset(){ m_curpos = 0; } 28 | const char* data(){ return &(*this)[0]; } 29 | const char* current(){ return&(*this)[m_curpos]; } 30 | void offset(int k){ m_curpos += k; } 31 | bool is_eof(){ return (m_curpos >= size()); } 32 | void input( char* in, size_t len){ insert(end(), in, in+len); } 33 | int findc(char c){ 34 | iterator itr = find(begin()+m_curpos, end(), c); 35 | if (itr != end()) 36 | { 37 | return itr - (begin()+m_curpos); 38 | } 39 | return -1; 40 | } 41 | 42 | private: 43 | // 当前字节流位置 44 | unsigned int m_curpos; 45 | }; 46 | 47 | class Serializer 48 | { 49 | public: 50 | Serializer() { m_byteorder = LittleEndian; } 51 | ~Serializer(){ } 52 | 53 | Serializer(StreamBuffer dev, int byteorder=LittleEndian){ 54 | m_byteorder = byteorder; 55 | m_iodevice = dev; 56 | } 57 | 58 | public: 59 | enum ByteOrder { 60 | BigEndian, 61 | LittleEndian 62 | }; 63 | 64 | public: 65 | void reset(){ 66 | m_iodevice.reset(); 67 | } 68 | int size(){ 69 | return m_iodevice.size(); 70 | } 71 | void skip_raw_date(int k){ 72 | m_iodevice.offset(k); 73 | } 74 | const char* data(){ 75 | return m_iodevice.data(); 76 | } 77 | void byte_orser(char* in, int len){ 78 | if (m_byteorder == BigEndian){ 79 | reverse(in, in+len); 80 | } 81 | } 82 | void write_raw_data(char* in, int len){ 83 | m_iodevice.input(in, len); 84 | m_iodevice.offset(len); 85 | } 86 | const char* current(){ 87 | return m_iodevice.current(); 88 | } 89 | void clear(){ 90 | m_iodevice.clear(); 91 | reset(); 92 | } 93 | 94 | template 95 | void output_type(T& t); 96 | 97 | template 98 | void input_type(T t); 99 | 100 | // 直接给一个长度, 返回当前位置以后x个字节数据 101 | void get_length_mem(char* p, int len){ 102 | memcpy(p, m_iodevice.current(), len); 103 | m_iodevice.offset(len); 104 | } 105 | 106 | public: 107 | template 108 | void getv(Serializer& ds, Tuple& t) { 109 | ds >> std::get(t); 110 | } 111 | 112 | template 113 | Tuple get_tuple(std::index_sequence) { 114 | Tuple t; 115 | initializer_list{((getv(*this, t)), 0)...}; 116 | return t; 117 | } 118 | 119 | template 120 | Serializer &operator >> (T& i){ 121 | output_type(i); 122 | return *this; 123 | } 124 | 125 | template 126 | Serializer &operator << (T i){ 127 | input_type(i); 128 | return *this; 129 | } 130 | 131 | private: 132 | int m_byteorder; 133 | StreamBuffer m_iodevice; 134 | }; 135 | 136 | template 137 | inline void Serializer::output_type(T& t) 138 | { 139 | int len = sizeof(T); 140 | char* d = new char[len]; 141 | if (!m_iodevice.is_eof()){ 142 | memcpy(d, m_iodevice.current(), len); 143 | m_iodevice.offset(len); 144 | byte_orser(d, len); 145 | t = *reinterpret_cast(&d[0]); 146 | } 147 | delete [] d; 148 | } 149 | 150 | template<> 151 | inline void Serializer::output_type(std::string& in) 152 | { 153 | int marklen = sizeof(uint16_t); 154 | char* d = new char[marklen]; 155 | memcpy(d, m_iodevice.current(), marklen); 156 | byte_orser(d, marklen); 157 | int len = *reinterpret_cast(&d[0]); 158 | m_iodevice.offset(marklen); 159 | delete [] d; 160 | if (len == 0) return; 161 | in.insert(in.begin(), m_iodevice.current(), m_iodevice.current() + len); 162 | m_iodevice.offset(len); 163 | } 164 | 165 | template 166 | inline void Serializer::input_type(T t) 167 | { 168 | int len = sizeof(T); 169 | char* d = new char[len]; 170 | const char* p = reinterpret_cast(&t); 171 | memcpy(d, p, len); 172 | byte_orser(d, len); 173 | m_iodevice.input(d, len); 174 | delete [] d; 175 | } 176 | 177 | template<> 178 | inline void Serializer::input_type(std::string in) 179 | { 180 | // 先存入字符串长度 181 | uint16_t len = in.size(); 182 | char* p = reinterpret_cast< char*>(&len); 183 | byte_orser(p, sizeof(uint16_t)); 184 | m_iodevice.input(p, sizeof(uint16_t)); 185 | 186 | // 存入字符串 187 | if (len == 0) return; 188 | char* d = new char[len]; 189 | memcpy(d, in.c_str(), len); 190 | m_iodevice.input(d, len); 191 | delete [] d; 192 | } 193 | 194 | template<> 195 | inline void Serializer::input_type(const char* in) 196 | { 197 | input_type(std::string(in)); 198 | } 199 | -------------------------------------------------------------------------------- /build-vs2015/bin/buttonrpc-client.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/button-chen/buttonrpc_cpp14/fe6a96bb2e9b71a6901675b4b37411defb6a253d/build-vs2015/bin/buttonrpc-client.exe -------------------------------------------------------------------------------- /build-vs2015/bin/buttonrpc-server.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/button-chen/buttonrpc_cpp14/fe6a96bb2e9b71a6901675b4b37411defb6a253d/build-vs2015/bin/buttonrpc-server.exe -------------------------------------------------------------------------------- /build-vs2015/bin/libzmq.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/button-chen/buttonrpc_cpp14/fe6a96bb2e9b71a6901675b4b37411defb6a253d/build-vs2015/bin/libzmq.dll -------------------------------------------------------------------------------- /build-vs2015/buttonrpc-demo/.vs/buttonrpc-demo/v14/.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/button-chen/buttonrpc_cpp14/fe6a96bb2e9b71a6901675b4b37411defb6a253d/build-vs2015/buttonrpc-demo/.vs/buttonrpc-demo/v14/.suo -------------------------------------------------------------------------------- /build-vs2015/buttonrpc-demo/buttonrpc-client.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {C930FB26-6804-45D9-A3A7-489CE1FE10DA} 23 | Win32Proj 24 | buttonrpcclient 25 | 8.1 26 | 27 | 28 | 29 | Application 30 | true 31 | v140 32 | Unicode 33 | 34 | 35 | Application 36 | false 37 | v140 38 | true 39 | Unicode 40 | 41 | 42 | Application 43 | true 44 | v140 45 | Unicode 46 | 47 | 48 | Application 49 | false 50 | v140 51 | true 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | true 74 | 75 | 76 | true 77 | 78 | 79 | false 80 | ../bin 81 | 82 | 83 | false 84 | 85 | 86 | 87 | 88 | 89 | Level3 90 | Disabled 91 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 92 | true 93 | 94 | 95 | Console 96 | true 97 | 98 | 99 | 100 | 101 | 102 | 103 | Level3 104 | Disabled 105 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 106 | true 107 | 108 | 109 | Console 110 | true 111 | 112 | 113 | 114 | 115 | Level3 116 | 117 | 118 | MaxSpeed 119 | true 120 | true 121 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 122 | true 123 | ../depends/include;../../ 124 | 125 | 126 | Console 127 | true 128 | true 129 | true 130 | ../depends/lib 131 | libzmq.lib;%(AdditionalDependencies) 132 | 133 | 134 | 135 | 136 | Level3 137 | 138 | 139 | MaxSpeed 140 | true 141 | true 142 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 143 | true 144 | 145 | 146 | Console 147 | true 148 | true 149 | true 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /build-vs2015/buttonrpc-demo/buttonrpc-client.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 源文件 20 | 21 | 22 | -------------------------------------------------------------------------------- /build-vs2015/buttonrpc-demo/buttonrpc-demo.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "buttonrpc-client", "buttonrpc-client.vcxproj", "{C930FB26-6804-45D9-A3A7-489CE1FE10DA}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "buttonrpc-server", "buttonrpc-server.vcxproj", "{F8D66155-35D2-416F-B965-609073F0B286}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|x64 = Debug|x64 13 | Debug|x86 = Debug|x86 14 | Release|x64 = Release|x64 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {C930FB26-6804-45D9-A3A7-489CE1FE10DA}.Debug|x64.ActiveCfg = Debug|x64 19 | {C930FB26-6804-45D9-A3A7-489CE1FE10DA}.Debug|x64.Build.0 = Debug|x64 20 | {C930FB26-6804-45D9-A3A7-489CE1FE10DA}.Debug|x86.ActiveCfg = Debug|Win32 21 | {C930FB26-6804-45D9-A3A7-489CE1FE10DA}.Debug|x86.Build.0 = Debug|Win32 22 | {C930FB26-6804-45D9-A3A7-489CE1FE10DA}.Release|x64.ActiveCfg = Release|x64 23 | {C930FB26-6804-45D9-A3A7-489CE1FE10DA}.Release|x64.Build.0 = Release|x64 24 | {C930FB26-6804-45D9-A3A7-489CE1FE10DA}.Release|x86.ActiveCfg = Release|Win32 25 | {C930FB26-6804-45D9-A3A7-489CE1FE10DA}.Release|x86.Build.0 = Release|Win32 26 | {F8D66155-35D2-416F-B965-609073F0B286}.Debug|x64.ActiveCfg = Debug|x64 27 | {F8D66155-35D2-416F-B965-609073F0B286}.Debug|x64.Build.0 = Debug|x64 28 | {F8D66155-35D2-416F-B965-609073F0B286}.Debug|x86.ActiveCfg = Debug|Win32 29 | {F8D66155-35D2-416F-B965-609073F0B286}.Debug|x86.Build.0 = Debug|Win32 30 | {F8D66155-35D2-416F-B965-609073F0B286}.Release|x64.ActiveCfg = Release|x64 31 | {F8D66155-35D2-416F-B965-609073F0B286}.Release|x64.Build.0 = Release|x64 32 | {F8D66155-35D2-416F-B965-609073F0B286}.Release|x86.ActiveCfg = Release|Win32 33 | {F8D66155-35D2-416F-B965-609073F0B286}.Release|x86.Build.0 = Release|Win32 34 | EndGlobalSection 35 | GlobalSection(SolutionProperties) = preSolution 36 | HideSolutionNode = FALSE 37 | EndGlobalSection 38 | EndGlobal 39 | -------------------------------------------------------------------------------- /build-vs2015/buttonrpc-demo/buttonrpc-server.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {F8D66155-35D2-416F-B965-609073F0B286} 23 | Win32Proj 24 | buttonrpcserver 25 | 8.1 26 | 27 | 28 | 29 | Application 30 | true 31 | v140 32 | Unicode 33 | 34 | 35 | Application 36 | false 37 | v140 38 | true 39 | Unicode 40 | 41 | 42 | Application 43 | true 44 | v140 45 | Unicode 46 | 47 | 48 | Application 49 | false 50 | v140 51 | true 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | true 74 | 75 | 76 | true 77 | 78 | 79 | false 80 | ../bin 81 | 82 | 83 | false 84 | 85 | 86 | 87 | 88 | 89 | Level3 90 | Disabled 91 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 92 | true 93 | ../depends/include;../../;%(AdditionalIncludeDirectories) 94 | 95 | 96 | Console 97 | true 98 | ../depends/lib 99 | libzmq.lib;%(AdditionalDependencies) 100 | 101 | 102 | 103 | 104 | 105 | 106 | Level3 107 | Disabled 108 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 109 | true 110 | 111 | 112 | Console 113 | true 114 | 115 | 116 | 117 | 118 | Level3 119 | 120 | 121 | MaxSpeed 122 | true 123 | true 124 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 125 | true 126 | ../depends/include;../../;%(AdditionalIncludeDirectories) 127 | 128 | 129 | Console 130 | true 131 | true 132 | true 133 | ../depends/lib 134 | libzmq.lib;%(AdditionalDependencies) 135 | 136 | 137 | 138 | 139 | Level3 140 | 141 | 142 | MaxSpeed 143 | true 144 | true 145 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 146 | true 147 | 148 | 149 | Console 150 | true 151 | true 152 | true 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /build-vs2015/buttonrpc-demo/buttonrpc-server.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 源文件 20 | 21 | 22 | -------------------------------------------------------------------------------- /build-vs2015/buttonrpc-demo/buttonrpc-server.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /build-vs2015/depends/include/zmq.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file 3 | 4 | This file is part of 0MQ. 5 | 6 | 0MQ is free software; you can redistribute it and/or modify it under 7 | the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation; either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | 0MQ is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with this program. If not, see . 18 | 19 | ************************************************************************* 20 | NOTE to contributors. This file comprises the principal public contract 21 | for ZeroMQ API users (along with zmq_utils.h). Any change to this file 22 | supplied in a stable release SHOULD not break existing applications. 23 | In practice this means that the value of constants must not change, and 24 | that old values may not be reused for new constants. 25 | ************************************************************************* 26 | */ 27 | 28 | #ifndef __ZMQ_H_INCLUDED__ 29 | #define __ZMQ_H_INCLUDED__ 30 | 31 | /* Version macros for compile-time API version detection */ 32 | #define ZMQ_VERSION_MAJOR 4 33 | #define ZMQ_VERSION_MINOR 0 34 | #define ZMQ_VERSION_PATCH 3 35 | 36 | #define ZMQ_MAKE_VERSION(major, minor, patch) \ 37 | ((major) * 10000 + (minor) * 100 + (patch)) 38 | #define ZMQ_VERSION \ 39 | ZMQ_MAKE_VERSION(ZMQ_VERSION_MAJOR, ZMQ_VERSION_MINOR, ZMQ_VERSION_PATCH) 40 | 41 | #ifdef __cplusplus 42 | extern "C" { 43 | #endif 44 | 45 | #if !defined _WIN32_WCE 46 | #include 47 | #endif 48 | #include 49 | #include 50 | #if defined _WIN32 51 | #include 52 | #endif 53 | 54 | /* Handle DSO symbol visibility */ 55 | #if defined _WIN32 56 | # if defined ZMQ_STATIC 57 | # define ZMQ_EXPORT 58 | # elif defined DLL_EXPORT 59 | # define ZMQ_EXPORT __declspec(dllexport) 60 | # else 61 | # define ZMQ_EXPORT __declspec(dllimport) 62 | # endif 63 | #else 64 | # if defined __SUNPRO_C || defined __SUNPRO_CC 65 | # define ZMQ_EXPORT __global 66 | # elif (defined __GNUC__ && __GNUC__ >= 4) || defined __INTEL_COMPILER 67 | # define ZMQ_EXPORT __attribute__ ((visibility("default"))) 68 | # else 69 | # define ZMQ_EXPORT 70 | # endif 71 | #endif 72 | 73 | /* Define integer types needed for event interface */ 74 | #if defined ZMQ_HAVE_SOLARIS || defined ZMQ_HAVE_OPENVMS 75 | # include 76 | #elif defined _MSC_VER && _MSC_VER < 1600 77 | # ifndef int32_t 78 | typedef __int32 int32_t; 79 | # endif 80 | # ifndef uint16_t 81 | typedef unsigned __int16 uint16_t; 82 | # endif 83 | # ifndef uint8_t 84 | typedef unsigned __int8 uint8_t; 85 | # endif 86 | #else 87 | # include 88 | #endif 89 | 90 | 91 | /******************************************************************************/ 92 | /* 0MQ errors. */ 93 | /******************************************************************************/ 94 | 95 | /* A number random enough not to collide with different errno ranges on */ 96 | /* different OSes. The assumption is that error_t is at least 32-bit type. */ 97 | #define ZMQ_HAUSNUMERO 156384712 98 | 99 | /* On Windows platform some of the standard POSIX errnos are not defined. */ 100 | #ifndef ENOTSUP 101 | #define ENOTSUP (ZMQ_HAUSNUMERO + 1) 102 | #endif 103 | #ifndef EPROTONOSUPPORT 104 | #define EPROTONOSUPPORT (ZMQ_HAUSNUMERO + 2) 105 | #endif 106 | #ifndef ENOBUFS 107 | #define ENOBUFS (ZMQ_HAUSNUMERO + 3) 108 | #endif 109 | #ifndef ENETDOWN 110 | #define ENETDOWN (ZMQ_HAUSNUMERO + 4) 111 | #endif 112 | #ifndef EADDRINUSE 113 | #define EADDRINUSE (ZMQ_HAUSNUMERO + 5) 114 | #endif 115 | #ifndef EADDRNOTAVAIL 116 | #define EADDRNOTAVAIL (ZMQ_HAUSNUMERO + 6) 117 | #endif 118 | #ifndef ECONNREFUSED 119 | #define ECONNREFUSED (ZMQ_HAUSNUMERO + 7) 120 | #endif 121 | #ifndef EINPROGRESS 122 | #define EINPROGRESS (ZMQ_HAUSNUMERO + 8) 123 | #endif 124 | #ifndef ENOTSOCK 125 | #define ENOTSOCK (ZMQ_HAUSNUMERO + 9) 126 | #endif 127 | #ifndef EMSGSIZE 128 | #define EMSGSIZE (ZMQ_HAUSNUMERO + 10) 129 | #endif 130 | #ifndef EAFNOSUPPORT 131 | #define EAFNOSUPPORT (ZMQ_HAUSNUMERO + 11) 132 | #endif 133 | #ifndef ENETUNREACH 134 | #define ENETUNREACH (ZMQ_HAUSNUMERO + 12) 135 | #endif 136 | #ifndef ECONNABORTED 137 | #define ECONNABORTED (ZMQ_HAUSNUMERO + 13) 138 | #endif 139 | #ifndef ECONNRESET 140 | #define ECONNRESET (ZMQ_HAUSNUMERO + 14) 141 | #endif 142 | #ifndef ENOTCONN 143 | #define ENOTCONN (ZMQ_HAUSNUMERO + 15) 144 | #endif 145 | #ifndef ETIMEDOUT 146 | #define ETIMEDOUT (ZMQ_HAUSNUMERO + 16) 147 | #endif 148 | #ifndef EHOSTUNREACH 149 | #define EHOSTUNREACH (ZMQ_HAUSNUMERO + 17) 150 | #endif 151 | #ifndef ENETRESET 152 | #define ENETRESET (ZMQ_HAUSNUMERO + 18) 153 | #endif 154 | 155 | /* Native 0MQ error codes. */ 156 | #define EFSM (ZMQ_HAUSNUMERO + 51) 157 | #define ENOCOMPATPROTO (ZMQ_HAUSNUMERO + 52) 158 | #define ETERM (ZMQ_HAUSNUMERO + 53) 159 | #define EMTHREAD (ZMQ_HAUSNUMERO + 54) 160 | 161 | /* Run-time API version detection */ 162 | ZMQ_EXPORT void zmq_version (int *major, int *minor, int *patch); 163 | 164 | /* This function retrieves the errno as it is known to 0MQ library. The goal */ 165 | /* of this function is to make the code 100% portable, including where 0MQ */ 166 | /* compiled with certain CRT library (on Windows) is linked to an */ 167 | /* application that uses different CRT library. */ 168 | ZMQ_EXPORT int zmq_errno (void); 169 | 170 | /* Resolves system errors and 0MQ errors to human-readable string. */ 171 | ZMQ_EXPORT const char *zmq_strerror (int errnum); 172 | 173 | /******************************************************************************/ 174 | /* 0MQ infrastructure (a.k.a. context) initialisation & termination. */ 175 | /******************************************************************************/ 176 | 177 | /* New API */ 178 | /* Context options */ 179 | #define ZMQ_IO_THREADS 1 180 | #define ZMQ_MAX_SOCKETS 2 181 | 182 | /* Default for new contexts */ 183 | #define ZMQ_IO_THREADS_DFLT 1 184 | #define ZMQ_MAX_SOCKETS_DFLT 1023 185 | 186 | ZMQ_EXPORT void *zmq_ctx_new (void); 187 | ZMQ_EXPORT int zmq_ctx_term (void *context); 188 | ZMQ_EXPORT int zmq_ctx_shutdown (void *ctx_); 189 | ZMQ_EXPORT int zmq_ctx_set (void *context, int option, int optval); 190 | ZMQ_EXPORT int zmq_ctx_get (void *context, int option); 191 | 192 | /* Old (legacy) API */ 193 | ZMQ_EXPORT void *zmq_init (int io_threads); 194 | ZMQ_EXPORT int zmq_term (void *context); 195 | ZMQ_EXPORT int zmq_ctx_destroy (void *context); 196 | 197 | 198 | /******************************************************************************/ 199 | /* 0MQ message definition. */ 200 | /******************************************************************************/ 201 | 202 | typedef struct zmq_msg_t {unsigned char _ [32];} zmq_msg_t; 203 | 204 | typedef void (zmq_free_fn) (void *data, void *hint); 205 | 206 | ZMQ_EXPORT int zmq_msg_init (zmq_msg_t *msg); 207 | ZMQ_EXPORT int zmq_msg_init_size (zmq_msg_t *msg, size_t size); 208 | ZMQ_EXPORT int zmq_msg_init_data (zmq_msg_t *msg, void *data, 209 | size_t size, zmq_free_fn *ffn, void *hint); 210 | ZMQ_EXPORT int zmq_msg_send (zmq_msg_t *msg, void *s, int flags); 211 | ZMQ_EXPORT int zmq_msg_recv (zmq_msg_t *msg, void *s, int flags); 212 | ZMQ_EXPORT int zmq_msg_close (zmq_msg_t *msg); 213 | ZMQ_EXPORT int zmq_msg_move (zmq_msg_t *dest, zmq_msg_t *src); 214 | ZMQ_EXPORT int zmq_msg_copy (zmq_msg_t *dest, zmq_msg_t *src); 215 | ZMQ_EXPORT void *zmq_msg_data (zmq_msg_t *msg); 216 | ZMQ_EXPORT size_t zmq_msg_size (zmq_msg_t *msg); 217 | ZMQ_EXPORT int zmq_msg_more (zmq_msg_t *msg); 218 | ZMQ_EXPORT int zmq_msg_get (zmq_msg_t *msg, int option); 219 | ZMQ_EXPORT int zmq_msg_set (zmq_msg_t *msg, int option, int optval); 220 | 221 | 222 | /******************************************************************************/ 223 | /* 0MQ socket definition. */ 224 | /******************************************************************************/ 225 | 226 | /* Socket types. */ 227 | #define ZMQ_PAIR 0 228 | #define ZMQ_PUB 1 229 | #define ZMQ_SUB 2 230 | #define ZMQ_REQ 3 231 | #define ZMQ_REP 4 232 | #define ZMQ_DEALER 5 233 | #define ZMQ_ROUTER 6 234 | #define ZMQ_PULL 7 235 | #define ZMQ_PUSH 8 236 | #define ZMQ_XPUB 9 237 | #define ZMQ_XSUB 10 238 | #define ZMQ_STREAM 11 239 | 240 | /* Deprecated aliases */ 241 | #define ZMQ_XREQ ZMQ_DEALER 242 | #define ZMQ_XREP ZMQ_ROUTER 243 | 244 | /* Socket options. */ 245 | #define ZMQ_AFFINITY 4 246 | #define ZMQ_IDENTITY 5 247 | #define ZMQ_SUBSCRIBE 6 248 | #define ZMQ_UNSUBSCRIBE 7 249 | #define ZMQ_RATE 8 250 | #define ZMQ_RECOVERY_IVL 9 251 | #define ZMQ_SNDBUF 11 252 | #define ZMQ_RCVBUF 12 253 | #define ZMQ_RCVMORE 13 254 | #define ZMQ_FD 14 255 | #define ZMQ_EVENTS 15 256 | #define ZMQ_TYPE 16 257 | #define ZMQ_LINGER 17 258 | #define ZMQ_RECONNECT_IVL 18 259 | #define ZMQ_BACKLOG 19 260 | #define ZMQ_RECONNECT_IVL_MAX 21 261 | #define ZMQ_MAXMSGSIZE 22 262 | #define ZMQ_SNDHWM 23 263 | #define ZMQ_RCVHWM 24 264 | #define ZMQ_MULTICAST_HOPS 25 265 | #define ZMQ_RCVTIMEO 27 266 | #define ZMQ_SNDTIMEO 28 267 | #define ZMQ_LAST_ENDPOINT 32 268 | #define ZMQ_ROUTER_MANDATORY 33 269 | #define ZMQ_TCP_KEEPALIVE 34 270 | #define ZMQ_TCP_KEEPALIVE_CNT 35 271 | #define ZMQ_TCP_KEEPALIVE_IDLE 36 272 | #define ZMQ_TCP_KEEPALIVE_INTVL 37 273 | #define ZMQ_TCP_ACCEPT_FILTER 38 274 | #define ZMQ_IMMEDIATE 39 275 | #define ZMQ_XPUB_VERBOSE 40 276 | #define ZMQ_ROUTER_RAW 41 277 | #define ZMQ_IPV6 42 278 | #define ZMQ_MECHANISM 43 279 | #define ZMQ_PLAIN_SERVER 44 280 | #define ZMQ_PLAIN_USERNAME 45 281 | #define ZMQ_PLAIN_PASSWORD 46 282 | #define ZMQ_CURVE_SERVER 47 283 | #define ZMQ_CURVE_PUBLICKEY 48 284 | #define ZMQ_CURVE_SECRETKEY 49 285 | #define ZMQ_CURVE_SERVERKEY 50 286 | #define ZMQ_PROBE_ROUTER 51 287 | #define ZMQ_REQ_CORRELATE 52 288 | #define ZMQ_REQ_RELAXED 53 289 | #define ZMQ_CONFLATE 54 290 | #define ZMQ_ZAP_DOMAIN 55 291 | 292 | /* Message options */ 293 | #define ZMQ_MORE 1 294 | 295 | /* Send/recv options. */ 296 | #define ZMQ_DONTWAIT 1 297 | #define ZMQ_SNDMORE 2 298 | 299 | /* Security mechanisms */ 300 | #define ZMQ_NULL 0 301 | #define ZMQ_PLAIN 1 302 | #define ZMQ_CURVE 2 303 | 304 | /* Deprecated options and aliases */ 305 | #define ZMQ_IPV4ONLY 31 306 | #define ZMQ_DELAY_ATTACH_ON_CONNECT ZMQ_IMMEDIATE 307 | #define ZMQ_NOBLOCK ZMQ_DONTWAIT 308 | #define ZMQ_FAIL_UNROUTABLE ZMQ_ROUTER_MANDATORY 309 | #define ZMQ_ROUTER_BEHAVIOR ZMQ_ROUTER_MANDATORY 310 | 311 | /******************************************************************************/ 312 | /* 0MQ socket events and monitoring */ 313 | /******************************************************************************/ 314 | 315 | /* Socket transport events (tcp and ipc only) */ 316 | #define ZMQ_EVENT_CONNECTED 1 317 | #define ZMQ_EVENT_CONNECT_DELAYED 2 318 | #define ZMQ_EVENT_CONNECT_RETRIED 4 319 | 320 | #define ZMQ_EVENT_LISTENING 8 321 | #define ZMQ_EVENT_BIND_FAILED 16 322 | 323 | #define ZMQ_EVENT_ACCEPTED 32 324 | #define ZMQ_EVENT_ACCEPT_FAILED 64 325 | 326 | #define ZMQ_EVENT_CLOSED 128 327 | #define ZMQ_EVENT_CLOSE_FAILED 256 328 | #define ZMQ_EVENT_DISCONNECTED 512 329 | #define ZMQ_EVENT_MONITOR_STOPPED 1024 330 | 331 | #define ZMQ_EVENT_ALL ( ZMQ_EVENT_CONNECTED | ZMQ_EVENT_CONNECT_DELAYED | \ 332 | ZMQ_EVENT_CONNECT_RETRIED | ZMQ_EVENT_LISTENING | \ 333 | ZMQ_EVENT_BIND_FAILED | ZMQ_EVENT_ACCEPTED | \ 334 | ZMQ_EVENT_ACCEPT_FAILED | ZMQ_EVENT_CLOSED | \ 335 | ZMQ_EVENT_CLOSE_FAILED | ZMQ_EVENT_DISCONNECTED | \ 336 | ZMQ_EVENT_MONITOR_STOPPED) 337 | 338 | /* Socket event data */ 339 | typedef struct { 340 | uint16_t event; // id of the event as bitfield 341 | int32_t value ; // value is either error code, fd or reconnect interval 342 | } zmq_event_t; 343 | 344 | ZMQ_EXPORT void *zmq_socket (void *, int type); 345 | ZMQ_EXPORT int zmq_close (void *s); 346 | ZMQ_EXPORT int zmq_setsockopt (void *s, int option, const void *optval, 347 | size_t optvallen); 348 | ZMQ_EXPORT int zmq_getsockopt (void *s, int option, void *optval, 349 | size_t *optvallen); 350 | ZMQ_EXPORT int zmq_bind (void *s, const char *addr); 351 | ZMQ_EXPORT int zmq_connect (void *s, const char *addr); 352 | ZMQ_EXPORT int zmq_unbind (void *s, const char *addr); 353 | ZMQ_EXPORT int zmq_disconnect (void *s, const char *addr); 354 | ZMQ_EXPORT int zmq_send (void *s, const void *buf, size_t len, int flags); 355 | ZMQ_EXPORT int zmq_send_const (void *s, const void *buf, size_t len, int flags); 356 | ZMQ_EXPORT int zmq_recv (void *s, void *buf, size_t len, int flags); 357 | ZMQ_EXPORT int zmq_socket_monitor (void *s, const char *addr, int events); 358 | 359 | ZMQ_EXPORT int zmq_sendmsg (void *s, zmq_msg_t *msg, int flags); 360 | ZMQ_EXPORT int zmq_recvmsg (void *s, zmq_msg_t *msg, int flags); 361 | 362 | /* Experimental */ 363 | struct iovec; 364 | 365 | ZMQ_EXPORT int zmq_sendiov (void *s, struct iovec *iov, size_t count, int flags); 366 | ZMQ_EXPORT int zmq_recviov (void *s, struct iovec *iov, size_t *count, int flags); 367 | 368 | /******************************************************************************/ 369 | /* I/O multiplexing. */ 370 | /******************************************************************************/ 371 | 372 | #define ZMQ_POLLIN 1 373 | #define ZMQ_POLLOUT 2 374 | #define ZMQ_POLLERR 4 375 | 376 | typedef struct 377 | { 378 | void *socket; 379 | #if defined _WIN32 380 | SOCKET fd; 381 | #else 382 | int fd; 383 | #endif 384 | short events; 385 | short revents; 386 | } zmq_pollitem_t; 387 | 388 | #define ZMQ_POLLITEMS_DFLT 16 389 | 390 | ZMQ_EXPORT int zmq_poll (zmq_pollitem_t *items, int nitems, long timeout); 391 | 392 | /* Built-in message proxy (3-way) */ 393 | 394 | ZMQ_EXPORT int zmq_proxy (void *frontend, void *backend, void *capture); 395 | 396 | /* Encode a binary key as printable text using ZMQ RFC 32 */ 397 | ZMQ_EXPORT char *zmq_z85_encode (char *dest, uint8_t *data, size_t size); 398 | 399 | /* Encode a binary key from printable text per ZMQ RFC 32 */ 400 | ZMQ_EXPORT uint8_t *zmq_z85_decode (uint8_t *dest, char *string); 401 | 402 | /* Deprecated aliases */ 403 | #define ZMQ_STREAMER 1 404 | #define ZMQ_FORWARDER 2 405 | #define ZMQ_QUEUE 3 406 | /* Deprecated method */ 407 | ZMQ_EXPORT int zmq_device (int type, void *frontend, void *backend); 408 | 409 | #undef ZMQ_EXPORT 410 | 411 | #ifdef __cplusplus 412 | } 413 | #endif 414 | 415 | #endif 416 | 417 | -------------------------------------------------------------------------------- /build-vs2015/depends/include/zmq.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016-2017 ZeroMQ community 3 | Copyright (c) 2009-2011 250bpm s.r.o. 4 | Copyright (c) 2011 Botond Ballo 5 | Copyright (c) 2007-2009 iMatix Corporation 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to 9 | deal in the Software without restriction, including without limitation the 10 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | sell copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef __ZMQ_HPP_INCLUDED__ 27 | #define __ZMQ_HPP_INCLUDED__ 28 | 29 | #if (__cplusplus >= 201103L) 30 | #define ZMQ_CPP11 31 | #define ZMQ_NOTHROW noexcept 32 | #define ZMQ_EXPLICIT explicit 33 | #elif (defined(_MSC_VER) && (_MSC_VER >= 1900)) 34 | #define ZMQ_CPP11 35 | #define ZMQ_NOTHROW noexcept 36 | #define ZMQ_EXPLICIT explicit 37 | #else 38 | #define ZMQ_CPP03 39 | #define ZMQ_NOTHROW 40 | #define ZMQ_EXPLICIT 41 | #endif 42 | 43 | #include 44 | 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | 53 | #ifdef ZMQ_CPP11 54 | #include 55 | #include 56 | #include 57 | #endif 58 | 59 | // Detect whether the compiler supports C++11 rvalue references. 60 | #if (defined(__GNUC__) && (__GNUC__ > 4 || \ 61 | (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) && \ 62 | defined(__GXX_EXPERIMENTAL_CXX0X__)) 63 | #define ZMQ_HAS_RVALUE_REFS 64 | #define ZMQ_DELETED_FUNCTION = delete 65 | #elif defined(__clang__) 66 | #if __has_feature(cxx_rvalue_references) 67 | #define ZMQ_HAS_RVALUE_REFS 68 | #endif 69 | 70 | #if __has_feature(cxx_deleted_functions) 71 | #define ZMQ_DELETED_FUNCTION = delete 72 | #else 73 | #define ZMQ_DELETED_FUNCTION 74 | #endif 75 | #elif defined(_MSC_VER) && (_MSC_VER >= 1900) 76 | #define ZMQ_HAS_RVALUE_REFS 77 | #define ZMQ_DELETED_FUNCTION = delete 78 | #elif defined(_MSC_VER) && (_MSC_VER >= 1600) 79 | #define ZMQ_HAS_RVALUE_REFS 80 | #define ZMQ_DELETED_FUNCTION 81 | #else 82 | #define ZMQ_DELETED_FUNCTION 83 | #endif 84 | 85 | #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3, 3, 0) 86 | #define ZMQ_NEW_MONITOR_EVENT_LAYOUT 87 | #endif 88 | 89 | #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 1, 0) 90 | #define ZMQ_HAS_PROXY_STEERABLE 91 | /* Socket event data */ 92 | typedef struct { 93 | uint16_t event; // id of the event as bitfield 94 | int32_t value ; // value is either error code, fd or reconnect interval 95 | } zmq_event_t; 96 | #endif 97 | 98 | // Avoid using deprecated message receive function when possible 99 | #if ZMQ_VERSION < ZMQ_MAKE_VERSION(3, 2, 0) 100 | # define zmq_msg_recv(msg, socket, flags) zmq_recvmsg(socket, msg, flags) 101 | #endif 102 | 103 | 104 | // In order to prevent unused variable warnings when building in non-debug 105 | // mode use this macro to make assertions. 106 | #ifndef NDEBUG 107 | # define ZMQ_ASSERT(expression) assert(expression) 108 | #else 109 | # define ZMQ_ASSERT(expression) (void)(expression) 110 | #endif 111 | 112 | namespace zmq 113 | { 114 | 115 | typedef zmq_free_fn free_fn; 116 | typedef zmq_pollitem_t pollitem_t; 117 | 118 | class error_t : public std::exception 119 | { 120 | public: 121 | 122 | error_t () : errnum (zmq_errno ()) {} 123 | #ifdef ZMQ_CPP11 124 | virtual const char *what () const noexcept 125 | { 126 | return zmq_strerror (errnum); 127 | } 128 | #else 129 | virtual const char *what() const throw () 130 | { 131 | return zmq_strerror(errnum); 132 | } 133 | #endif 134 | int num () const 135 | { 136 | return errnum; 137 | } 138 | 139 | private: 140 | 141 | int errnum; 142 | }; 143 | 144 | inline int poll (zmq_pollitem_t const* items_, size_t nitems_, long timeout_ = -1) 145 | { 146 | int rc = zmq_poll (const_cast(items_), static_cast(nitems_), timeout_); 147 | if (rc < 0) 148 | throw error_t (); 149 | return rc; 150 | } 151 | 152 | #ifdef ZMQ_CPP11 153 | inline int poll(zmq_pollitem_t const* items, size_t nitems, std::chrono::milliseconds timeout) 154 | { 155 | return poll(items, nitems, static_cast(timeout.count())); 156 | } 157 | 158 | inline int poll(std::vector const& items, std::chrono::milliseconds timeout) 159 | { 160 | return poll(items.data(), items.size(), static_cast(timeout.count())); 161 | } 162 | 163 | inline int poll(std::vector const& items, long timeout_ = -1) 164 | { 165 | return poll(items.data(), items.size(), timeout_); 166 | } 167 | #endif 168 | 169 | 170 | 171 | inline void proxy (void *frontend, void *backend, void *capture) 172 | { 173 | int rc = zmq_proxy (frontend, backend, capture); 174 | if (rc != 0) 175 | throw error_t (); 176 | } 177 | 178 | #ifdef ZMQ_HAS_PROXY_STEERABLE 179 | inline void proxy_steerable (void *frontend, void *backend, void *capture, void *control) 180 | { 181 | int rc = zmq_proxy_steerable (frontend, backend, capture, control); 182 | if (rc != 0) 183 | throw error_t (); 184 | } 185 | #endif 186 | 187 | inline void version (int *major_, int *minor_, int *patch_) 188 | { 189 | zmq_version (major_, minor_, patch_); 190 | } 191 | 192 | #ifdef ZMQ_CPP11 193 | inline std::tuple version() 194 | { 195 | std::tuple v; 196 | zmq_version(&std::get<0>(v), &std::get<1>(v), &std::get<2>(v) ); 197 | return v; 198 | } 199 | #endif 200 | 201 | class message_t 202 | { 203 | friend class socket_t; 204 | 205 | public: 206 | 207 | inline message_t () 208 | { 209 | int rc = zmq_msg_init (&msg); 210 | if (rc != 0) 211 | throw error_t (); 212 | } 213 | 214 | inline explicit message_t (size_t size_) 215 | { 216 | int rc = zmq_msg_init_size (&msg, size_); 217 | if (rc != 0) 218 | throw error_t (); 219 | } 220 | 221 | template message_t(I first, I last): 222 | msg() 223 | { 224 | typedef typename std::iterator_traits::difference_type size_type; 225 | typedef typename std::iterator_traits::value_type value_t; 226 | 227 | size_type const size_ = std::distance(first, last)*sizeof(value_t); 228 | int const rc = zmq_msg_init_size (&msg, size_); 229 | if (rc != 0) 230 | throw error_t (); 231 | value_t* dest = data(); 232 | while (first != last) 233 | { 234 | *dest = *first; 235 | ++dest; ++first; 236 | } 237 | } 238 | 239 | inline message_t (const void *data_, size_t size_) 240 | { 241 | int rc = zmq_msg_init_size (&msg, size_); 242 | if (rc != 0) 243 | throw error_t (); 244 | memcpy(data(), data_, size_); 245 | } 246 | 247 | inline message_t (void *data_, size_t size_, free_fn *ffn_, 248 | void *hint_ = NULL) 249 | { 250 | int rc = zmq_msg_init_data (&msg, data_, size_, ffn_, hint_); 251 | if (rc != 0) 252 | throw error_t (); 253 | } 254 | 255 | #ifdef ZMQ_HAS_RVALUE_REFS 256 | inline message_t (message_t &&rhs): msg (rhs.msg) 257 | { 258 | int rc = zmq_msg_init (&rhs.msg); 259 | if (rc != 0) 260 | throw error_t (); 261 | } 262 | 263 | inline message_t &operator = (message_t &&rhs) ZMQ_NOTHROW 264 | { 265 | std::swap (msg, rhs.msg); 266 | return *this; 267 | } 268 | #endif 269 | 270 | inline ~message_t () ZMQ_NOTHROW 271 | { 272 | int rc = zmq_msg_close (&msg); 273 | ZMQ_ASSERT (rc == 0); 274 | } 275 | 276 | inline void rebuild () 277 | { 278 | int rc = zmq_msg_close (&msg); 279 | if (rc != 0) 280 | throw error_t (); 281 | rc = zmq_msg_init (&msg); 282 | if (rc != 0) 283 | throw error_t (); 284 | } 285 | 286 | inline void rebuild (size_t size_) 287 | { 288 | int rc = zmq_msg_close (&msg); 289 | if (rc != 0) 290 | throw error_t (); 291 | rc = zmq_msg_init_size (&msg, size_); 292 | if (rc != 0) 293 | throw error_t (); 294 | } 295 | 296 | inline void rebuild (const void *data_, size_t size_) 297 | { 298 | int rc = zmq_msg_close (&msg); 299 | if (rc != 0) 300 | throw error_t (); 301 | rc = zmq_msg_init_size (&msg, size_); 302 | if (rc != 0) 303 | throw error_t (); 304 | memcpy(data(), data_, size_); 305 | } 306 | 307 | inline void rebuild (void *data_, size_t size_, free_fn *ffn_, 308 | void *hint_ = NULL) 309 | { 310 | int rc = zmq_msg_close (&msg); 311 | if (rc != 0) 312 | throw error_t (); 313 | rc = zmq_msg_init_data (&msg, data_, size_, ffn_, hint_); 314 | if (rc != 0) 315 | throw error_t (); 316 | } 317 | 318 | inline void move (message_t const *msg_) 319 | { 320 | int rc = zmq_msg_move (&msg, const_cast(&(msg_->msg))); 321 | if (rc != 0) 322 | throw error_t (); 323 | } 324 | 325 | inline void copy (message_t const *msg_) 326 | { 327 | int rc = zmq_msg_copy (&msg, const_cast(&(msg_->msg))); 328 | if (rc != 0) 329 | throw error_t (); 330 | } 331 | 332 | inline bool more () const ZMQ_NOTHROW 333 | { 334 | int rc = zmq_msg_more (const_cast(&msg) ); 335 | return rc != 0; 336 | } 337 | 338 | inline void *data () ZMQ_NOTHROW 339 | { 340 | return zmq_msg_data (&msg); 341 | } 342 | 343 | inline const void* data () const ZMQ_NOTHROW 344 | { 345 | return zmq_msg_data (const_cast(&msg)); 346 | } 347 | 348 | inline size_t size () const ZMQ_NOTHROW 349 | { 350 | return zmq_msg_size (const_cast(&msg)); 351 | } 352 | 353 | template T* data() ZMQ_NOTHROW 354 | { 355 | return static_cast( data() ); 356 | } 357 | 358 | template T const* data() const ZMQ_NOTHROW 359 | { 360 | return static_cast( data() ); 361 | } 362 | 363 | inline bool equal(const message_t* other) const ZMQ_NOTHROW 364 | { 365 | if (size() != other->size()) 366 | return false; 367 | std::string a(data(), size()); 368 | std::string b(other->data(), other->size()); 369 | return a == b; 370 | } 371 | 372 | #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 1, 0) 373 | inline const char* gets(const char *property_) 374 | { 375 | const char* value = zmq_msg_gets (&msg, property_); 376 | if (value == NULL) 377 | throw error_t (); 378 | return value; 379 | } 380 | #endif 381 | 382 | private: 383 | // The underlying message 384 | zmq_msg_t msg; 385 | 386 | // Disable implicit message copying, so that users won't use shared 387 | // messages (less efficient) without being aware of the fact. 388 | message_t (const message_t&) ZMQ_DELETED_FUNCTION; 389 | void operator = (const message_t&) ZMQ_DELETED_FUNCTION; 390 | }; 391 | 392 | class context_t 393 | { 394 | friend class socket_t; 395 | 396 | public: 397 | inline context_t () 398 | { 399 | ptr = zmq_ctx_new (); 400 | if (ptr == NULL) 401 | throw error_t (); 402 | } 403 | 404 | 405 | inline explicit context_t (int io_threads_, int max_sockets_ = ZMQ_MAX_SOCKETS_DFLT) 406 | { 407 | ptr = zmq_ctx_new (); 408 | if (ptr == NULL) 409 | throw error_t (); 410 | 411 | int rc = zmq_ctx_set (ptr, ZMQ_IO_THREADS, io_threads_); 412 | ZMQ_ASSERT (rc == 0); 413 | 414 | rc = zmq_ctx_set (ptr, ZMQ_MAX_SOCKETS, max_sockets_); 415 | ZMQ_ASSERT (rc == 0); 416 | } 417 | 418 | #ifdef ZMQ_HAS_RVALUE_REFS 419 | inline context_t (context_t &&rhs) ZMQ_NOTHROW : ptr (rhs.ptr) 420 | { 421 | rhs.ptr = NULL; 422 | } 423 | inline context_t &operator = (context_t &&rhs) ZMQ_NOTHROW 424 | { 425 | std::swap (ptr, rhs.ptr); 426 | return *this; 427 | } 428 | #endif 429 | 430 | inline int setctxopt(int option_, int optval_) 431 | { 432 | int rc = zmq_ctx_set (ptr, option_, optval_); 433 | ZMQ_ASSERT (rc == 0); 434 | return rc; 435 | } 436 | 437 | inline int getctxopt(int option_) 438 | { 439 | return zmq_ctx_get (ptr, option_); 440 | } 441 | 442 | inline ~context_t () ZMQ_NOTHROW 443 | { 444 | close(); 445 | } 446 | 447 | inline void close() ZMQ_NOTHROW 448 | { 449 | if (ptr == NULL) 450 | return; 451 | 452 | int rc = zmq_ctx_destroy (ptr); 453 | ZMQ_ASSERT (rc == 0); 454 | ptr = NULL; 455 | } 456 | 457 | // Be careful with this, it's probably only useful for 458 | // using the C api together with an existing C++ api. 459 | // Normally you should never need to use this. 460 | inline ZMQ_EXPLICIT operator void* () ZMQ_NOTHROW 461 | { 462 | return ptr; 463 | } 464 | 465 | inline ZMQ_EXPLICIT operator void const* () const ZMQ_NOTHROW 466 | { 467 | return ptr; 468 | } 469 | private: 470 | 471 | void *ptr; 472 | 473 | context_t (const context_t&) ZMQ_DELETED_FUNCTION; 474 | void operator = (const context_t&) ZMQ_DELETED_FUNCTION; 475 | }; 476 | 477 | #ifdef ZMQ_CPP11 478 | enum class socket_type: int 479 | { 480 | req = ZMQ_REQ, 481 | rep = ZMQ_REP, 482 | dealer = ZMQ_DEALER, 483 | router = ZMQ_ROUTER, 484 | pub = ZMQ_PUB, 485 | sub = ZMQ_SUB, 486 | xpub = ZMQ_XPUB, 487 | xsub = ZMQ_XSUB, 488 | push = ZMQ_PUSH, 489 | pull = ZMQ_PULL, 490 | #if ZMQ_VERSION_MAJOR >= 4 491 | stream = ZMQ_STREAM, 492 | #endif 493 | pair = ZMQ_PAIR 494 | }; 495 | #endif 496 | 497 | class socket_t 498 | { 499 | friend class monitor_t; 500 | friend class poller_t; 501 | public: 502 | inline socket_t(context_t& context_, int type_) 503 | { 504 | init(context_, type_); 505 | } 506 | 507 | #ifdef ZMQ_CPP11 508 | inline socket_t(context_t& context_, socket_type type_) 509 | { 510 | init(context_, static_cast(type_)); 511 | } 512 | #endif 513 | 514 | #ifdef ZMQ_HAS_RVALUE_REFS 515 | inline socket_t(socket_t&& rhs) ZMQ_NOTHROW : 516 | ptr(rhs.ptr), 517 | ctxptr(rhs.ctxptr) 518 | { 519 | rhs.ptr = NULL; 520 | rhs.ctxptr = NULL; 521 | } 522 | inline socket_t& operator=(socket_t&& rhs) ZMQ_NOTHROW 523 | { 524 | std::swap(ptr, rhs.ptr); 525 | return *this; 526 | } 527 | #endif 528 | 529 | inline ~socket_t () ZMQ_NOTHROW 530 | { 531 | close(); 532 | } 533 | 534 | inline operator void* () ZMQ_NOTHROW 535 | { 536 | return ptr; 537 | } 538 | 539 | inline operator void const* () const ZMQ_NOTHROW 540 | { 541 | return ptr; 542 | } 543 | 544 | inline void close() ZMQ_NOTHROW 545 | { 546 | if(ptr == NULL) 547 | // already closed 548 | return ; 549 | int rc = zmq_close (ptr); 550 | ZMQ_ASSERT (rc == 0); 551 | ptr = 0 ; 552 | } 553 | 554 | template void setsockopt(int option_, T const& optval) 555 | { 556 | setsockopt(option_, &optval, sizeof(T) ); 557 | } 558 | 559 | inline void setsockopt (int option_, const void *optval_, 560 | size_t optvallen_) 561 | { 562 | int rc = zmq_setsockopt (ptr, option_, optval_, optvallen_); 563 | if (rc != 0) 564 | throw error_t (); 565 | } 566 | 567 | inline void getsockopt (int option_, void *optval_, 568 | size_t *optvallen_) const 569 | { 570 | int rc = zmq_getsockopt (ptr, option_, optval_, optvallen_); 571 | if (rc != 0) 572 | throw error_t (); 573 | } 574 | 575 | template T getsockopt(int option_) const 576 | { 577 | T optval; 578 | size_t optlen = sizeof(T); 579 | getsockopt(option_, &optval, &optlen ); 580 | return optval; 581 | } 582 | 583 | inline void bind(std::string const& addr) 584 | { 585 | bind(addr.c_str()); 586 | } 587 | 588 | inline void bind (const char *addr_) 589 | { 590 | int rc = zmq_bind (ptr, addr_); 591 | if (rc != 0) 592 | throw error_t (); 593 | } 594 | 595 | inline void unbind(std::string const& addr) 596 | { 597 | unbind(addr.c_str()); 598 | } 599 | 600 | inline void unbind (const char *addr_) 601 | { 602 | int rc = zmq_unbind (ptr, addr_); 603 | if (rc != 0) 604 | throw error_t (); 605 | } 606 | 607 | inline void connect(std::string const& addr) 608 | { 609 | connect(addr.c_str()); 610 | } 611 | 612 | inline void connect (const char *addr_) 613 | { 614 | int rc = zmq_connect (ptr, addr_); 615 | if (rc != 0) 616 | throw error_t (); 617 | } 618 | 619 | inline void disconnect(std::string const& addr) 620 | { 621 | disconnect(addr.c_str()); 622 | } 623 | 624 | inline void disconnect (const char *addr_) 625 | { 626 | int rc = zmq_disconnect (ptr, addr_); 627 | if (rc != 0) 628 | throw error_t (); 629 | } 630 | 631 | inline bool connected() const ZMQ_NOTHROW 632 | { 633 | return(ptr != NULL); 634 | } 635 | 636 | inline size_t send (const void *buf_, size_t len_, int flags_ = 0) 637 | { 638 | int nbytes = zmq_send (ptr, buf_, len_, flags_); 639 | if (nbytes >= 0) 640 | return (size_t) nbytes; 641 | if (zmq_errno () == EAGAIN) 642 | return 0; 643 | throw error_t (); 644 | } 645 | 646 | inline bool send (message_t &msg_, int flags_ = 0) 647 | { 648 | int nbytes = zmq_msg_send (&(msg_.msg), ptr, flags_); 649 | if (nbytes >= 0) 650 | return true; 651 | if (zmq_errno () == EAGAIN) 652 | return false; 653 | throw error_t (); 654 | } 655 | 656 | template bool send(I first, I last, int flags_=0) 657 | { 658 | zmq::message_t msg(first, last); 659 | return send(msg, flags_); 660 | } 661 | 662 | #ifdef ZMQ_HAS_RVALUE_REFS 663 | inline bool send (message_t &&msg_, int flags_ = 0) 664 | { 665 | return send(msg_, flags_); 666 | } 667 | #endif 668 | 669 | inline size_t recv (void *buf_, size_t len_, int flags_ = 0) 670 | { 671 | int nbytes = zmq_recv (ptr, buf_, len_, flags_); 672 | if (nbytes >= 0) 673 | return (size_t) nbytes; 674 | if (zmq_errno () == EAGAIN) 675 | return 0; 676 | throw error_t (); 677 | } 678 | 679 | inline bool recv (message_t *msg_, int flags_ = 0) 680 | { 681 | int nbytes = zmq_msg_recv (&(msg_->msg), ptr, flags_); 682 | if (nbytes >= 0) 683 | return true; 684 | if (zmq_errno () == EAGAIN) 685 | return false; 686 | throw error_t (); 687 | } 688 | 689 | private: 690 | inline void init(context_t& context_, int type_) 691 | { 692 | ctxptr = context_.ptr; 693 | ptr = zmq_socket (context_.ptr, type_ ); 694 | if (ptr == NULL) 695 | throw error_t (); 696 | } 697 | 698 | void *ptr; 699 | void *ctxptr; 700 | 701 | socket_t (const socket_t&) ZMQ_DELETED_FUNCTION; 702 | void operator = (const socket_t&) ZMQ_DELETED_FUNCTION; 703 | }; 704 | 705 | class monitor_t 706 | { 707 | public: 708 | monitor_t() : socketPtr(NULL), monitor_socket(NULL) {} 709 | 710 | virtual ~monitor_t() 711 | { 712 | if (socketPtr) 713 | zmq_socket_monitor(socketPtr, NULL, 0); 714 | 715 | if (monitor_socket) 716 | zmq_close (monitor_socket); 717 | 718 | } 719 | 720 | 721 | #ifdef ZMQ_HAS_RVALUE_REFS 722 | monitor_t(monitor_t&& rhs) ZMQ_NOTHROW : 723 | socketPtr(rhs.socketPtr), 724 | monitor_socket(rhs.monitor_socket) 725 | { 726 | rhs.socketPtr = NULL; 727 | rhs.monitor_socket = NULL; 728 | } 729 | 730 | socket_t& operator=(socket_t&& rhs) ZMQ_DELETED_FUNCTION ; 731 | #endif 732 | 733 | 734 | 735 | void monitor(socket_t &socket, std::string const& addr, int events = ZMQ_EVENT_ALL) 736 | { 737 | monitor(socket, addr.c_str(), events); 738 | } 739 | 740 | void monitor(socket_t &socket, const char *addr_, int events = ZMQ_EVENT_ALL) 741 | { 742 | init (socket, addr_, events) ; 743 | while(true) 744 | { 745 | check_event(-1) ; 746 | } 747 | } 748 | 749 | void init(socket_t &socket, std::string const& addr, int events = ZMQ_EVENT_ALL) 750 | { 751 | init(socket, addr.c_str(), events); 752 | } 753 | 754 | void init(socket_t &socket, const char *addr_, int events = ZMQ_EVENT_ALL) 755 | { 756 | int rc = zmq_socket_monitor(socket.ptr, addr_, events); 757 | if (rc != 0) 758 | throw error_t (); 759 | 760 | socketPtr = socket.ptr; 761 | monitor_socket = zmq_socket (socket.ctxptr, ZMQ_PAIR); 762 | assert (monitor_socket); 763 | 764 | rc = zmq_connect (monitor_socket, addr_); 765 | assert (rc == 0); 766 | 767 | on_monitor_started(); 768 | } 769 | 770 | bool check_event(int timeout = 0) 771 | { 772 | assert (monitor_socket); 773 | 774 | zmq_msg_t eventMsg; 775 | zmq_msg_init (&eventMsg); 776 | 777 | zmq::pollitem_t items [] = { 778 | { monitor_socket, 0, ZMQ_POLLIN, 0 }, 779 | }; 780 | 781 | zmq::poll (&items [0], 1, timeout); 782 | 783 | if (items [0].revents & ZMQ_POLLIN) 784 | { 785 | int rc = zmq_msg_recv (&eventMsg, monitor_socket, 0); 786 | if (rc == -1 && zmq_errno() == ETERM) 787 | return false; 788 | assert (rc != -1); 789 | 790 | } 791 | else 792 | { 793 | zmq_msg_close (&eventMsg); 794 | return false; 795 | } 796 | 797 | #if ZMQ_VERSION_MAJOR >= 4 798 | const char* data = static_cast(zmq_msg_data(&eventMsg)); 799 | zmq_event_t msgEvent; 800 | memcpy(&msgEvent.event, data, sizeof(uint16_t)); data += sizeof(uint16_t); 801 | memcpy(&msgEvent.value, data, sizeof(int32_t)); 802 | zmq_event_t* event = &msgEvent; 803 | #else 804 | zmq_event_t* event = static_cast(zmq_msg_data(&eventMsg)); 805 | #endif 806 | 807 | #ifdef ZMQ_NEW_MONITOR_EVENT_LAYOUT 808 | zmq_msg_t addrMsg; 809 | zmq_msg_init (&addrMsg); 810 | int rc = zmq_msg_recv (&addrMsg, monitor_socket, 0); 811 | if (rc == -1 && zmq_errno() == ETERM) 812 | { 813 | zmq_msg_close (&eventMsg); 814 | return false; 815 | } 816 | 817 | assert (rc != -1); 818 | const char* str = static_cast(zmq_msg_data (&addrMsg)); 819 | std::string address(str, str + zmq_msg_size(&addrMsg)); 820 | zmq_msg_close (&addrMsg); 821 | #else 822 | // Bit of a hack, but all events in the zmq_event_t union have the same layout so this will work for all event types. 823 | std::string address = event->data.connected.addr; 824 | #endif 825 | 826 | #ifdef ZMQ_EVENT_MONITOR_STOPPED 827 | if (event->event == ZMQ_EVENT_MONITOR_STOPPED) 828 | { 829 | zmq_msg_close (&eventMsg); 830 | return true; 831 | } 832 | 833 | #endif 834 | 835 | switch (event->event) { 836 | case ZMQ_EVENT_CONNECTED: 837 | on_event_connected(*event, address.c_str()); 838 | break; 839 | case ZMQ_EVENT_CONNECT_DELAYED: 840 | on_event_connect_delayed(*event, address.c_str()); 841 | break; 842 | case ZMQ_EVENT_CONNECT_RETRIED: 843 | on_event_connect_retried(*event, address.c_str()); 844 | break; 845 | case ZMQ_EVENT_LISTENING: 846 | on_event_listening(*event, address.c_str()); 847 | break; 848 | case ZMQ_EVENT_BIND_FAILED: 849 | on_event_bind_failed(*event, address.c_str()); 850 | break; 851 | case ZMQ_EVENT_ACCEPTED: 852 | on_event_accepted(*event, address.c_str()); 853 | break; 854 | case ZMQ_EVENT_ACCEPT_FAILED: 855 | on_event_accept_failed(*event, address.c_str()); 856 | break; 857 | case ZMQ_EVENT_CLOSED: 858 | on_event_closed(*event, address.c_str()); 859 | break; 860 | case ZMQ_EVENT_CLOSE_FAILED: 861 | on_event_close_failed(*event, address.c_str()); 862 | break; 863 | case ZMQ_EVENT_DISCONNECTED: 864 | on_event_disconnected(*event, address.c_str()); 865 | break; 866 | #ifdef ZMQ_BUILD_DRAFT_API 867 | #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3) 868 | case ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL: 869 | on_event_handshake_failed_no_detail(*event, address.c_str()); 870 | break; 871 | case ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL: 872 | on_event_handshake_failed_protocol(*event, address.c_str()); 873 | break; 874 | case ZMQ_EVENT_HANDSHAKE_FAILED_AUTH: 875 | on_event_handshake_failed_auth(*event, address.c_str()); 876 | break; 877 | case ZMQ_EVENT_HANDSHAKE_SUCCEEDED: 878 | on_event_handshake_succeeded(*event, address.c_str()); 879 | break; 880 | #elif ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 1) 881 | case ZMQ_EVENT_HANDSHAKE_FAILED: 882 | on_event_handshake_failed(*event, address.c_str()); 883 | break; 884 | case ZMQ_EVENT_HANDSHAKE_SUCCEED: 885 | on_event_handshake_succeed(*event, address.c_str()); 886 | break; 887 | #endif 888 | #endif 889 | default: 890 | on_event_unknown(*event, address.c_str()); 891 | break; 892 | } 893 | zmq_msg_close (&eventMsg); 894 | 895 | return true ; 896 | } 897 | 898 | #ifdef ZMQ_EVENT_MONITOR_STOPPED 899 | void abort() 900 | { 901 | if (socketPtr) 902 | zmq_socket_monitor(socketPtr, NULL, 0); 903 | 904 | if (monitor_socket) 905 | zmq_close (monitor_socket); 906 | 907 | socketPtr = NULL; 908 | monitor_socket = NULL; 909 | } 910 | #endif 911 | virtual void on_monitor_started() {} 912 | virtual void on_event_connected(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } 913 | virtual void on_event_connect_delayed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } 914 | virtual void on_event_connect_retried(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } 915 | virtual void on_event_listening(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } 916 | virtual void on_event_bind_failed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } 917 | virtual void on_event_accepted(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } 918 | virtual void on_event_accept_failed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } 919 | virtual void on_event_closed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } 920 | virtual void on_event_close_failed(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } 921 | virtual void on_event_disconnected(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } 922 | #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3) 923 | virtual void on_event_handshake_failed_no_detail(const zmq_event_t &event_, const char* addr_) { (void) event_; (void) addr_; } 924 | virtual void on_event_handshake_failed_protocol(const zmq_event_t &event_, const char* addr_) { (void) event_; (void) addr_; } 925 | virtual void on_event_handshake_failed_auth(const zmq_event_t &event_, const char* addr_) { (void) event_; (void) addr_; } 926 | virtual void on_event_handshake_succeeded(const zmq_event_t &event_, const char* addr_) { (void) event_; (void) addr_; } 927 | #elif ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 1) 928 | virtual void on_event_handshake_failed(const zmq_event_t &event_, const char* addr_) { (void) event_; (void) addr_; } 929 | virtual void on_event_handshake_succeed(const zmq_event_t &event_, const char* addr_) { (void) event_; (void) addr_; } 930 | #endif 931 | virtual void on_event_unknown(const zmq_event_t &event_, const char* addr_) { (void)event_; (void)addr_; } 932 | private: 933 | 934 | monitor_t (const monitor_t&) ZMQ_DELETED_FUNCTION; 935 | void operator = (const monitor_t&) ZMQ_DELETED_FUNCTION; 936 | 937 | void* socketPtr; 938 | void *monitor_socket ; 939 | }; 940 | 941 | #if defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER) 942 | class poller_t 943 | { 944 | public: 945 | poller_t () : poller_ptr (zmq_poller_new ()) 946 | { 947 | if (!poller_ptr) 948 | throw error_t (); 949 | } 950 | 951 | ~poller_t () 952 | { 953 | zmq_poller_destroy (&poller_ptr); 954 | } 955 | 956 | bool add (zmq::socket_t &socket, short events, std::function &handler) 957 | { 958 | if (0 == zmq_poller_add (poller_ptr, socket.ptr, handler ? &handler : NULL, events)) { 959 | poller_events.emplace_back (zmq_poller_event_t ()); 960 | return true; 961 | } 962 | return false; 963 | } 964 | 965 | bool remove (zmq::socket_t &socket) 966 | { 967 | if (0 == zmq_poller_remove (poller_ptr, socket.ptr)) { 968 | poller_events.pop_back (); 969 | return true; 970 | } 971 | return false; 972 | } 973 | 974 | bool wait (std::chrono::milliseconds timeout) 975 | { 976 | int rc = zmq_poller_wait_all (poller_ptr, poller_events.data (), static_cast (poller_events.size ()), static_cast(timeout.count ())); 977 | if (rc >= 0) { 978 | std::for_each (poller_events.begin (), poller_events.begin () + rc, [](zmq_poller_event_t& event) { 979 | if (event.user_data != NULL) 980 | (*reinterpret_cast*> (event.user_data)) (); 981 | }); 982 | return true; 983 | } 984 | 985 | #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3) 986 | if (zmq_errno () == EAGAIN) 987 | #else 988 | if (zmq_errno () == ETIMEDOUT) 989 | #endif 990 | return false; 991 | 992 | throw error_t (); 993 | } 994 | 995 | private: 996 | void *poller_ptr; 997 | std::vector poller_events; 998 | }; 999 | #endif // defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER) 1000 | 1001 | } 1002 | 1003 | #endif 1004 | -------------------------------------------------------------------------------- /build-vs2015/depends/lib/libzmq.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/button-chen/buttonrpc_cpp14/fe6a96bb2e9b71a6901675b4b37411defb6a253d/build-vs2015/depends/lib/libzmq.dll -------------------------------------------------------------------------------- /build-vs2015/depends/lib/libzmq.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/button-chen/buttonrpc_cpp14/fe6a96bb2e9b71a6901675b4b37411defb6a253d/build-vs2015/depends/lib/libzmq.lib -------------------------------------------------------------------------------- /buttonrpc.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * buttonrpc library 4 | * Copyright 2018-04-28 Button 5 | * 6 | */ 7 | 8 | #pragma once 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include "Serializer.hpp" 17 | 18 | 19 | class Serializer; 20 | 21 | template 22 | struct type_xx{ typedef T type; }; 23 | 24 | template<> 25 | struct type_xx{ typedef int8_t type; }; 26 | 27 | 28 | // 打包帮助模板 29 | template 30 | void package_params_impl(Serializer& ds, const Tuple& t, std::index_sequence) 31 | { 32 | initializer_list{((ds << std::get(t)), 0)...}; 33 | } 34 | 35 | template 36 | void package_params(Serializer& ds, const std::tuple& t) 37 | { 38 | package_params_impl(ds, t, std::index_sequence_for{}); 39 | } 40 | 41 | // 用tuple做参数调用函数模板类 42 | template 43 | decltype(auto) invoke_impl(Function&& func, Tuple&& t, std::index_sequence) 44 | { 45 | return func(std::get(std::forward(t))...); 46 | } 47 | 48 | template 49 | decltype(auto) invoke(Function&& func, Tuple&& t) 50 | { 51 | constexpr auto size = std::tuple_size::type>::value; 52 | return invoke_impl(std::forward(func), std::forward(t), std::make_index_sequence{}); 53 | } 54 | 55 | // 调用帮助类,主要用于返回是否void的情况 56 | template 57 | typename std::enable_if::value, typename type_xx::type >::type 58 | call_helper(F f, ArgsTuple args) { 59 | invoke(f, args); 60 | return 0; 61 | } 62 | 63 | template 64 | typename std::enable_if::value, typename type_xx::type >::type 65 | call_helper(F f, ArgsTuple args) { 66 | return invoke(f, args); 67 | } 68 | 69 | // rpc 类定义 70 | class buttonrpc 71 | { 72 | public: 73 | enum rpc_role{ 74 | RPC_CLIENT, 75 | RPC_SERVER 76 | }; 77 | enum rpc_err_code { 78 | RPC_ERR_SUCCESS = 0, 79 | RPC_ERR_FUNCTIION_NOT_BIND, 80 | RPC_ERR_RECV_TIMEOUT 81 | }; 82 | 83 | // wrap return value 84 | template 85 | class value_t { 86 | public: 87 | typedef typename type_xx::type type; 88 | typedef std::string msg_type; 89 | typedef uint16_t code_type; 90 | 91 | value_t() { code_ = 0; msg_.clear(); } 92 | bool valid() { return (code_ == 0 ? true : false); } 93 | int error_code() { return code_; } 94 | std::string error_msg() { return msg_; } 95 | type val() { return val_; } 96 | 97 | void set_val(const type& val) { val_ = val; } 98 | void set_code(code_type code) { code_ = code; } 99 | void set_msg(msg_type msg) { msg_ = msg; } 100 | 101 | friend Serializer& operator >> (Serializer& in, value_t& d) { 102 | in >> d.code_ >> d.msg_; 103 | if (d.code_ == 0) { 104 | in >> d.val_; 105 | } 106 | return in; 107 | } 108 | friend Serializer& operator << (Serializer& out, value_t d) { 109 | out << d.code_ << d.msg_ << d.val_; 110 | return out; 111 | } 112 | private: 113 | code_type code_; 114 | msg_type msg_; 115 | type val_; 116 | }; 117 | 118 | buttonrpc(); 119 | ~buttonrpc(); 120 | 121 | // network 122 | void as_client(std::string ip, int port); 123 | void as_server(int port); 124 | void send(zmq::message_t& data); 125 | void recv(zmq::message_t& data); 126 | void set_timeout(uint32_t ms); 127 | void run(); 128 | 129 | public: 130 | // server 131 | template 132 | void bind(std::string name, F func); 133 | 134 | template 135 | void bind(std::string name, F func, S* s); 136 | 137 | // client 138 | template 139 | value_t call(std::string name, Params... ps) { 140 | using args_type = std::tuple::type...>; 141 | args_type args = std::make_tuple(ps...); 142 | 143 | Serializer ds; 144 | ds << name; 145 | package_params(ds, args); 146 | return net_call(ds); 147 | } 148 | 149 | template 150 | value_t call(std::string name) { 151 | Serializer ds; 152 | ds << name; 153 | return net_call(ds); 154 | } 155 | 156 | private: 157 | Serializer* call_(std::string name, const char* data, int len); 158 | 159 | template 160 | value_t net_call(Serializer& ds); 161 | 162 | template 163 | void callproxy(F fun, Serializer* pr, const char* data, int len); 164 | 165 | template 166 | void callproxy(F fun, S* s, Serializer* pr, const char* data, int len); 167 | 168 | // 函数指针 169 | template 170 | void callproxy_(R(*func)(Params...), Serializer* pr, const char* data, int len) { 171 | callproxy_(std::function(func), pr, data, len); 172 | } 173 | 174 | // 类成员函数指针 175 | template 176 | void callproxy_(R(C::* func)(Params...), S* s, Serializer* pr, const char* data, int len) { 177 | 178 | using args_type = std::tuple::type...>; 179 | 180 | Serializer ds(StreamBuffer(data, len)); 181 | constexpr auto N = std::tuple_size::type>::value; 182 | args_type args = ds.get_tuple < args_type >(std::make_index_sequence{}); 183 | 184 | auto ff = [=](Params... ps)->R { 185 | return (s->*func)(ps...); 186 | }; 187 | typename type_xx::type r = call_helper(ff, args); 188 | 189 | value_t val; 190 | val.set_code(RPC_ERR_SUCCESS); 191 | val.set_val(r); 192 | (*pr) << val; 193 | } 194 | 195 | // functional 196 | template 197 | void callproxy_(std::function func, Serializer* pr, const char* data, int len) { 198 | 199 | using args_type = std::tuple::type...>; 200 | 201 | Serializer ds(StreamBuffer(data, len)); 202 | constexpr auto N = std::tuple_size::type>::value; 203 | args_type args = ds.get_tuple < args_type > (std::make_index_sequence{}); 204 | 205 | typename type_xx::type r = call_helper(func, args); 206 | 207 | value_t val; 208 | val.set_code(RPC_ERR_SUCCESS); 209 | val.set_val(r); 210 | (*pr) << val; 211 | } 212 | 213 | private: 214 | std::map> m_handlers; 215 | 216 | zmq::context_t m_context; 217 | std::unique_ptr> m_socket; 218 | 219 | rpc_err_code m_error_code; 220 | 221 | int m_role; 222 | }; 223 | 224 | inline buttonrpc::buttonrpc() : m_context(1){ 225 | m_error_code = RPC_ERR_SUCCESS; 226 | } 227 | 228 | inline buttonrpc::~buttonrpc(){ 229 | m_context.close(); 230 | } 231 | 232 | // network 233 | inline void buttonrpc::as_client( std::string ip, int port ) 234 | { 235 | m_role = RPC_CLIENT; 236 | m_socket = std::unique_ptr>(new zmq::socket_t(m_context, ZMQ_REQ), [](zmq::socket_t* sock){ sock->close(); delete sock; sock =nullptr;}); 237 | ostringstream os; 238 | os << "tcp://" << ip << ":" << port; 239 | m_socket->connect (os.str()); 240 | } 241 | 242 | inline void buttonrpc::as_server( int port ) 243 | { 244 | m_role = RPC_SERVER; 245 | m_socket = std::unique_ptr>(new zmq::socket_t(m_context, ZMQ_REP), [](zmq::socket_t* sock){ sock->close(); delete sock; sock =nullptr;}); 246 | ostringstream os; 247 | os << "tcp://*:" << port; 248 | m_socket->bind (os.str()); 249 | } 250 | 251 | inline void buttonrpc::send( zmq::message_t& data ) 252 | { 253 | m_socket->send(data); 254 | } 255 | 256 | inline void buttonrpc::recv( zmq::message_t& data ) 257 | { 258 | m_socket->recv(&data); 259 | } 260 | 261 | inline void buttonrpc::set_timeout(uint32_t ms) 262 | { 263 | // only client can set 264 | if (m_role == RPC_CLIENT) { 265 | m_socket->setsockopt(ZMQ_RCVTIMEO, ms); 266 | } 267 | } 268 | 269 | inline void buttonrpc::run() 270 | { 271 | // only server can call 272 | if (m_role != RPC_SERVER) { 273 | return; 274 | } 275 | while (1){ 276 | zmq::message_t data; 277 | recv(data); 278 | StreamBuffer iodev((char*)data.data(), data.size()); 279 | Serializer ds(iodev); 280 | 281 | std::string funname; 282 | ds >> funname; 283 | Serializer* r = call_(funname, ds.current(), ds.size()- funname.size()); 284 | 285 | zmq::message_t retmsg (r->size()); 286 | memcpy (retmsg.data (), r->data(), r->size()); 287 | send(retmsg); 288 | delete r; 289 | } 290 | } 291 | 292 | // 处理函数相关 293 | 294 | inline Serializer* buttonrpc::call_(std::string name, const char* data, int len) 295 | { 296 | Serializer* ds = new Serializer(); 297 | if (m_handlers.find(name) == m_handlers.end()) { 298 | (*ds) << value_t::code_type(RPC_ERR_FUNCTIION_NOT_BIND); 299 | (*ds) << value_t::msg_type("function not bind: " + name); 300 | return ds; 301 | } 302 | auto fun = m_handlers[name]; 303 | fun(ds, data, len); 304 | ds->reset(); 305 | return ds; 306 | } 307 | 308 | template 309 | inline void buttonrpc::bind( std::string name, F func ) 310 | { 311 | m_handlers[name] = std::bind(&buttonrpc::callproxy, this, func, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); 312 | } 313 | 314 | template 315 | inline void buttonrpc::bind(std::string name, F func, S* s) 316 | { 317 | m_handlers[name] = std::bind(&buttonrpc::callproxy, this, func, s, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); 318 | } 319 | 320 | template 321 | inline void buttonrpc::callproxy( F fun, Serializer* pr, const char* data, int len ) 322 | { 323 | callproxy_(fun, pr, data, len); 324 | } 325 | 326 | template 327 | inline void buttonrpc::callproxy(F fun, S * s, Serializer * pr, const char * data, int len) 328 | { 329 | callproxy_(fun, s, pr, data, len); 330 | } 331 | 332 | template 333 | inline buttonrpc::value_t buttonrpc::net_call(Serializer& ds) 334 | { 335 | zmq::message_t request(ds.size() + 1); 336 | memcpy(request.data(), ds.data(), ds.size()); 337 | if (m_error_code != RPC_ERR_RECV_TIMEOUT) { 338 | send(request); 339 | } 340 | zmq::message_t reply; 341 | recv(reply); 342 | value_t val; 343 | if (reply.size() == 0) { 344 | // timeout 345 | m_error_code = RPC_ERR_RECV_TIMEOUT; 346 | val.set_code(RPC_ERR_RECV_TIMEOUT); 347 | val.set_msg("recv timeout"); 348 | return val; 349 | } 350 | m_error_code = RPC_ERR_SUCCESS; 351 | ds.clear(); 352 | ds.write_raw_data((char*)reply.data(), reply.size()); 353 | ds.reset(); 354 | 355 | ds >> val; 356 | return val; 357 | } 358 | -------------------------------------------------------------------------------- /example/main_client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "buttonrpc.hpp" 5 | 6 | #ifdef _WIN32 7 | #include // use sleep 8 | #else 9 | #include 10 | #endif 11 | 12 | 13 | #define buttont_assert(exp) { \ 14 | if (!(exp)) {\ 15 | std::cout << "ERROR: "; \ 16 | std::cout << "function: " << __FUNCTION__ << ", line: " << __LINE__ << std::endl; \ 17 | system("pause"); \ 18 | }\ 19 | }\ 20 | 21 | 22 | struct PersonInfo 23 | { 24 | int age; 25 | std::string name; 26 | float height; 27 | 28 | // must implement 29 | friend Serializer& operator >> (Serializer& in, PersonInfo& d) { 30 | in >> d.age >> d.name >> d.height; 31 | return in; 32 | } 33 | friend Serializer& operator << (Serializer& out, PersonInfo d) { 34 | out << d.age << d.name << d.height; 35 | return out; 36 | } 37 | }; 38 | 39 | int main() 40 | { 41 | buttonrpc client; 42 | client.as_client("127.0.0.1", 5555); 43 | client.set_timeout(2000); 44 | 45 | int callcnt = 0; 46 | while (1){ 47 | std::cout << "current call count: " << ++callcnt << std::endl; 48 | 49 | client.call("foo_1"); 50 | 51 | client.call("foo_2", 10); 52 | 53 | int foo3r = client.call("foo_3", 10).val(); 54 | buttont_assert(foo3r == 100); 55 | 56 | int foo4r = client.call("foo_4", 10, "buttonrpc", 100, (float)10.8).val(); 57 | buttont_assert(foo4r == 1000); 58 | 59 | PersonInfo dd = { 10, "buttonrpc", 170 }; 60 | dd = client.call("foo_5", dd, 120).val(); 61 | buttont_assert(dd.age == 20); 62 | buttont_assert(dd.name == "buttonrpc is good"); 63 | buttont_assert(dd.height == 180); 64 | 65 | int foo6r = client.call("foo_6", 10, "buttonrpc", 100).val(); 66 | buttont_assert(foo6r == 1000); 67 | 68 | buttonrpc::value_t xx = client.call("foo_7", 666); 69 | buttont_assert(!xx.valid()); 70 | #ifdef _WIN32 71 | Sleep(1000); 72 | #else 73 | sleep(1); 74 | #endif 75 | } 76 | 77 | return 0; 78 | } 79 | -------------------------------------------------------------------------------- /example/main_server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "buttonrpc.hpp" 4 | 5 | 6 | #define buttont_assert(exp) { \ 7 | if (!(exp)) {\ 8 | std::cout << "ERROR: "; \ 9 | std::cout << "function: " << __FUNCTION__ << ", line: " << __LINE__ << std::endl; \ 10 | system("pause"); \ 11 | }\ 12 | }\ 13 | 14 | 15 | // 测试例子 16 | void foo_1() { 17 | 18 | } 19 | 20 | void foo_2(int arg1) { 21 | buttont_assert(arg1 == 10); 22 | } 23 | 24 | int foo_3(int arg1) { 25 | buttont_assert(arg1 == 10); 26 | return arg1 * arg1; 27 | } 28 | 29 | int foo_4(int arg1, std::string arg2, int arg3, float arg4) { 30 | buttont_assert(arg1 == 10); 31 | buttont_assert(arg2 == "buttonrpc"); 32 | buttont_assert(arg3 == 100); 33 | buttont_assert((arg4 > 10.0) && (arg4 < 11.0)); 34 | return arg1 * arg3; 35 | } 36 | 37 | class ClassMem 38 | { 39 | public: 40 | int bar(int arg1, std::string arg2, int arg3) { 41 | buttont_assert(arg1 == 10); 42 | buttont_assert(arg2 == "buttonrpc"); 43 | buttont_assert(arg3 == 100); 44 | return arg1 * arg3; 45 | } 46 | }; 47 | 48 | struct PersonInfo 49 | { 50 | int age; 51 | std::string name; 52 | float height; 53 | 54 | // must implement 55 | friend Serializer& operator >> (Serializer& in, PersonInfo& d) { 56 | in >> d.age >> d.name >> d.height; 57 | return in; 58 | } 59 | friend Serializer& operator << (Serializer& out, PersonInfo d) { 60 | out << d.age << d.name << d.height; 61 | return out; 62 | } 63 | }; 64 | 65 | PersonInfo foo_5(PersonInfo d, int weigth) 66 | { 67 | buttont_assert(d.age == 10); 68 | buttont_assert(d.name == "buttonrpc"); 69 | buttont_assert(d.height == 170); 70 | 71 | PersonInfo ret; 72 | ret.age = d.age + 10; 73 | ret.name = d.name + " is good"; 74 | ret.height = d.height + 10; 75 | return ret; 76 | } 77 | 78 | int main() 79 | { 80 | buttonrpc server; 81 | server.as_server(5555); 82 | 83 | server.bind("foo_1", foo_1); 84 | server.bind("foo_2", foo_2); 85 | server.bind("foo_3", std::function(foo_3)); 86 | server.bind("foo_4", foo_4); 87 | server.bind("foo_5", foo_5); 88 | 89 | ClassMem s; 90 | server.bind("foo_6", &ClassMem::bar, &s); 91 | 92 | std::cout << "run rpc server on: " << 5555 << std::endl; 93 | server.run(); 94 | 95 | return 0; 96 | } 97 | --------------------------------------------------------------------------------