├── .gitignore ├── CMakeLists.txt ├── demo ├── CMakeLists.txt ├── async │ ├── client.cpp │ └── server.cpp ├── http_client │ └── http_client.cpp ├── raw │ └── raw.cpp ├── reqrep │ └── reqrep.cpp └── rest │ └── server.cpp ├── include └── nngpp │ ├── aio.h │ ├── aio_view.h │ ├── buffer.h │ ├── core.h │ ├── ctx.h │ ├── ctx_view.h │ ├── dialer.h │ ├── dialer_view.h │ ├── error.h │ ├── http │ ├── client.h │ ├── client_view.h │ ├── conn.h │ ├── conn_view.h │ ├── handler.h │ ├── handler_view.h │ ├── http.h │ ├── misc.h │ ├── req.h │ ├── req_view.h │ ├── res.h │ ├── res_view.h │ ├── server.h │ └── server_view.h │ ├── listener.h │ ├── listener_view.h │ ├── msg.h │ ├── msg_body.h │ ├── msg_header.h │ ├── msg_view.h │ ├── nngpp.h │ ├── option.h │ ├── pipe.h │ ├── pipe_view.h │ ├── platform │ ├── cv.h │ ├── cv_view.h │ ├── mtx.h │ ├── mtx_view.h │ ├── platform.h │ ├── thread.h │ └── thread_view.h │ ├── protocol │ ├── bus0.h │ ├── pair0.h │ ├── pair1.h │ ├── pub0.h │ ├── pull0.h │ ├── push0.h │ ├── rep0.h │ ├── req0.h │ ├── respond0.h │ ├── sub0.h │ └── survey0.h │ ├── socket.h │ ├── socket_view.h │ ├── stat.h │ ├── stat_view.h │ ├── stream │ ├── dialer.h │ ├── dialer_view.h │ ├── listener.h │ ├── listener_view.h │ ├── stream.h │ └── stream_view.h │ ├── transport │ ├── inproc.h │ ├── ipc.h │ ├── tcp.h │ ├── tls.h │ ├── tls │ │ ├── config.h │ │ ├── config_view.h │ │ └── engine.h │ ├── ws.h │ ├── wss.h │ └── zerotier.h │ ├── url.h │ ├── url_view.h │ └── view.h ├── license.txt ├── makefile ├── perf ├── inproc.h ├── inproc_lat.cpp ├── inproc_thr.cpp ├── latency.h ├── local_lat.cpp ├── local_thr.cpp ├── misc.h ├── remote_lat.cpp ├── remote_thr.cpp └── throughput.h ├── project └── vs2019 │ ├── async_client.vcxproj │ ├── async_client.vcxproj.filters │ ├── async_client.vcxproj.user │ ├── async_server.vcxproj │ ├── async_server.vcxproj.filters │ ├── async_server.vcxproj.user │ ├── http_client.vcxproj │ ├── http_client.vcxproj.filters │ ├── http_client.vcxproj.user │ ├── inproc_lat.vcxproj │ ├── inproc_lat.vcxproj.filters │ ├── inproc_lat.vcxproj.user │ ├── inproc_thr.vcxproj │ ├── inproc_thr.vcxproj.filters │ ├── inproc_thr.vcxproj.user │ ├── local_lat.vcxproj │ ├── local_lat.vcxproj.filters │ ├── local_lat.vcxproj.user │ ├── local_thr.vcxproj │ ├── local_thr.vcxproj.filters │ ├── local_thr.vcxproj.user │ ├── nngpp.sln │ ├── raw.vcxproj │ ├── raw.vcxproj.filters │ ├── raw.vcxproj.user │ ├── remote_lat.vcxproj │ ├── remote_lat.vcxproj.filters │ ├── remote_lat.vcxproj.user │ ├── remote_thr.vcxproj │ ├── remote_thr.vcxproj.filters │ ├── remote_thr.vcxproj.user │ ├── reqrep.vcxproj │ ├── reqrep.vcxproj.filters │ ├── reqrep.vcxproj.user │ ├── rest.vcxproj │ ├── rest.vcxproj.filters │ ├── rest.vcxproj.user │ ├── test.vcxproj │ ├── test.vcxproj.filters │ └── test.vcxproj.user ├── readme.md └── test ├── CMakeLists.txt ├── bus.cpp ├── device.cpp ├── hello_world.cpp ├── http_client.cpp ├── ipcsupp.cpp ├── main.cpp ├── message.cpp ├── pipe.cpp ├── reconnect.cpp ├── respondpoll.cpp ├── scalability.cpp ├── synch.cpp ├── tcpsupp.cpp └── tls.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | build/ 3 | 4 | # Visual Studio stuff 5 | project/*/.vs 6 | 7 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.1) 2 | project(nngpp CXX) 3 | 4 | include(GNUInstallDirs) 5 | 6 | option(NNGPP_BUILD_DEMOS "build nngpp demos" off) 7 | option(NNGPP_BUILD_TESTS "build nngpp tests" off) 8 | 9 | set(CMAKE_CXX_STANDARD 14) 10 | 11 | find_package(nng) 12 | 13 | file(GLOB_RECURSE includes include/*.h) 14 | 15 | add_library(nngpp INTERFACE) 16 | target_include_directories(nngpp INTERFACE $) 17 | target_link_libraries(nngpp INTERFACE nng::nng) 18 | 19 | if (NNGPP_BUILD_DEMOS) 20 | add_subdirectory(demo) 21 | endif() 22 | 23 | if (NNGPP_BUILD_TESTS) 24 | option(NNGPP_BUILD_TLS_TEST "build nngpp tls tests (requires mbedtls)" off) 25 | add_subdirectory(test) 26 | endif() 27 | 28 | install(TARGETS nngpp EXPORT nngpp-target) 29 | install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) 30 | install(EXPORT nngpp-target DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/nngpp 31 | NAMESPACE nng:: FILE nngpp-config.cmake) 32 | -------------------------------------------------------------------------------- /demo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(async_server async/server.cpp) 2 | target_link_libraries(async_server nngpp) 3 | target_include_directories(async_server PUBLIC ${CMAKE_SOURCE_DIR}/include) 4 | 5 | add_executable(async_client async/client.cpp) 6 | target_link_libraries(async_client nngpp) 7 | target_include_directories(async_client PUBLIC ${CMAKE_SOURCE_DIR}/include) 8 | 9 | add_executable(http_client http_client/http_client.cpp) 10 | target_link_libraries(http_client nngpp) 11 | target_include_directories(http_client PUBLIC ${CMAKE_SOURCE_DIR}/include) 12 | 13 | add_executable(raw raw/raw.cpp) 14 | target_link_libraries(raw nngpp) 15 | target_include_directories(raw PUBLIC ${CMAKE_SOURCE_DIR}/include) 16 | 17 | add_executable(reqrep reqrep/reqrep.cpp) 18 | target_link_libraries(reqrep nngpp) 19 | target_include_directories(reqrep PUBLIC ${CMAKE_SOURCE_DIR}/include) 20 | 21 | add_executable(rest rest/server.cpp) 22 | target_link_libraries(rest nngpp) 23 | target_include_directories(rest PUBLIC ${CMAKE_SOURCE_DIR}/include) 24 | 25 | -------------------------------------------------------------------------------- /demo/async/client.cpp: -------------------------------------------------------------------------------- 1 | // This is a port of the nng demo to nngpp 2 | // See https://github.com/nanomsg/nng/tree/master/demo/async 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | // The client runs just once, and then returns. 11 | void client(const char* url, const char* msecstr) { 12 | auto msec = atoi(msecstr); 13 | 14 | auto sock = nng::req::open(); 15 | sock.dial(url); 16 | 17 | auto start = nng::clock(); 18 | auto msg = nng::make_msg(0); 19 | msg.body().append_u32(msec); 20 | sock.send(std::move(msg)); 21 | msg = sock.recv_msg(); 22 | auto end = nng::clock(); 23 | 24 | printf("Request took %u milliseconds.\n", (uint32_t)(end - start)); 25 | } 26 | 27 | int main(int argc, char** argv) try { 28 | if (argc != 3) { 29 | fprintf(stderr, "Usage: %s \n", argv[0]); 30 | return 1; 31 | } 32 | client(argv[1], argv[2]); 33 | } 34 | catch( const nng::exception& e ) { 35 | fprintf(stderr, "%s: %s\n", e.who(), e.what()); 36 | return 1; 37 | } 38 | -------------------------------------------------------------------------------- /demo/async/server.cpp: -------------------------------------------------------------------------------- 1 | // This is a port of the nng demo to nngpp 2 | // See https://github.com/nanomsg/nng/tree/master/demo/async 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | // Parallel is the maximum number of outstanding requests we can handle. 11 | // This is *NOT* the number of threads in use, but instead represents 12 | // outstanding work items. Select a small number to reduce memory size. 13 | // (Each one of these can be thought of as a request-reply loop.) Note 14 | // that you will probably run into limitations on the number of open file 15 | // descriptors if you set this too high. (If not for that limit, this could 16 | // be set in the thousands, each context consumes a couple of KB.) 17 | #ifndef PARALLEL 18 | #define PARALLEL 128 19 | #endif 20 | 21 | void server_cb(void* arg); 22 | 23 | // The server keeps a list of work items, sorted by expiration time, 24 | // so that we can use this to set the timeout to the correct value for 25 | // use in poll. 26 | struct work { 27 | enum { INIT, RECV, WAIT, SEND } state = INIT; 28 | nng::aio aio{ server_cb, this }; 29 | nng::msg msg; 30 | nng::ctx ctx; 31 | 32 | explicit work( nng::socket_view sock ) : ctx(sock) {} 33 | }; 34 | 35 | void server_cb(void* arg) try { 36 | work* work = (struct work*)arg; 37 | uint32_t when; 38 | 39 | switch(work->state) { 40 | case work::INIT: 41 | work->state = work::RECV; 42 | work->ctx.recv( work->aio ); 43 | break; 44 | case work::RECV: 45 | { 46 | auto result = work->aio.result(); 47 | if( result != nng::error::success ) { 48 | throw nng::exception(result); 49 | } 50 | } 51 | { 52 | auto msg = work->aio.release_msg(); 53 | try { 54 | when = msg.body().trim_u32(); 55 | } 56 | catch( const nng::exception& ) { 57 | // bad message, just ignore it. 58 | work->ctx.recv( work->aio ); 59 | return; 60 | } 61 | work->msg = std::move(msg); 62 | } 63 | work->state = work::WAIT; 64 | nng::sleep( when, work->aio ); 65 | break; 66 | case work::WAIT: 67 | // We could add more data to the message here. 68 | work->aio.set_msg( std::move(work->msg) ); 69 | work->state = work::SEND; 70 | work->ctx.send( work->aio ); 71 | break; 72 | case work::SEND: 73 | { 74 | auto result = work->aio.result(); 75 | if( result != nng::error::success ) { 76 | throw nng::exception(result); 77 | } 78 | } 79 | work->state = work::RECV; 80 | work->ctx.recv( work->aio ); 81 | break; 82 | default: 83 | throw nng::exception(nng::error::state); 84 | break; 85 | } 86 | } 87 | catch( const nng::exception& e ) { 88 | fprintf(stderr, "server_cb: %s: %s\n", e.who(), e.what()); 89 | exit(1); 90 | } 91 | catch( ... ) { 92 | fprintf(stderr, "server_cb: unknown exception\n"); 93 | exit(1); 94 | } 95 | 96 | // The server runs forever. 97 | void server(const char* url) { 98 | // Create the socket. 99 | auto sock = nng::rep::open(); 100 | 101 | std::unique_ptr works[PARALLEL]; 102 | for(int i=0;i(sock); 104 | } 105 | 106 | sock.listen(url); 107 | 108 | for(int i=0;i\n", argv[0]); 120 | return 1; 121 | } 122 | server(argv[1]); 123 | } 124 | catch( const nng::exception& e ) { 125 | fprintf(stderr, "%s: %s\n", e.who(), e.what()); 126 | return 1; 127 | } 128 | -------------------------------------------------------------------------------- /demo/http_client/http_client.cpp: -------------------------------------------------------------------------------- 1 | // This is a port of the nng demo to nngpp 2 | // See https://github.com/nanomsg/nng/tree/master/demo/http_client 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int main( int argc, char** argv ) try { 10 | if(argc < 2) { 11 | fprintf(stderr, "No URL supplied!\n"); 12 | return 1; 13 | } 14 | 15 | nng::url url( argv[1] ); 16 | nng::http::client client( url ); 17 | 18 | auto aio = nng::make_aio(); 19 | client.connect( aio ); 20 | 21 | aio.wait(); 22 | { 23 | auto result = aio.result(); 24 | if( result != nng::error::success ) { 25 | throw nng::exception(result); 26 | } 27 | } 28 | 29 | // Get the connection, at the 0th output. 30 | nng::http::conn_view conn = aio.get_output(0); 31 | 32 | // Request is already set up with URL, and for GET via HTTP/1.1. 33 | // The Host: header is already set up too. 34 | 35 | // Send the request, and wait for that to finish. 36 | nng::http::req req(url); 37 | conn.write(req,aio); 38 | aio.wait(); 39 | { 40 | auto result = aio.result(); 41 | if( result != nng::error::success ) { 42 | throw nng::exception(result); 43 | } 44 | } 45 | 46 | // Read a response. 47 | auto res = nng::http::make_res(); 48 | conn.read(res,aio); 49 | aio.wait(); 50 | { 51 | auto result = aio.result(); 52 | if( result != nng::error::success ) { 53 | throw nng::exception(result); 54 | } 55 | } 56 | 57 | if(res.get_status() != nng::http::status::ok) { 58 | fprintf(stderr, "HTTP Server Responded: %d %s\n", (int)res.get_status(), res.get_reason()); 59 | } 60 | 61 | // This only supports regular transfer encoding (no Chunked-Encoding, 62 | // and a Content-Length header is required.) 63 | auto hdr = res.get_header("Content-Length"); 64 | if(!hdr) { 65 | fprintf(stderr, "Missing Content-Length header.\n"); 66 | return 1; 67 | } 68 | 69 | auto len = atoi(hdr); 70 | if(len == 0) { 71 | return 0; 72 | } 73 | 74 | // Allocate a buffer to receive the body data. 75 | nng::buffer data(len); 76 | 77 | // Set up a single iov to point to the buffer. 78 | // Following never fails with fewer than 5 elements. 79 | aio.set_iov( data ); 80 | 81 | // Now attempt to receive the data. 82 | conn.read_all(aio); 83 | 84 | // Wait for it to complete. 85 | aio.wait(); 86 | { 87 | auto result = aio.result(); 88 | if( result != nng::error::success ) { 89 | throw nng::exception(result); 90 | } 91 | } 92 | 93 | fwrite(data.data(), 1, data.size(), stdout); 94 | } 95 | catch( const nng::exception& e ) { 96 | fprintf(stderr, "%s: %s\n", e.who(), e.what()); 97 | return 1; 98 | } 99 | -------------------------------------------------------------------------------- /demo/raw/raw.cpp: -------------------------------------------------------------------------------- 1 | // This is a port of the nng demo to nngpp 2 | // See https://github.com/nanomsg/nng/tree/master/demo/raw 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | // Parallel is the maximum number of outstanding requests we can handle. 14 | // This is *NOT* the number of threads in use, but instead represents 15 | // outstanding work items. Select a small number to reduce memory size. 16 | // (Each one of these can be thought of as a request-reply loop.) 17 | #ifndef PARALLEL 18 | #define PARALLEL 32 19 | #endif 20 | 21 | void server_cb(void* arg); 22 | 23 | // The server keeps a list of work items, sorted by expiration time, 24 | // so that we can use this to set the timeout to the correct value for 25 | // use in poll. 26 | struct work { 27 | enum { INIT, RECV, WAIT, SEND } state = INIT; 28 | nng::aio aio{ server_cb, this }; 29 | nng::socket_view sock; 30 | nng::msg msg; 31 | 32 | explicit work( nng::socket_view sock ) : sock(sock) {} 33 | }; 34 | 35 | void server_cb(void* arg) try { 36 | work* work = (struct work*)arg; 37 | uint32_t when; 38 | 39 | switch(work->state) { 40 | case work::INIT: 41 | work->state = work::RECV; 42 | work->sock.recv( work->aio ); 43 | break; 44 | case work::RECV: 45 | { 46 | auto result = work->aio.result(); 47 | if( result != nng::error::success ) { 48 | throw nng::exception(result); 49 | } 50 | } 51 | { 52 | auto msg = work->aio.release_msg(); 53 | try { 54 | when = msg.body().trim_u32(); 55 | } 56 | catch( const nng::exception& ) { 57 | // bad message, just ignore it. 58 | work->sock.recv( work->aio ); 59 | return; 60 | } 61 | 62 | work->msg = std::move(msg); 63 | } 64 | work->state = work::WAIT; 65 | nng::sleep( when, work->aio ); 66 | break; 67 | case work::WAIT: 68 | // We could add more data to the message here. 69 | work->aio.set_msg( std::move(work->msg) ); 70 | work->state = work::SEND; 71 | work->sock.send( work->aio ); 72 | break; 73 | case work::SEND: 74 | { 75 | auto result = work->aio.result(); 76 | if( result != nng::error::success ) { 77 | throw nng::exception(result); 78 | } 79 | } 80 | work->state = work::RECV; 81 | work->sock.recv( work->aio ); 82 | break; 83 | default: 84 | throw nng::exception(nng::error::state); 85 | break; 86 | } 87 | } 88 | catch( const nng::exception& e ) { 89 | fprintf(stderr, "server_cb: %s: %s\n", e.who(), e.what()); 90 | exit(1); 91 | } 92 | catch( ... ) { 93 | fprintf(stderr, "server_cb: unknown exception\n"); 94 | exit(1); 95 | } 96 | 97 | 98 | // The server runs forever. 99 | void server(const char* url) { 100 | 101 | // Create the socket. 102 | auto sock = nng::rep::open_raw(); 103 | 104 | std::unique_ptr works[PARALLEL]; 105 | for (int i=0;i(sock); 107 | } 108 | 109 | sock.listen(url); 110 | 111 | for(int i=0;i [-s|]\n", argv[0]); 142 | return 1; 143 | } 144 | if(strcmp(argv[2], "-s") == 0) { 145 | server(argv[1]); 146 | } 147 | else { 148 | client(argv[1], argv[2]); 149 | } 150 | } 151 | catch( const nng::exception& e ) { 152 | fprintf(stderr, "%s: %s\n", e.who(), e.what()); 153 | return 1; 154 | } 155 | 156 | -------------------------------------------------------------------------------- /demo/reqrep/reqrep.cpp: -------------------------------------------------------------------------------- 1 | // This is a port of the nng demo to nngpp 2 | // See https://github.com/nanomsg/nng/tree/master/demo/reqrep 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define CLIENT "client" 14 | #define SERVER "server" 15 | #define DATECMD 1 16 | 17 | #define PUT64(ptr, u) \ 18 | do { \ 19 | (ptr)[0] = (uint8_t)(((uint64_t)(u)) >> 56); \ 20 | (ptr)[1] = (uint8_t)(((uint64_t)(u)) >> 48); \ 21 | (ptr)[2] = (uint8_t)(((uint64_t)(u)) >> 40); \ 22 | (ptr)[3] = (uint8_t)(((uint64_t)(u)) >> 32); \ 23 | (ptr)[4] = (uint8_t)(((uint64_t)(u)) >> 24); \ 24 | (ptr)[5] = (uint8_t)(((uint64_t)(u)) >> 16); \ 25 | (ptr)[6] = (uint8_t)(((uint64_t)(u)) >> 8); \ 26 | (ptr)[7] = (uint8_t)((uint64_t)(u)); \ 27 | } while(0) 28 | 29 | #define GET64(ptr, v) \ 30 | v = (((uint64_t)((uint8_t)(ptr)[0])) << 56) + \ 31 | (((uint64_t)((uint8_t)(ptr)[1])) << 48) + \ 32 | (((uint64_t)((uint8_t)(ptr)[2])) << 40) + \ 33 | (((uint64_t)((uint8_t)(ptr)[3])) << 32) + \ 34 | (((uint64_t)((uint8_t)(ptr)[4])) << 24) + \ 35 | (((uint64_t)((uint8_t)(ptr)[5])) << 16) + \ 36 | (((uint64_t)((uint8_t)(ptr)[6])) << 8) + \ 37 | (((uint64_t)(uint8_t)(ptr)[7])) 38 | 39 | void showdate(time_t now) { 40 | printf("%s", asctime(localtime(&now))); 41 | } 42 | 43 | void server(const char* url) { 44 | auto sock = nng::rep::open(); 45 | sock.listen(url); 46 | while(true) { 47 | uint64_t val; 48 | auto buf = sock.recv(); 49 | if( buf.size() == sizeof(uint64_t) && ((GET64(buf.data(), val)) == DATECMD) ) { 50 | printf("SERVER: RECEIVED DATE REQUEST\n"); 51 | auto now = time(nullptr); 52 | printf("SERVER: SENDING DATE: "); 53 | showdate(now); 54 | 55 | // Reuse the buffer. We know it is big enough. 56 | PUT64(buf.data(), (uint64_t)now); 57 | sock.send( std::move(buf) ); 58 | } 59 | } 60 | } 61 | 62 | void client(const char* url) { 63 | auto sock = nng::req::open(); 64 | sock.dial(url); 65 | 66 | printf("CLIENT: SENDING DATE REQUEST\n"); 67 | 68 | uint8_t cmd[sizeof(uint64_t)]; 69 | PUT64(cmd,DATECMD); 70 | 71 | sock.send( cmd ); 72 | auto buf = sock.recv(); 73 | 74 | if(buf.size() == sizeof(uint64_t)) { 75 | uint64_t now; 76 | GET64(buf.data(), now); 77 | printf("CLIENT: RECEIVED DATE: "); 78 | showdate((time_t)now); 79 | } else { 80 | printf("CLIENT: GOT WRONG SIZE!\n"); 81 | } 82 | } 83 | 84 | int main( int argc, char** argv ) try { 85 | if(argc > 1 && strcmp(CLIENT, argv[1]) == 0) { 86 | client(argv[2]); 87 | return 0; 88 | } 89 | 90 | if(argc > 1 && strcmp(SERVER, argv[1]) == 0) { 91 | server(argv[2]); 92 | return 0; 93 | } 94 | 95 | fprintf(stderr, "Usage: reqrep %s|%s ...\n", CLIENT, SERVER); 96 | return 1; 97 | } 98 | catch( const nng::exception& e ) { 99 | fprintf(stderr, "%s: %s\n", e.who(), e.what()); 100 | return 1; 101 | } 102 | 103 | -------------------------------------------------------------------------------- /include/nngpp/aio.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_AIO_H 2 | #define NNGPP_AIO_H 3 | #include "aio_view.h" 4 | 5 | namespace nng { 6 | 7 | struct aio : aio_view { 8 | 9 | aio() = default; 10 | 11 | explicit aio( nng_aio* a ) noexcept : aio_view(a) {} 12 | 13 | explicit aio( void (*cb)(void*), void* arg ) { 14 | int r = nng_aio_alloc( &a, cb, arg ); 15 | if( r != 0 ) { 16 | throw exception(r,"nng_aio_alloc"); 17 | } 18 | } 19 | 20 | aio( const aio& rhs ) = delete; 21 | 22 | aio( aio&& rhs ) noexcept : aio_view(rhs.a) { 23 | rhs.a = nullptr; 24 | } 25 | 26 | aio& operator=( const aio& rhs ) = delete; 27 | 28 | aio& operator=( aio&& rhs ) noexcept { 29 | if( this != &rhs ) { 30 | if( a != nullptr ) nng_aio_free(a); 31 | a = rhs.a; 32 | rhs.a = nullptr; 33 | } 34 | return *this; 35 | } 36 | 37 | ~aio() { 38 | if( a != nullptr ) nng_aio_free(a); 39 | } 40 | 41 | nng_aio* release() noexcept { 42 | auto out = a; 43 | a = nullptr; 44 | return out; 45 | } 46 | 47 | }; 48 | 49 | inline aio make_aio( void (*cb)(void*), void* arg ) { 50 | return aio(cb,arg); 51 | } 52 | 53 | inline aio make_aio() { 54 | return aio(nullptr,nullptr); 55 | } 56 | 57 | } 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /include/nngpp/aio_view.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_AIO_VIEW_H 2 | #define NNGPP_AIO_VIEW_H 3 | #include "msg.h" 4 | 5 | namespace nng { 6 | 7 | struct aio_view { 8 | protected: 9 | nng_aio* a = nullptr; 10 | 11 | public: 12 | aio_view() = default; 13 | 14 | aio_view( nng_aio* a ) noexcept : a(a) {} 15 | 16 | nng_aio* get() const noexcept { 17 | return a; 18 | } 19 | 20 | nng_aio* operator->() const noexcept { 21 | return a; 22 | } 23 | 24 | explicit operator bool() const noexcept { 25 | return a != nullptr; 26 | } 27 | 28 | void stop() const noexcept { 29 | nng_aio_stop(a); 30 | } 31 | 32 | error result() const noexcept { 33 | return (error)nng_aio_result(a); 34 | } 35 | 36 | size_t count() const noexcept { 37 | return nng_aio_count(a); 38 | } 39 | 40 | void cancel() const noexcept { 41 | nng_aio_cancel(a); 42 | } 43 | 44 | void abort( int err_code ) const noexcept { 45 | nng_aio_abort(a,err_code); 46 | } 47 | 48 | void wait() const noexcept { 49 | nng_aio_wait(a); 50 | } 51 | 52 | void set_msg( msg_view m ) const noexcept { 53 | nng_aio_set_msg(a,m.get()); 54 | } 55 | 56 | void set_msg( msg&& m ) const noexcept { 57 | set_msg(m.release()); 58 | } 59 | 60 | msg_view get_msg() const noexcept { 61 | return nng_aio_get_msg(a); 62 | } 63 | 64 | msg release_msg() const noexcept { 65 | auto m = nng_aio_get_msg(a); 66 | nng_aio_set_msg(a,nullptr); 67 | return msg(m); 68 | } 69 | 70 | template 71 | void set_input( unsigned int index, T* arg ) const { 72 | int r = nng_aio_set_input(a,index,(void*)arg); 73 | if( r != 0 ) { 74 | throw exception(r,"nng_aio_set_input"); 75 | } 76 | } 77 | 78 | template 79 | T* get_input( unsigned int index ) const noexcept { 80 | return (T*)nng_aio_get_input(a,index); 81 | } 82 | 83 | template 84 | void set_output( unsigned int index, T* arg ) const { 85 | int r = nng_aio_set_output(a,index,(void*)arg); 86 | if( r != 0 ) { 87 | throw exception(r,"nng_aio_set_output"); 88 | } 89 | } 90 | 91 | template 92 | T* get_output( unsigned int index ) const noexcept { 93 | return (T*)nng_aio_get_output(a,index); 94 | } 95 | 96 | void set_timeout( nng_duration when ) const noexcept { 97 | nng_aio_set_timeout(a,when); 98 | } 99 | 100 | void set_iov( unsigned int niov, const nng_iov* iov ) const { 101 | int r = nng_aio_set_iov(a,niov,iov); 102 | if( r != 0 ) { 103 | throw exception(r,"nng_aio_set_iov"); 104 | } 105 | } 106 | 107 | void set_iov( const nng_iov& iov ) const { 108 | set_iov(1,&iov); 109 | } 110 | 111 | bool begin() const noexcept { 112 | return nng_aio_begin(a); 113 | } 114 | 115 | void finish( error e = error::success ) const noexcept { 116 | nng_aio_finish(a,(int)e); 117 | } 118 | 119 | void defer( nng_aio_cancelfn fn, void* arg ) const noexcept { 120 | nng_aio_defer(a,fn,arg); 121 | } 122 | 123 | }; 124 | 125 | inline void sleep( nng_duration ms, aio_view a ) noexcept { 126 | nng_sleep_aio(ms,a.get()); 127 | } 128 | 129 | } 130 | 131 | #endif 132 | -------------------------------------------------------------------------------- /include/nngpp/buffer.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_BUFFER_H 2 | #define NNGPP_BUFFER_H 3 | #include "view.h" 4 | 5 | namespace nng { 6 | 7 | struct buffer : view { 8 | 9 | buffer() = default; 10 | 11 | template 12 | explicit buffer( T* d, size_t s ) noexcept : view((pointer)d,s) {} 13 | 14 | explicit buffer( size_t sz ) : view(nng_alloc(sz),sz) { 15 | if( d == nullptr ) { 16 | s = 0; 17 | throw exception(NNG_ENOMEM,"nng_alloc"); 18 | } 19 | } 20 | 21 | buffer( const buffer& rhs ) : buffer(rhs.s) { 22 | memcpy(d,rhs.d,s); 23 | } 24 | 25 | buffer( buffer&& rhs ) noexcept : view(rhs.d,rhs.s) { 26 | rhs.d = nullptr; 27 | rhs.s = 0; 28 | } 29 | 30 | buffer& operator=( const buffer& rhs ) { 31 | if( this != &rhs ) { 32 | if( s != rhs.s ) { 33 | if( d != nullptr ) nng_free(d,s); 34 | d = nng_alloc(rhs.s); 35 | s = rhs.s; 36 | if( d == nullptr ) { 37 | s = 0; 38 | throw exception(NNG_ENOMEM,"nng_alloc"); 39 | } 40 | } 41 | memcpy(d,rhs.d,s); 42 | } 43 | return *this; 44 | } 45 | 46 | buffer& operator=( buffer&& rhs ) noexcept { 47 | if( this != &rhs ) { 48 | if( d != nullptr ) nng_free(d,s); 49 | d = rhs.d; 50 | s = rhs.s; 51 | rhs.d = nullptr; 52 | rhs.s = 0; 53 | } 54 | return *this; 55 | } 56 | 57 | ~buffer() { 58 | if( d != nullptr ) nng_free(d,s); 59 | } 60 | 61 | pointer release() noexcept { 62 | auto out = d; 63 | d = nullptr; 64 | s = 0; 65 | return out; 66 | } 67 | 68 | }; 69 | 70 | inline buffer make_buffer( size_t sz ) { 71 | return buffer(sz); 72 | } 73 | 74 | } 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /include/nngpp/core.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_CORE_H 2 | #define NNGPP_CORE_H 3 | #include 4 | 5 | namespace nng { 6 | 7 | enum class sockaddr_family { 8 | unspec = NNG_AF_UNSPEC, 9 | inproc = NNG_AF_INPROC, 10 | ipc = NNG_AF_IPC, 11 | inet = NNG_AF_INET, 12 | inet6 = NNG_AF_INET6, 13 | zt = NNG_AF_ZT 14 | }; 15 | 16 | enum class pipe_ev { 17 | add_pre = NNG_PIPE_EV_ADD_PRE, 18 | add_post = NNG_PIPE_EV_ADD_POST, 19 | rem_post = NNG_PIPE_EV_REM_POST, 20 | num = NNG_PIPE_EV_NUM 21 | }; 22 | 23 | namespace flag { 24 | enum { 25 | alloc = NNG_FLAG_ALLOC, 26 | nonblock = NNG_FLAG_NONBLOCK 27 | }; 28 | } 29 | 30 | inline const char* version() noexcept { 31 | return nng_version(); 32 | } 33 | 34 | inline void fini() noexcept { 35 | nng_fini(); 36 | } 37 | 38 | inline void close_all() noexcept { 39 | nng_closeall(); 40 | } 41 | 42 | } 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /include/nngpp/ctx.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_CTX_H 2 | #define NNGPP_CTX_H 3 | #include "ctx_view.h" 4 | #include "socket_view.h" 5 | 6 | namespace nng { 7 | 8 | struct ctx : ctx_view { 9 | 10 | ctx() = default; 11 | 12 | explicit ctx( nng_ctx c ) noexcept : ctx_view(c) {} 13 | 14 | explicit ctx( socket_view s ) { 15 | int r = nng_ctx_open( &c, s.get() ); 16 | if( r != 0 ) { 17 | throw exception(r,"nng_ctx_open"); 18 | } 19 | } 20 | 21 | ctx( const ctx& rhs ) = delete; 22 | 23 | ctx( ctx&& rhs ) noexcept : ctx_view(rhs.c) { 24 | rhs.c.id = 0; 25 | } 26 | 27 | ctx& operator=( const ctx& rhs ) = delete; 28 | 29 | ctx& operator=( ctx&& rhs ) { 30 | if( this != &rhs ) { 31 | if( c.id != 0 ) { 32 | int r = nng_ctx_close(c); 33 | if( r != 0 && r != (int)nng::error::closed ) { 34 | throw exception(r,"nng_ctx_close"); 35 | } 36 | } 37 | c = rhs.c; 38 | rhs.c.id = 0; 39 | } 40 | return *this; 41 | } 42 | 43 | ~ctx() { 44 | if( c.id != 0 ) nng_ctx_close(c); 45 | } 46 | 47 | nng_ctx release() noexcept { 48 | auto out = c; 49 | c.id = 0; 50 | return out; 51 | } 52 | 53 | }; 54 | 55 | inline ctx make_ctx( socket_view s ) { 56 | return ctx(s); 57 | } 58 | 59 | } 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /include/nngpp/ctx_view.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_CTX_VIEW_H 2 | #define NNGPP_CTX_VIEW_H 3 | #include "aio_view.h" 4 | 5 | namespace nng { 6 | 7 | struct ctx_view { 8 | protected: 9 | nng_ctx c{0}; 10 | 11 | public: 12 | ctx_view() = default; 13 | 14 | ctx_view( nng_ctx c ) noexcept : c(c) {} 15 | 16 | nng_ctx get() const noexcept { 17 | return c; 18 | } 19 | 20 | explicit operator bool() const noexcept { 21 | return c.id != 0; 22 | } 23 | 24 | int id() const noexcept { 25 | return nng_ctx_id(c); 26 | } 27 | 28 | void send( aio_view a ) const noexcept { 29 | nng_ctx_send(c,a.get()); 30 | } 31 | 32 | void recv( aio_view a ) const noexcept { 33 | nng_ctx_recv(c,a.get()); 34 | } 35 | 36 | void set_opt( const char* name, view v ) const { 37 | int r = nng_ctx_set(c,name,v.data(),v.size()); 38 | if( r != 0 ) { 39 | throw exception(r,"nng_ctx_set"); 40 | } 41 | } 42 | 43 | void set_opt_bool( const char* name, bool value ) const { 44 | int r = nng_ctx_set_bool(c,name,value); 45 | if( r != 0 ) { 46 | throw exception(r,"nng_ctx_set_bool"); 47 | } 48 | } 49 | 50 | void set_opt_int( const char* name, int value ) const { 51 | int r = nng_ctx_set_int(c,name,value); 52 | if( r != 0 ) { 53 | throw exception(r,"nng_ctx_set_int"); 54 | } 55 | } 56 | 57 | void set_opt_size( const char* name, size_t value ) const { 58 | int r = nng_ctx_set_size(c,name,value); 59 | if( r != 0 ) { 60 | throw exception(r,"nng_ctx_set_size"); 61 | } 62 | } 63 | 64 | void set_opt_uint64( const char* name, uint64_t value ) const { 65 | int r = nng_ctx_set_uint64(c,name,value); 66 | if( r != 0 ) { 67 | throw exception(r,"nng_ctx_set_uint64"); 68 | } 69 | } 70 | 71 | void set_opt_string( const char* name, const char* value ) const { 72 | int r = nng_ctx_set_string(c,name,value); 73 | if( r != 0 ) { 74 | throw exception(r,"nng_ctx_set_string"); 75 | } 76 | } 77 | 78 | void set_opt_ptr( const char* name, void* value ) const { 79 | int r = nng_ctx_set_ptr(c,name,value); 80 | if( r != 0 ) { 81 | throw exception(r,"nng_ctx_set_ptr"); 82 | } 83 | } 84 | 85 | void set_opt_ms( const char* name, nng_duration value ) const { 86 | int r = nng_ctx_set_ms(c,name,value); 87 | if( r != 0 ) { 88 | throw exception(r,"nng_ctx_set_ms"); 89 | } 90 | } 91 | 92 | void set_opt_addr( const char* name, const nng_sockaddr* value ) const { 93 | int r = nng_ctx_set_addr(c,name,value); 94 | if( r != 0 ) { 95 | throw exception(r,"nng_ctx_set_addr"); 96 | } 97 | } 98 | 99 | size_t get_opt( const char* name, buffer& out ) const { 100 | size_t size = out.size(); 101 | int r = nng_ctx_get(c,name,out.data(),&size); 102 | if( r != 0 ) { 103 | throw exception(r,"nng_ctx_get"); 104 | } 105 | return size; 106 | } 107 | 108 | bool get_opt_bool( const char* name ) const { 109 | bool out; 110 | int r = nng_ctx_get_bool(c,name,&out); 111 | if( r != 0 ) { 112 | throw exception(r,"nng_ctx_get_bool"); 113 | } 114 | return out; 115 | } 116 | 117 | int get_opt_int( const char* name ) const { 118 | int out; 119 | int r = nng_ctx_get_int(c,name,&out); 120 | if( r != 0 ) { 121 | throw exception(r,"nng_ctx_get_int"); 122 | } 123 | return out; 124 | } 125 | 126 | size_t get_opt_size( const char* name ) const { 127 | size_t out; 128 | int r = nng_ctx_get_size(c,name,&out); 129 | if( r != 0 ) { 130 | throw exception(r,"nng_ctx_get_size"); 131 | } 132 | return out; 133 | } 134 | 135 | uint64_t get_opt_uint64( const char* name ) const { 136 | uint64_t out; 137 | int r = nng_ctx_get_uint64(c,name,&out); 138 | if( r != 0 ) { 139 | throw exception(r,"nng_ctx_get_uint64"); 140 | } 141 | return out; 142 | } 143 | 144 | buffer get_opt_string( const char* name ) const { 145 | char* out; 146 | int r = nng_ctx_get_string(c,name,&out); 147 | if( r != 0 ) { 148 | throw exception(r,"nng_ctx_get_string"); 149 | } 150 | return buffer(out, strlen(out) + 1); 151 | } 152 | 153 | void* get_opt_ptr( const char* name ) const { 154 | void* out; 155 | int r = nng_ctx_get_ptr(c,name,&out); 156 | if( r != 0 ) { 157 | throw exception(r,"nng_ctx_get_ptr"); 158 | } 159 | return out; 160 | } 161 | 162 | nng_duration get_opt_ms( const char* name ) const { 163 | nng_duration out; 164 | int r = nng_ctx_get_ms(c,name,&out); 165 | if( r != 0 ) { 166 | throw exception(r,"nng_ctx_get_ms"); 167 | } 168 | return out; 169 | } 170 | 171 | nng_sockaddr get_opt_addr( const char* name ) const { 172 | nng_sockaddr out; 173 | int r = nng_ctx_get_addr(c,name,&out); 174 | if( r != 0 ) { 175 | throw exception(r,"nng_ctx_get_addr"); 176 | } 177 | return out; 178 | } 179 | 180 | }; 181 | 182 | inline nng_duration get_opt_recv_timeout( ctx_view s ) { 183 | return s.get_opt_ms( to_name(option::recv_timeout) ); 184 | } 185 | 186 | inline nng_duration get_opt_send_timeout( ctx_view s ) { 187 | return s.get_opt_ms( to_name(option::send_timeout) ); 188 | } 189 | 190 | inline void set_opt_recv_timeout( ctx_view s, nng_duration v ) { 191 | s.set_opt_ms( to_name(option::recv_timeout), v ); 192 | } 193 | 194 | inline void set_opt_send_timeout( ctx_view s, nng_duration v ) { 195 | s.set_opt_ms( to_name(option::send_timeout), v ); 196 | } 197 | 198 | } 199 | 200 | #endif 201 | -------------------------------------------------------------------------------- /include/nngpp/dialer.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_DIALER_H 2 | #define NNGPP_DIALER_H 3 | #include "dialer_view.h" 4 | #include "socket_view.h" 5 | 6 | namespace nng { 7 | 8 | struct dialer : dialer_view { 9 | 10 | dialer() = default; 11 | 12 | explicit dialer( nng_dialer d ) noexcept : dialer_view(d) {} 13 | 14 | explicit dialer( socket_view s, const char* addr, int flags ) { 15 | int r = nng_dial( s.get(), addr, &d, flags ); 16 | if( r != 0 ) { 17 | throw exception(r,"nng_dial"); 18 | } 19 | } 20 | 21 | explicit dialer( socket_view s, const char* addr ) { 22 | int r = nng_dialer_create( &d, s.get(), addr ); 23 | if( r != 0 ) { 24 | throw exception(r,"nng_dialer_create"); 25 | } 26 | } 27 | 28 | dialer( const dialer& rhs ) = delete; 29 | 30 | dialer( dialer&& rhs ) noexcept : dialer_view(rhs.d) { 31 | rhs.d.id = 0; 32 | } 33 | 34 | dialer& operator=( const dialer& rhs ) = delete; 35 | 36 | dialer& operator=( dialer&& rhs ) { 37 | if( this != &rhs ) { 38 | if( d.id != 0 ) { 39 | int r = nng_dialer_close(d); 40 | if( r != 0 && r != (int)nng::error::closed ) { 41 | throw exception(r,"nng_dialer_close"); 42 | } 43 | } 44 | d = rhs.d; 45 | rhs.d.id = 0; 46 | } 47 | return *this; 48 | } 49 | 50 | ~dialer() { 51 | if( d.id != 0 ) nng_dialer_close(d); 52 | } 53 | 54 | nng_dialer release() noexcept { 55 | auto out = d; 56 | d.id = 0; 57 | return out; 58 | } 59 | 60 | }; 61 | 62 | inline dialer make_dialer( socket_view s, const char* addr, int flags ) { 63 | return dialer(s,addr,flags); 64 | } 65 | 66 | inline dialer make_dialer( socket_view s, const char* addr ) { 67 | return dialer(s,addr); 68 | } 69 | 70 | } 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /include/nngpp/dialer_view.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_DIALER_VIEW_H 2 | #define NNGPP_DIALER_VIEW_H 3 | #include "option.h" 4 | #include "buffer.h" 5 | 6 | namespace nng { 7 | 8 | struct dialer_view { 9 | protected: 10 | nng_dialer d{0}; 11 | 12 | public: 13 | 14 | dialer_view() = default; 15 | 16 | dialer_view( nng_dialer d ) noexcept : d(d) {} 17 | 18 | nng_dialer get() const noexcept { 19 | return d; 20 | } 21 | 22 | explicit operator bool() const noexcept { 23 | return d.id != 0; 24 | } 25 | 26 | void start( int flags = 0 ) const { 27 | int r = nng_dialer_start(d,flags); 28 | if( r != 0 ) { 29 | throw exception(r,"nng_dialer_start"); 30 | } 31 | } 32 | 33 | int id() const noexcept { 34 | return nng_dialer_id(d); 35 | } 36 | 37 | void set_opt( const char* name, view v ) const { 38 | int r = nng_dialer_set(d,name,v.data(),v.size()); 39 | if( r != 0 ) { 40 | throw exception(r,"nng_dialer_set"); 41 | } 42 | } 43 | 44 | void set_opt_bool( const char* name, bool val ) const { 45 | int r = nng_dialer_set_bool(d,name,val); 46 | if( r != 0 ) { 47 | throw exception(r,"nng_dialer_set_bool"); 48 | } 49 | } 50 | 51 | void set_opt_int( const char* name, int val ) const { 52 | int r = nng_dialer_set_int(d,name,val); 53 | if( r != 0 ) { 54 | throw exception(r,"nng_dialer_set_int"); 55 | } 56 | } 57 | 58 | void set_opt_size( const char* name, size_t val ) const { 59 | int r = nng_dialer_set_size(d,name,val); 60 | if( r != 0 ) { 61 | throw exception(r,"nng_dialer_set_size"); 62 | } 63 | } 64 | 65 | void set_opt_uint64( const char* name, uint64_t val ) const { 66 | int r = nng_dialer_set_uint64(d,name,val); 67 | if( r != 0 ) { 68 | throw exception(r,"nng_dialer_set_uint64"); 69 | } 70 | } 71 | 72 | void set_opt_string( const char* name, const char* val ) const { 73 | int r = nng_dialer_set_string(d,name,val); 74 | if( r != 0 ) { 75 | throw exception(r,"nng_dialer_set_string"); 76 | } 77 | } 78 | 79 | void set_opt_ptr( const char* name, void* val ) const { 80 | int r = nng_dialer_set_ptr(d,name,val); 81 | if( r != 0 ) { 82 | throw exception(r,"nng_dialer_set_ptr"); 83 | } 84 | } 85 | 86 | void set_opt_ms( const char* name, nng_duration val ) const { 87 | int r = nng_dialer_set_ms(d,name,val); 88 | if( r != 0 ) { 89 | throw exception(r,"nng_dialer_set_ms"); 90 | } 91 | } 92 | 93 | void set_opt_addr( const char* name, const nng_sockaddr* val ) const { 94 | int r = nng_dialer_set_addr(d,name,val); 95 | if( r != 0 ) { 96 | throw exception(r,"nng_dialer_set_addr"); 97 | } 98 | } 99 | 100 | size_t get_opt( const char* name, buffer& out ) const { 101 | size_t size = out.size(); 102 | int r = nng_dialer_get(d,name,out.data(),&size); 103 | if( r != 0 ) { 104 | throw exception(r,"nng_dialer_get"); 105 | } 106 | return size; 107 | } 108 | 109 | bool get_opt_bool( const char* name ) const { 110 | bool out; 111 | int r = nng_dialer_get_bool(d,name,&out); 112 | if( r != 0 ) { 113 | throw exception(r,"nng_dialer_get_bool"); 114 | } 115 | return out; 116 | } 117 | 118 | int get_opt_int( const char* name ) const { 119 | int out; 120 | int r = nng_dialer_get_int(d,name,&out); 121 | if( r != 0 ) { 122 | throw exception(r,"nng_dialer_get_int"); 123 | } 124 | return out; 125 | } 126 | 127 | size_t get_opt_size( const char* name ) const { 128 | size_t out; 129 | int r = nng_dialer_get_size(d,name,&out); 130 | if( r != 0 ) { 131 | throw exception(r,"nng_dialer_get_size"); 132 | } 133 | return out; 134 | } 135 | 136 | uint64_t get_opt_uint64( const char* name ) const { 137 | uint64_t out; 138 | int r = nng_dialer_get_uint64(d,name,&out); 139 | if( r != 0 ) { 140 | throw exception(r,"nng_dialer_get_uint64"); 141 | } 142 | return out; 143 | } 144 | 145 | buffer get_opt_string( const char* name ) const { 146 | char* data; 147 | int r = nng_dialer_get_string(d,name,&data); 148 | if( r != 0 ) { 149 | throw exception(r,"nng_dialer_get_string"); 150 | } 151 | return buffer(data,strlen(data)+1); 152 | } 153 | 154 | void* get_opt_ptr( const char* name ) const { 155 | void* out; 156 | int r = nng_dialer_get_ptr(d,name,&out); 157 | if( r != 0 ) { 158 | throw exception(r,"nng_dialer_get_ptr"); 159 | } 160 | return out; 161 | } 162 | 163 | nng_duration get_opt_ms( const char* name ) const { 164 | nng_duration out; 165 | int r = nng_dialer_get_ms(d,name,&out); 166 | if( r != 0 ) { 167 | throw exception(r,"nng_dialer_get_ms"); 168 | } 169 | return out; 170 | } 171 | 172 | nng_sockaddr get_opt_addr( const char* name ) const { 173 | nng_sockaddr out; 174 | int r = nng_dialer_get_addr(d,name,&out); 175 | if( r != 0 ) { 176 | throw exception(r,"nng_dialer_get_addr"); 177 | } 178 | return out; 179 | } 180 | 181 | }; 182 | 183 | inline buffer get_opt_url( dialer_view s ) { 184 | return s.get_opt_string( to_name(option::url) ); 185 | } 186 | 187 | inline size_t get_opt_recv_size_max( dialer_view s ) { 188 | return s.get_opt_size( to_name(option::recv_size_max) ); 189 | } 190 | 191 | inline nng_duration get_opt_reconnect_time_min( dialer_view s ) { 192 | return s.get_opt_ms( to_name(option::reconnect_time_min) ); 193 | } 194 | 195 | inline nng_duration get_opt_reconnect_time_max( dialer_view s ) { 196 | return s.get_opt_ms( to_name(option::reconnect_time_max) ); 197 | } 198 | 199 | inline void set_opt_recv_size_max( dialer_view s, size_t v ) { 200 | s.set_opt_size( to_name(option::recv_size_max), v ); 201 | } 202 | 203 | inline void set_opt_reconnect_time_min( dialer_view s, nng_duration v ) { 204 | s.set_opt_ms( to_name(option::reconnect_time_min), v ); 205 | } 206 | 207 | inline void set_opt_reconnect_time_max( dialer_view s, nng_duration v ) { 208 | s.set_opt_ms( to_name(option::reconnect_time_max), v ); 209 | } 210 | 211 | } 212 | 213 | #endif 214 | -------------------------------------------------------------------------------- /include/nngpp/error.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_ERROR_H 2 | #define NNGPP_ERROR_H 3 | #include 4 | #include 5 | 6 | namespace nng { 7 | 8 | enum class error { 9 | success = 0, 10 | intr = NNG_EINTR, 11 | nomem = NNG_ENOMEM, 12 | inval = NNG_EINVAL, 13 | busy = NNG_EBUSY, 14 | timedout = NNG_ETIMEDOUT, 15 | connrefused = NNG_ECONNREFUSED, 16 | closed = NNG_ECLOSED, 17 | again = NNG_EAGAIN, 18 | notsup = NNG_ENOTSUP, 19 | addrinuse = NNG_EADDRINUSE, 20 | state = NNG_ESTATE, 21 | noent = NNG_ENOENT, 22 | proto = NNG_EPROTO, 23 | unreachable = NNG_EUNREACHABLE, 24 | addrinval = NNG_EADDRINVAL, 25 | perm = NNG_EPERM, 26 | msgsize = NNG_EMSGSIZE, 27 | connaborted = NNG_ECONNABORTED, 28 | connreset = NNG_ECONNRESET, 29 | canceled = NNG_ECANCELED, 30 | nofiles = NNG_ENOFILES, 31 | nospc = NNG_ENOSPC, 32 | exist = NNG_EEXIST, 33 | readonly = NNG_EREADONLY, 34 | writeonly = NNG_EWRITEONLY, 35 | crypto = NNG_ECRYPTO, 36 | peerauth = NNG_EPEERAUTH, 37 | noarg = NNG_ENOARG, 38 | ambiguous = NNG_EAMBIGUOUS, 39 | badtype = NNG_EBADTYPE, 40 | connshut = NNG_ECONNSHUT, 41 | internal = NNG_EINTERNAL, 42 | syserr = NNG_ESYSERR, 43 | tranerr = NNG_ETRANERR 44 | }; 45 | 46 | inline const char* to_string( error e ) noexcept { 47 | return nng_strerror( (int)e ); 48 | } 49 | 50 | class exception : public std::exception { 51 | const char* source; 52 | int err; 53 | public: 54 | 55 | explicit exception( int e, const char* s = "" ) noexcept : source(s), err(e) {} 56 | 57 | explicit exception( error e, const char* s = "" ) noexcept : exception((int)e,s) {} 58 | 59 | error get_error() const noexcept { 60 | return (error)err; 61 | } 62 | 63 | const char* who() const noexcept { 64 | return source; 65 | } 66 | 67 | const char* what() const noexcept final { 68 | return nng_strerror(err); 69 | } 70 | }; 71 | 72 | } 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /include/nngpp/http/client.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_HTTP_CLIENT_H 2 | #define NNGPP_HTTP_CLIENT_H 3 | #include "client_view.h" 4 | #include 5 | 6 | namespace nng { namespace http { 7 | 8 | struct client : client_view { 9 | 10 | client() = default; 11 | 12 | explicit client( nng_http_client* c ) noexcept : client_view(c) {} 13 | 14 | explicit client( url_view u ) { 15 | int r = nng_http_client_alloc( &c, u.get() ); 16 | if( r != 0 ) { 17 | throw exception(r,"nng_http_client_alloc"); 18 | } 19 | } 20 | 21 | client( const client& rhs ) = delete; 22 | 23 | client( client&& rhs ) noexcept : client_view(rhs.c) { 24 | rhs.c = nullptr; 25 | } 26 | 27 | client& operator=( const client& rhs ) = delete; 28 | 29 | client& operator=( client&& rhs ) noexcept { 30 | if( this != &rhs ) { 31 | if( c != nullptr ) nng_http_client_free(c); 32 | c = rhs.c; 33 | rhs.c = nullptr; 34 | } 35 | return *this; 36 | } 37 | 38 | ~client() { 39 | if( c != nullptr ) nng_http_client_free(c); 40 | } 41 | 42 | nng_http_client* release() noexcept { 43 | auto out = c; 44 | c = nullptr; 45 | return out; 46 | } 47 | 48 | }; 49 | 50 | inline client make_client( url_view u ) { 51 | return client(u); 52 | } 53 | 54 | }} 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /include/nngpp/http/client_view.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_HTTP_CLIENT_VIEW_H 2 | #define NNGPP_HTTP_CLIENT_VIEW_H 3 | #include 4 | #include 5 | #include "req_view.h" 6 | #include "res_view.h" 7 | 8 | namespace nng { namespace http { 9 | 10 | struct client_view { 11 | protected: 12 | nng_http_client* c = nullptr; 13 | 14 | public: 15 | client_view() = default; 16 | 17 | client_view( nng_http_client* c ) noexcept : c(c) {} 18 | 19 | nng_http_client* get() const noexcept { 20 | return c; 21 | } 22 | 23 | nng_http_client* operator->() const noexcept { 24 | return c; 25 | } 26 | 27 | explicit operator bool() const noexcept { 28 | return c != nullptr; 29 | } 30 | 31 | tls::config_view get_tls() const { 32 | nng_tls_config* cfg; 33 | int r = nng_http_client_get_tls(c,&cfg); 34 | if( r != 0 ) { 35 | throw exception(r,"nng_http_client_get_tls"); 36 | } 37 | return cfg; 38 | } 39 | 40 | void set_tls( tls::config_view cfg ) const { 41 | int r = nng_http_client_set_tls(c,cfg.get()); 42 | if( r != 0 ) { 43 | throw exception(r,"nng_http_client_set_tls"); 44 | } 45 | } 46 | 47 | void connect( aio_view a ) const noexcept { 48 | nng_http_client_connect(c,a.get()); 49 | } 50 | 51 | void transact( req_view q, res_view s, aio_view a ) const noexcept { 52 | nng_http_client_transact(c,q.get(),s.get(),a.get()); 53 | } 54 | }; 55 | 56 | }} 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /include/nngpp/http/conn.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_HTTP_CONN_H 2 | #define NNGPP_HTTP_CONN_H 3 | #include "conn_view.h" 4 | 5 | namespace nng { namespace http { 6 | 7 | struct conn : conn_view { 8 | 9 | conn() = default; 10 | 11 | explicit conn( nng_http_conn* n ) noexcept : conn_view(n) {} 12 | 13 | conn( const conn& rhs ) = delete; 14 | 15 | conn( conn&& rhs ) noexcept : conn_view(rhs.n) { 16 | rhs.n = nullptr; 17 | } 18 | 19 | conn& operator=( const conn& rhs ) = delete; 20 | 21 | conn& operator=( conn&& rhs ) noexcept { 22 | if( this != &rhs ) { 23 | if( n != nullptr ) nng_http_conn_close(n); 24 | n = rhs.n; 25 | rhs.n = nullptr; 26 | } 27 | return *this; 28 | } 29 | 30 | ~conn() { 31 | if( n != nullptr ) nng_http_conn_close(n); 32 | } 33 | 34 | nng_http_conn* release() noexcept { 35 | auto out = n; 36 | n = nullptr; 37 | return out; 38 | } 39 | 40 | }; 41 | 42 | }} 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /include/nngpp/http/conn_view.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_HTTP_CONN_VIEW_H 2 | #define NNGPP_HTTP_CONN_VIEW_H 3 | #include 4 | #include "req_view.h" 5 | #include "res_view.h" 6 | 7 | namespace nng { namespace http { 8 | 9 | struct conn_view { 10 | protected: 11 | nng_http_conn* n = nullptr; 12 | 13 | public: 14 | conn_view() = default; 15 | 16 | conn_view( nng_http_conn* n ) noexcept : n(n) {} 17 | 18 | nng_http_conn* get() const noexcept { 19 | return n; 20 | } 21 | 22 | nng_http_conn* operator->() const noexcept { 23 | return n; 24 | } 25 | 26 | explicit operator bool() const noexcept { 27 | return n != nullptr; 28 | } 29 | 30 | void read( aio_view a ) const noexcept { 31 | nng_http_conn_read(n,a.get()); 32 | } 33 | 34 | void read_all( aio_view a ) const noexcept { 35 | nng_http_conn_read_all(n,a.get()); 36 | } 37 | 38 | void read( req_view q, aio_view a ) const noexcept { 39 | nng_http_conn_read_req(n,q.get(),a.get()); 40 | } 41 | 42 | void read( res_view s, aio_view a ) const noexcept { 43 | nng_http_conn_read_res(n,s.get(),a.get()); 44 | } 45 | 46 | void write( aio_view a ) const noexcept { 47 | nng_http_conn_write(n,a.get()); 48 | } 49 | 50 | void write_all( aio_view a ) const noexcept { 51 | nng_http_conn_write_all(n,a.get()); 52 | } 53 | 54 | void write( req_view q, aio_view a ) const noexcept { 55 | nng_http_conn_write_req(n,q.get(),a.get()); 56 | } 57 | 58 | void write( res_view s, aio_view a ) const noexcept { 59 | nng_http_conn_write_res(n,s.get(),a.get()); 60 | } 61 | 62 | void hijack() const { 63 | int r = nng_http_hijack(n); 64 | if( r != 0 ) { 65 | throw exception(r,"nng_http_hijack"); 66 | } 67 | } 68 | 69 | void transact( req_view q, res_view s, aio_view a ) const noexcept { 70 | nng_http_conn_transact(n,q.get(),s.get(),a.get()); 71 | } 72 | }; 73 | 74 | }} 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /include/nngpp/http/handler.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_HTTP_HANDLER_H 2 | #define NNGPP_HTTP_HANDLER_H 3 | #include "handler_view.h" 4 | 5 | namespace nng { namespace http { 6 | 7 | struct path_type_file {}; 8 | struct path_type_dir {}; 9 | 10 | struct handler : handler_view { 11 | 12 | handler() = default; 13 | 14 | explicit handler( nng_http_handler* h ) noexcept : handler_view(h) {} 15 | 16 | explicit handler( const char* uri, void (*cb)(nng_aio*) ) { 17 | int r = nng_http_handler_alloc( &h, uri, cb ); 18 | if( r != 0 ) { 19 | throw exception(r,"nng_http_handler_alloc"); 20 | } 21 | } 22 | 23 | explicit handler( const char* uri, const char* path, path_type_file ) { 24 | int r = nng_http_handler_alloc_file( &h, uri, path ); 25 | if( r != 0 ) { 26 | throw exception(r,"nng_http_handler_alloc_file"); 27 | } 28 | } 29 | 30 | explicit handler( const char* uri, const char* path, path_type_dir ) { 31 | int r = nng_http_handler_alloc_directory( &h, uri, path ); 32 | if( r != 0 ) { 33 | throw exception(r,"nng_http_handler_alloc_directory"); 34 | } 35 | } 36 | 37 | explicit handler( const char* uri, const void* data, size_t size, const char* ctype ) { 38 | int r = nng_http_handler_alloc_static( &h, uri, data, size, ctype ); 39 | if( r != 0 ) { 40 | throw exception(r,"nng_http_handler_alloc_static"); 41 | } 42 | } 43 | 44 | handler( const handler& rhs ) = delete; 45 | 46 | handler( handler&& rhs ) noexcept : handler_view(rhs.h) { 47 | rhs.h = nullptr; 48 | } 49 | 50 | handler& operator=( const handler& rhs ) = delete; 51 | 52 | handler& operator=( handler&& rhs ) noexcept { 53 | if( this != &rhs ) { 54 | if( h != nullptr ) nng_http_handler_free(h); 55 | h = rhs.h; 56 | rhs.h = nullptr; 57 | } 58 | return *this; 59 | } 60 | 61 | ~handler() { 62 | if( h != nullptr ) nng_http_handler_free(h); 63 | } 64 | 65 | nng_http_handler* release() noexcept { 66 | auto out = h; 67 | h = nullptr; 68 | return out; 69 | } 70 | 71 | }; 72 | 73 | inline handler make_handler( const char* uri, void (*cb)(nng_aio*) ) { 74 | return handler(uri,cb); 75 | } 76 | 77 | inline handler make_handler( const char* uri, const char* path, path_type_file path_type ) { 78 | return handler(uri,path,path_type); 79 | } 80 | 81 | inline handler make_handler( const char* uri, const char* path, path_type_dir path_type ) { 82 | return handler(uri,path,path_type); 83 | } 84 | 85 | inline handler make_handler( const char* uri, const void* data, size_t size, const char* ctype ) { 86 | return handler(uri,data,size,ctype); 87 | } 88 | 89 | }} 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /include/nngpp/http/handler_view.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_HTTP_HANDLER_VIEW_H 2 | #define NNGPP_HTTP_HANDLER_VIEW_H 3 | #include 4 | #include "misc.h" 5 | 6 | namespace nng { namespace http { 7 | 8 | struct handler_view { 9 | protected: 10 | nng_http_handler* h = nullptr; 11 | 12 | public: 13 | handler_view() = default; 14 | 15 | handler_view( nng_http_handler* h ) noexcept : h(h) {} 16 | 17 | nng_http_handler* get() const noexcept { 18 | return h; 19 | } 20 | 21 | nng_http_handler* operator->() const noexcept { 22 | return h; 23 | } 24 | 25 | explicit operator bool() const noexcept { 26 | return h != nullptr; 27 | } 28 | 29 | void set_method( const char* method ) const { 30 | int r = nng_http_handler_set_method(h,method); 31 | if( r != 0 ) { 32 | throw exception(r,"nng_http_handler_set_method"); 33 | } 34 | } 35 | 36 | void set_method( verb v ) const { 37 | set_method( to_name(v) ); 38 | } 39 | 40 | void set_host( const char* host ) const { 41 | int r = nng_http_handler_set_host(h,host); 42 | if( r != 0 ) { 43 | throw exception(r,"nng_http_handler_set_host"); 44 | } 45 | } 46 | 47 | void set_tree() const { 48 | int r = nng_http_handler_set_tree(h); 49 | if( r != 0 ) { 50 | throw exception(r,"nng_http_handler_set_tree"); 51 | } 52 | } 53 | 54 | void set_tree_exclusive() const { 55 | int r = nng_http_handler_set_tree_exclusive(h); 56 | if( r != 0 ) { 57 | throw exception(r,"nng_http_handler_set_tree_exclusive"); 58 | } 59 | } 60 | 61 | void* get_data() const noexcept { 62 | return nng_http_handler_get_data(h); 63 | } 64 | 65 | void set_data( void* data, void (*dtor)(void*) ) const { 66 | int r = nng_http_handler_set_data(h,data,dtor); 67 | if( r != 0 ) { 68 | throw exception(r,"nng_http_handler_set_data"); 69 | } 70 | } 71 | 72 | void collect_body( bool want, size_t maxsz ) const { 73 | int r = nng_http_handler_collect_body(h,want,maxsz); 74 | if( r != 0 ) { 75 | throw exception(r,"nng_http_handler_collect_body"); 76 | } 77 | } 78 | }; 79 | 80 | }} 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /include/nngpp/http/http.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_HTTP_H 2 | #define NNGPP_HTTP_H 3 | #include "client.h" 4 | #include "conn.h" 5 | #include "handler.h" 6 | #include "req.h" 7 | #include "res.h" 8 | #include "server.h" 9 | #endif 10 | -------------------------------------------------------------------------------- /include/nngpp/http/misc.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_HTTP_MISC_H 2 | #define NNGPP_HTTP_MISC_H 3 | #include 4 | 5 | namespace nng { namespace http { 6 | 7 | enum class status { 8 | continue_ = NNG_HTTP_STATUS_CONTINUE, 9 | switching = NNG_HTTP_STATUS_SWITCHING, 10 | processing = NNG_HTTP_STATUS_PROCESSING, 11 | ok = NNG_HTTP_STATUS_OK, 12 | created = NNG_HTTP_STATUS_CREATED, 13 | accepted = NNG_HTTP_STATUS_ACCEPTED, 14 | not_authoritative = NNG_HTTP_STATUS_NOT_AUTHORITATIVE, 15 | no_content = NNG_HTTP_STATUS_NO_CONTENT, 16 | reset_content = NNG_HTTP_STATUS_RESET_CONTENT, 17 | partial_content = NNG_HTTP_STATUS_PARTIAL_CONTENT, 18 | multi_status = NNG_HTTP_STATUS_MULTI_STATUS, 19 | already_reported = NNG_HTTP_STATUS_ALREADY_REPORTED, 20 | im_used = NNG_HTTP_STATUS_IM_USED, 21 | multiple_choices = NNG_HTTP_STATUS_MULTIPLE_CHOICES, 22 | moved_permanently = NNG_HTTP_STATUS_STATUS_MOVED_PERMANENTLY, 23 | found = NNG_HTTP_STATUS_FOUND, 24 | see_other = NNG_HTTP_STATUS_SEE_OTHER, 25 | not_modified = NNG_HTTP_STATUS_NOT_MODIFIED, 26 | use_proxy = NNG_HTTP_STATUS_USE_PROXY, 27 | temporary_redirect = NNG_HTTP_STATUS_TEMPORARY_REDIRECT, 28 | permanent_redirect = NNG_HTTP_STATUS_PERMANENT_REDIRECT, 29 | bad_request = NNG_HTTP_STATUS_BAD_REQUEST, 30 | unauthorized = NNG_HTTP_STATUS_UNAUTHORIZED, 31 | payment_required = NNG_HTTP_STATUS_PAYMENT_REQUIRED, 32 | forbidden = NNG_HTTP_STATUS_FORBIDDEN, 33 | not_found = NNG_HTTP_STATUS_NOT_FOUND, 34 | method_not_allowed = NNG_HTTP_STATUS_METHOD_NOT_ALLOWED, 35 | not_acceptable = NNG_HTTP_STATUS_NOT_ACCEPTABLE, 36 | proxy_auth_required = NNG_HTTP_STATUS_PROXY_AUTH_REQUIRED, 37 | request_timeout = NNG_HTTP_STATUS_REQUEST_TIMEOUT, 38 | conflict = NNG_HTTP_STATUS_CONFLICT, 39 | gone = NNG_HTTP_STATUS_GONE, 40 | length_required = NNG_HTTP_STATUS_LENGTH_REQUIRED, 41 | precondition_failed = NNG_HTTP_STATUS_PRECONDITION_FAILED, 42 | payload_too_large = NNG_HTTP_STATUS_PAYLOAD_TOO_LARGE, 43 | entity_too_long = NNG_HTTP_STATUS_ENTITY_TOO_LONG, 44 | unsupported_media_type = NNG_HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE, 45 | range_not_satisfiable = NNG_HTTP_STATUS_RANGE_NOT_SATISFIABLE, 46 | expectation_failed = NNG_HTTP_STATUS_EXPECTATION_FAILED, 47 | teapot = NNG_HTTP_STATUS_TEAPOT, 48 | unprocessable_entity = NNG_HTTP_STATUS_UNPROCESSABLE_ENTITY, 49 | locked = NNG_HTTP_STATUS_LOCKED, 50 | failed_dependency = NNG_HTTP_STATUS_FAILED_DEPENDENCY, 51 | upgrade_required = NNG_HTTP_STATUS_UPGRADE_REQUIRED, 52 | precondition_required = NNG_HTTP_STATUS_PRECONDITION_REQUIRED, 53 | too_many_requests = NNG_HTTP_STATUS_TOO_MANY_REQUESTS, 54 | headers_too_large = NNG_HTTP_STATUS_HEADERS_TOO_LARGE, 55 | unavail_legal_reasons = NNG_HTTP_STATUS_UNAVAIL_LEGAL_REASONS, 56 | internal_server_error = NNG_HTTP_STATUS_INTERNAL_SERVER_ERROR, 57 | not_implemented = NNG_HTTP_STATUS_NOT_IMPLEMENTED, 58 | bad_gateway = NNG_HTTP_STATUS_BAD_GATEWAY, 59 | service_unavailable = NNG_HTTP_STATUS_SERVICE_UNAVAILABLE, 60 | gateway_timeout = NNG_HTTP_STATUS_GATEWAY_TIMEOUT, 61 | http_version_not_supp = NNG_HTTP_STATUS_HTTP_VERSION_NOT_SUPP, 62 | variant_also_negotiates = NNG_HTTP_STATUS_VARIANT_ALSO_NEGOTIATES, 63 | insufficient_storage = NNG_HTTP_STATUS_INSUFFICIENT_STORAGE, 64 | loop_detected = NNG_HTTP_STATUS_LOOP_DETECTED, 65 | not_extended = NNG_HTTP_STATUS_NOT_EXTENDED, 66 | network_auth_required = NNG_HTTP_STATUS_NETWORK_AUTH_REQUIRED 67 | }; 68 | 69 | enum class verb { 70 | get, 71 | head, 72 | post, 73 | put, 74 | delete_, 75 | trace, 76 | options, 77 | connect, 78 | patch 79 | }; 80 | 81 | namespace detail { 82 | 83 | #if __cpp_inline_variables >= 201606 84 | inline 85 | #else 86 | static 87 | #endif 88 | const char* const verb_name[] { 89 | "GET", 90 | "HEAD", 91 | "POST", 92 | "PUT", 93 | "DELETE", 94 | "TRACE", 95 | "OPTIONS", 96 | "CONNECT", 97 | "PATCH" 98 | }; 99 | 100 | } 101 | 102 | inline const char* to_name( verb v ) noexcept { 103 | return detail::verb_name[(int)v]; 104 | } 105 | 106 | }} 107 | 108 | #endif 109 | -------------------------------------------------------------------------------- /include/nngpp/http/req.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_HTTP_REQ_H 2 | #define NNGPP_HTTP_REQ_H 3 | #include "req_view.h" 4 | #include 5 | 6 | namespace nng { namespace http { 7 | 8 | struct req : req_view { 9 | 10 | req() = default; 11 | 12 | explicit req( nng_http_req* q ) noexcept : req_view(q) {} 13 | 14 | explicit req( url_view u ) { 15 | int r = nng_http_req_alloc( &q, u.get() ); 16 | if( r != 0 ) { 17 | throw exception(r,"nng_http_req_alloc"); 18 | } 19 | } 20 | 21 | req( const req& rhs ) = delete; 22 | 23 | req( req&& rhs ) noexcept : req_view(rhs.q) { 24 | rhs.q = nullptr; 25 | } 26 | 27 | req& operator=( const req& rhs ) = delete; 28 | 29 | req& operator=( req&& rhs ) noexcept { 30 | if( this != &rhs ) { 31 | if( q != nullptr ) nng_http_req_free(q); 32 | q = rhs.q; 33 | rhs.q = nullptr; 34 | } 35 | return *this; 36 | } 37 | 38 | ~req() { 39 | if( q != nullptr ) nng_http_req_free(q); 40 | } 41 | 42 | nng_http_req* release() noexcept { 43 | auto out = q; 44 | q = nullptr; 45 | return out; 46 | } 47 | 48 | }; 49 | 50 | inline req make_req( url_view u ) { 51 | return req(u); 52 | } 53 | 54 | }} 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /include/nngpp/http/req_view.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_HTTP_REQ_VIEW_H 2 | #define NNGPP_HTTP_REQ_VIEW_H 3 | #include 4 | #include "misc.h" 5 | 6 | namespace nng { namespace http { 7 | 8 | struct req_view { 9 | protected: 10 | nng_http_req* q = nullptr; 11 | 12 | public: 13 | req_view() = default; 14 | 15 | req_view( nng_http_req* q ) noexcept : q(q) {} 16 | 17 | nng_http_req* get() const noexcept { 18 | return q; 19 | } 20 | 21 | nng_http_req* operator->() const noexcept { 22 | return q; 23 | } 24 | 25 | explicit operator bool() const noexcept { 26 | return q != nullptr; 27 | } 28 | 29 | void reset() const noexcept { 30 | nng_http_req_reset(q); 31 | } 32 | 33 | const char* get_method() const noexcept { 34 | return nng_http_req_get_method(q); 35 | } 36 | 37 | void set_method( const char* method ) const { 38 | int r = nng_http_req_set_method(q,method); 39 | if( r != 0 ) { 40 | throw exception(r,"nng_http_req_set_method"); 41 | } 42 | } 43 | 44 | const char* get_version() const noexcept { 45 | return nng_http_req_get_version(q); 46 | } 47 | 48 | void set_version( const char* version ) const { 49 | int r = nng_http_req_set_version(q,version); 50 | if( r != 0 ) { 51 | throw exception(r,"nng_http_req_set_version"); 52 | } 53 | } 54 | 55 | const char* get_uri() const noexcept { 56 | return nng_http_req_get_uri(q); 57 | } 58 | 59 | void set_uri( const char* uri ) const { 60 | int r = nng_http_req_set_uri(q,uri); 61 | if( r != 0 ) { 62 | throw exception(r,"nng_http_req_set_uri"); 63 | } 64 | } 65 | 66 | const char* get_header( const char* name ) const noexcept { 67 | return nng_http_req_get_header(q,name); 68 | } 69 | 70 | void set_header( const char* name, const char* value ) const { 71 | int r = nng_http_req_set_header(q,name,value); 72 | if( r != 0 ) { 73 | throw exception(r,"nng_http_req_set_header"); 74 | } 75 | } 76 | 77 | void add_header( const char* name, const char* value ) const { 78 | int r = nng_http_req_add_header(q,name,value); 79 | if( r != 0 ) { 80 | throw exception(r,"nng_http_req_add_header"); 81 | } 82 | } 83 | 84 | void del_header( const char* name ) const { 85 | int r = nng_http_req_del_header(q,name); 86 | if( r != 0 ) { 87 | throw exception(r,"nng_http_req_del_header"); 88 | } 89 | } 90 | 91 | view get_data() const noexcept { 92 | void* data; 93 | size_t size; 94 | nng_http_req_get_data(q,&data,&size); 95 | return view(data,size); 96 | } 97 | 98 | void set_data( view v ) const { 99 | int r = nng_http_req_set_data(q,v.data(),v.size()); 100 | if( r != 0 ) { 101 | throw exception(r,"nng_http_req_set_data"); 102 | } 103 | } 104 | 105 | void copy_data( view v ) const { 106 | int r = nng_http_req_copy_data(q,v.data(),v.size()); 107 | if( r != 0 ) { 108 | throw exception(r,"nng_http_req_copy_data"); 109 | } 110 | } 111 | 112 | }; 113 | 114 | }} 115 | 116 | #endif 117 | -------------------------------------------------------------------------------- /include/nngpp/http/res.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_HTTP_RES_H 2 | #define NNGPP_HTTP_RES_H 3 | #include "res_view.h" 4 | 5 | namespace nng { namespace http { 6 | 7 | struct res : res_view { 8 | 9 | res() = default; 10 | 11 | explicit res( nng_http_res* s ) noexcept : res_view(s) {} 12 | 13 | explicit res( status code ) { 14 | int r = nng_http_res_alloc_error( &s, (uint16_t)code ); 15 | if( r != 0 ) { 16 | throw exception(r,"nng_http_res_alloc_error"); 17 | } 18 | } 19 | 20 | res( const res& rhs ) = delete; 21 | 22 | res( res&& rhs ) noexcept : res_view(rhs.s) { 23 | rhs.s = nullptr; 24 | } 25 | 26 | res& operator=( const res& rhs ) = delete; 27 | 28 | res& operator=( res&& rhs ) noexcept { 29 | if( this != &rhs ) { 30 | if( s != nullptr ) nng_http_res_free(s); 31 | s = rhs.s; 32 | rhs.s = nullptr; 33 | } 34 | return *this; 35 | } 36 | 37 | ~res() { 38 | if( s != nullptr ) nng_http_res_free(s); 39 | } 40 | 41 | nng_http_res* release() noexcept { 42 | auto out = s; 43 | s = nullptr; 44 | return out; 45 | } 46 | 47 | }; 48 | 49 | inline res make_res() { 50 | nng_http_res* s; 51 | int r = nng_http_res_alloc( &s ); 52 | if( r != 0 ) { 53 | throw exception(r,"nng_http_res_alloc"); 54 | } 55 | return res(s); 56 | } 57 | 58 | inline res make_res( status code ) { 59 | return res(code); 60 | } 61 | 62 | }} 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /include/nngpp/http/res_view.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_HTTP_RES_VIEW_H 2 | #define NNGPP_HTTP_RES_VIEW_H 3 | #include 4 | #include "misc.h" 5 | 6 | namespace nng { namespace http { 7 | 8 | struct res_view { 9 | protected: 10 | nng_http_res* s = nullptr; 11 | 12 | public: 13 | res_view() = default; 14 | 15 | res_view( nng_http_res* s ) noexcept : s(s) {} 16 | 17 | nng_http_res* get() const noexcept { 18 | return s; 19 | } 20 | 21 | nng_http_res* operator->() const noexcept { 22 | return s; 23 | } 24 | 25 | explicit operator bool() const noexcept { 26 | return s != nullptr; 27 | } 28 | 29 | void reset() const noexcept { 30 | nng_http_res_reset(s); 31 | } 32 | 33 | status get_status() const noexcept { 34 | return (status)nng_http_res_get_status(s); 35 | } 36 | 37 | void set_status( status status ) const { 38 | int r = nng_http_res_set_status(s,(uint16_t)status); 39 | if( r != 0 ) { 40 | throw exception(r,"nng_http_res_set_status"); 41 | } 42 | } 43 | 44 | const char* get_reason() const noexcept { 45 | return nng_http_res_get_reason(s); 46 | } 47 | 48 | void set_reason( const char* reason ) const { 49 | int r = nng_http_res_set_reason(s,reason); 50 | if( r != 0 ) { 51 | throw exception(r,"nng_http_res_set_reason"); 52 | } 53 | } 54 | 55 | const char* get_header( const char* name ) const noexcept { 56 | return nng_http_res_get_header(s,name); 57 | } 58 | 59 | void set_header( const char* name, const char* value ) const { 60 | int r = nng_http_res_set_header(s,name,value); 61 | if( r != 0 ) { 62 | throw exception(r,"nng_http_res_set_header"); 63 | } 64 | } 65 | 66 | void add_header( const char* name, const char* value ) const { 67 | int r = nng_http_res_add_header(s,name,value); 68 | if( r != 0 ) { 69 | throw exception(r,"nng_http_res_add_header"); 70 | } 71 | } 72 | 73 | void del_header( const char* name ) const { 74 | int r = nng_http_res_del_header(s,name); 75 | if( r != 0 ) { 76 | throw exception(r,"nng_http_res_del_header"); 77 | } 78 | } 79 | 80 | const char* get_version() const noexcept { 81 | return nng_http_res_get_version(s); 82 | } 83 | 84 | void set_version( const char* version ) const { 85 | int r = nng_http_res_set_version(s,version); 86 | if( r != 0 ) { 87 | throw exception(r,"nng_http_res_set_version"); 88 | } 89 | } 90 | 91 | view get_data() const noexcept { 92 | void* data; 93 | size_t size; 94 | nng_http_res_get_data(s,&data,&size); 95 | return view(data,size); 96 | } 97 | 98 | void set_data( view v ) const { 99 | int r = nng_http_res_set_data(s,v.data(),v.size()); 100 | if( r != 0 ) { 101 | throw exception(r,"nng_http_res_set_data"); 102 | } 103 | } 104 | 105 | void copy_data( view v ) const { 106 | int r = nng_http_res_copy_data(s,v.data(),v.size()); 107 | if( r != 0 ) { 108 | throw exception(r,"nng_http_res_copy_data"); 109 | } 110 | } 111 | }; 112 | 113 | }} 114 | 115 | #endif 116 | -------------------------------------------------------------------------------- /include/nngpp/http/server.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_HTTP_SERVER_H 2 | #define NNGPP_HTTP_SERVER_H 3 | #include "server_view.h" 4 | #include 5 | 6 | namespace nng { namespace http { 7 | 8 | struct server : server_view { 9 | 10 | server() = default; 11 | 12 | explicit server( nng_http_server* s ) noexcept : server_view(s) {} 13 | 14 | explicit server( url_view u ) { 15 | int r = nng_http_server_hold( &s, u.get() ); 16 | if( r != 0 ) { 17 | throw exception(r,"nng_http_server_hold"); 18 | } 19 | } 20 | 21 | server( const server& rhs ) = delete; 22 | 23 | server( server&& rhs ) noexcept : server_view(rhs.s) { 24 | rhs.s = nullptr; 25 | } 26 | 27 | server& operator=( const server& rhs ) = delete; 28 | 29 | server& operator=( server&& rhs ) noexcept { 30 | if( this != &rhs ) { 31 | if( s != nullptr ) nng_http_server_release(s); 32 | s = rhs.s; 33 | rhs.s = nullptr; 34 | } 35 | return *this; 36 | } 37 | 38 | ~server() { 39 | if( s != nullptr ) nng_http_server_release(s); 40 | } 41 | 42 | nng_http_server* release() noexcept { 43 | auto out = s; 44 | s = nullptr; 45 | return out; 46 | } 47 | 48 | }; 49 | 50 | inline server make_server( url_view u ) { 51 | return server(u); 52 | } 53 | 54 | }} 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /include/nngpp/http/server_view.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_HTTP_SERVER_VIEW_H 2 | #define NNGPP_HTTP_SERVER_VIEW_H 3 | #include 4 | #include "handler.h" 5 | #include "res_view.h" 6 | 7 | namespace nng { namespace http { 8 | 9 | struct server_view { 10 | protected: 11 | nng_http_server* s = nullptr; 12 | 13 | public: 14 | server_view() = default; 15 | 16 | server_view( nng_http_server* s ) noexcept : s(s) {} 17 | 18 | nng_http_server* get() const noexcept { 19 | return s; 20 | } 21 | 22 | nng_http_server* operator->() const noexcept { 23 | return s; 24 | } 25 | 26 | explicit operator bool() const noexcept { 27 | return s != nullptr; 28 | } 29 | 30 | void start() const { 31 | int r = nng_http_server_start(s); 32 | if( r != 0 ) { 33 | throw exception(r,"nng_http_server_start"); 34 | } 35 | } 36 | 37 | void stop() const noexcept { 38 | nng_http_server_stop(s); 39 | } 40 | 41 | void add_handler( handler&& h ) const { 42 | int r = nng_http_server_add_handler(s,h.get()); 43 | if( r != 0 ) { 44 | throw exception(r,"nng_http_server_add_handler"); 45 | } 46 | // if successful, the handler is owned by the server 47 | h.release(); 48 | } 49 | 50 | handler remove_handler( handler_view h ) const { 51 | int r = nng_http_server_del_handler(s,h.get()); 52 | if( r != 0 ) { 53 | throw exception(r,"nng_http_server_del_handler"); 54 | } 55 | return handler(h.get()); 56 | } 57 | 58 | nng_sockaddr get_addr() const { 59 | nng_sockaddr out; 60 | int r = nng_http_server_get_addr(s, &out); 61 | if( r != 0 ) { 62 | throw exception(r,"nng_http_server_get_addr"); 63 | } 64 | return out; 65 | } 66 | 67 | tls::config_view get_tls() const { 68 | nng_tls_config* cfg; 69 | int r = nng_http_server_get_tls(s,&cfg); 70 | if( r != 0 ) { 71 | throw exception(r,"nng_http_server_get_tls"); 72 | } 73 | return cfg; 74 | } 75 | 76 | void set_tls( tls::config_view cfg ) const { 77 | int r = nng_http_server_set_tls(s,cfg.get()); 78 | if( r != 0 ) { 79 | throw exception(r,"nng_http_server_set_tls"); 80 | } 81 | } 82 | 83 | void set_error_page( uint16_t code, const char* body ) const { 84 | int r = nng_http_server_set_error_page(s,code,body); 85 | if( r != 0 ) { 86 | throw exception(r,"nng_http_server_set_error_page"); 87 | } 88 | } 89 | 90 | void set_error_file( uint16_t code, const char* path ) const { 91 | int r = nng_http_server_set_error_file(s,code,path); 92 | if( r != 0 ) { 93 | throw exception(r,"nng_http_server_set_error_file"); 94 | } 95 | } 96 | 97 | void set_res_error( res_view res ) const { 98 | int r = nng_http_server_res_error(s,res.get()); 99 | if( r != 0 ) { 100 | throw exception(r,"nng_http_server_res_error"); 101 | } 102 | } 103 | 104 | }; 105 | 106 | }} 107 | 108 | #endif 109 | -------------------------------------------------------------------------------- /include/nngpp/listener.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_LISTENER_H 2 | #define NNGPP_LISTENER_H 3 | #include "listener_view.h" 4 | #include "socket_view.h" 5 | 6 | namespace nng { 7 | 8 | struct listener : listener_view { 9 | 10 | listener() = default; 11 | 12 | explicit listener( nng_listener lis ) noexcept : listener_view(lis) {} 13 | 14 | explicit listener( socket_view s, const char* addr, int flags ) { 15 | int r = nng_listen( s.get(), addr, &lis, flags ); 16 | if( r != 0 ) { 17 | throw exception(r,"nng_listen"); 18 | } 19 | } 20 | 21 | explicit listener( socket_view s, const char* addr ) { 22 | int r = nng_listener_create( &lis, s.get(), addr ); 23 | if( r != 0 ) { 24 | throw exception(r,"nng_listener_create"); 25 | } 26 | } 27 | 28 | listener( const listener& rhs ) = delete; 29 | 30 | listener( listener&& rhs ) noexcept : listener_view(rhs.lis) { 31 | rhs.lis.id = 0; 32 | } 33 | 34 | listener& operator=( const listener& rhs ) = delete; 35 | 36 | listener& operator=( listener&& rhs ) { 37 | if( this != &rhs ) { 38 | if( lis.id != 0 ) { 39 | int r = nng_listener_close(lis); 40 | if( r != 0 && r != (int)nng::error::closed ) { 41 | throw exception(r,"nng_listener_close"); 42 | } 43 | } 44 | lis = rhs.lis; 45 | rhs.lis.id = 0; 46 | } 47 | return *this; 48 | } 49 | 50 | ~listener() { 51 | if( lis.id != 0 ) nng_listener_close(lis); 52 | } 53 | 54 | nng_listener release() noexcept { 55 | auto out = lis; 56 | lis.id = 0; 57 | return out; 58 | } 59 | 60 | }; 61 | 62 | inline listener make_listener( socket_view s, const char* addr, int flags ) { 63 | return listener(s,addr,flags); 64 | } 65 | 66 | inline listener make_listener( socket_view s, const char* addr ) { 67 | return listener(s,addr); 68 | } 69 | 70 | } 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /include/nngpp/listener_view.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_LISTENER_VIEW_H 2 | #define NNGPP_LISTENER_VIEW_H 3 | #include "option.h" 4 | #include "buffer.h" 5 | 6 | namespace nng { 7 | 8 | struct listener_view { 9 | protected: 10 | nng_listener lis{0}; 11 | 12 | public: 13 | listener_view() = default; 14 | 15 | listener_view( nng_listener lis ) noexcept : lis(lis) {} 16 | 17 | nng_listener get() const noexcept { 18 | return lis; 19 | } 20 | 21 | explicit operator bool() const noexcept { 22 | return lis.id != 0; 23 | } 24 | 25 | void start( int flags = 0 ) const { 26 | int r = nng_listener_start(lis,flags); 27 | if( r != 0 ) { 28 | throw exception(r,"nng_listener_start"); 29 | } 30 | } 31 | 32 | int id() const noexcept { 33 | return nng_listener_id(lis); 34 | } 35 | 36 | void set_opt( const char* name, view v ) const { 37 | int r = nng_listener_set(lis,name,v.data(),v.size()); 38 | if( r != 0 ) { 39 | throw exception(r,"nng_listener_set"); 40 | } 41 | } 42 | 43 | void set_opt_bool( const char* name, bool value ) const { 44 | int r = nng_listener_set_bool(lis,name,value); 45 | if( r != 0 ) { 46 | throw exception(r,"nng_listener_set_bool"); 47 | } 48 | } 49 | 50 | void set_opt_int( const char* name, int value ) const { 51 | int r = nng_listener_set_int(lis,name,value); 52 | if( r != 0 ) { 53 | throw exception(r,"nng_listener_set_int"); 54 | } 55 | } 56 | 57 | void set_opt_size( const char* name, size_t value ) const { 58 | int r = nng_listener_set_size(lis,name,value); 59 | if( r != 0 ) { 60 | throw exception(r,"nng_listener_set_size"); 61 | } 62 | } 63 | 64 | void set_opt_uint64( const char* name, uint64_t value ) const { 65 | int r = nng_listener_set_uint64(lis,name,value); 66 | if( r != 0 ) { 67 | throw exception(r,"nng_listener_set_uint64"); 68 | } 69 | } 70 | 71 | void set_opt_string( const char* name, const char* value ) const { 72 | int r = nng_listener_set_string(lis,name,value); 73 | if( r != 0 ) { 74 | throw exception(r,"nng_listener_set_string"); 75 | } 76 | } 77 | 78 | void set_opt_ptr( const char* name, void* value ) const { 79 | int r = nng_listener_set_ptr(lis,name,value); 80 | if( r != 0 ) { 81 | throw exception(r,"nng_listener_set_ptr"); 82 | } 83 | } 84 | 85 | void set_opt_ms( const char* name, nng_duration value ) const { 86 | int r = nng_listener_set_ms(lis,name,value); 87 | if( r != 0 ) { 88 | throw exception(r,"nng_listener_set_ms"); 89 | } 90 | } 91 | 92 | void set_opt_addr( const char* name, const nng_sockaddr* value ) const { 93 | int r = nng_listener_set_addr(lis,name,value); 94 | if( r != 0 ) { 95 | throw exception(r,"nng_listener_set_addr"); 96 | } 97 | } 98 | 99 | size_t get_opt( const char* name, buffer& out ) const { 100 | size_t size = out.size(); 101 | int r = nng_listener_get(lis,name,out.data(),&size); 102 | if( r != 0 ) { 103 | throw exception(r,"nng_listener_get"); 104 | } 105 | return size; 106 | } 107 | 108 | bool get_opt_bool( const char* name ) const { 109 | bool out; 110 | int r = nng_listener_get_bool(lis,name,&out); 111 | if( r != 0 ) { 112 | throw exception(r,"nng_listener_get_bool"); 113 | } 114 | return out; 115 | } 116 | 117 | int get_opt_int( const char* name ) const { 118 | int out; 119 | int r = nng_listener_get_int(lis,name,&out); 120 | if( r != 0 ) { 121 | throw exception(r,"nng_listener_get_int"); 122 | } 123 | return out; 124 | } 125 | 126 | size_t get_opt_size( const char* name ) const { 127 | size_t out; 128 | int r = nng_listener_get_size(lis,name,&out); 129 | if( r != 0 ) { 130 | throw exception(r,"nng_listener_get_size"); 131 | } 132 | return out; 133 | } 134 | 135 | uint64_t get_opt_uint64( const char* name ) const { 136 | uint64_t out; 137 | int r = nng_listener_get_uint64(lis,name,&out); 138 | if( r != 0 ) { 139 | throw exception(r,"nng_listener_get_uint64"); 140 | } 141 | return out; 142 | } 143 | 144 | buffer get_opt_string( const char* name ) const { 145 | char* data; 146 | int r = nng_listener_get_string(lis,name,&data); 147 | if( r != 0 ) { 148 | throw exception(r,"nng_listener_get_string"); 149 | } 150 | return buffer(data,strlen(data)+1); 151 | } 152 | 153 | void* get_opt_ptr( const char* name ) const { 154 | void* out; 155 | int r = nng_listener_get_ptr(lis,name,&out); 156 | if( r != 0 ) { 157 | throw exception(r,"nng_listener_get_ptr"); 158 | } 159 | return out; 160 | } 161 | 162 | nng_duration get_opt_ms( const char* name ) const { 163 | nng_duration out; 164 | int r = nng_listener_get_ms(lis,name,&out); 165 | if( r != 0 ) { 166 | throw exception(r,"nng_listener_get_ms"); 167 | } 168 | return out; 169 | } 170 | 171 | nng_sockaddr get_opt_addr( const char* name ) const { 172 | nng_sockaddr out; 173 | int r = nng_listener_get_addr(lis,name,&out); 174 | if( r != 0 ) { 175 | throw exception(r,"nng_listener_get_addr"); 176 | } 177 | return out; 178 | } 179 | }; 180 | 181 | inline nng_sockaddr get_opt_local_address( listener_view s ) { 182 | return s.get_opt_addr( to_name(option::local_address) ); 183 | } 184 | 185 | inline buffer get_opt_url( listener_view s ) { 186 | return s.get_opt_string( to_name(option::url) ); 187 | } 188 | 189 | inline size_t get_opt_recv_size_max( listener_view s ) { 190 | return s.get_opt_size( to_name(option::recv_size_max) ); 191 | } 192 | 193 | inline void set_opt_recv_size_max( listener_view s, size_t v ) { 194 | s.set_opt_size( to_name(option::recv_size_max), v ); 195 | } 196 | 197 | } 198 | 199 | #endif 200 | -------------------------------------------------------------------------------- /include/nngpp/msg.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_MSG_H 2 | #define NNGPP_MSG_H 3 | #include "msg_view.h" 4 | 5 | namespace nng { 6 | 7 | struct msg : msg_view { 8 | 9 | msg() = default; 10 | 11 | explicit msg( nng_msg* m ) noexcept : msg_view(m) {} 12 | 13 | explicit msg( size_t size ) { 14 | int r = nng_msg_alloc( &m, size ); 15 | if( r != 0 ) { 16 | throw exception(r,"nng_msg_alloc"); 17 | } 18 | } 19 | 20 | msg( const msg& rhs ) : msg_view() { 21 | int r = nng_msg_dup(&m,rhs.get()); 22 | if( r != 0 ) { 23 | throw exception(r,"nng_msg_dup"); 24 | } 25 | } 26 | 27 | msg( msg&& rhs ) noexcept : msg_view(rhs.m) { 28 | rhs.m = nullptr; 29 | } 30 | 31 | msg& operator=( const msg& rhs ) { 32 | if( this != &rhs ) { 33 | if( m != nullptr ) nng_msg_free(m); 34 | int r = nng_msg_dup(&m,rhs.get()); 35 | if( r != 0 ) { 36 | throw exception(r,"nng_msg_dup"); 37 | } 38 | } 39 | return *this; 40 | } 41 | 42 | msg& operator=( msg&& rhs ) noexcept { 43 | if( this != &rhs ) { 44 | if( m != nullptr ) nng_msg_free(m); 45 | m = rhs.m; 46 | rhs.m = nullptr; 47 | } 48 | return *this; 49 | } 50 | 51 | ~msg() { 52 | if( m != nullptr ) nng_msg_free(m); 53 | } 54 | 55 | nng_msg* release() noexcept { 56 | auto out = m; 57 | m = nullptr; 58 | return out; 59 | } 60 | 61 | }; 62 | 63 | inline msg make_msg( size_t size ) { 64 | return msg(size); 65 | } 66 | 67 | } 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /include/nngpp/msg_body.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_MSG_BODY_H 2 | #define NNGPP_MSG_BODY_H 3 | #include "view.h" 4 | 5 | namespace nng { 6 | 7 | class msg_body { 8 | nng_msg* m; 9 | 10 | public: 11 | 12 | explicit msg_body( nng_msg* m ) noexcept : m(m) {} 13 | 14 | nng_msg* get_msg() const noexcept { 15 | return m; 16 | } 17 | 18 | template 19 | T* data() const noexcept { 20 | return (T*)nng_msg_body(m); 21 | } 22 | 23 | size_t size() const noexcept { 24 | return nng_msg_len(m); 25 | } 26 | 27 | view get() const noexcept { 28 | return view( 29 | nng_msg_body(m), 30 | nng_msg_len(m) 31 | ); 32 | } 33 | 34 | void clear() const noexcept { 35 | nng_msg_clear(m); 36 | } 37 | 38 | void append( view v ) const { 39 | int r = nng_msg_append(m,v.data(),v.size()); 40 | if( r != 0 ) { 41 | throw exception(r,"nng_msg_append"); 42 | } 43 | } 44 | 45 | void insert( view v ) const { 46 | int r = nng_msg_insert(m,v.data(),v.size()); 47 | if( r != 0 ) { 48 | throw exception(r,"nng_msg_insert"); 49 | } 50 | } 51 | 52 | void trim( size_t size ) const { 53 | int r = nng_msg_trim(m,size); 54 | if( r != 0 ) { 55 | throw exception(r,"nng_msg_trim"); 56 | } 57 | } 58 | 59 | void chop( size_t size ) const { 60 | int r = nng_msg_chop(m,size); 61 | if( r != 0 ) { 62 | throw exception(r,"nng_msg_chop"); 63 | } 64 | } 65 | 66 | void append_u16( uint16_t val ) const { 67 | int r = nng_msg_append_u16(m,val); 68 | if( r != 0 ) { 69 | throw exception(r,"nng_msg_append_u16"); 70 | } 71 | } 72 | 73 | void append_u32( uint32_t val ) const { 74 | int r = nng_msg_append_u32(m,val); 75 | if( r != 0 ) { 76 | throw exception(r,"nng_msg_append_u32"); 77 | } 78 | } 79 | 80 | void append_u64( uint64_t val ) const { 81 | int r = nng_msg_append_u64(m,val); 82 | if( r != 0 ) { 83 | throw exception(r,"nng_msg_append_u64"); 84 | } 85 | } 86 | 87 | void insert_u16( uint16_t val ) const { 88 | int r = nng_msg_insert_u16(m,val); 89 | if( r != 0 ) { 90 | throw exception(r,"nng_msg_insert_u16"); 91 | } 92 | } 93 | 94 | void insert_u32( uint32_t val ) const { 95 | int r = nng_msg_insert_u32(m,val); 96 | if( r != 0 ) { 97 | throw exception(r,"nng_msg_insert_u32"); 98 | } 99 | } 100 | 101 | void insert_u64( uint64_t val ) const { 102 | int r = nng_msg_insert_u64(m,val); 103 | if( r != 0 ) { 104 | throw exception(r,"nng_msg_insert_u64"); 105 | } 106 | } 107 | 108 | uint16_t trim_u16() const { 109 | uint16_t val; 110 | int r = nng_msg_trim_u16(m,&val); 111 | if( r != 0 ) { 112 | throw exception(r,"nng_msg_trim_u16"); 113 | } 114 | return val; 115 | } 116 | 117 | uint32_t trim_u32() const { 118 | uint32_t val; 119 | int r = nng_msg_trim_u32(m,&val); 120 | if( r != 0 ) { 121 | throw exception(r,"nng_msg_trim_u32"); 122 | } 123 | return val; 124 | } 125 | 126 | uint64_t trim_u64() const { 127 | uint64_t val; 128 | int r = nng_msg_trim_u64(m,&val); 129 | if( r != 0 ) { 130 | throw exception(r,"nng_msg_trim_u64"); 131 | } 132 | return val; 133 | } 134 | 135 | uint16_t chop_u16() const { 136 | uint16_t val; 137 | int r = nng_msg_chop_u16(m,&val); 138 | if( r != 0 ) { 139 | throw exception(r,"nng_msg_chop_u16"); 140 | } 141 | return val; 142 | } 143 | 144 | uint32_t chop_u32() const { 145 | uint32_t val; 146 | int r = nng_msg_chop_u32(m,&val); 147 | if( r != 0 ) { 148 | throw exception(r,"nng_msg_chop_u32"); 149 | } 150 | return val; 151 | } 152 | 153 | uint64_t chop_u64() const { 154 | uint64_t val; 155 | int r = nng_msg_chop_u64(m,&val); 156 | if( r != 0 ) { 157 | throw exception(r,"nng_msg_chop_u64"); 158 | } 159 | return val; 160 | } 161 | 162 | }; 163 | 164 | } 165 | 166 | #endif 167 | -------------------------------------------------------------------------------- /include/nngpp/msg_header.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_MSG_HEADER_H 2 | #define NNGPP_MSG_HEADER_H 3 | #include "view.h" 4 | 5 | namespace nng { 6 | 7 | class msg_header { 8 | nng_msg* m; 9 | 10 | public: 11 | 12 | explicit msg_header( nng_msg* m ) noexcept : m(m) {} 13 | 14 | nng_msg* get_msg() const noexcept { 15 | return m; 16 | } 17 | 18 | template 19 | T* data() const noexcept { 20 | return (T*)nng_msg_header(m); 21 | } 22 | 23 | size_t size() const noexcept { 24 | return nng_msg_header_len(m); 25 | } 26 | 27 | view get() const noexcept { 28 | return view( 29 | nng_msg_header(m), 30 | nng_msg_header_len(m) 31 | ); 32 | } 33 | 34 | void clear() const noexcept { 35 | nng_msg_header_clear(m); 36 | } 37 | 38 | void append( view v ) const { 39 | int r = nng_msg_header_append(m,v.data(),v.size()); 40 | if( r != 0 ) { 41 | throw exception(r,"nng_msg_header_append"); 42 | } 43 | } 44 | void insert( view v ) const { 45 | int r = nng_msg_header_insert(m,v.data(),v.size()); 46 | if( r != 0 ) { 47 | throw exception(r,"nng_msg_header_insert"); 48 | } 49 | } 50 | 51 | void trim( size_t size ) const { 52 | int r = nng_msg_header_trim(m,size); 53 | if( r != 0 ) { 54 | throw exception(r,"nng_msg_header_trim"); 55 | } 56 | } 57 | 58 | void chop( size_t size ) const { 59 | int r = nng_msg_header_chop(m,size); 60 | if( r != 0 ) { 61 | throw exception(r,"nng_msg_header_chop"); 62 | } 63 | } 64 | 65 | void append_u16( uint16_t val ) const { 66 | int r = nng_msg_header_append_u16(m,val); 67 | if( r != 0 ) { 68 | throw exception(r,"nng_msg_header_append_u16"); 69 | } 70 | } 71 | 72 | void append_u32( uint32_t val ) const { 73 | int r = nng_msg_header_append_u32(m,val); 74 | if( r != 0 ) { 75 | throw exception(r,"nng_msg_header_append_u32"); 76 | } 77 | } 78 | 79 | void append_u64( uint64_t val ) const { 80 | int r = nng_msg_header_append_u64(m,val); 81 | if( r != 0 ) { 82 | throw exception(r,"nng_msg_header_append_u64"); 83 | } 84 | } 85 | 86 | void insert_u16( uint16_t val ) const { 87 | int r = nng_msg_header_insert_u16(m,val); 88 | if( r != 0 ) { 89 | throw exception(r,"nng_msg_header_insert_u16"); 90 | } 91 | } 92 | 93 | void insert_u32( uint32_t val ) const { 94 | int r = nng_msg_header_insert_u32(m,val); 95 | if( r != 0 ) { 96 | throw exception(r,"nng_msg_header_insert_u32"); 97 | } 98 | } 99 | 100 | void insert_u64( uint64_t val ) const { 101 | int r = nng_msg_header_insert_u64(m,val); 102 | if( r != 0 ) { 103 | throw exception(r,"nng_msg_header_insert_u64"); 104 | } 105 | } 106 | 107 | uint16_t trim_u16() const { 108 | uint16_t val; 109 | int r = nng_msg_header_trim_u16(m,&val); 110 | if( r != 0 ) { 111 | throw exception(r,"nng_msg_header_trim_u16"); 112 | } 113 | return val; 114 | } 115 | 116 | uint32_t trim_u32() const { 117 | uint32_t val; 118 | int r = nng_msg_header_trim_u32(m,&val); 119 | if( r != 0 ) { 120 | throw exception(r,"nng_msg_header_trim_u32"); 121 | } 122 | return val; 123 | } 124 | 125 | uint64_t trim_u64() const { 126 | uint64_t val; 127 | int r = nng_msg_header_trim_u64(m,&val); 128 | if( r != 0 ) { 129 | throw exception(r,"nng_msg_header_trim_u64"); 130 | } 131 | return val; 132 | } 133 | 134 | uint16_t chop_u16() const { 135 | uint16_t val; 136 | int r = nng_msg_header_chop_u16(m,&val); 137 | if( r != 0 ) { 138 | throw exception(r,"nng_msg_header_chop_u16"); 139 | } 140 | return val; 141 | } 142 | 143 | uint32_t chop_u32() const { 144 | uint32_t val; 145 | int r = nng_msg_header_chop_u32(m,&val); 146 | if( r != 0 ) { 147 | throw exception(r,"nng_msg_header_chop_u32"); 148 | } 149 | return val; 150 | } 151 | 152 | uint64_t chop_u64() const { 153 | uint64_t val; 154 | int r = nng_msg_header_chop_u64(m,&val); 155 | if( r != 0 ) { 156 | throw exception(r,"nng_msg_header_chop_u64"); 157 | } 158 | return val; 159 | } 160 | 161 | }; 162 | 163 | } 164 | 165 | #endif 166 | -------------------------------------------------------------------------------- /include/nngpp/msg_view.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_MSG_VIEW_H 2 | #define NNGPP_MSG_VIEW_H 3 | #include "msg_header.h" 4 | #include "msg_body.h" 5 | #include "pipe_view.h" 6 | 7 | namespace nng { 8 | 9 | struct msg_view { 10 | protected: 11 | nng_msg* m = nullptr; 12 | 13 | public: 14 | msg_view() = default; 15 | 16 | msg_view( nng_msg* m ) noexcept : m(m) {} 17 | 18 | nng_msg* get() const noexcept { 19 | return m; 20 | } 21 | 22 | nng_msg* operator->() const noexcept { 23 | return m; 24 | } 25 | 26 | explicit operator bool() const noexcept { 27 | return m != nullptr; 28 | } 29 | 30 | void realloc( size_t size ) const { 31 | int r = nng_msg_realloc(m,size); 32 | if( r != 0 ) { 33 | throw exception(r,"nng_msg_realloc"); 34 | } 35 | } 36 | 37 | msg_header header() const noexcept { 38 | return msg_header(m); 39 | } 40 | 41 | msg_body body() const noexcept { 42 | return msg_body(m); 43 | } 44 | 45 | void set_pipe( pipe_view p ) const noexcept { 46 | nng_msg_set_pipe(m,p.get()); 47 | } 48 | 49 | pipe_view get_pipe() const noexcept { 50 | return nng_msg_get_pipe(m); 51 | } 52 | }; 53 | 54 | } 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /include/nngpp/nngpp.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_NNGPP_H 2 | #define NNGPP_NNGPP_H 3 | #include "socket.h" 4 | #include "ctx.h" 5 | #include "dialer.h" 6 | #include "listener.h" 7 | #include "pipe.h" 8 | #include "aio.h" 9 | #include "url.h" 10 | #include "stat.h" 11 | #include "stream/dialer.h" 12 | #include "stream/listener.h" 13 | #include "stream/stream.h" 14 | #endif 15 | -------------------------------------------------------------------------------- /include/nngpp/option.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_OPTION_H 2 | #define NNGPP_OPTION_H 3 | #include 4 | 5 | namespace nng { 6 | 7 | enum option_type { 8 | bool_, 9 | int_, 10 | ms, 11 | size, 12 | uint64, 13 | ptr, 14 | string, 15 | addr, 16 | }; 17 | 18 | enum class option { 19 | socket_name, // string 20 | raw, // bool 21 | protocol, // int 22 | protocol_name, // string 23 | peer, // int 24 | peer_name, // string 25 | recv_buffer, // int 26 | send_buffer, // int 27 | recv_fd, // int 28 | send_fd, // int 29 | recv_timeout, // ms 30 | send_timeout, // ms 31 | local_address, // sockaddr 32 | remote_address, // sockaddr 33 | url, // string 34 | ttl_max, // int 35 | recv_size_max, // size 36 | reconnect_time_min, // ms 37 | reconnect_time_max // ms 38 | }; 39 | 40 | namespace detail { 41 | 42 | #if __cpp_inline_variables >= 201606 43 | inline 44 | #else 45 | static 46 | #endif 47 | constexpr const char* option_names[] = { 48 | NNG_OPT_SOCKNAME, 49 | NNG_OPT_RAW, 50 | NNG_OPT_PROTO, 51 | NNG_OPT_PROTONAME, 52 | NNG_OPT_PEER, 53 | NNG_OPT_PEERNAME, 54 | NNG_OPT_RECVBUF, 55 | NNG_OPT_SENDBUF, 56 | NNG_OPT_RECVFD, 57 | NNG_OPT_SENDFD, 58 | NNG_OPT_RECVTIMEO, 59 | NNG_OPT_SENDTIMEO, 60 | NNG_OPT_LOCADDR, 61 | NNG_OPT_REMADDR, 62 | NNG_OPT_URL, 63 | NNG_OPT_MAXTTL, 64 | NNG_OPT_RECVMAXSZ, 65 | NNG_OPT_RECONNMINT, 66 | NNG_OPT_RECONNMAXT 67 | }; 68 | 69 | #if __cpp_inline_variables >= 201606 70 | inline 71 | #else 72 | static 73 | #endif 74 | constexpr option_type option_types[] = { 75 | option_type::string, 76 | option_type::bool_, 77 | option_type::int_, 78 | option_type::string, 79 | option_type::int_, 80 | option_type::string, 81 | option_type::int_, 82 | option_type::int_, 83 | option_type::int_, 84 | option_type::int_, 85 | option_type::ms, 86 | option_type::ms, 87 | option_type::addr, 88 | option_type::addr, 89 | option_type::string, 90 | option_type::int_, 91 | option_type::size, 92 | option_type::ms, 93 | option_type::ms 94 | }; 95 | 96 | } 97 | 98 | constexpr const char* to_name( option o ) noexcept { 99 | return detail::option_names[(int)o]; 100 | } 101 | 102 | constexpr option_type to_type( option o ) noexcept { 103 | return detail::option_types[(int)o]; 104 | } 105 | 106 | } 107 | 108 | #endif 109 | -------------------------------------------------------------------------------- /include/nngpp/pipe.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_PIPE_H 2 | #define NNGPP_PIPE_H 3 | #include "pipe_view.h" 4 | 5 | namespace nng { 6 | 7 | struct pipe : pipe_view { 8 | 9 | pipe() = default; 10 | 11 | explicit pipe( nng_pipe p ) noexcept : pipe_view(p) {} 12 | 13 | pipe( const pipe& rhs ) = delete; 14 | 15 | pipe( pipe&& rhs ) noexcept : pipe_view(rhs.p) { 16 | rhs.p.id = 0; 17 | } 18 | 19 | pipe& operator=( const pipe& rhs ) = delete; 20 | 21 | pipe& operator=( pipe&& rhs ) { 22 | if( this != &rhs ) { 23 | if( p.id != 0 ) { 24 | int r = nng_pipe_close(p); 25 | if( r != 0 ) { 26 | throw exception(r,"nng_pipe_close"); 27 | } 28 | } 29 | p = rhs.p; 30 | rhs.p.id = 0; 31 | } 32 | return *this; 33 | } 34 | 35 | ~pipe() { 36 | if( p.id != 0 ) nng_pipe_close(p); 37 | } 38 | 39 | nng_pipe release() noexcept { 40 | auto out = p; 41 | p.id = 0; 42 | return out; 43 | } 44 | 45 | }; 46 | 47 | } 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /include/nngpp/pipe_view.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_PIPE_VIEW_H 2 | #define NNGPP_PIPE_VIEW_H 3 | #include "dialer_view.h" 4 | #include "listener_view.h" 5 | 6 | namespace nng { 7 | 8 | struct socket_view; 9 | 10 | struct pipe_view { 11 | protected: 12 | nng_pipe p{0}; 13 | 14 | public: 15 | pipe_view() = default; 16 | 17 | pipe_view( nng_pipe p ) noexcept : p(p) {} 18 | 19 | nng_pipe get() const noexcept { 20 | return p; 21 | } 22 | 23 | explicit operator bool() const noexcept { 24 | return p.id != 0; 25 | } 26 | 27 | int id() const noexcept { 28 | return nng_pipe_id(p); 29 | } 30 | 31 | size_t get_opt( const char* name, buffer& out ) const { 32 | size_t size = out.size(); 33 | int r = nng_pipe_get(p,name,out.data(),&size); 34 | if( r != 0 ) { 35 | throw exception(r,"nng_pipe_get"); 36 | } 37 | return size; 38 | } 39 | 40 | bool get_opt_bool( const char* name ) const { 41 | bool out; 42 | int r = nng_pipe_get_bool(p,name,&out); 43 | if( r != 0 ) { 44 | throw exception(r,"nng_pipe_get_bool"); 45 | } 46 | return out; 47 | } 48 | 49 | int get_opt_int( const char* name ) const { 50 | int out; 51 | int r = nng_pipe_get_int(p,name,&out); 52 | if( r != 0 ) { 53 | throw exception(r,"nng_pipe_get_int"); 54 | } 55 | return out; 56 | } 57 | 58 | size_t get_opt_size( const char* name ) const { 59 | size_t out; 60 | int r = nng_pipe_get_size(p,name,&out); 61 | if( r != 0 ) { 62 | throw exception(r,"nng_pipe_get_size"); 63 | } 64 | return out; 65 | } 66 | 67 | uint64_t get_opt_uint64( const char* name ) const { 68 | uint64_t out; 69 | int r = nng_pipe_get_uint64(p,name,&out); 70 | if( r != 0 ) { 71 | throw exception(r,"nng_pipe_get_uint64"); 72 | } 73 | return out; 74 | } 75 | 76 | buffer get_opt_string( const char* name ) const { 77 | char* data; 78 | int r = nng_pipe_get_string(p,name,&data); 79 | if( r != 0 ) { 80 | throw exception(r,"nng_pipe_get_string"); 81 | } 82 | return buffer(data,strlen(data)+1); 83 | } 84 | 85 | void* get_opt_ptr( const char* name ) const { 86 | void* out; 87 | int r = nng_pipe_get_ptr(p,name,&out); 88 | if( r != 0 ) { 89 | throw exception(r,"nng_pipe_get_ptr"); 90 | } 91 | return out; 92 | } 93 | 94 | nng_duration get_opt_ms( const char* name ) const { 95 | nng_duration out; 96 | int r = nng_pipe_get_ms(p,name,&out); 97 | if( r != 0 ) { 98 | throw exception(r,"nng_pipe_get_ms"); 99 | } 100 | return out; 101 | } 102 | 103 | nng_sockaddr get_opt_addr( const char* name ) const { 104 | nng_sockaddr out; 105 | int r = nng_pipe_get_addr(p,name,&out); 106 | if( r != 0 ) { 107 | throw exception(r,"nng_pipe_get_addr"); 108 | } 109 | return out; 110 | } 111 | 112 | socket_view get_socket() const noexcept; 113 | 114 | dialer_view get_dialer() const noexcept { 115 | return nng_pipe_dialer(p); 116 | } 117 | 118 | listener_view get_listener() const noexcept { 119 | return nng_pipe_listener(p); 120 | } 121 | 122 | }; 123 | 124 | inline nng_sockaddr get_opt_local_address( pipe_view s ) { 125 | return s.get_opt_addr( to_name(option::local_address) ); 126 | } 127 | 128 | inline nng_sockaddr get_opt_remote_address( pipe_view s ) { 129 | return s.get_opt_addr( to_name(option::remote_address) ); 130 | } 131 | 132 | } 133 | 134 | #endif 135 | -------------------------------------------------------------------------------- /include/nngpp/platform/cv.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_CV_H 2 | #define NNGPP_CV_H 3 | #include "cv_view.h" 4 | #include "mtx_view.h" 5 | 6 | namespace nng { 7 | 8 | struct cv : cv_view { 9 | 10 | cv() = default; 11 | 12 | explicit cv( nng_cv* c ) noexcept : cv_view(c) {} 13 | 14 | explicit cv( mtx_view mut ) { 15 | int r = nng_cv_alloc( &c, mut.get() ); 16 | if( r != 0 ) { 17 | throw exception(r,"nng_cv_alloc"); 18 | } 19 | } 20 | 21 | cv( const cv& rhs ) = delete; 22 | 23 | cv( cv&& rhs ) noexcept : cv_view(rhs.c) { 24 | rhs.c = nullptr; 25 | } 26 | 27 | cv& operator=( const cv& rhs ) = delete; 28 | 29 | cv& operator=( cv&& rhs ) noexcept { 30 | if( this != &rhs ) { 31 | if( c != nullptr ) nng_cv_free(c); 32 | c = rhs.c; 33 | rhs.c = nullptr; 34 | } 35 | return *this; 36 | } 37 | 38 | ~cv() { 39 | if( c != nullptr ) nng_cv_free(c); 40 | } 41 | 42 | nng_cv* release() noexcept { 43 | auto out = c; 44 | c = nullptr; 45 | return out; 46 | } 47 | 48 | }; 49 | 50 | inline cv make_cv( mtx_view mut ) { 51 | return cv(mut); 52 | } 53 | 54 | } 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /include/nngpp/platform/cv_view.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_CV_VIEW_H 2 | #define NNGPP_CV_VIEW_H 3 | #include 4 | #include 5 | 6 | namespace nng { 7 | 8 | struct cv_view { 9 | protected: 10 | nng_cv* c = nullptr; 11 | 12 | public: 13 | cv_view() = default; 14 | 15 | cv_view( nng_cv* c ) noexcept : c(c) {} 16 | 17 | nng_cv* get() const noexcept { 18 | return c; 19 | } 20 | 21 | nng_cv* operator->() const noexcept { 22 | return c; 23 | } 24 | 25 | explicit operator bool() const noexcept { 26 | return c != nullptr; 27 | } 28 | 29 | void wait() const noexcept { 30 | nng_cv_wait(c); 31 | } 32 | 33 | /** wait until time t 34 | * returns true if signalled, false if timed out 35 | */ 36 | bool wait_until( nng_time t ) const { 37 | int r = nng_cv_until(c,t); 38 | if( r != 0 && r != (int)error::timedout ) { 39 | throw exception(r,"nng_cv_until"); 40 | } 41 | return r == 0; 42 | } 43 | 44 | void wake_all() const noexcept { 45 | nng_cv_wake(c); 46 | } 47 | 48 | void wake_one() const noexcept { 49 | nng_cv_wake1(c); 50 | } 51 | 52 | }; 53 | 54 | } 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /include/nngpp/platform/mtx.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_MTX_H 2 | #define NNGPP_MTX_H 3 | #include "mtx_view.h" 4 | #include 5 | 6 | namespace nng { 7 | 8 | struct mtx : mtx_view { 9 | 10 | mtx() = default; 11 | 12 | explicit mtx( nng_mtx* m ) noexcept : mtx_view(m) {} 13 | 14 | mtx( const mtx& rhs ) = delete; 15 | 16 | mtx( mtx&& rhs ) noexcept : mtx_view(rhs.m) { 17 | rhs.m = nullptr; 18 | } 19 | 20 | mtx& operator=( const mtx& rhs ) = delete; 21 | 22 | mtx& operator=( mtx&& rhs ) noexcept { 23 | if( this != &rhs ) { 24 | if( m != nullptr ) nng_mtx_free(m); 25 | m = rhs.m; 26 | rhs.m = nullptr; 27 | } 28 | return *this; 29 | } 30 | 31 | ~mtx() { 32 | if( m != nullptr ) nng_mtx_free(m); 33 | } 34 | 35 | nng_mtx* release() noexcept { 36 | auto out = m; 37 | m = nullptr; 38 | return out; 39 | } 40 | 41 | }; 42 | 43 | inline mtx make_mtx() { 44 | nng_mtx* m; 45 | int r = nng_mtx_alloc( &m ); 46 | if( r != 0 ) { 47 | throw exception(r,"nng_mtx_alloc"); 48 | } 49 | return mtx(m); 50 | } 51 | 52 | } 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /include/nngpp/platform/mtx_view.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_MTX_VIEW_H 2 | #define NNGPP_MTX_VIEW_H 3 | #include 4 | #include 5 | 6 | namespace nng { 7 | 8 | struct mtx_view { 9 | protected: 10 | nng_mtx* m = nullptr; 11 | 12 | public: 13 | mtx_view() = default; 14 | 15 | mtx_view( nng_mtx* m ) noexcept : m(m) {} 16 | 17 | nng_mtx* get() const noexcept { 18 | return m; 19 | } 20 | 21 | nng_mtx* operator->() const noexcept { 22 | return m; 23 | } 24 | 25 | explicit operator bool() const noexcept { 26 | return m != nullptr; 27 | } 28 | 29 | void lock() const noexcept { 30 | nng_mtx_lock(m); 31 | } 32 | 33 | void unlock() const noexcept { 34 | nng_mtx_unlock(m); 35 | } 36 | 37 | }; 38 | 39 | } 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /include/nngpp/platform/platform.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_PLATFORM_H 2 | #define NNGPP_PLATFORM_H 3 | #include "cv.h" 4 | #include "mtx.h" 5 | #include "thread.h" 6 | 7 | namespace nng { 8 | 9 | inline nng_time clock() noexcept { 10 | return nng_clock(); 11 | } 12 | 13 | inline void msleep( nng_duration dt ) noexcept { 14 | nng_msleep(dt); 15 | } 16 | 17 | inline uint32_t random() noexcept { 18 | return nng_random(); 19 | } 20 | 21 | } 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /include/nngpp/platform/thread.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_THREAD_H 2 | #define NNGPP_THREAD_H 3 | #include "thread_view.h" 4 | #include 5 | 6 | namespace nng { 7 | 8 | struct thread : thread_view { 9 | 10 | thread() = default; 11 | 12 | explicit thread( nng_thread* t ) noexcept : thread_view(t) {} 13 | 14 | explicit thread( void(*f)(void*), void* arg ) { 15 | int r = nng_thread_create( &t, f, arg ); 16 | if( r != 0 ) { 17 | throw exception(r,"nng_thread_create"); 18 | } 19 | } 20 | 21 | thread( const thread& rhs ) = delete; 22 | 23 | thread( thread&& rhs ) noexcept : thread_view(rhs.t) { 24 | rhs.t = nullptr; 25 | } 26 | 27 | thread& operator=( const thread& rhs ) = delete; 28 | 29 | thread& operator=( thread&& rhs ) noexcept { 30 | if( this != &rhs ) { 31 | if( t != nullptr ) nng_thread_destroy(t); 32 | t = rhs.t; 33 | rhs.t = nullptr; 34 | } 35 | return *this; 36 | } 37 | 38 | ~thread() { 39 | if( t != nullptr ) nng_thread_destroy(t); 40 | } 41 | 42 | nng_thread* release() noexcept { 43 | auto out = t; 44 | t = nullptr; 45 | return out; 46 | } 47 | 48 | }; 49 | 50 | inline thread make_thread( void(*f)(void*), void* arg ) { 51 | return thread(f,arg); 52 | } 53 | 54 | } 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /include/nngpp/platform/thread_view.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_THREAD_VIEW_H 2 | #define NNGPP_THREAD_VIEW_H 3 | #include 4 | #include 5 | 6 | namespace nng { 7 | 8 | struct thread_view { 9 | protected: 10 | nng_thread* t = nullptr; 11 | 12 | public: 13 | thread_view() = default; 14 | 15 | thread_view( nng_thread* t ) noexcept : t(t) {} 16 | 17 | nng_thread* get() const noexcept { 18 | return t; 19 | } 20 | 21 | nng_thread* operator->() const noexcept { 22 | return t; 23 | } 24 | 25 | explicit operator bool() const noexcept { 26 | return t != nullptr; 27 | } 28 | 29 | void set_name(const char* name) const noexcept { 30 | nng_thread_set_name(t, name); 31 | } 32 | 33 | }; 34 | 35 | } 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /include/nngpp/protocol/bus0.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_BUS0_H 2 | #define NNGPP_BUS0_H 3 | #include 4 | #include 5 | 6 | namespace nng { namespace bus { 7 | inline namespace v0 { 8 | 9 | inline socket open() { 10 | nng_socket s; 11 | int r = nng_bus0_open(&s); 12 | if( r != 0 ) { 13 | throw exception(r,"nng_bus0_open"); 14 | } 15 | return socket(s); 16 | } 17 | 18 | inline socket open_raw() { 19 | nng_socket s; 20 | int r = nng_bus0_open_raw(&s); 21 | if( r != 0 ) { 22 | throw exception(r,"nng_bus0_open_raw"); 23 | } 24 | return socket(s); 25 | } 26 | 27 | } 28 | }} 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /include/nngpp/protocol/pair0.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_PAIR0_H 2 | #define NNGPP_PAIR0_H 3 | #include 4 | #include 5 | 6 | namespace nng { namespace pair { namespace v0 { 7 | 8 | inline socket open() { 9 | nng_socket s; 10 | int r = nng_pair0_open(&s); 11 | if( r != 0 ) { 12 | throw exception(r,"nng_pair0_open"); 13 | } 14 | return socket(s); 15 | } 16 | 17 | inline socket open_raw() { 18 | nng_socket s; 19 | int r = nng_pair0_open_raw(&s); 20 | if( r != 0 ) { 21 | throw exception(r,"nng_pair0_open_raw"); 22 | } 23 | return socket(s); 24 | } 25 | 26 | }}} 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /include/nngpp/protocol/pair1.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_PAIR1_H 2 | #define NNGPP_PAIR1_H 3 | #include 4 | #include 5 | 6 | namespace nng { namespace pair { 7 | inline namespace v1 { 8 | 9 | inline socket open() { 10 | nng_socket s; 11 | int r = nng_pair1_open(&s); 12 | if( r != 0 ) { 13 | throw exception(r,"nng_pair1_open"); 14 | } 15 | return socket(s); 16 | } 17 | 18 | inline socket open_raw() { 19 | nng_socket s; 20 | int r = nng_pair1_open_raw(&s); 21 | if( r != 0 ) { 22 | throw exception(r,"nng_pair1_open_raw"); 23 | } 24 | return socket(s); 25 | } 26 | 27 | inline socket open_poly() { 28 | nng_socket s; 29 | int r = nng_pair1_open_poly(&s); 30 | if( r != 0 ) { 31 | throw exception(r,"nng_pair1_open_poly"); 32 | } 33 | return socket(s); 34 | } 35 | 36 | enum class option { 37 | poly // bool 38 | }; 39 | 40 | namespace detail { 41 | 42 | #if __cpp_inline_variables >= 201606 43 | inline 44 | #else 45 | static 46 | #endif 47 | const char* const option_names[] = { 48 | NNG_OPT_PAIR1_POLY 49 | }; 50 | 51 | } 52 | 53 | inline const char* to_name( option o ) noexcept { 54 | return detail::option_names[(int)o]; 55 | } 56 | 57 | inline bool get_opt_poly( socket_view s ) { 58 | return s.get_opt_bool( to_name(option::poly) ); 59 | } 60 | 61 | } 62 | }} 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /include/nngpp/protocol/pub0.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_PUB0_H 2 | #define NNGPP_PUB0_H 3 | #include 4 | #include 5 | 6 | namespace nng { namespace pub { 7 | inline namespace v0 { 8 | 9 | inline socket open() { 10 | nng_socket s; 11 | int r = nng_pub0_open(&s); 12 | if( r != 0 ) { 13 | throw exception(r,"nng_pub0_open"); 14 | } 15 | return socket(s); 16 | } 17 | 18 | inline socket open_raw() { 19 | nng_socket s; 20 | int r = nng_pub0_open_raw(&s); 21 | if( r != 0 ) { 22 | throw exception(r,"nng_pub0_open_raw"); 23 | } 24 | return socket(s); 25 | } 26 | 27 | } 28 | }} 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /include/nngpp/protocol/pull0.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_PULL0_H 2 | #define NNGPP_PULL0_H 3 | #include 4 | #include 5 | 6 | namespace nng { namespace pull { 7 | inline namespace v0 { 8 | 9 | inline socket open() { 10 | nng_socket s; 11 | int r = nng_pull0_open(&s); 12 | if( r != 0 ) { 13 | throw exception(r,"nng_pull0_open"); 14 | } 15 | return socket(s); 16 | } 17 | 18 | inline socket open_raw() { 19 | nng_socket s; 20 | int r = nng_pull0_open_raw(&s); 21 | if( r != 0 ) { 22 | throw exception(r,"nng_pull0_open_raw"); 23 | } 24 | return socket(s); 25 | } 26 | 27 | } 28 | }} 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /include/nngpp/protocol/push0.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_PUSHE0_H 2 | #define NNGPP_PUSHE0_H 3 | #include 4 | #include 5 | 6 | namespace nng { namespace push { 7 | inline namespace v0 { 8 | 9 | inline socket open() { 10 | nng_socket s; 11 | int r = nng_push0_open(&s); 12 | if( r != 0 ) { 13 | throw exception(r,"nng_push0_open"); 14 | } 15 | return socket(s); 16 | } 17 | 18 | inline socket open_raw() { 19 | nng_socket s; 20 | int r = nng_push0_open_raw(&s); 21 | if( r != 0 ) { 22 | throw exception(r,"nng_push0_open_raw"); 23 | } 24 | return socket(s); 25 | } 26 | 27 | } 28 | }} 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /include/nngpp/protocol/rep0.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_REP0_H 2 | #define NNGPP_REP0_H 3 | #include 4 | #include 5 | 6 | namespace nng { namespace rep { 7 | inline namespace v0 { 8 | 9 | inline socket open() { 10 | nng_socket s; 11 | int r = nng_rep0_open(&s); 12 | if( r != 0 ) { 13 | throw exception(r,"nng_rep0_open"); 14 | } 15 | return socket(s); 16 | } 17 | 18 | inline socket open_raw() { 19 | nng_socket s; 20 | int r = nng_rep0_open_raw(&s); 21 | if( r != 0 ) { 22 | throw exception(r,"nng_rep0_open_raw"); 23 | } 24 | return socket(s); 25 | } 26 | 27 | } 28 | }} 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /include/nngpp/protocol/req0.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_REQ0_H 2 | #define NNGPP_REQ0_H 3 | #include 4 | #include 5 | 6 | namespace nng { namespace req { 7 | inline namespace v0 { 8 | 9 | inline socket open() { 10 | nng_socket s; 11 | int r = nng_req0_open(&s); 12 | if( r != 0 ) { 13 | throw exception(r,"nng_req0_open"); 14 | } 15 | return socket(s); 16 | } 17 | 18 | inline socket open_raw() { 19 | nng_socket s; 20 | int r = nng_req0_open_raw(&s); 21 | if( r != 0 ) { 22 | throw exception(r,"nng_req0_open_raw"); 23 | } 24 | return socket(s); 25 | } 26 | 27 | enum class option { 28 | resend_time // ms 29 | }; 30 | 31 | namespace detail { 32 | 33 | #if __cpp_inline_variables >= 201606 34 | inline 35 | #else 36 | static 37 | #endif 38 | const char* const option_names[] = { 39 | NNG_OPT_REQ_RESENDTIME 40 | }; 41 | 42 | } 43 | 44 | inline const char* to_name( option o ) noexcept { 45 | return detail::option_names[(int)o]; 46 | } 47 | 48 | inline nng_duration get_opt_resend_time( socket_view s ) { 49 | return s.get_opt_ms( to_name(option::resend_time) ); 50 | } 51 | 52 | inline void set_opt_resend_time( socket_view s, nng_duration v ) { 53 | s.set_opt_ms( to_name(option::resend_time), v ); 54 | } 55 | 56 | inline nng_duration get_opt_resend_time( ctx_view s ) { 57 | return s.get_opt_ms( to_name(option::resend_time) ); 58 | } 59 | 60 | inline void set_opt_resend_time( ctx_view s, nng_duration v ) { 61 | s.set_opt_ms( to_name(option::resend_time), v ); 62 | } 63 | 64 | } 65 | }} 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /include/nngpp/protocol/respond0.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_RESPOND0_H 2 | #define NNGPP_RESPOND0_H 3 | #include 4 | #include 5 | 6 | namespace nng { namespace respond { 7 | inline namespace v0 { 8 | 9 | inline socket open() { 10 | nng_socket s; 11 | int r = nng_respondent0_open(&s); 12 | if( r != 0 ) { 13 | throw exception(r,"nng_respondent0_open"); 14 | } 15 | return socket(s); 16 | } 17 | 18 | inline socket open_raw() { 19 | nng_socket s; 20 | int r = nng_respondent0_open_raw(&s); 21 | if( r != 0 ) { 22 | throw exception(r,"nng_respondent0_open_raw"); 23 | } 24 | return socket(s); 25 | } 26 | 27 | } 28 | }} 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /include/nngpp/protocol/sub0.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_SUB0_H 2 | #define NNGPP_SUB0_H 3 | #include 4 | #include 5 | 6 | namespace nng { namespace sub { 7 | inline namespace v0 { 8 | 9 | inline socket open() { 10 | nng_socket s; 11 | int r = nng_sub0_open(&s); 12 | if( r != 0 ) { 13 | throw exception(r,"nng_sub0_open"); 14 | } 15 | return socket(s); 16 | } 17 | 18 | inline socket open_raw() { 19 | nng_socket s; 20 | int r = nng_sub0_open_raw(&s); 21 | if( r != 0 ) { 22 | throw exception(r,"nng_sub0_open_raw"); 23 | } 24 | return socket(s); 25 | } 26 | 27 | enum class option { 28 | subscribe, // opaque 29 | unsubscribe, // opaque 30 | prefnew // bool 31 | }; 32 | 33 | namespace detail { 34 | 35 | #if __cpp_inline_variables >= 201606 36 | inline 37 | #else 38 | static 39 | #endif 40 | const char* const option_names[] = { 41 | NNG_OPT_SUB_SUBSCRIBE, 42 | NNG_OPT_SUB_UNSUBSCRIBE, 43 | NNG_OPT_SUB_PREFNEW 44 | }; 45 | 46 | } 47 | 48 | inline const char* to_name( option o ) noexcept { 49 | return detail::option_names[(int)o]; 50 | } 51 | 52 | inline void set_opt_subscribe( socket_view s, view v ) { 53 | s.set_opt( to_name(option::subscribe), v ); 54 | } 55 | 56 | inline void set_opt_unsubscribe( socket_view s, view v ) { 57 | s.set_opt( to_name(option::unsubscribe), v ); 58 | } 59 | 60 | inline bool get_opt_prefnew( socket_view s ) { 61 | return s.get_opt_bool( to_name(option::prefnew) ); 62 | } 63 | 64 | inline void set_opt_prefnew( socket_view s, bool v ) { 65 | s.set_opt_bool( to_name(option::prefnew), v ); 66 | } 67 | 68 | } 69 | }} 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /include/nngpp/protocol/survey0.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_SURVEY0_H 2 | #define NNGPP_SURVEY0_H 3 | #include 4 | #include 5 | 6 | namespace nng { namespace survey { 7 | inline namespace v0 { 8 | 9 | inline socket open() { 10 | nng_socket s; 11 | int r = nng_surveyor0_open(&s); 12 | if( r != 0 ) { 13 | throw exception(r,"nng_surveyor0_open"); 14 | } 15 | return socket(s); 16 | } 17 | 18 | inline socket open_raw() { 19 | nng_socket s; 20 | int r = nng_surveyor0_open_raw(&s); 21 | if( r != 0 ) { 22 | throw exception(r,"nng_surveyor0_open_raw"); 23 | } 24 | return socket(s); 25 | } 26 | 27 | enum class option { 28 | survey_time // ms 29 | }; 30 | 31 | namespace detail { 32 | 33 | #if __cpp_inline_variables >= 201606 34 | inline 35 | #else 36 | static 37 | #endif 38 | const char* const option_names[] = { 39 | NNG_OPT_SURVEYOR_SURVEYTIME 40 | }; 41 | 42 | } 43 | 44 | inline const char* to_name( option o ) noexcept { 45 | return detail::option_names[(int)o]; 46 | } 47 | 48 | inline nng_duration get_opt_survey_time( socket_view s ) { 49 | return s.get_opt_ms( to_name(option::survey_time) ); 50 | } 51 | 52 | inline void set_opt_survey_time( socket_view s, nng_duration v ) { 53 | s.set_opt_ms( to_name(option::survey_time), v ); 54 | } 55 | 56 | inline nng_duration get_opt_survey_time( ctx_view s ) { 57 | return s.get_opt_ms( to_name(option::survey_time) ); 58 | } 59 | 60 | inline void set_opt_survey_time( ctx_view s, nng_duration v ) { 61 | s.set_opt_ms( to_name(option::survey_time), v ); 62 | } 63 | 64 | } 65 | }} 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /include/nngpp/socket.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_SOCKET_H 2 | #define NNGPP_SOCKET_H 3 | #include "socket_view.h" 4 | 5 | namespace nng { 6 | 7 | struct socket : socket_view { 8 | 9 | socket() = default; 10 | 11 | explicit socket( nng_socket s ) noexcept : socket_view(s) {} 12 | 13 | socket( const socket& rhs ) = delete; 14 | 15 | socket( socket&& rhs ) noexcept : socket_view(rhs.s) { 16 | rhs.s.id = 0; 17 | } 18 | 19 | socket& operator=( const socket& rhs ) = delete; 20 | 21 | socket& operator=( socket&& rhs ) { 22 | if( this != &rhs ) { 23 | if( s.id != 0 ) { 24 | int r = nng_close(s); 25 | if( r != 0 && r != (int)nng::error::closed ) { 26 | throw exception(r,"nng_close"); 27 | } 28 | } 29 | s = rhs.s; 30 | rhs.s.id = 0; 31 | } 32 | return *this; 33 | } 34 | 35 | ~socket() { 36 | if( s.id != 0 ) nng_close(s); 37 | } 38 | 39 | nng_socket release() noexcept { 40 | auto out = s; 41 | s.id = 0; 42 | return out; 43 | } 44 | 45 | }; 46 | 47 | } 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /include/nngpp/stat.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_STAT_H 2 | #define NNGPP_STAT_H 3 | #include "stat_view.h" 4 | #include "error.h" 5 | 6 | namespace nng { 7 | 8 | struct stat : stat_view { 9 | 10 | stat() = default; 11 | 12 | explicit stat( nng_stat* s ) noexcept : stat_view(s) {} 13 | 14 | stat( const stat& rhs ) = delete; 15 | 16 | stat( stat&& rhs ) noexcept : stat_view(rhs.s) { 17 | rhs.s = nullptr; 18 | } 19 | 20 | stat& operator=( const stat& rhs ) = delete; 21 | 22 | stat& operator=( stat&& rhs ) noexcept { 23 | if( this != &rhs ) { 24 | if( s != nullptr ) nng_stats_free(s); 25 | s = rhs.s; 26 | rhs.s = nullptr; 27 | } 28 | return *this; 29 | } 30 | 31 | ~stat() { 32 | if( s != nullptr ) nng_stats_free(s); 33 | } 34 | 35 | nng_stat* release() noexcept { 36 | auto out = s; 37 | s = nullptr; 38 | return out; 39 | } 40 | 41 | }; 42 | 43 | inline stat make_stat() { 44 | nng_stat* s; 45 | int r = nng_stats_get(&s); 46 | if( r != 0 ) { 47 | throw exception(r,"nng_stats_get"); 48 | } 49 | return stat(s); 50 | } 51 | 52 | } 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /include/nngpp/stat_view.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_STAT_VIEW_H 2 | #define NNGPP_STAT_VIEW_H 3 | #include "socket_view.h" 4 | 5 | namespace nng { 6 | 7 | enum class stat_type { 8 | scope = NNG_STAT_SCOPE, 9 | level = NNG_STAT_LEVEL, 10 | counter = NNG_STAT_COUNTER, 11 | string = NNG_STAT_STRING, 12 | boolean = NNG_STAT_BOOLEAN, 13 | id = NNG_STAT_ID 14 | }; 15 | 16 | enum class stat_unit { 17 | none = NNG_UNIT_NONE, 18 | bytes = NNG_UNIT_BYTES, 19 | messages = NNG_UNIT_MESSAGES, 20 | millis = NNG_UNIT_MILLIS, 21 | events = NNG_UNIT_EVENTS 22 | }; 23 | 24 | struct stat_view { 25 | protected: 26 | nng_stat* s = nullptr; 27 | 28 | public: 29 | stat_view() = default; 30 | 31 | stat_view( nng_stat* s ) noexcept : s(s) {} 32 | 33 | nng_stat* get() const noexcept { 34 | return s; 35 | } 36 | 37 | nng_stat* operator->() const noexcept { 38 | return s; 39 | } 40 | 41 | explicit operator bool() const noexcept { 42 | return s != nullptr; 43 | } 44 | 45 | void dump() const noexcept { 46 | nng_stats_dump(s); 47 | } 48 | 49 | stat_view next() const noexcept { 50 | return nng_stat_next(s); 51 | } 52 | 53 | stat_view child() const noexcept { 54 | return nng_stat_child(s); 55 | } 56 | 57 | const char* name() const noexcept { 58 | return nng_stat_name(s); 59 | } 60 | 61 | stat_type type() const noexcept { 62 | return (stat_type)nng_stat_type(s); 63 | } 64 | 65 | stat_unit unit() const noexcept { 66 | return (stat_unit)nng_stat_unit(s); 67 | } 68 | 69 | uint64_t value() const noexcept { 70 | return nng_stat_value(s); 71 | } 72 | 73 | const char* string() const noexcept { 74 | return nng_stat_string(s); 75 | } 76 | 77 | const char* desc() const noexcept { 78 | return nng_stat_desc(s); 79 | } 80 | 81 | uint64_t timestamp() const noexcept { 82 | return nng_stat_timestamp(s); 83 | } 84 | 85 | stat_view find(const char* name) const noexcept { 86 | return nng_stat_find(s, name); 87 | } 88 | 89 | stat_view find(socket_view socket) const noexcept { 90 | return nng_stat_find_socket(s, socket.get()); 91 | } 92 | 93 | stat_view find(dialer_view dialer) const noexcept { 94 | return nng_stat_find_dialer(s, dialer.get()); 95 | } 96 | 97 | stat_view find(listener_view listener) const noexcept { 98 | return nng_stat_find_listener(s, listener.get()); 99 | } 100 | }; 101 | 102 | } 103 | 104 | #endif 105 | -------------------------------------------------------------------------------- /include/nngpp/stream/dialer.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_STREAM_DIALER_H 2 | #define NNGPP_STREAM_DIALER_H 3 | #include "dialer_view.h" 4 | #include 5 | 6 | namespace nng { namespace stream { 7 | 8 | struct dialer : dialer_view { 9 | 10 | dialer() = default; 11 | 12 | explicit dialer( nng_stream_dialer* d ) noexcept : dialer_view(d) {} 13 | 14 | explicit dialer( const char* url ) { 15 | int r = nng_stream_dialer_alloc( &d, url ); 16 | if( r != 0 ) { 17 | throw exception(r,"nng_stream_dialer_alloc"); 18 | } 19 | } 20 | 21 | explicit dialer( nng::url_view url ) { 22 | int r = nng_stream_dialer_alloc_url( &d, url.get() ); 23 | if( r != 0 ) { 24 | throw exception(r,"nng_stream_dialer_alloc_url"); 25 | } 26 | } 27 | 28 | dialer( const dialer& rhs ) = delete; 29 | 30 | dialer( dialer&& rhs ) noexcept : dialer_view(rhs.d) { 31 | rhs.d = nullptr; 32 | } 33 | 34 | dialer& operator=( const dialer& rhs ) = delete; 35 | 36 | dialer& operator=( dialer&& rhs ) noexcept { 37 | if( this != &rhs ) { 38 | if( d != nullptr ) nng_stream_dialer_free(d); 39 | d = rhs.d; 40 | rhs.d = nullptr; 41 | } 42 | return *this; 43 | } 44 | 45 | ~dialer() { 46 | if( d != nullptr ) nng_stream_dialer_free(d); 47 | } 48 | 49 | nng_stream_dialer* release() noexcept { 50 | auto out = d; 51 | d = nullptr; 52 | return out; 53 | } 54 | 55 | }; 56 | 57 | inline dialer make_dialer( const char* url ) { 58 | return dialer(url); 59 | } 60 | 61 | inline dialer make_dialer( nng::url_view url ) { 62 | return dialer(url); 63 | } 64 | 65 | }} 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /include/nngpp/stream/dialer_view.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_STREAM_DIALER_VIEW_H 2 | #define NNGPP_STREAM_DIALER_VIEW_H 3 | #include 4 | 5 | namespace nng { namespace stream { 6 | 7 | struct dialer_view { 8 | protected: 9 | nng_stream_dialer* d = nullptr; 10 | 11 | public: 12 | dialer_view() = default; 13 | 14 | dialer_view( nng_stream_dialer* d ) noexcept : d(d) {} 15 | 16 | nng_stream_dialer* get() const noexcept { 17 | return d; 18 | } 19 | 20 | nng_stream_dialer* operator->() const noexcept { 21 | return d; 22 | } 23 | 24 | explicit operator bool() const noexcept { 25 | return d != nullptr; 26 | } 27 | 28 | void close() const noexcept { 29 | nng_stream_dialer_close(d); 30 | } 31 | 32 | void dial( aio_view a ) const noexcept { 33 | nng_stream_dialer_dial(d,a.get()); 34 | } 35 | 36 | void get( const char* name, void* val, size_t* szp ) const { 37 | int r = nng_stream_dialer_get(d,name,val,szp); 38 | if( r != 0 ) { 39 | throw exception(r,"nng_stream_dialer_get"); 40 | } 41 | } 42 | 43 | template 44 | T get( const char* name ) const { 45 | T out; 46 | size_t size = sizeof(out); 47 | get(name,&out,&size); 48 | return out; 49 | } 50 | 51 | bool get_bool( const char* name ) const { 52 | bool out; 53 | int r = nng_stream_dialer_get_bool(d,name,&out); 54 | if( r != 0 ) { 55 | throw exception(r,"nng_stream_dialer_get_bool"); 56 | } 57 | return out; 58 | } 59 | 60 | int get_int( const char* name ) const { 61 | int out; 62 | int r = nng_stream_dialer_get_int(d,name,&out); 63 | if( r != 0 ) { 64 | throw exception(r,"nng_stream_dialer_get_int"); 65 | } 66 | return out; 67 | } 68 | 69 | size_t get_size( const char* name ) const { 70 | size_t out; 71 | int r = nng_stream_dialer_get_size(d,name,&out); 72 | if( r != 0 ) { 73 | throw exception(r,"nng_stream_dialer_get_size"); 74 | } 75 | return out; 76 | } 77 | 78 | uint64_t get_uint64( const char* name ) const { 79 | uint64_t out; 80 | int r = nng_stream_dialer_get_uint64(d,name,&out); 81 | if( r != 0 ) { 82 | throw exception(r,"nng_stream_dialer_get_uint64"); 83 | } 84 | return out; 85 | } 86 | 87 | buffer get_string( const char* name ) const { 88 | char* data; 89 | int r = nng_stream_dialer_get_string(d,name,&data); 90 | if( r != 0 ) { 91 | throw exception(r,"nng_stream_dialer_get_string"); 92 | } 93 | return buffer(data,strlen(data)+1); 94 | } 95 | 96 | void* get_ptr( const char* name ) const { 97 | void* out; 98 | int r = nng_stream_dialer_get_ptr(d,name,&out); 99 | if( r != 0 ) { 100 | throw exception(r,"nng_stream_dialer_get_ptr"); 101 | } 102 | return out; 103 | } 104 | 105 | nng_duration get_ms( const char* name ) const { 106 | nng_duration out; 107 | int r = nng_stream_dialer_get_ms(d,name,&out); 108 | if( r != 0 ) { 109 | throw exception(r,"nng_stream_dialer_get_ms"); 110 | } 111 | return out; 112 | } 113 | 114 | nng_sockaddr get_addr( const char* name ) const { 115 | nng_sockaddr data; 116 | int r = nng_stream_dialer_get_addr(d,name,&data); 117 | if( r != 0 ) { 118 | throw exception(r,"nng_stream_dialer_get_addr"); 119 | } 120 | return data; 121 | } 122 | 123 | void set( const char* name, const void* val, size_t sz ) const { 124 | int r = nng_stream_dialer_set(d,name,val,sz); 125 | if( r != 0 ) { 126 | throw exception(r,"nng_stream_dialer_set"); 127 | } 128 | } 129 | 130 | template 131 | void set( const char* name, const T& v ) const { 132 | set(name,&v,sizeof(v)); 133 | } 134 | 135 | void set_bool( const char* name, bool value ) const { 136 | int r = nng_stream_dialer_set_bool(d,name,value); 137 | if( r != 0 ) { 138 | throw exception(r,"nng_stream_dialer_set_bool"); 139 | } 140 | } 141 | 142 | void set_int( const char* name, int value ) const { 143 | int r = nng_stream_dialer_set_int(d,name,value); 144 | if( r != 0 ) { 145 | throw exception(r,"nng_stream_dialer_set_int"); 146 | } 147 | } 148 | 149 | void set_size( const char* name, size_t value ) const { 150 | int r = nng_stream_dialer_set_size(d,name,value); 151 | if( r != 0 ) { 152 | throw exception(r,"nng_stream_dialer_set_size"); 153 | } 154 | } 155 | 156 | void set_uint64( const char* name, uint64_t value ) const { 157 | int r = nng_stream_dialer_set_uint64(d,name,value); 158 | if( r != 0 ) { 159 | throw exception(r,"nng_stream_dialer_set_uint64"); 160 | } 161 | } 162 | 163 | void set_string( const char* name, const char* value ) const { 164 | int r = nng_stream_dialer_set_string(d,name,value); 165 | if( r != 0 ) { 166 | throw exception(r,"nng_stream_dialer_set_string"); 167 | } 168 | } 169 | 170 | void set_ptr( const char* name, void* value ) const { 171 | int r = nng_stream_dialer_set_ptr(d,name,value); 172 | if( r != 0 ) { 173 | throw exception(r,"nng_stream_dialer_set_ptr"); 174 | } 175 | } 176 | 177 | void set_ms( const char* name, nng_duration value ) const { 178 | int r = nng_stream_dialer_set_ms(d,name,value); 179 | if( r != 0 ) { 180 | throw exception(r,"nng_stream_dialer_set_ms"); 181 | } 182 | } 183 | 184 | void set_addr( const char* name, const nng_sockaddr* value ) const { 185 | int r = nng_stream_dialer_set_addr(d,name,value); 186 | if( r != 0 ) { 187 | throw exception(r,"nng_stream_dialer_set_addr"); 188 | } 189 | } 190 | 191 | }; 192 | 193 | }} 194 | 195 | #endif 196 | -------------------------------------------------------------------------------- /include/nngpp/stream/listener.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_STREAM_LISTENER_H 2 | #define NNGPP_STREAM_LISTENER_H 3 | #include "listener_view.h" 4 | #include 5 | 6 | namespace nng { namespace stream { 7 | 8 | struct listener : listener_view { 9 | 10 | listener() = default; 11 | 12 | explicit listener( nng_stream_listener* d ) noexcept : listener_view(d) {} 13 | 14 | explicit listener( const char* url ) { 15 | int r = nng_stream_listener_alloc( &d, url ); 16 | if( r != 0 ) { 17 | throw exception(r,"nng_stream_listener_alloc"); 18 | } 19 | } 20 | 21 | explicit listener( nng::url_view url ) { 22 | int r = nng_stream_listener_alloc_url( &d, url.get() ); 23 | if( r != 0 ) { 24 | throw exception(r,"nng_stream_listener_alloc_url"); 25 | } 26 | } 27 | 28 | listener( const listener& rhs ) = delete; 29 | 30 | listener( listener&& rhs ) noexcept : listener_view(rhs.d) { 31 | rhs.d = nullptr; 32 | } 33 | 34 | listener& operator=( const listener& rhs ) = delete; 35 | 36 | listener& operator=( listener&& rhs ) noexcept { 37 | if( this != &rhs ) { 38 | if( d != nullptr ) nng_stream_listener_free(d); 39 | d = rhs.d; 40 | rhs.d = nullptr; 41 | } 42 | return *this; 43 | } 44 | 45 | ~listener() { 46 | if( d != nullptr ) nng_stream_listener_free(d); 47 | } 48 | 49 | nng_stream_listener* release() noexcept { 50 | auto out = d; 51 | d = nullptr; 52 | return out; 53 | } 54 | 55 | }; 56 | 57 | inline listener make_listener( const char* url ) { 58 | return listener(url); 59 | } 60 | 61 | inline listener make_listener( nng::url_view url ) { 62 | return listener(url); 63 | } 64 | 65 | }} 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /include/nngpp/stream/listener_view.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_STREAM_LISTENER_VIEW_H 2 | #define NNGPP_STREAM_LISTENER_VIEW_H 3 | #include 4 | 5 | namespace nng { namespace stream { 6 | 7 | struct listener_view { 8 | protected: 9 | nng_stream_listener* d = nullptr; 10 | 11 | public: 12 | listener_view() = default; 13 | 14 | listener_view( nng_stream_listener* d ) noexcept : d(d) {} 15 | 16 | nng_stream_listener* get() const noexcept { 17 | return d; 18 | } 19 | 20 | nng_stream_listener* operator->() const noexcept { 21 | return d; 22 | } 23 | 24 | explicit operator bool() const noexcept { 25 | return d != nullptr; 26 | } 27 | 28 | void close() const noexcept { 29 | nng_stream_listener_close(d); 30 | } 31 | 32 | void listen() const { 33 | int r = nng_stream_listener_listen(d); 34 | if( r != 0 ) { 35 | throw exception(r,"nng_stream_listener_listen"); 36 | } 37 | } 38 | 39 | void accept( aio_view a ) const noexcept { 40 | nng_stream_listener_accept(d,a.get()); 41 | } 42 | 43 | void get( const char* name, void* val, size_t* szp ) const { 44 | int r = nng_stream_listener_get(d,name,val,szp); 45 | if( r != 0 ) { 46 | throw exception(r,"nng_stream_listener_get"); 47 | } 48 | } 49 | 50 | template 51 | T get( const char* name ) const { 52 | T out; 53 | size_t size = sizeof(out); 54 | get(name,&out,&size); 55 | return out; 56 | } 57 | 58 | bool get_bool( const char* name ) const { 59 | bool out; 60 | int r = nng_stream_listener_get_bool(d,name,&out); 61 | if( r != 0 ) { 62 | throw exception(r,"nng_stream_listener_get_bool"); 63 | } 64 | return out; 65 | } 66 | 67 | int get_int( const char* name ) const { 68 | int out; 69 | int r = nng_stream_listener_get_int(d,name,&out); 70 | if( r != 0 ) { 71 | throw exception(r,"nng_stream_listener_get_int"); 72 | } 73 | return out; 74 | } 75 | 76 | size_t get_size( const char* name ) const { 77 | size_t out; 78 | int r = nng_stream_listener_get_size(d,name,&out); 79 | if( r != 0 ) { 80 | throw exception(r,"nng_stream_listener_get_size"); 81 | } 82 | return out; 83 | } 84 | 85 | uint64_t get_uint64( const char* name ) const { 86 | uint64_t out; 87 | int r = nng_stream_listener_get_uint64(d,name,&out); 88 | if( r != 0 ) { 89 | throw exception(r,"nng_stream_listener_get_uint64"); 90 | } 91 | return out; 92 | } 93 | 94 | buffer get_string( const char* name ) const { 95 | char* data; 96 | int r = nng_stream_listener_get_string(d,name,&data); 97 | if( r != 0 ) { 98 | throw exception(r,"nng_stream_listener_get_string"); 99 | } 100 | return buffer(data,strlen(data)+1); 101 | } 102 | 103 | void* get_ptr( const char* name ) const { 104 | void* out; 105 | int r = nng_stream_listener_get_ptr(d,name,&out); 106 | if( r != 0 ) { 107 | throw exception(r,"nng_stream_listener_get_ptr"); 108 | } 109 | return out; 110 | } 111 | 112 | nng_duration get_ms( const char* name ) const { 113 | nng_duration out; 114 | int r = nng_stream_listener_get_ms(d,name,&out); 115 | if( r != 0 ) { 116 | throw exception(r,"nng_stream_listener_get_ms"); 117 | } 118 | return out; 119 | } 120 | 121 | nng_sockaddr get_addr( const char* name ) const { 122 | nng_sockaddr data; 123 | int r = nng_stream_listener_get_addr(d,name,&data); 124 | if( r != 0 ) { 125 | throw exception(r,"nng_stream_listener_get_addr"); 126 | } 127 | return data; 128 | } 129 | 130 | void set( const char* name, const void* val, size_t sz ) const { 131 | int r = nng_stream_listener_set(d,name,val,sz); 132 | if( r != 0 ) { 133 | throw exception(r,"nng_stream_listener_set"); 134 | } 135 | } 136 | 137 | template 138 | void set( const char* name, const T& v ) const { 139 | set(name,&v,sizeof(v)); 140 | } 141 | 142 | void set_bool( const char* name, bool value ) const { 143 | int r = nng_stream_listener_set_bool(d,name,value); 144 | if( r != 0 ) { 145 | throw exception(r,"nng_stream_listener_set_bool"); 146 | } 147 | } 148 | 149 | void set_int( const char* name, int value ) const { 150 | int r = nng_stream_listener_set_int(d,name,value); 151 | if( r != 0 ) { 152 | throw exception(r,"nng_stream_listener_set_int"); 153 | } 154 | } 155 | 156 | void set_size( const char* name, size_t value ) const { 157 | int r = nng_stream_listener_set_size(d,name,value); 158 | if( r != 0 ) { 159 | throw exception(r,"nng_stream_listener_set_size"); 160 | } 161 | } 162 | 163 | void set_uint64( const char* name, uint64_t value ) const { 164 | int r = nng_stream_listener_set_uint64(d,name,value); 165 | if( r != 0 ) { 166 | throw exception(r,"nng_stream_listener_set_uint64"); 167 | } 168 | } 169 | 170 | void set_string( const char* name, const char* value ) const { 171 | int r = nng_stream_listener_set_string(d,name,value); 172 | if( r != 0 ) { 173 | throw exception(r,"nng_stream_listener_set_string"); 174 | } 175 | } 176 | 177 | void set_ptr( const char* name, void* value ) const { 178 | int r = nng_stream_listener_set_ptr(d,name,value); 179 | if( r != 0 ) { 180 | throw exception(r,"nng_stream_listener_set_ptr"); 181 | } 182 | } 183 | 184 | void set_ms( const char* name, nng_duration value ) const { 185 | int r = nng_stream_listener_set_ms(d,name,value); 186 | if( r != 0 ) { 187 | throw exception(r,"nng_stream_listener_set_ms"); 188 | } 189 | } 190 | 191 | void set_addr( const char* name, const nng_sockaddr* value ) const { 192 | int r = nng_stream_listener_set_addr(d,name,value); 193 | if( r != 0 ) { 194 | throw exception(r,"nng_stream_listener_set_addr"); 195 | } 196 | } 197 | 198 | }; 199 | 200 | }} 201 | 202 | #endif 203 | -------------------------------------------------------------------------------- /include/nngpp/stream/stream.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_STREAM_STREAM_H 2 | #define NNGPP_STREAM_STREAM_H 3 | #include "stream_view.h" 4 | #include "dialer.h" 5 | #include "listener.h" 6 | 7 | namespace nng { namespace stream { 8 | 9 | struct stream : stream_view { 10 | 11 | stream() = default; 12 | 13 | explicit stream( nng_stream* s ) noexcept : stream_view(s) {} 14 | 15 | stream( const stream& rhs ) = delete; 16 | 17 | stream( stream&& rhs ) noexcept : stream_view(rhs.s) { 18 | rhs.s = nullptr; 19 | } 20 | 21 | stream& operator=( const stream& rhs ) = delete; 22 | 23 | stream& operator=( stream&& rhs ) noexcept { 24 | if( this != &rhs ) { 25 | if( s != nullptr ) nng_stream_free(s); 26 | s = rhs.s; 27 | rhs.s = nullptr; 28 | } 29 | return *this; 30 | } 31 | 32 | ~stream() { 33 | if( s != nullptr ) nng_stream_free(s); 34 | } 35 | 36 | nng_stream* release() noexcept { 37 | auto out = s; 38 | s = nullptr; 39 | return out; 40 | } 41 | 42 | }; 43 | 44 | }} 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /include/nngpp/stream/stream_view.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_STREAM_STREAM_VIEW_H 2 | #define NNGPP_STREAM_STREAM_VIEW_H 3 | #include 4 | 5 | namespace nng { namespace stream { 6 | 7 | struct stream_view { 8 | protected: 9 | nng_stream* s = nullptr; 10 | 11 | public: 12 | stream_view() = default; 13 | 14 | stream_view( nng_stream* s ) noexcept : s(s) {} 15 | 16 | nng_stream* get() const noexcept { 17 | return s; 18 | } 19 | 20 | nng_stream* operator->() const noexcept { 21 | return s; 22 | } 23 | 24 | explicit operator bool() const noexcept { 25 | return s != nullptr; 26 | } 27 | 28 | void close() const noexcept { 29 | nng_stream_close(s); 30 | } 31 | 32 | void send( nng::aio_view a ) const noexcept { 33 | nng_stream_send(s,a.get()); 34 | } 35 | 36 | void recv( nng::aio_view a ) const noexcept { 37 | nng_stream_recv(s,a.get()); 38 | } 39 | 40 | void get( const char* name, void* val, size_t* szp ) const { 41 | int r = nng_stream_get(s,name,val,szp); 42 | if( r != 0 ) { 43 | throw exception(r,"nng_stream_get"); 44 | } 45 | } 46 | 47 | template 48 | T get( const char* name ) const { 49 | T out; 50 | size_t size = sizeof(out); 51 | get(name,&out,&size); 52 | return out; 53 | } 54 | 55 | bool get_bool( const char* name ) const { 56 | bool out; 57 | int r = nng_stream_get_bool(s,name,&out); 58 | if( r != 0 ) { 59 | throw exception(r,"nng_stream_get_bool"); 60 | } 61 | return out; 62 | } 63 | 64 | int get_int( const char* name ) const { 65 | int out; 66 | int r = nng_stream_get_int(s,name,&out); 67 | if( r != 0 ) { 68 | throw exception(r,"nng_stream_get_int"); 69 | } 70 | return out; 71 | } 72 | 73 | size_t get_size( const char* name ) const { 74 | size_t out; 75 | int r = nng_stream_get_size(s,name,&out); 76 | if( r != 0 ) { 77 | throw exception(r,"nng_stream_get_size"); 78 | } 79 | return out; 80 | } 81 | 82 | uint64_t get_uint64( const char* name ) const { 83 | uint64_t out; 84 | int r = nng_stream_get_uint64(s,name,&out); 85 | if( r != 0 ) { 86 | throw exception(r,"nng_stream_get_uint64"); 87 | } 88 | return out; 89 | } 90 | 91 | buffer get_string( const char* name ) const { 92 | char* data; 93 | int r = nng_stream_get_string(s,name,&data); 94 | if( r != 0 ) { 95 | throw exception(r,"nng_stream_get_string"); 96 | } 97 | return buffer(data,strlen(data)+1); 98 | } 99 | 100 | void* get_ptr( const char* name ) const { 101 | void* out; 102 | int r = nng_stream_get_ptr(s,name,&out); 103 | if( r != 0 ) { 104 | throw exception(r,"nng_stream_get_ptr"); 105 | } 106 | return out; 107 | } 108 | 109 | nng_duration get_ms( const char* name ) const { 110 | nng_duration out; 111 | int r = nng_stream_get_ms(s,name,&out); 112 | if( r != 0 ) { 113 | throw exception(r,"nng_stream_get_ms"); 114 | } 115 | return out; 116 | } 117 | 118 | nng_sockaddr get_addr( const char* name ) const { 119 | nng_sockaddr data; 120 | int r = nng_stream_get_addr(s,name,&data); 121 | if( r != 0 ) { 122 | throw exception(r,"nng_stream_get_addr"); 123 | } 124 | return data; 125 | } 126 | 127 | void set( const char* name, const void* val, size_t sz ) const { 128 | int r = nng_stream_set(s,name,val,sz); 129 | if( r != 0 ) { 130 | throw exception(r,"nng_stream_set"); 131 | } 132 | } 133 | 134 | template 135 | void set( const char* name, const T& v ) const { 136 | set(name,&v,sizeof(v)); 137 | } 138 | 139 | void set_bool( const char* name, bool value ) const { 140 | int r = nng_stream_set_bool(s,name,value); 141 | if( r != 0 ) { 142 | throw exception(r,"nng_stream_set_bool"); 143 | } 144 | } 145 | 146 | void set_int( const char* name, int value ) const { 147 | int r = nng_stream_set_int(s,name,value); 148 | if( r != 0 ) { 149 | throw exception(r,"nng_stream_set_int"); 150 | } 151 | } 152 | 153 | void set_size( const char* name, size_t value ) const { 154 | int r = nng_stream_set_size(s,name,value); 155 | if( r != 0 ) { 156 | throw exception(r,"nng_stream_set_size"); 157 | } 158 | } 159 | 160 | void set_uint64( const char* name, uint64_t value ) const { 161 | int r = nng_stream_set_uint64(s,name,value); 162 | if( r != 0 ) { 163 | throw exception(r,"nng_stream_set_uint64"); 164 | } 165 | } 166 | 167 | void set_string( const char* name, const char* value ) const { 168 | int r = nng_stream_set_string(s,name,value); 169 | if( r != 0 ) { 170 | throw exception(r,"nng_stream_set_string"); 171 | } 172 | } 173 | 174 | void set_ptr( const char* name, void* value ) const { 175 | int r = nng_stream_set_ptr(s,name,value); 176 | if( r != 0 ) { 177 | throw exception(r,"nng_stream_set_ptr"); 178 | } 179 | } 180 | 181 | void set_ms( const char* name, nng_duration value ) const { 182 | int r = nng_stream_set_ms(s,name,value); 183 | if( r != 0 ) { 184 | throw exception(r,"nng_stream_set_ms"); 185 | } 186 | } 187 | 188 | void set_addr( const char* name, const nng_sockaddr& value ) const { 189 | int r = nng_stream_set_addr(s,name,&value); 190 | if( r != 0 ) { 191 | throw exception(r,"nng_stream_set_addr"); 192 | } 193 | } 194 | 195 | }; 196 | 197 | }} 198 | 199 | #endif 200 | -------------------------------------------------------------------------------- /include/nngpp/transport/inproc.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_TRANSPORT_INPROC_H 2 | #define NNGPP_TRANSPORT_INPROC_H 3 | #include 4 | #include 5 | 6 | namespace nng { namespace inproc { 7 | 8 | inline void register_transport() { 9 | int r = nng_inproc_register(); 10 | if( r != 0 ) { 11 | throw exception(r,"nng_inproc_register"); 12 | } 13 | } 14 | 15 | }} 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /include/nngpp/transport/ipc.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_TRANSPORT_IPC_H 2 | #define NNGPP_TRANSPORT_IPC_H 3 | #include 4 | #include 5 | #include 6 | 7 | namespace nng { namespace ipc { 8 | 9 | inline void register_transport() { 10 | int r = nng_ipc_register(); 11 | if( r != 0 ) { 12 | throw exception(r,"nng_ipc_register"); 13 | } 14 | } 15 | 16 | enum class option { 17 | peer_uid, // u64 18 | peer_gid, // u64 19 | peer_pid, // u64 20 | peer_zoneid, // u64 21 | security_descriptor, // pointer 22 | permissions // int 23 | }; 24 | 25 | namespace detail { 26 | 27 | #if __cpp_inline_variables >= 201606 28 | inline 29 | #else 30 | static 31 | #endif 32 | const char* const option_names[] = { 33 | NNG_OPT_IPC_PEER_UID, 34 | NNG_OPT_IPC_PEER_GID, 35 | NNG_OPT_IPC_PEER_PID, 36 | NNG_OPT_IPC_PEER_ZONEID, 37 | NNG_OPT_IPC_SECURITY_DESCRIPTOR, 38 | NNG_OPT_IPC_PERMISSIONS 39 | }; 40 | 41 | } 42 | 43 | inline const char* to_name( option o ) noexcept { 44 | return detail::option_names[(int)o]; 45 | } 46 | 47 | inline uint64_t get_opt_peer_uid( nng::pipe_view s ) { 48 | return s.get_opt_uint64( to_name(option::peer_uid) ); 49 | } 50 | 51 | inline uint64_t get_opt_peer_gid( nng::pipe_view s ) { 52 | return s.get_opt_uint64( to_name(option::peer_gid) ); 53 | } 54 | 55 | inline uint64_t get_opt_peer_pid( nng::pipe_view s ) { 56 | return s.get_opt_uint64( to_name(option::peer_pid) ); 57 | } 58 | 59 | inline uint64_t get_opt_peer_zoneid( nng::pipe_view s ) { 60 | return s.get_opt_uint64( to_name(option::peer_zoneid) ); 61 | } 62 | 63 | inline void set_opt_security_descriptor( nng::listener_view s, void* v ) { 64 | s.set_opt_ptr( to_name(option::security_descriptor), v ); 65 | } 66 | 67 | inline void set_opt_permissions( nng::listener_view s, int v ) { 68 | s.set_opt_int( to_name(option::permissions), v ); 69 | } 70 | 71 | }} 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /include/nngpp/transport/tcp.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_TRANSPORT_TCP_H 2 | #define NNGPP_TRANSPORT_TCP_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace nng { namespace tcp { 10 | 11 | inline void register_transport() { 12 | int r = nng_tcp_register(); 13 | if( r != 0 ) { 14 | throw exception(r,"nng_tcp_register"); 15 | } 16 | } 17 | 18 | enum class option { 19 | no_delay, 20 | keep_alive, 21 | bound_port 22 | }; 23 | 24 | namespace detail { 25 | 26 | #if __cpp_inline_variables >= 201606 27 | inline 28 | #else 29 | static 30 | #endif 31 | const char* const option_names[] = { 32 | NNG_OPT_TCP_NODELAY, // bool 33 | NNG_OPT_TCP_KEEPALIVE, // bool 34 | NNG_OPT_TCP_BOUND_PORT // int 35 | }; 36 | 37 | } 38 | 39 | inline const char* to_name( option o ) noexcept { 40 | return detail::option_names[(int)o]; 41 | } 42 | 43 | inline bool get_opt_no_delay( nng::pipe_view s ) { 44 | return s.get_opt_bool( to_name(option::no_delay) ); 45 | } 46 | 47 | inline bool get_opt_keep_alive( nng::pipe_view s ) { 48 | return s.get_opt_bool( to_name(option::keep_alive) ); 49 | } 50 | 51 | inline int get_opt_bound_port( nng::pipe_view s ) { 52 | return s.get_opt_int( to_name(option::bound_port) ); 53 | } 54 | 55 | inline bool get_opt_no_delay( nng::dialer_view s ) { 56 | return s.get_opt_bool( to_name(option::no_delay) ); 57 | } 58 | 59 | inline bool get_opt_keep_alive( nng::dialer_view s ) { 60 | return s.get_opt_bool( to_name(option::keep_alive) ); 61 | } 62 | 63 | inline bool get_opt_no_delay( nng::listener_view s ) { 64 | return s.get_opt_bool( to_name(option::no_delay) ); 65 | } 66 | 67 | inline bool get_opt_keep_alive( nng::listener_view s ) { 68 | return s.get_opt_bool( to_name(option::keep_alive) ); 69 | } 70 | 71 | inline int get_opt_bound_port( nng::listener_view s ) { 72 | return s.get_opt_int( to_name(option::bound_port) ); 73 | } 74 | 75 | inline bool get_opt_no_delay( nng::socket_view s ) { 76 | return s.get_opt_bool( to_name(option::no_delay) ); 77 | } 78 | 79 | inline bool get_opt_keep_alive( nng::socket_view s ) { 80 | return s.get_opt_bool( to_name(option::keep_alive) ); 81 | } 82 | 83 | inline void set_opt_no_delay( nng::dialer_view s, bool v ) { 84 | s.set_opt_bool( to_name(option::no_delay), v ); 85 | } 86 | 87 | inline void set_opt_keep_alive( nng::dialer_view s, bool v ) { 88 | s.set_opt_bool( to_name(option::keep_alive), v ); 89 | } 90 | 91 | inline void set_opt_no_delay( nng::listener_view s, bool v ) { 92 | s.set_opt_bool( to_name(option::no_delay), v ); 93 | } 94 | 95 | inline void set_opt_keep_alive( nng::listener_view s, bool v ) { 96 | s.set_opt_bool( to_name(option::keep_alive), v ); 97 | } 98 | 99 | inline void set_opt_no_delay( nng::socket_view s, bool v ) { 100 | s.set_opt_bool( to_name(option::no_delay), v ); 101 | } 102 | 103 | inline void set_opt_keep_alive( nng::socket_view s, bool v ) { 104 | s.set_opt_bool( to_name(option::keep_alive), v ); 105 | } 106 | 107 | }} 108 | 109 | #endif 110 | -------------------------------------------------------------------------------- /include/nngpp/transport/tls.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_TRANSPORT_TLS_H 2 | #define NNGPP_TRANSPORT_TLS_H 3 | #include 4 | #include 5 | #include 6 | #include "tls/config.h" 7 | #include 8 | 9 | namespace nng { namespace tls { 10 | 11 | inline void register_transport() { 12 | int r = nng_tls_register(); 13 | if( r != 0 ) { 14 | throw exception(r,"nng_tls_register"); 15 | } 16 | } 17 | 18 | enum class option { 19 | config, // ptr 20 | auth_mode, // int 21 | cert_key_file, // string 22 | ca_file, // string 23 | server_name, // string 24 | verified // bool 25 | }; 26 | 27 | namespace detail { 28 | 29 | #if __cpp_inline_variables >= 201606 30 | inline 31 | #else 32 | static 33 | #endif 34 | const char* const option_names[] = { 35 | NNG_OPT_TLS_CONFIG, 36 | NNG_OPT_TLS_AUTH_MODE, 37 | NNG_OPT_TLS_CERT_KEY_FILE, 38 | NNG_OPT_TLS_CA_FILE, 39 | NNG_OPT_TLS_SERVER_NAME, 40 | NNG_OPT_TLS_VERIFIED 41 | }; 42 | 43 | } 44 | 45 | inline const char* to_name( option o ) noexcept { 46 | return detail::option_names[(int)o]; 47 | } 48 | 49 | inline bool get_opt_verified( nng::pipe_view s ) { 50 | return s.get_opt_bool( to_name(option::verified) ); 51 | } 52 | 53 | inline config_view get_opt_config( nng::dialer_view s ) { 54 | return (nng_tls_config*)s.get_opt_ptr( to_name(option::config) ); 55 | } 56 | 57 | inline config_view get_opt_config( nng::listener_view s ) { 58 | return (nng_tls_config*)s.get_opt_ptr( to_name(option::config) ); 59 | } 60 | 61 | inline void set_opt_config( nng::dialer_view s, config_view v ) { 62 | s.set_opt_ptr( to_name(option::config), v.get() ); 63 | } 64 | 65 | inline void set_opt_config( nng::listener_view s, config_view v ) { 66 | s.set_opt_ptr( to_name(option::config), v.get() ); 67 | } 68 | 69 | inline void set_opt_auth_mode( nng::dialer_view s, auth_mode v ) { 70 | s.set_opt_int( to_name(option::auth_mode), (int)v ); 71 | } 72 | 73 | inline void set_opt_auth_mode( nng::listener_view s, auth_mode v ) { 74 | s.set_opt_int( to_name(option::auth_mode), (int)v ); 75 | } 76 | 77 | inline void set_opt_cert_key_file( nng::dialer_view s, const char* v ) { 78 | s.set_opt_string( to_name(option::cert_key_file), v ); 79 | } 80 | 81 | inline void set_opt_cert_key_file( nng::listener_view s, const char* v ) { 82 | s.set_opt_string( to_name(option::cert_key_file), v ); 83 | } 84 | 85 | inline void set_opt_ca_file( nng::dialer_view s, const char* v ) { 86 | s.set_opt_string( to_name(option::ca_file), v ); 87 | } 88 | 89 | inline void set_opt_ca_file( nng::listener_view s, const char* v ) { 90 | s.set_opt_string( to_name(option::ca_file), v ); 91 | } 92 | 93 | inline void set_opt_server_name( nng::dialer_view s, const char* v ) { 94 | s.set_opt_string( to_name(option::server_name), v ); 95 | } 96 | 97 | inline void set_opt_server_name( nng::listener_view s, const char* v ) { 98 | s.set_opt_string( to_name(option::server_name), v ); 99 | } 100 | 101 | }} 102 | 103 | #endif 104 | -------------------------------------------------------------------------------- /include/nngpp/transport/tls/config.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_TLS_CONFIG_H 2 | #define NNGPP_TLS_CONFIG_H 3 | #include "config_view.h" 4 | 5 | namespace nng { namespace tls { 6 | 7 | struct config : config_view { 8 | 9 | config() = default; 10 | 11 | explicit config( nng_tls_config* c ) noexcept : config_view(c) {} 12 | 13 | explicit config( mode mode ) { 14 | int r = nng_tls_config_alloc( &c, (nng_tls_mode)mode ); 15 | if( r != 0 ) { 16 | throw exception(r,"nng_tls_config_alloc"); 17 | } 18 | } 19 | 20 | config( const config& rhs ) = delete; 21 | 22 | config( config&& rhs ) noexcept : config_view(rhs.c) { 23 | rhs.c = nullptr; 24 | } 25 | 26 | config& operator=( const config& rhs ) = delete; 27 | 28 | config& operator=( config&& rhs ) noexcept { 29 | if( this != &rhs ) { 30 | if( c != nullptr ) nng_tls_config_free(c); 31 | c = rhs.c; 32 | rhs.c = nullptr; 33 | } 34 | return *this; 35 | } 36 | 37 | ~config() { 38 | if( c != nullptr ) nng_tls_config_free(c); 39 | } 40 | 41 | nng_tls_config* release() noexcept { 42 | auto out = c; 43 | c = nullptr; 44 | return out; 45 | } 46 | 47 | }; 48 | 49 | inline config config_view::hold() const noexcept { 50 | nng_tls_config_hold(c); 51 | return config(c); 52 | } 53 | 54 | inline config make_config( mode mode ) { 55 | return config(mode); 56 | } 57 | 58 | }} 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /include/nngpp/transport/tls/config_view.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_TLS_CONFIG_VIEW_H 2 | #define NNGPP_TLS_CONFIG_VIEW_H 3 | #include 4 | #include 5 | 6 | namespace nng { namespace tls { 7 | 8 | enum class mode { 9 | client = NNG_TLS_MODE_CLIENT, 10 | server = NNG_TLS_MODE_SERVER 11 | }; 12 | 13 | enum class auth_mode { 14 | none = NNG_TLS_AUTH_MODE_NONE, 15 | optional = NNG_TLS_AUTH_MODE_OPTIONAL, 16 | required = NNG_TLS_AUTH_MODE_REQUIRED 17 | }; 18 | 19 | enum class version { 20 | tls_1_0 = NNG_TLS_1_0, 21 | tls_1_1 = NNG_TLS_1_1, 22 | tls_1_2 = NNG_TLS_1_2, 23 | tls_1_3 = NNG_TLS_1_3 24 | }; 25 | 26 | struct config; 27 | 28 | struct config_view { 29 | protected: 30 | nng_tls_config* c = nullptr; 31 | 32 | public: 33 | config_view() = default; 34 | 35 | config_view( nng_tls_config* c ) noexcept : c(c) {} 36 | 37 | nng_tls_config* get() const noexcept { 38 | return c; 39 | } 40 | 41 | nng_tls_config* operator->() const noexcept { 42 | return c; 43 | } 44 | 45 | explicit operator bool() const noexcept { 46 | return c != nullptr; 47 | } 48 | 49 | config hold() const noexcept; 50 | 51 | const config_view& config_server_name( const char* name ) const { 52 | int r = nng_tls_config_server_name(c,name); 53 | if( r != 0 ) { 54 | throw exception(r,"nng_tls_config_server_name"); 55 | } 56 | return *this; 57 | } 58 | 59 | const config_view& config_ca_chain( const char* chain, const char* crl = nullptr ) const { 60 | int r = nng_tls_config_ca_chain(c,chain,crl); 61 | if( r != 0 ) { 62 | throw exception(r,"nng_tls_config_ca_chain"); 63 | } 64 | return *this; 65 | } 66 | 67 | const config_view& config_own_cert( const char* cert, const char* key, const char* pass = nullptr ) const { 68 | int r = nng_tls_config_own_cert(c,cert,key,pass); 69 | if( r != 0 ) { 70 | throw exception(r,"nng_tls_config_own_cert"); 71 | } 72 | return *this; 73 | } 74 | 75 | const config_view& config_key( const uint8_t* data, size_t size ) const { 76 | int r = nng_tls_config_key(c,data,size); 77 | if( r != 0 ) { 78 | throw exception(r,"nng_tls_config_key"); 79 | } 80 | return *this; 81 | } 82 | 83 | const config_view& config_pass( const char* pass ) const { 84 | int r = nng_tls_config_pass(c,pass); 85 | if( r != 0 ) { 86 | throw exception(r,"nng_tls_config_pass"); 87 | } 88 | return *this; 89 | } 90 | 91 | const config_view& config_auth_mode( auth_mode mode ) const { 92 | int r = nng_tls_config_auth_mode(c,(nng_tls_auth_mode)mode); 93 | if( r != 0 ) { 94 | throw exception(r,"nng_tls_config_auth_mode"); 95 | } 96 | return *this; 97 | } 98 | 99 | const config_view& config_ca_file( const char* path ) const { 100 | int r = nng_tls_config_ca_file(c,path); 101 | if( r != 0 ) { 102 | throw exception(r,"nng_tls_config_ca_file"); 103 | } 104 | return *this; 105 | } 106 | 107 | const config_view& config_cert_key_file( const char* path, const char* pass = nullptr ) const { 108 | int r = nng_tls_config_cert_key_file(c,path,pass); 109 | if( r != 0 ) { 110 | throw exception(r,"nng_tls_config_cert_key_file"); 111 | } 112 | return *this; 113 | } 114 | 115 | const config_view& config_version( version min_ver, version max_ver ) const { 116 | int r = nng_tls_config_version(c,(nng_tls_version)min_ver,(nng_tls_version)max_ver); 117 | if( r != 0 ) { 118 | throw exception(r,"nng_tls_config_version"); 119 | } 120 | return *this; 121 | } 122 | 123 | }; 124 | 125 | }} 126 | 127 | #endif 128 | -------------------------------------------------------------------------------- /include/nngpp/transport/tls/engine.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_TLS_ENGINE_H 2 | #define NNGPP_TLS_ENGINE_H 3 | #include 4 | #include 5 | 6 | namespace nng { namespace tls { namespace engine { 7 | 8 | enum class version { 9 | v0 = NNG_TLS_ENGINE_V0, 10 | v1 = NNG_TLS_ENGINE_V1, 11 | version = NNG_TLS_ENGINE_VERSION 12 | }; 13 | 14 | inline void register_(const nng_tls_engine* e) { 15 | int r = nng_tls_engine_register(e); 16 | if( r != 0 ) { 17 | throw exception(r,"nng_tls_engine_register"); 18 | } 19 | } 20 | 21 | inline void send(void* arg, const uint8_t* buf, size_t* szp) { 22 | int r = nng_tls_engine_send(arg, buf, szp); 23 | if( r != 0 ) { 24 | throw exception(r,"nng_tls_engine_send"); 25 | } 26 | } 27 | 28 | inline void recv(void* arg, uint8_t* buf, size_t* szp) { 29 | int r = nng_tls_engine_recv(arg, buf, szp); 30 | if( r != 0 ) { 31 | throw exception(r,"nng_tls_engine_recv"); 32 | } 33 | } 34 | 35 | inline const char* name() noexcept { 36 | return nng_tls_engine_name(); 37 | } 38 | 39 | inline const char* description() noexcept { 40 | return nng_tls_engine_description(); 41 | } 42 | 43 | inline bool fips_mode() noexcept { 44 | return nng_tls_engine_fips_mode(); 45 | } 46 | 47 | }}} 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /include/nngpp/transport/ws.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_TRANSPORT_WS_H 2 | #define NNGPP_TRANSPORT_WS_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace nng { namespace ws { 9 | 10 | inline void register_transport() { 11 | int r = nng_ws_register(); 12 | if( r != 0 ) { 13 | throw exception(r,"nng_ws_register"); 14 | } 15 | } 16 | 17 | enum class option { 18 | request_headers, // string 19 | response_headers, // string 20 | request_header, // string 21 | response_header, // string 22 | request_uri, // string 23 | send_frame_max, // size 24 | recv_frame_max, // size 25 | protocol, // string 26 | send_text, // bool 27 | recv_text, // bool 28 | }; 29 | 30 | namespace detail { 31 | 32 | #if __cpp_inline_variables >= 201606 33 | inline 34 | #else 35 | static 36 | #endif 37 | const char* const option_names[] = { 38 | NNG_OPT_WS_REQUEST_HEADERS, 39 | NNG_OPT_WS_RESPONSE_HEADERS, 40 | NNG_OPT_WS_REQUEST_HEADER, 41 | NNG_OPT_WS_RESPONSE_HEADER, 42 | NNG_OPT_WS_REQUEST_URI, 43 | NNG_OPT_WS_SENDMAXFRAME, 44 | NNG_OPT_WS_RECVMAXFRAME, 45 | NNG_OPT_WS_PROTOCOL, 46 | NNG_OPT_WS_SEND_TEXT, 47 | NNG_OPT_WS_RECV_TEXT 48 | }; 49 | 50 | } 51 | 52 | inline const char* to_name( option o ) noexcept { 53 | return detail::option_names[(int)o]; 54 | } 55 | 56 | inline buffer get_opt_request_headers( nng::pipe_view s ) { 57 | return s.get_opt_string( to_name(option::request_headers) ); 58 | } 59 | 60 | inline buffer get_opt_response_headers( nng::pipe_view s ) { 61 | return s.get_opt_string( to_name(option::response_headers) ); 62 | } 63 | 64 | inline buffer get_opt_request_header( nng::pipe_view s ) { 65 | return s.get_opt_string( to_name(option::request_header) ); 66 | } 67 | 68 | inline buffer get_opt_response_header( nng::pipe_view s ) { 69 | return s.get_opt_string( to_name(option::response_header) ); 70 | } 71 | 72 | inline buffer get_opt_request_uri( nng::pipe_view s ) { 73 | return s.get_opt_string( to_name(option::request_uri) ); 74 | } 75 | 76 | inline void set_opt_request_headers( nng::dialer_view s, const char* v ) { 77 | s.set_opt_string( to_name(option::request_headers), v ); 78 | } 79 | 80 | inline void set_opt_response_headers( nng::listener_view s, const char* v ) { 81 | s.set_opt_string( to_name(option::response_headers), v ); 82 | } 83 | 84 | inline void set_opt_request_header( nng::dialer_view s, const char* v ) { 85 | s.set_opt_string( to_name(option::request_header), v ); 86 | } 87 | 88 | inline void set_opt_response_header( nng::listener_view s, const char* v ) { 89 | s.set_opt_string( to_name(option::response_header), v ); 90 | } 91 | 92 | inline void set_opt_request_uri( nng::dialer_view s, const char* v ) { 93 | s.set_opt_string( to_name(option::request_uri), v ); 94 | } 95 | 96 | }} 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /include/nngpp/transport/wss.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_TRANSPORT_WSS_H 2 | #define NNGPP_TRANSPORT_WSS_H 3 | #include 4 | #include 5 | 6 | namespace nng { namespace wss { 7 | 8 | inline void register_transport() { 9 | int r = nng_wss_register(); 10 | if( r != 0 ) { 11 | throw exception(r,"nng_wss_register"); 12 | } 13 | } 14 | 15 | }} 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /include/nngpp/url.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_URL_H 2 | #define NNGPP_URL_H 3 | #include "url_view.h" 4 | 5 | namespace nng { 6 | 7 | struct url : url_view { 8 | 9 | url() = default; 10 | 11 | explicit url( nng_url* u ) noexcept : url_view(u) {} 12 | 13 | explicit url( const char* str ) { 14 | int r = nng_url_parse( &u, str ); 15 | if( r != 0 ) { 16 | throw exception(r,"nng_url_parse"); 17 | } 18 | } 19 | 20 | url( const url& rhs ) : url_view() { 21 | int r = nng_url_clone(&u,rhs.get()); 22 | if( r != 0 ) { 23 | throw exception(r,"nng_url_parse"); 24 | } 25 | } 26 | 27 | url( url&& rhs ) noexcept : url_view(rhs.u) { 28 | rhs.u = nullptr; 29 | } 30 | 31 | url& operator=( const url& rhs ) { 32 | if( this != &rhs ) { 33 | if( u != nullptr ) nng_url_free(u); 34 | int r = nng_url_clone(&u,rhs.get()); 35 | if( r != 0 ) { 36 | throw exception(r,"nng_url_clone"); 37 | } 38 | } 39 | return *this; 40 | } 41 | 42 | url& operator=( url&& rhs ) noexcept { 43 | if( this != &rhs ) { 44 | if( u != nullptr ) nng_url_free(u); 45 | u = rhs.u; 46 | rhs.u = nullptr; 47 | } 48 | return *this; 49 | } 50 | 51 | ~url() { 52 | if( u != nullptr ) nng_url_free(u); 53 | } 54 | 55 | nng_url* release() noexcept { 56 | auto out = u; 57 | u = nullptr; 58 | return out; 59 | } 60 | 61 | }; 62 | 63 | inline url make_url( const char* str ) { 64 | return url(str); 65 | } 66 | 67 | } 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /include/nngpp/url_view.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_URL_VIEW_H 2 | #define NNGPP_URL_VIEW_H 3 | #include "view.h" 4 | 5 | namespace nng { 6 | 7 | struct url_view { 8 | protected: 9 | nng_url* u = nullptr; 10 | 11 | public: 12 | url_view() = default; 13 | 14 | url_view( nng_url* u ) noexcept : u(u) {} 15 | 16 | nng_url* get() const noexcept { 17 | return u; 18 | } 19 | 20 | nng_url* operator->() const noexcept { 21 | return u; 22 | } 23 | 24 | explicit operator bool() const noexcept { 25 | return u != nullptr; 26 | } 27 | 28 | bool operator==( const url_view& rhs ) const noexcept { 29 | view view_left(u->u_rawurl,strlen(u->u_rawurl)); 30 | view view_right(rhs.u->u_rawurl,strlen(rhs.u->u_rawurl)); 31 | return view_left == view_right; 32 | } 33 | 34 | bool operator!=( const url_view& rhs ) const noexcept { 35 | return !(*this == rhs); 36 | } 37 | 38 | }; 39 | 40 | } 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /include/nngpp/view.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_VIEW_H 2 | #define NNGPP_VIEW_H 3 | #include 4 | #include "error.h" 5 | 6 | namespace nng { 7 | 8 | struct view { 9 | protected: 10 | using pointer = void*; 11 | pointer d = nullptr; 12 | size_t s = 0; 13 | 14 | public: 15 | view() = default; 16 | 17 | template 18 | view( T* d, size_t s ) noexcept : d((pointer)d), s(s) {} 19 | 20 | template 21 | view( T(&d)[N] ) noexcept : d((pointer)d), s(N * sizeof(T)) {} 22 | 23 | view( nng_iov x ) noexcept : view(x.iov_buf,x.iov_len) {} 24 | 25 | template 26 | T* data() const noexcept { 27 | return (T*)d; 28 | } 29 | 30 | size_t size() const noexcept { 31 | return s; 32 | } 33 | 34 | explicit operator bool() const noexcept { 35 | return d != nullptr; 36 | } 37 | 38 | bool operator==( const view& rhs ) const noexcept { 39 | return s == rhs.s && memcmp(d,rhs.d,s) == 0; 40 | } 41 | 42 | bool operator!=( const view& rhs ) const noexcept { 43 | return !(*this == rhs); 44 | } 45 | 46 | operator nng_iov() const noexcept { 47 | return { d, s }; 48 | } 49 | 50 | }; 51 | 52 | } 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright 2018 Chris Welshman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), 7 | to deal in the Software without restriction, including without limitation 8 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | and/or sell copies of the Software, and to permit persons to whom 10 | the Software is furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included 13 | in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | IN THE SOFTWARE. -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | 2 | # defaults 3 | CXX = g++ 4 | CATCH_INC = 5 | NNG_INC = 6 | NNG_LNK = -lnng -lmbedtls -lmbedx509 -lmbedcrypto 7 | 8 | ENV = 9 | include $(ENV) 10 | 11 | BASE_DIR = $(shell pwd) 12 | BIN_DIR = $(BASE_DIR)/bin 13 | INC_DIR = $(BASE_DIR)/include 14 | TEST_DIR = $(BASE_DIR)/test 15 | PERF_DIR = $(BASE_DIR)/perf 16 | DEMO_DIR = $(BASE_DIR)/demo 17 | 18 | INC_FLG = -I$(INC_DIR) -I$(NNG_INC) -I$(CATCH_INC) 19 | LIB_FLG = $(NNG_LNK) -lpthread 20 | 21 | REL_FLG = -Wall -Wextra -std=c++17 -march=native -O3 -DNDEBUG -Wno-unused-parameter 22 | DBG_FLG = -Wall -Wextra -std=c++17 -march=native -g -Wno-unused-parameter 23 | 24 | TEST_FILES = $(shell echo $(TEST_DIR)/*.cpp) 25 | TEST_BIN = $(BIN_DIR)/test 26 | 27 | DEMO_FILES = $(shell echo $(DEMO_DIR)/*/*.cpp) 28 | DEMO_BINS = $(patsubst $(DEMO_DIR)/%.cpp,$(BIN_DIR)/demo/%,$(DEMO_FILES)) 29 | 30 | PERF_FILES = $(shell echo $(PERF_DIR)/*.cpp) 31 | PERF_BINS = $(patsubst $(PERF_DIR)/%.cpp,$(BIN_DIR)/perf/%,$(PERF_FILES)) 32 | 33 | all: demo perf $(TEST_BIN) 34 | 35 | $(BIN_DIR)/demo/%: $(DEMO_DIR)/%.cpp 36 | @mkdir -p $(dir $@) 37 | $(CXX) $(INC_FLG) $(REL_FLG) -o $@ $^ $(LIB_FLG) 38 | 39 | $(BIN_DIR)/perf/%: $(PERF_DIR)/%.cpp 40 | @mkdir -p $(dir $@) 41 | $(CXX) $(INC_FLG) $(REL_FLG) -o $@ $^ $(LIB_FLG) 42 | 43 | demo: $(DEMO_BINS) 44 | 45 | perf: $(PERF_BINS) 46 | 47 | $(TEST_BIN): $(TEST_FILES) 48 | @mkdir -p $(BIN_DIR) 49 | $(CXX) $(INC_FLG) $(DBG_FLG) -o $@ $^ $(LIB_FLG) 50 | 51 | test: $(TEST_BIN) 52 | @$(TEST_BIN) 53 | 54 | clean: 55 | @rm -rf $(TEST_BIN) $(DEMO_BINS) $(PERF_BINS) 56 | 57 | .PHONY: all demo perf test clean 58 | -------------------------------------------------------------------------------- /perf/inproc.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_PERF_INPROC_H 2 | #define NNGPP_PERF_INPROC_H 3 | 4 | struct inproc_args { 5 | int count; 6 | int msgsize; 7 | const char* addr; 8 | void (*func)(const char*, size_t, int); 9 | }; 10 | 11 | static void do_inproc(void* args) { 12 | auto ia = (inproc_args*)args; 13 | ia->func(ia->addr, ia->msgsize, ia->count); 14 | } 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /perf/inproc_lat.cpp: -------------------------------------------------------------------------------- 1 | // This is a port of nng perf to nngpp 2 | // See https://github.com/nanomsg/nng/tree/master/perf 3 | 4 | #include 5 | #include "latency.h" 6 | #include "inproc.h" 7 | 8 | int main(int argc, char** argv) try { 9 | if(argc != 3) { 10 | fprintf(stderr,"Usage: inproc_lat "); 11 | return 1; 12 | } 13 | 14 | inproc_args ia; 15 | ia.addr = "inproc://latency_test"; 16 | ia.msgsize = parse_int(argv[1], "Invalid message size"); 17 | ia.count = parse_int(argv[2], "Invalid count"); 18 | ia.func = latency_server; 19 | 20 | nng::thread thr( do_inproc, &ia ); 21 | 22 | // Sleep a bit. 23 | nng::msleep(100); 24 | 25 | latency_client("inproc://latency_test", ia.msgsize, ia.count); 26 | } 27 | catch( const nng::exception& e ) { 28 | fprintf(stderr, "%s: %s\n", e.who(), e.what()); 29 | return 1; 30 | } 31 | -------------------------------------------------------------------------------- /perf/inproc_thr.cpp: -------------------------------------------------------------------------------- 1 | // This is a port of nng perf to nngpp 2 | // See https://github.com/nanomsg/nng/tree/master/perf 3 | 4 | #include 5 | #include "throughput.h" 6 | #include "inproc.h" 7 | #include "misc.h" 8 | 9 | int main(int argc, char** argv) try { 10 | if(argc != 3) { 11 | fprintf(stderr,"Usage: inproc_thr "); 12 | return 1; 13 | } 14 | 15 | inproc_args ia; 16 | ia.addr = "inproc://tput_test"; 17 | ia.msgsize = parse_int(argv[1], "Invalid message size"); 18 | ia.count = parse_int(argv[2], "Invalid count"); 19 | ia.func = throughput_server; 20 | 21 | nng::thread thr( do_inproc, &ia ); 22 | 23 | // Sleep a bit. 24 | nng::msleep(100); 25 | 26 | throughput_client("inproc://tput_test", ia.msgsize, ia.count); 27 | } 28 | catch( const nng::exception& e ) { 29 | fprintf(stderr, "%s: %s\n", e.who(), e.what()); 30 | return 1; 31 | } 32 | -------------------------------------------------------------------------------- /perf/latency.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_PERF_LATENCY_H 2 | #define NNGPP_PERF_LATENCY_H 3 | #include 4 | #include 5 | #include 6 | #include "misc.h" 7 | 8 | void latency_client(const char* addr, size_t msgsize, int trips) { 9 | nng_time start, end; 10 | { 11 | auto s = nng::pair::open(); 12 | s.dial(addr); 13 | nng::msg msg(msgsize); 14 | 15 | start = nng::clock(); 16 | for(int i = 0; i < trips; ++i) { 17 | s.send( std::move(msg) ); 18 | msg = s.recv_msg(); 19 | } 20 | end = nng::clock(); 21 | } 22 | 23 | auto total = (float)(end - start) / 1000; 24 | auto latency = (float)(total * 1000000) / (trips * 2); 25 | printf("total time: %.3f [s]\n", total); 26 | printf("message size: %d [B]\n", (int)msgsize); 27 | printf("round trip count: %d\n", trips); 28 | printf("average latency: %.3f [us]\n", latency); 29 | } 30 | 31 | void latency_server(const char* addr, size_t msgsize, int trips) { 32 | auto s = nng::pair::open(); 33 | s.listen(addr); 34 | for(int i = 0; i < trips; ++i) { 35 | auto msg = s.recv_msg(); 36 | if( msg.body().size() != msgsize ) { 37 | die("wrong message size: %d != %d", msg.body().size(), msgsize); 38 | } 39 | s.send( std::move(msg) ); 40 | } 41 | 42 | // Wait a bit for things to drain... linger should do this. 43 | // 100ms ought to be enough. 44 | nng::msleep(100); 45 | } 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /perf/local_lat.cpp: -------------------------------------------------------------------------------- 1 | // This is a port of nng perf to nngpp 2 | // See https://github.com/nanomsg/nng/tree/master/perf 3 | 4 | #include 5 | #include "latency.h" 6 | #include "misc.h" 7 | 8 | int main(int argc, char** argv) try { 9 | if(argc != 4) { 10 | fprintf(stderr,"Usage: local_lat "); 11 | return 1; 12 | } 13 | 14 | auto msgsize = parse_int(argv[2], "Invalid message size"); 15 | auto trips = parse_int(argv[3], "Invalid round-trips"); 16 | 17 | latency_server(argv[1], msgsize, trips); 18 | } 19 | catch( const nng::exception& e ) { 20 | fprintf(stderr, "%s: %s\n", e.who(), e.what()); 21 | return 1; 22 | } 23 | -------------------------------------------------------------------------------- /perf/local_thr.cpp: -------------------------------------------------------------------------------- 1 | // This is a port of nng perf to nngpp 2 | // See https://github.com/nanomsg/nng/tree/master/perf 3 | 4 | #include 5 | #include "throughput.h" 6 | #include "misc.h" 7 | 8 | int main(int argc, char** argv) try { 9 | if(argc != 4) { 10 | fprintf(stderr,"Usage: local_thr "); 11 | return 1; 12 | } 13 | 14 | auto msgsize = parse_int(argv[2], "Invalid message size"); 15 | auto trips = parse_int(argv[3], "Invalid count"); 16 | 17 | throughput_server(argv[1], msgsize, trips); 18 | } 19 | catch( const nng::exception& e ) { 20 | fprintf(stderr, "%s: %s\n", e.who(), e.what()); 21 | return 1; 22 | } 23 | -------------------------------------------------------------------------------- /perf/misc.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_PERF_MISC_H 2 | #define NNGPP_PERF_MISC_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | static int parse_int(const char* arg, const char* what) { 9 | char* eptr; 10 | auto val = strtol(arg, &eptr, 10); 11 | // Must be a postive number less than around a billion. 12 | if((val < 0) || (val > (1 << 30)) || (*eptr != 0) || (eptr == arg)) { 13 | throw std::runtime_error(what); 14 | } 15 | return (int)val; 16 | } 17 | 18 | static void die(const char* fmt, ...) { 19 | va_list ap; 20 | va_start(ap, fmt); 21 | vfprintf(stderr, fmt, ap); 22 | va_end(ap); 23 | fprintf(stderr, "\n"); 24 | exit(2); 25 | } 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /perf/remote_lat.cpp: -------------------------------------------------------------------------------- 1 | // This is a port of nng perf to nngpp 2 | // See https://github.com/nanomsg/nng/tree/master/perf 3 | 4 | #include 5 | #include "latency.h" 6 | #include "misc.h" 7 | 8 | int main(int argc, char** argv) try { 9 | if(argc != 4) { 10 | fprintf(stderr,"Usage: remote_lat "); 11 | return 1; 12 | } 13 | 14 | auto msgsize = parse_int(argv[2], "Invalid message size"); 15 | auto trips = parse_int(argv[3], "Invalid round-trips"); 16 | 17 | latency_client(argv[1], msgsize, trips); 18 | } 19 | catch( const nng::exception& e ) { 20 | fprintf(stderr, "%s: %s\n", e.who(), e.what()); 21 | return 1; 22 | } 23 | -------------------------------------------------------------------------------- /perf/remote_thr.cpp: -------------------------------------------------------------------------------- 1 | // This is a port of nng perf to nngpp 2 | // See https://github.com/nanomsg/nng/tree/master/perf 3 | 4 | #include 5 | #include "throughput.h" 6 | #include "misc.h" 7 | 8 | int main(int argc, char** argv) try { 9 | if(argc != 4) { 10 | fprintf(stderr,"Usage: remote_thr "); 11 | return 1; 12 | } 13 | 14 | auto msgsize = parse_int(argv[2], "message size"); 15 | auto trips = parse_int(argv[3], "count"); 16 | 17 | throughput_client(argv[1], msgsize, trips); 18 | } 19 | catch( const nng::exception& e ) { 20 | fprintf(stderr, "%s: %s\n", e.who(), e.what()); 21 | return 1; 22 | } 23 | -------------------------------------------------------------------------------- /perf/throughput.h: -------------------------------------------------------------------------------- 1 | #ifndef NNGPP_PERF_THROUGHPUT_H 2 | #define NNGPP_PERF_THROUGHPUT_H 3 | #include 4 | #include 5 | #include 6 | #include "misc.h" 7 | 8 | void throughput_server(const char* addr, size_t msgsize, int count) { 9 | nng_time start, end; 10 | { 11 | auto s = nng::pair::open(); 12 | nng::set_opt_recv_buffer( s, 128 ); 13 | s.listen(addr); 14 | 15 | // Receive first synchronization message. 16 | s.recv_msg(); 17 | start = nng::clock(); 18 | 19 | for(int i = 0; i < count; ++i) { 20 | auto msg = s.recv_msg(); 21 | if(msg.body().size() != msgsize) { 22 | die("wrong message size: %d != %d", msg.body().size(), msgsize); 23 | } 24 | } 25 | end = nng::clock(); 26 | // Send a synchronization message (empty) to the other side, 27 | // and wait a bit to make sure it goes out the wire. 28 | s.send( nng::view("",0) ); 29 | nng::msleep(200); 30 | } 31 | auto total = (float)(end - start) / 1000; 32 | auto msgpersec = (float)count / total; 33 | auto mbps = (float)(msgpersec * 8 * msgsize) / (1024 * 1024); 34 | printf("total time: %.3f [s]\n", total); 35 | printf("message size: %d [B]\n", (int)msgsize); 36 | printf("message count: %d\n", count); 37 | printf("throughput: %.f [msg/s]\n", msgpersec); 38 | printf("throughput: %.3f [Mb/s]\n", mbps); 39 | } 40 | 41 | void throughput_client(const char* addr, size_t msgsize, int count) { 42 | auto s = nng::pair::open(); 43 | nng::set_opt_send_buffer( s, 128 ); 44 | nng::set_opt_recv_timeout( s, 5000 ); 45 | s.dial(addr); 46 | 47 | // We send one extra zero length message to start the timer. 48 | s.send( nng::make_msg(0) ); 49 | 50 | for(int i = 0; i < count; ++i) { 51 | s.send( nng::make_msg(msgsize) ); 52 | } 53 | // Attempt to get the completion indication from the other side. 54 | s.recv_msg(); 55 | } 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /project/vs2019/async_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;ipp;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 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /project/vs2019/async_client.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(SolutionDir)..\..\ 5 | WindowsLocalDebugger 6 | 7 | 8 | $(SolutionDir)..\..\ 9 | WindowsLocalDebugger 10 | 11 | 12 | $(SolutionDir)..\..\ 13 | WindowsLocalDebugger 14 | 15 | 16 | $(SolutionDir)..\..\ 17 | WindowsLocalDebugger 18 | 19 | -------------------------------------------------------------------------------- /project/vs2019/async_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;ipp;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 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /project/vs2019/async_server.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(SolutionDir)..\..\ 5 | WindowsLocalDebugger 6 | 7 | 8 | $(SolutionDir)..\..\ 9 | WindowsLocalDebugger 10 | 11 | 12 | $(SolutionDir)..\..\ 13 | WindowsLocalDebugger 14 | 15 | 16 | $(SolutionDir)..\..\ 17 | WindowsLocalDebugger 18 | 19 | -------------------------------------------------------------------------------- /project/vs2019/http_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;ipp;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 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /project/vs2019/http_client.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(SolutionDir)..\..\ 5 | WindowsLocalDebugger 6 | 7 | 8 | $(SolutionDir)..\..\ 9 | WindowsLocalDebugger 10 | 11 | 12 | $(SolutionDir)..\..\ 13 | WindowsLocalDebugger 14 | 15 | 16 | $(SolutionDir)..\..\ 17 | WindowsLocalDebugger 18 | 19 | -------------------------------------------------------------------------------- /project/vs2019/inproc_lat.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;ipp;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 | Source Files 20 | 21 | 22 | 23 | 24 | Header Files 25 | 26 | 27 | Header Files 28 | 29 | 30 | Header Files 31 | 32 | 33 | -------------------------------------------------------------------------------- /project/vs2019/inproc_lat.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(SolutionDir)..\..\ 5 | WindowsLocalDebugger 6 | 7 | 8 | $(SolutionDir)..\..\ 9 | WindowsLocalDebugger 10 | 11 | 12 | $(SolutionDir)..\..\ 13 | WindowsLocalDebugger 14 | 15 | 16 | $(SolutionDir)..\..\ 17 | WindowsLocalDebugger 18 | 19 | -------------------------------------------------------------------------------- /project/vs2019/inproc_thr.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;ipp;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 | Source Files 20 | 21 | 22 | 23 | 24 | Header Files 25 | 26 | 27 | Header Files 28 | 29 | 30 | Header Files 31 | 32 | 33 | -------------------------------------------------------------------------------- /project/vs2019/inproc_thr.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(SolutionDir)..\..\ 5 | WindowsLocalDebugger 6 | 7 | 8 | $(SolutionDir)..\..\ 9 | WindowsLocalDebugger 10 | 11 | 12 | $(SolutionDir)..\..\ 13 | WindowsLocalDebugger 14 | 15 | 16 | $(SolutionDir)..\..\ 17 | WindowsLocalDebugger 18 | 19 | -------------------------------------------------------------------------------- /project/vs2019/local_lat.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;ipp;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 | Source Files 20 | 21 | 22 | 23 | 24 | Header Files 25 | 26 | 27 | Header Files 28 | 29 | 30 | Header Files 31 | 32 | 33 | -------------------------------------------------------------------------------- /project/vs2019/local_lat.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(SolutionDir)..\..\ 5 | WindowsLocalDebugger 6 | 7 | 8 | $(SolutionDir)..\..\ 9 | WindowsLocalDebugger 10 | 11 | 12 | $(SolutionDir)..\..\ 13 | WindowsLocalDebugger 14 | 15 | 16 | $(SolutionDir)..\..\ 17 | WindowsLocalDebugger 18 | 19 | -------------------------------------------------------------------------------- /project/vs2019/local_thr.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;ipp;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 | Source Files 20 | 21 | 22 | 23 | 24 | Header Files 25 | 26 | 27 | Header Files 28 | 29 | 30 | Header Files 31 | 32 | 33 | -------------------------------------------------------------------------------- /project/vs2019/local_thr.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(SolutionDir)..\..\ 5 | WindowsLocalDebugger 6 | 7 | 8 | $(SolutionDir)..\..\ 9 | WindowsLocalDebugger 10 | 11 | 12 | $(SolutionDir)..\..\ 13 | WindowsLocalDebugger 14 | 15 | 16 | $(SolutionDir)..\..\ 17 | WindowsLocalDebugger 18 | 19 | -------------------------------------------------------------------------------- /project/vs2019/raw.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;ipp;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 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /project/vs2019/raw.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(SolutionDir)..\..\ 5 | WindowsLocalDebugger 6 | 7 | 8 | $(SolutionDir)..\..\ 9 | WindowsLocalDebugger 10 | 11 | 12 | $(SolutionDir)..\..\ 13 | WindowsLocalDebugger 14 | 15 | 16 | $(SolutionDir)..\..\ 17 | WindowsLocalDebugger 18 | 19 | -------------------------------------------------------------------------------- /project/vs2019/remote_lat.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;ipp;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 | Source Files 20 | 21 | 22 | 23 | 24 | Header Files 25 | 26 | 27 | Header Files 28 | 29 | 30 | Header Files 31 | 32 | 33 | -------------------------------------------------------------------------------- /project/vs2019/remote_lat.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(SolutionDir)..\..\ 5 | WindowsLocalDebugger 6 | 7 | 8 | $(SolutionDir)..\..\ 9 | WindowsLocalDebugger 10 | 11 | 12 | $(SolutionDir)..\..\ 13 | WindowsLocalDebugger 14 | 15 | 16 | $(SolutionDir)..\..\ 17 | WindowsLocalDebugger 18 | 19 | -------------------------------------------------------------------------------- /project/vs2019/remote_thr.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;ipp;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 | Source Files 20 | 21 | 22 | 23 | 24 | Header Files 25 | 26 | 27 | Header Files 28 | 29 | 30 | Header Files 31 | 32 | 33 | -------------------------------------------------------------------------------- /project/vs2019/remote_thr.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(SolutionDir)..\..\ 5 | WindowsLocalDebugger 6 | 7 | 8 | $(SolutionDir)..\..\ 9 | WindowsLocalDebugger 10 | 11 | 12 | $(SolutionDir)..\..\ 13 | WindowsLocalDebugger 14 | 15 | 16 | $(SolutionDir)..\..\ 17 | WindowsLocalDebugger 18 | 19 | -------------------------------------------------------------------------------- /project/vs2019/reqrep.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;ipp;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 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /project/vs2019/reqrep.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(SolutionDir)..\..\ 5 | WindowsLocalDebugger 6 | 7 | 8 | $(SolutionDir)..\..\ 9 | WindowsLocalDebugger 10 | 11 | 12 | $(SolutionDir)..\..\ 13 | WindowsLocalDebugger 14 | 15 | 16 | $(SolutionDir)..\..\ 17 | WindowsLocalDebugger 18 | 19 | -------------------------------------------------------------------------------- /project/vs2019/rest.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;ipp;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 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /project/vs2019/rest.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(SolutionDir)..\..\ 5 | WindowsLocalDebugger 6 | 7 | 8 | $(SolutionDir)..\..\ 9 | WindowsLocalDebugger 10 | 11 | 12 | $(SolutionDir)..\..\ 13 | WindowsLocalDebugger 14 | 15 | 16 | $(SolutionDir)..\..\ 17 | WindowsLocalDebugger 18 | 19 | -------------------------------------------------------------------------------- /project/vs2019/test.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(SolutionDir)..\..\ 5 | WindowsLocalDebugger 6 | 7 | 8 | $(SolutionDir)..\..\ 9 | WindowsLocalDebugger 10 | 11 | 12 | $(SolutionDir)..\..\ 13 | WindowsLocalDebugger 14 | [tls] 15 | 16 | 17 | $(SolutionDir)..\..\ 18 | WindowsLocalDebugger 19 | 20 | 21 | false 22 | 23 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(Catch2) 2 | 3 | set(test_sources 4 | bus.cpp 5 | device.cpp 6 | hello_world.cpp 7 | http_client.cpp 8 | ipcsupp.cpp 9 | main.cpp 10 | message.cpp 11 | pipe.cpp 12 | reconnect.cpp 13 | respondpoll.cpp 14 | scalability.cpp 15 | synch.cpp 16 | tcpsupp.cpp 17 | ) 18 | 19 | if (NNGPP_BUILD_TLS_TEST) 20 | list(APPEND test_sources tls.cpp) 21 | endif() 22 | 23 | add_executable(tests ${test_sources}) 24 | target_include_directories(tests PUBLIC ${CMAKE_SOURCE_DIR}/include) 25 | target_link_libraries(tests nngpp Catch2::Catch2) 26 | -------------------------------------------------------------------------------- /test/bus.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | TEST_CASE("BUS pattern","[bus]") { 6 | auto addr = "inproc://bus"; 7 | 8 | SECTION("We can create a BUS socket") { 9 | auto bus = nng::bus::open(); 10 | REQUIRE(bus); 11 | } 12 | 13 | SECTION("We can create a linked BUS topology") { 14 | 15 | auto bus1 = nng::bus::open(); 16 | REQUIRE(bus1); 17 | auto bus2 = nng::bus::open(); 18 | REQUIRE(bus2); 19 | auto bus3 = nng::bus::open(); 20 | REQUIRE(bus3); 21 | 22 | REQUIRE_NOTHROW( bus1.listen(addr) ); 23 | REQUIRE_NOTHROW( bus2.dial(addr) ); 24 | REQUIRE_NOTHROW( bus3.dial(addr) ); 25 | 26 | nng_duration rtimeo = 50; 27 | REQUIRE_NOTHROW( nng::set_opt_recv_timeout( bus1, rtimeo ) ); 28 | REQUIRE_NOTHROW( nng::set_opt_recv_timeout( bus2, rtimeo ) ); 29 | REQUIRE_NOTHROW( nng::set_opt_recv_timeout( bus3, rtimeo ) ); 30 | 31 | SECTION("Messages delivered") { 32 | auto expected_error = nng::exception(nng::error::timedout).what(); 33 | 34 | REQUIRE_THROWS_WITH( bus1.recv_msg(), expected_error ); 35 | REQUIRE_THROWS_WITH( bus2.recv_msg(), expected_error ); 36 | REQUIRE_THROWS_WITH( bus3.recv_msg(), expected_error ); 37 | 38 | { 39 | auto msg = nng::make_msg(0); 40 | REQUIRE(msg); 41 | 42 | msg.body().append("99bits"); 43 | REQUIRE_NOTHROW( bus2.send( std::move(msg) ) ); 44 | REQUIRE_NOTHROW( msg = bus1.recv_msg() ); 45 | REQUIRE( msg.body().get() == "99bits" ); 46 | 47 | REQUIRE_THROWS_WITH( msg = bus3.recv_msg(), expected_error ); 48 | } 49 | { 50 | auto msg = nng::make_msg(0); 51 | REQUIRE(msg); 52 | 53 | msg.body().append("onthe"); 54 | REQUIRE_NOTHROW( bus1.send( std::move(msg) ) ); 55 | 56 | REQUIRE_NOTHROW( msg = bus2.recv_msg() ); 57 | REQUIRE( msg.body().get() == "onthe" ); 58 | REQUIRE_NOTHROW( msg = bus3.recv_msg() ); 59 | REQUIRE( msg.body().get() == "onthe" ); 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /test/device.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | TEST_CASE("We cannot create cooked mode device","[device]") { 8 | auto s1 = nng::pair::v1::open(); 9 | REQUIRE(s1); 10 | REQUIRE_THROWS_WITH( 11 | nng::device(s1,s1), 12 | nng::exception(nng::error::inval).what() 13 | ); 14 | } 15 | 16 | TEST_CASE("PAIRv1 device","[device]") { 17 | auto addr1 = "inproc://dev1"; 18 | auto addr2 = "inproc://dev2"; 19 | 20 | SECTION("We can create a PAIRv1 device") { 21 | std::thread thr; 22 | { 23 | auto dev1 = nng::pair::v1::open_raw(); 24 | REQUIRE(dev1); 25 | auto dev2 = nng::pair::v1::open_raw(); 26 | REQUIRE(dev2); 27 | 28 | thr = std::thread([&] { 29 | try { nng::device(dev1,dev2); } 30 | catch(...) {} 31 | }); 32 | 33 | REQUIRE_NOTHROW( dev1.listen(addr1) ); 34 | REQUIRE_NOTHROW( dev2.listen(addr2) ); 35 | 36 | auto end1 = nng::pair::v1::open(); 37 | REQUIRE(end1); 38 | auto end2 = nng::pair::v1::open(); 39 | REQUIRE(end2); 40 | 41 | REQUIRE_NOTHROW( end1.dial(addr1) ); 42 | REQUIRE_NOTHROW( end2.dial(addr2) ); 43 | 44 | nng_duration tmo = 1000; 45 | REQUIRE_NOTHROW( nng::set_opt_recv_timeout(end1,tmo) ); 46 | REQUIRE_NOTHROW( nng::set_opt_recv_timeout(end2,tmo) ); 47 | 48 | nng::msleep(100); 49 | SECTION("Device can send and receive") { 50 | { 51 | auto msg = nng::make_msg(0); 52 | REQUIRE(msg); 53 | 54 | msg.body().append("ALPHA"); 55 | REQUIRE_NOTHROW( end1.send(std::move(msg)) ); 56 | REQUIRE_NOTHROW( msg = end2.recv_msg() ); 57 | REQUIRE( msg.body().get() == "ALPHA" ); 58 | } 59 | { 60 | auto msg = nng::make_msg(0); 61 | REQUIRE(msg); 62 | 63 | msg.body().append("OMEGA"); 64 | REQUIRE_NOTHROW( end2.send(std::move(msg)) ); 65 | REQUIRE_NOTHROW( msg = end1.recv_msg() ); 66 | REQUIRE( msg.body().get() == "OMEGA" ); 67 | } 68 | } 69 | } 70 | thr.join(); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /test/http_client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | namespace Catch { 7 | 8 | template<> 9 | struct is_range : std::false_type { 10 | }; 11 | 12 | } 13 | 14 | TEST_CASE("HTTP Client","[httpclient]") { 15 | 16 | SECTION("Given a TCP connection to httpbin.org") { 17 | 18 | auto aio = nng::make_aio(); 19 | REQUIRE(aio); 20 | 21 | nng::url url("http://example.org/"); 22 | REQUIRE(url); 23 | 24 | nng::http::client cli(url); 25 | REQUIRE(cli); 26 | 27 | cli.connect(aio); 28 | aio.wait(); 29 | 30 | REQUIRE( aio.result() == nng::error::success ); 31 | 32 | nng::http::conn_view http = aio.get_output(0); 33 | 34 | SECTION("We can initiate a message") { 35 | REQUIRE(http); 36 | 37 | nng::http::req req(url); 38 | REQUIRE(req); 39 | auto res = nng::http::make_res(); 40 | REQUIRE(res); 41 | 42 | http.write(req,aio); 43 | aio.wait(); 44 | 45 | REQUIRE( aio.result() == nng::error::success ); 46 | 47 | http.read(res,aio); 48 | aio.wait(); 49 | 50 | REQUIRE( aio.result() == nng::error::success ); 51 | REQUIRE( res.get_status() == nng::http::status::ok ); 52 | 53 | SECTION("The message contents are correct") { 54 | auto cstr = res.get_header("Content-Length"); 55 | REQUIRE(cstr); 56 | auto sz = atoi(cstr); 57 | REQUIRE(sz > 0); 58 | 59 | nng::buffer data(sz); 60 | REQUIRE(data); 61 | 62 | nng_iov iov = data; 63 | REQUIRE_NOTHROW( aio.set_iov(iov) ); 64 | 65 | aio.wait(); 66 | REQUIRE( aio.result() == nng::error::success ); 67 | 68 | http.read_all(aio); 69 | aio.wait(); 70 | REQUIRE( aio.result() == nng::error::success ); 71 | 72 | } 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /test/ipcsupp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | TEST_CASE("Supplemental IPC", "[ipc]") { 6 | 7 | INFO("We can create a dialer and listener"); 8 | auto url = "ipc:///tmp/ipcsupp_test"; 9 | 10 | auto d = nng::stream::dialer(url); 11 | REQUIRE(d); 12 | auto l = nng::stream::listener(url); 13 | REQUIRE(l); 14 | 15 | INFO("Listener listens"); 16 | REQUIRE_NOTHROW(l.listen()); 17 | 18 | INFO("We can dial it"); 19 | nng::aio daio(nullptr,nullptr); 20 | nng::aio laio(nullptr,nullptr); 21 | nng::aio maio(nullptr,nullptr); 22 | 23 | d.dial(daio); 24 | l.accept(laio); 25 | 26 | daio.wait(); 27 | laio.wait(); 28 | 29 | REQUIRE(daio.result() == nng::error::success); 30 | REQUIRE(laio.result() == nng::error::success); 31 | 32 | nng::stream::stream c1( daio.get_output(0) ); 33 | nng::stream::stream c2( laio.get_output(0) ); 34 | REQUIRE(c1); 35 | REQUIRE(c2); 36 | 37 | INFO("They exchange messages"); 38 | nng::aio aio1(nullptr,nullptr); 39 | nng::aio aio2(nullptr,nullptr); 40 | 41 | char buf1[5]; 42 | memcpy(buf1, "TEST", 5); 43 | 44 | char buf2[5]; 45 | memset(buf2, 0, 5); 46 | 47 | aio1.set_iov( {buf1, 5} ); 48 | aio2.set_iov( {buf2, 5} ); 49 | c1.send(aio1); 50 | c2.recv(aio2); 51 | aio1.wait(); 52 | aio2.wait(); 53 | 54 | REQUIRE(aio1.result() == nng::error::success); 55 | REQUIRE(aio1.count() == 5); 56 | 57 | REQUIRE(aio2.result() == nng::error::success); 58 | REQUIRE(aio2.count() == 5); 59 | 60 | REQUIRE(memcmp(buf1, buf2, 5) == 0); 61 | 62 | INFO("Socket name matches"); 63 | { 64 | nng_sockaddr sa2; 65 | REQUIRE_NOTHROW(sa2 = c2.get_addr(to_name(nng::option::local_address))); 66 | REQUIRE(sa2.s_ipc.sa_family == NNG_AF_IPC); 67 | REQUIRE(strcmp(sa2.s_ipc.sa_path, url + strlen("ipc://")) == 0); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /test/main.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_RUNNER 2 | #define CATCH_CONFIG_COLOUR_NONE 3 | #include 4 | #include 5 | 6 | int main( int argc, char* argv[] ) { 7 | int result = Catch::Session().run( argc, argv ); 8 | nng::fini(); 9 | return result; 10 | } 11 | -------------------------------------------------------------------------------- /test/reconnect.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | TEST_CASE("Reconnect works","[reconnect]") { 9 | auto addr = "inproc://reconnect"; 10 | 11 | SECTION("Dialing before listening works") { 12 | auto push = nng::push::open(); 13 | REQUIRE(push); 14 | auto pull = nng::pull::open(); 15 | REQUIRE(pull); 16 | 17 | REQUIRE_NOTHROW( nng::set_opt_reconnect_time_min( pull, 10 ) ); 18 | REQUIRE_NOTHROW( nng::set_opt_reconnect_time_max( pull, 10 ) ); 19 | 20 | REQUIRE_NOTHROW( push.dial(addr,nng::flag::nonblock) ); 21 | nng::msleep(100); 22 | REQUIRE_NOTHROW( pull.listen(addr) ); 23 | 24 | SECTION("We can send a frame") { 25 | nng::msleep(100); 26 | 27 | auto msg = nng::make_msg(0); 28 | REQUIRE(msg); 29 | msg.body().append("hello"); 30 | REQUIRE_NOTHROW( push.send( std::move(msg) ) ); 31 | REQUIRE_NOTHROW( msg = pull.recv_msg() ); 32 | 33 | REQUIRE(msg); 34 | REQUIRE( msg.body().get() == "hello" ); 35 | } 36 | } 37 | 38 | SECTION("Reconnection works") { 39 | auto push = nng::push::open(); 40 | REQUIRE(push); 41 | auto pull = nng::pull::open(); 42 | REQUIRE(pull); 43 | 44 | REQUIRE_NOTHROW( nng::set_opt_reconnect_time_min( pull, 10 ) ); 45 | REQUIRE_NOTHROW( nng::set_opt_reconnect_time_max( pull, 10 ) ); 46 | 47 | REQUIRE_NOTHROW( push.dial(addr,nng::flag::nonblock) ); 48 | { 49 | nng::listener l( pull, addr, 0 ); 50 | REQUIRE(l); 51 | nng::msleep(100); 52 | } 53 | pull.listen(addr); 54 | 55 | SECTION("They still exchange frames") { 56 | nng::pipe_view p1; 57 | nng::msleep(100); 58 | { 59 | auto msg = nng::make_msg(0); 60 | REQUIRE(msg); 61 | msg.body().append("hello"); 62 | REQUIRE_NOTHROW( push.send( std::move(msg) ) ); 63 | REQUIRE_NOTHROW( msg = pull.recv_msg() ); 64 | REQUIRE(msg); 65 | REQUIRE( msg.body().get() == "hello" ); 66 | 67 | p1 = msg.get_pipe(); 68 | } 69 | SECTION("Even after pipe close") { 70 | nng::pipe_view p2; 71 | nng_pipe_close(p1.get()); 72 | nng::msleep(100); 73 | { 74 | auto msg = nng::make_msg(0); 75 | REQUIRE(msg); 76 | msg.body().append("again"); 77 | REQUIRE_NOTHROW( push.send( std::move(msg) ) ); 78 | REQUIRE_NOTHROW( msg = pull.recv_msg() ); 79 | REQUIRE(msg); 80 | REQUIRE( msg.body().get() == "again" ); 81 | 82 | p2 = msg.get_pipe(); 83 | } 84 | REQUIRE(p2.id() != p1.id()); 85 | } 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /test/respondpoll.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | TEST_CASE("Respondent pollable") { 8 | auto addr = "inproc://respondpoll"; 9 | 10 | SECTION("Given a connected survey pair") { 11 | auto surv = nng::survey::open(); 12 | REQUIRE(surv); 13 | auto resp = nng::respond::open(); 14 | REQUIRE(resp); 15 | nng::ctx ctx( resp ); 16 | REQUIRE(ctx); 17 | 18 | REQUIRE_NOTHROW( nng::set_opt_send_timeout(surv,2000) ); 19 | REQUIRE_NOTHROW( nng::set_opt_send_timeout(resp,2000) ); 20 | REQUIRE_NOTHROW( nng::set_opt_recv_timeout(surv,2000) ); 21 | REQUIRE_NOTHROW( nng::set_opt_recv_timeout(resp,2000) ); 22 | 23 | REQUIRE_NOTHROW( resp.listen(addr) ); 24 | 25 | SECTION("Respondent ctx not pollable") { 26 | REQUIRE_THROWS_WITH( 27 | ctx.get_opt_int( NNG_OPT_SENDFD ), 28 | nng::exception(nng::error::notsup).what() 29 | ); 30 | REQUIRE_THROWS_WITH( 31 | ctx.get_opt_int( NNG_OPT_RECVFD ), 32 | nng::exception(nng::error::notsup).what() 33 | ); 34 | } 35 | 36 | SECTION("Respondent starts not writable") { 37 | nng::get_opt_send_fd(resp); 38 | 39 | SECTION("And remains unwritable on connect") { 40 | REQUIRE_NOTHROW( surv.dial(addr) ); 41 | 42 | nng::msleep(100); 43 | 44 | SECTION("Becomes writable after recv") { 45 | surv.send( nng::make_msg(0) ); 46 | resp.recv_msg(); 47 | } 48 | } 49 | } 50 | 51 | SECTION("Respondent starts not readable") { 52 | nng::get_opt_recv_fd(resp); 53 | 54 | SECTION("And doesn't become readable on connect") { 55 | REQUIRE_NOTHROW( surv.dial(addr) ); 56 | nng::msleep(100); 57 | } 58 | 59 | SECTION("And becomes readable on data") { 60 | REQUIRE_NOTHROW( surv.dial(addr) ); 61 | nng::msleep(200); 62 | 63 | auto msg = nng::make_msg(0); 64 | msg.body().append( {"xyz",3} ); 65 | surv.send( std::move(msg) ); 66 | 67 | nng::msleep(300); // give time for msg to arrive 68 | 69 | SECTION("Is no longer readable after recv") { 70 | msg = resp.recv_msg(); 71 | } 72 | } 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /test/scalability.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace { 9 | 10 | static const char* addr = "inproc://scalability"; 11 | 12 | struct server { 13 | nng::socket rep = nng::rep::open(); 14 | 15 | void run() const { 16 | nng::set_opt_recv_buffer(rep,256); 17 | nng::set_opt_send_buffer(rep,256); 18 | rep.listen(addr); 19 | 20 | while(true) { 21 | try { 22 | rep.send( rep.recv_msg() ); 23 | } 24 | catch( const nng::exception& ) { 25 | break; 26 | } 27 | } 28 | } 29 | 30 | void stop() { 31 | rep = nng::socket(); 32 | } 33 | 34 | }; 35 | 36 | static void serve(void* arg) { 37 | ((server*)arg)->run(); 38 | } 39 | 40 | static void open_clients(nng::socket* clients, int num) { 41 | nng_duration t = 100; // 100ms 42 | for(int i=0;i clients(nclients); 68 | 69 | REQUIRE(server); 70 | 71 | REQUIRE_NOTHROW(open_clients(clients.data(), nclients)); 72 | 73 | REQUIRE_NOTHROW(transact(clients.data(), nclients)); 74 | 75 | sv.stop(); 76 | } 77 | 78 | -------------------------------------------------------------------------------- /test/synch.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | namespace { 7 | 8 | struct notifyarg { 9 | int did = 0; 10 | nng_duration when = 0; 11 | nng::mtx mx = nng::make_mtx(); 12 | nng::cv cv{mx}; 13 | }; 14 | 15 | static void notifyafter(void* arg) { 16 | auto na = (notifyarg*)arg; 17 | 18 | nng::msleep(na->when); 19 | std::lock_guard lock( na->mx ); 20 | na->did = 1; 21 | na->cv.wake_all(); 22 | } 23 | 24 | } 25 | 26 | TEST_CASE("We can lock and unlock a mutex","[synch]") { 27 | auto mx = nng::make_mtx(); 28 | mx.lock(); 29 | REQUIRE(1); 30 | mx.unlock(); 31 | REQUIRE(1); 32 | SECTION("And then lock it again","[synch]") { 33 | mx.lock(); 34 | REQUIRE(1); 35 | mx.unlock(); 36 | REQUIRE(1); 37 | } 38 | } 39 | TEST_CASE("Things block properly","[synch]") { 40 | notifyarg arg; 41 | nng::thread thr; 42 | { 43 | std::lock_guard lock( arg.mx ); 44 | thr = nng::thread(notifyafter,&arg); 45 | nng::msleep(10); 46 | REQUIRE(arg.did == 0); 47 | } 48 | nng::msleep(10); 49 | { 50 | std::lock_guard lock( arg.mx ); 51 | while(!arg.did) { 52 | arg.cv.wait(); 53 | } 54 | REQUIRE(arg.did != 0); 55 | } 56 | } 57 | 58 | TEST_CASE("Notification works","[synch]") { 59 | notifyarg arg; 60 | arg.did = 0; 61 | arg.when = 10; 62 | { 63 | nng::thread thr(notifyafter,&arg); 64 | std::lock_guard lock( arg.mx ); 65 | if(!arg.did) { 66 | arg.cv.wait(); 67 | } 68 | } 69 | REQUIRE(arg.did == 1); 70 | } 71 | 72 | TEST_CASE("Timeout works","[synch]") { 73 | notifyarg arg; 74 | arg.did = 0; 75 | arg.when = 200; 76 | nng::thread thr(notifyafter,&arg); 77 | std::lock_guard lock( arg.mx ); 78 | if(!arg.did) { 79 | arg.cv.wait_until(nng::clock() + 10); 80 | } 81 | REQUIRE(arg.did == 0); 82 | } 83 | 84 | TEST_CASE("Empty timeout is EAGAIN","[synch]") { 85 | notifyarg arg; 86 | std::lock_guard lock( arg.mx ); 87 | REQUIRE_THROWS_WITH( 88 | arg.cv.wait_until(0), 89 | nng::exception(nng::error::again).what() 90 | ); 91 | } 92 | 93 | TEST_CASE("Not running works","[synch]") { 94 | notifyarg arg; 95 | arg.did = 0; 96 | arg.when = 1; 97 | std::lock_guard lock( arg.mx ); 98 | if(!arg.did) { 99 | arg.cv.wait_until(nng::clock() + 10); 100 | } 101 | REQUIRE(arg.did == 0); 102 | } 103 | -------------------------------------------------------------------------------- /test/tcpsupp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | inline uint16_t test_htons( uint16_t in ) noexcept { 7 | in = ((in >> 8) & 0xff) | ((in & 0xff) << 8); 8 | return in; 9 | } 10 | 11 | TEST_CASE("Supplemental TCP", "[tcpapi]") { 12 | 13 | INFO("Listener listens (wildcard)"); 14 | auto l = nng::stream::listener("tcp://127.0.0.1"); 15 | REQUIRE(l); 16 | REQUIRE_NOTHROW(l.listen()); 17 | 18 | uint8_t ip[4]; 19 | ip[0] = 127; 20 | ip[1] = 0; 21 | ip[2] = 0; 22 | ip[3] = 1; 23 | 24 | auto sa = l.get_addr( to_name(nng::option::local_address) ); 25 | 26 | REQUIRE(sa.s_in.sa_port != 0); 27 | REQUIRE(memcmp(&sa.s_in.sa_addr, ip, 4) == 0); 28 | 29 | INFO("We can dial it"); 30 | nng::aio daio(nullptr,nullptr); 31 | nng::aio laio(nullptr,nullptr); 32 | nng::aio maio(nullptr,nullptr); 33 | 34 | char uri[64]; 35 | snprintf(uri, sizeof(uri), "tcp://127.0.0.1:%d", test_htons(sa.s_in.sa_port)); 36 | auto d = nng::stream::dialer(uri); 37 | REQUIRE(d); 38 | 39 | d.dial(daio); 40 | l.accept(laio); 41 | 42 | daio.wait(); 43 | REQUIRE(daio.result() == nng::error::success); 44 | laio.wait(); 45 | REQUIRE(laio.result() == nng::error::success); 46 | 47 | nng::stream::stream c1( daio.get_output(0) ); 48 | nng::stream::stream c2( laio.get_output(0) ); 49 | REQUIRE(c1); 50 | REQUIRE(c2); 51 | 52 | INFO("They exchange messages"); 53 | nng::aio aio1(nullptr,nullptr); 54 | nng::aio aio2(nullptr,nullptr); 55 | 56 | REQUIRE_NOTHROW(c1.set_bool( to_name(nng::tcp::option::no_delay), true) ); 57 | REQUIRE_NOTHROW(c2.set_bool( to_name(nng::tcp::option::no_delay), true) ); 58 | REQUIRE_NOTHROW(c1.set_bool( to_name(nng::tcp::option::keep_alive), true) ); 59 | 60 | char buf1[5]; 61 | memcpy(buf1, "TEST", 5); 62 | 63 | char buf2[5]; 64 | memset(buf2, 0, 5); 65 | 66 | aio1.set_iov( {buf1, 5} ); 67 | aio2.set_iov( {buf2, 5} ); 68 | c1.send(aio1); 69 | c2.recv(aio2); 70 | aio1.wait(); 71 | aio2.wait(); 72 | 73 | REQUIRE(aio1.result() == nng::error::success); 74 | REQUIRE(aio1.count() == 5); 75 | 76 | REQUIRE(aio2.result() == nng::error::success); 77 | REQUIRE(aio2.count() == 5); 78 | 79 | REQUIRE(memcmp(buf1, buf2, 5) == 0); 80 | 81 | INFO("Socket name matches"); 82 | { 83 | nng_sockaddr sa2; 84 | REQUIRE_NOTHROW(sa2 = c2.get_addr( to_name(nng::option::local_address) )); 85 | REQUIRE(sa2.s_in.sa_family == NNG_AF_INET); 86 | REQUIRE(sa2.s_in.sa_addr == sa.s_in.sa_addr); 87 | REQUIRE(sa2.s_in.sa_port == sa.s_in.sa_port); 88 | } 89 | 90 | INFO("Peer name matches") 91 | { 92 | nng_sockaddr sa2; 93 | REQUIRE_NOTHROW(sa2 = c1.get_addr( to_name(nng::option::remote_address) )); 94 | REQUIRE(sa2.s_in.sa_family == NNG_AF_INET); 95 | REQUIRE(sa2.s_in.sa_addr == sa.s_in.sa_addr); 96 | REQUIRE(sa2.s_in.sa_port == sa.s_in.sa_port); 97 | } 98 | 99 | } 100 | --------------------------------------------------------------------------------