From 66d0f3511fe8b2e6393606990a3d66a846672f69 Mon Sep 17 00:00:00 2001 From: Simon Giesecke Date: Sat, 19 Oct 2019 14:46:53 +0200 Subject: [PATCH] Problem: ipc transport not supported under Windows Solution: implement support --- CMakeLists.txt | 97 ++++++++++++++++++++---------------- builds/cmake/platform.hpp.in | 4 ++ configure.ac | 9 ++++ src/address.cpp | 6 +-- src/address.hpp | 8 ++- src/ipc_address.cpp | 6 +-- src/ipc_address.hpp | 9 ++-- src/ipc_connecter.cpp | 21 +++++--- src/ipc_connecter.hpp | 3 +- src/ipc_listener.cpp | 67 ++++++++++++++++++++++--- src/ipc_listener.hpp | 5 +- src/session_base.cpp | 6 +-- src/socket_base.cpp | 9 ++-- src/zmq.cpp | 2 +- tests/CMakeLists.txt | 9 +++- tests/test_rebind_ipc.cpp | 2 +- tests/test_reconnect_ivl.cpp | 2 +- tests/testutil_unity.cpp | 22 +++++++- tests/testutil_unity.hpp | 2 +- 19 files changed, 195 insertions(+), 94 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 03b5b964..608207b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -193,6 +193,54 @@ set(API_POLLER "" CACHE STRING "Choose polling system for zmq_poll(er)_*. valid set(POLLER "" CACHE STRING "Choose polling system for I/O threads. valid values are kqueue, epoll, devpoll, pollset, poll or select [default=autodetect]") + +if (WIN32) + # from https://stackoverflow.com/a/40217291/2019765 + macro(get_WIN32_WINNT version) + if (CMAKE_SYSTEM_VERSION) + set(ver ${CMAKE_SYSTEM_VERSION}) + string(REGEX MATCH "^([0-9]+).([0-9])" ver ${ver}) + string(REGEX MATCH "^([0-9]+)" verMajor ${ver}) + # Check for Windows 10, b/c we'll need to convert to hex 'A'. + if ("${verMajor}" MATCHES "10") + set(verMajor "A") + string(REGEX REPLACE "^([0-9]+)" ${verMajor} ver ${ver}) + endif ("${verMajor}" MATCHES "10") + # Remove all remaining '.' characters. + string(REPLACE "." "" ver ${ver}) + # Prepend each digit with a zero. + string(REGEX REPLACE "([0-9A-Z])" "0\\1" ver ${ver}) + set(${version} "0x${ver}") + endif(CMAKE_SYSTEM_VERSION) + endmacro(get_WIN32_WINNT) + + get_WIN32_WINNT(ZMQ_WIN32_WINNT_DEFAULT) + message(STATUS "Detected _WIN32_WINNT from CMAKE_SYSTEM_VERSION: ${ZMQ_WIN32_WINNT_DEFAULT}") + + # TODO limit _WIN32_WINNT to the actual Windows SDK version, which might be different from the default version installed with Visual Studio + if(MSVC_VERSION STREQUAL "1500" AND CMAKE_SYSTEM_VERSION VERSION_GREATER "6.0") + set(ZMQ_WIN32_WINNT_LIMIT "0x0600") + elseif(MSVC_VERSION STREQUAL "1600" AND CMAKE_SYSTEM_VERSION VERSION_GREATER "6.1") + set(ZMQ_WIN32_WINNT_LIMIT "0x0601") + elseif(MSVC_VERSION STREQUAL "1700" AND CMAKE_SYSTEM_VERSION VERSION_GREATER "6.1") + set(ZMQ_WIN32_WINNT_LIMIT "0x0601") + elseif(MSVC_VERSION STREQUAL "1800" AND CMAKE_SYSTEM_VERSION VERSION_GREATER "6.2") + set(ZMQ_WIN32_WINNT_LIMIT "0x0602") + endif() + if(ZMQ_WIN32_WINNT_LIMIT) + message(STATUS "Mismatch of Visual Studio Version (${MSVC_VERSION}) and CMAKE_SYSTEM_VERSION (${CMAKE_SYSTEM_VERSION}), limiting _WIN32_WINNT to ${ZMQ_WIN32_WINNT_LIMIT}, you may override this by setting ZMQ_WIN32_WINNT") + set(ZMQ_WIN32_WINNT_DEFAULT "${ZMQ_WIN32_WINNT_LIMIT}") + endif() + + set(ZMQ_WIN32_WINNT "${ZMQ_WIN32_WINNT_DEFAULT}" CACHE STRING "Value to set _WIN32_WINNT to for building [default=autodetect from build environment]") + + # On Windows Vista or greater, with MSVC 2013 or greater, default to epoll (which is required on Win 10 for ipc support) + if (ZMQ_WIN32_WINNT GREATER "0x05FF" AND MSVC_VERSION GREATER 1799 AND POLLER STREQUAL "") + set(POLLER "epoll") + endif() + + add_definitions(-D_WIN32_WINNT=${ZMQ_WIN32_WINNT}) +endif(WIN32) if(NOT MSVC) if(POLLER STREQUAL "") @@ -294,48 +342,11 @@ if(NOT CYGWIN) check_include_files(windows.h ZMQ_HAVE_WINDOWS) endif() -if (WIN32) - # from https://stackoverflow.com/a/40217291/2019765 - macro(get_WIN32_WINNT version) - if (CMAKE_SYSTEM_VERSION) - set(ver ${CMAKE_SYSTEM_VERSION}) - string(REGEX MATCH "^([0-9]+).([0-9])" ver ${ver}) - string(REGEX MATCH "^([0-9]+)" verMajor ${ver}) - # Check for Windows 10, b/c we'll need to convert to hex 'A'. - if ("${verMajor}" MATCHES "10") - set(verMajor "A") - string(REGEX REPLACE "^([0-9]+)" ${verMajor} ver ${ver}) - endif ("${verMajor}" MATCHES "10") - # Remove all remaining '.' characters. - string(REPLACE "." "" ver ${ver}) - # Prepend each digit with a zero. - string(REGEX REPLACE "([0-9A-Z])" "0\\1" ver ${ver}) - set(${version} "0x${ver}") - endif(CMAKE_SYSTEM_VERSION) - endmacro(get_WIN32_WINNT) - - get_WIN32_WINNT(ZMQ_WIN32_WINNT_DEFAULT) - message(STATUS "Detected _WIN32_WINNT from CMAKE_SYSTEM_VERSION: ${ZMQ_WIN32_WINNT_DEFAULT}") - - # TODO limit _WIN32_WINNT to the actual Windows SDK version, which might be different from the default version installed with Visual Studio - if(MSVC_VERSION STREQUAL "1500" AND CMAKE_SYSTEM_VERSION VERSION_GREATER "6.0") - set(ZMQ_WIN32_WINNT_LIMIT "0x0600") - elseif(MSVC_VERSION STREQUAL "1600" AND CMAKE_SYSTEM_VERSION VERSION_GREATER "6.1") - set(ZMQ_WIN32_WINNT_LIMIT "0x0601") - elseif(MSVC_VERSION STREQUAL "1700" AND CMAKE_SYSTEM_VERSION VERSION_GREATER "6.1") - set(ZMQ_WIN32_WINNT_LIMIT "0x0601") - elseif(MSVC_VERSION STREQUAL "1800" AND CMAKE_SYSTEM_VERSION VERSION_GREATER "6.2") - set(ZMQ_WIN32_WINNT_LIMIT "0x0602") - endif() - if(ZMQ_WIN32_WINNT_LIMIT) - message(STATUS "Mismatch of Visual Studio Version (${MSVC_VERSION}) and CMAKE_SYSTEM_VERSION (${CMAKE_SYSTEM_VERSION}), limiting _WIN32_WINNT to ${ZMQ_WIN32_WINNT_LIMIT}, you may override this by setting ZMQ_WIN32_WINNT") - set(ZMQ_WIN32_WINNT_DEFAULT "${ZMQ_WIN32_WINNT_LIMIT}") - endif() - - set(ZMQ_WIN32_WINNT "${ZMQ_WIN32_WINNT_DEFAULT}" CACHE STRING "Value to set _WIN32_WINNT to for building [default=autodetect from build environment]") - - add_definitions(-D_WIN32_WINNT=${ZMQ_WIN32_WINNT}) -endif(WIN32) +if(NOT WIN32) + set(ZMQ_HAVE_IPC 1) +else() + check_include_files("winsock2.h;afunix.h" ZMQ_HAVE_IPC) +endif() ###################### BEGIN condition_variable_t selection if(NOT ZMQ_CV_IMPL) @@ -438,6 +449,8 @@ if(NOT MSVC) check_cxx_symbol_exists(mkdtemp stdlib.h HAVE_MKDTEMP) check_cxx_symbol_exists(accept4 sys/socket.h HAVE_ACCEPT4) check_cxx_symbol_exists(strnlen string.h HAVE_STRNLEN) +else() + set(HAVE_STRNLEN 1) endif() add_definitions(-D_REENTRANT -D_THREAD_SAFE) diff --git a/builds/cmake/platform.hpp.in b/builds/cmake/platform.hpp.in index d67eca62..0bd9fcab 100644 --- a/builds/cmake/platform.hpp.in +++ b/builds/cmake/platform.hpp.in @@ -51,6 +51,8 @@ #cmakedefine HAVE_ACCEPT4 #cmakedefine HAVE_STRNLEN +#cmakedefine ZMQ_HAVE_IPC + #cmakedefine ZMQ_USE_BUILTIN_SHA1 #cmakedefine ZMQ_USE_NSS #cmakedefine ZMQ_HAVE_WS @@ -104,8 +106,10 @@ #define ZMQ_HAVE_OPENBSD #endif +// TODO better move OS-specific defines to the automake files, and check for availability of IPC with an explicit test there #if defined __VMS #define ZMQ_HAVE_OPENVMS + #undef ZMQ_HAVE_IPC #endif #if defined __APPLE__ diff --git a/configure.ac b/configure.ac index d4ee9d5c..f6619cfe 100644 --- a/configure.ac +++ b/configure.ac @@ -143,6 +143,15 @@ if test "x$zmq_militant" = "xyes"; then AC_DEFINE(ZMQ_ACT_MILITANT, 1, [Enable militant API assertions]) fi +# IPC is available on all platforms supported by autotools build at the moment except OpenVMS and VxWorks. +case "${host_os}" in + *vxworks*|*openvms*) + ;; + *) + AC_DEFINE(ZMQ_HAVE_IPC, 1, [Have AF_UNIX sockets for ipc transport]) + ;; +esac + # Memory mis-use detection AC_MSG_CHECKING([whether to enable ASan]) AC_ARG_ENABLE(address-sanitizer, [AS_HELP_STRING([--enable-address-sanitizer=yes/no], diff --git a/src/address.cpp b/src/address.cpp index 23138377..9ec83c2f 100644 --- a/src/address.cpp +++ b/src/address.cpp @@ -74,8 +74,7 @@ zmq::address_t::~address_t () } #endif -#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS \ - && !defined ZMQ_HAVE_VXWORKS +#if defined ZMQ_HAVE_IPC else if (protocol == protocol_name::ipc) { LIBZMQ_DELETE (resolved.ipc_addr); } @@ -106,8 +105,7 @@ int zmq::address_t::to_string (std::string &addr_) const if (protocol == protocol_name::wss && resolved.ws_addr) return resolved.ws_addr->to_string (addr_); #endif -#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS \ - && !defined ZMQ_HAVE_VXWORKS +#if defined ZMQ_HAVE_IPC if (protocol == protocol_name::ipc && resolved.ipc_addr) return resolved.ipc_addr->to_string (addr_); #endif diff --git a/src/address.hpp b/src/address.hpp index 1f683d6c..8539f41e 100644 --- a/src/address.hpp +++ b/src/address.hpp @@ -46,7 +46,7 @@ class ctx_t; class tcp_address_t; class udp_address_t; class ws_address_t; -#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS +#if defined ZMQ_HAVE_IPC class ipc_address_t; #endif #if defined ZMQ_HAVE_LINUX || defined ZMQ_HAVE_VXWORKS @@ -67,8 +67,7 @@ static const char ws[] = "ws"; #ifdef ZMQ_HAVE_WSS static const char wss[] = "wss"; #endif -#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS \ - && !defined ZMQ_HAVE_VXWORKS +#if defined ZMQ_HAVE_IPC static const char ipc[] = "ipc"; #endif #if defined ZMQ_HAVE_TIPC @@ -101,8 +100,7 @@ struct address_t #ifdef ZMQ_HAVE_WS ws_address_t *ws_addr; #endif -#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS \ - && !defined ZMQ_HAVE_VXWORKS +#if defined ZMQ_HAVE_IPC ipc_address_t *ipc_addr; #endif #if defined ZMQ_HAVE_LINUX || defined ZMQ_HAVE_VXWORKS diff --git a/src/ipc_address.cpp b/src/ipc_address.cpp index 7a4f8c43..4325b439 100644 --- a/src/ipc_address.cpp +++ b/src/ipc_address.cpp @@ -30,8 +30,7 @@ #include "precompiled.hpp" #include "ipc_address.hpp" -#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS \ - && !defined ZMQ_HAVE_VXWORKS +#if defined ZMQ_HAVE_IPC #include "err.hpp" @@ -86,7 +85,8 @@ int zmq::ipc_address_t::resolve (const char *path_) if (path_[0] == '@') *_address.sun_path = '\0'; - _addrlen = offsetof (sockaddr_un, sun_path) + path_len; + _addrlen = + static_cast (offsetof (sockaddr_un, sun_path) + path_len); return 0; } diff --git a/src/ipc_address.hpp b/src/ipc_address.hpp index 37f8447e..59e42605 100644 --- a/src/ipc_address.hpp +++ b/src/ipc_address.hpp @@ -32,11 +32,14 @@ #include -#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS \ - && !defined ZMQ_HAVE_VXWORKS +#if defined ZMQ_HAVE_IPC +#if defined _MSC_VER +#include +#else #include #include +#endif namespace zmq { @@ -58,7 +61,7 @@ class ipc_address_t private: struct sockaddr_un _address; - size_t _addrlen; + socklen_t _addrlen; ipc_address_t (const ipc_address_t &); const ipc_address_t &operator= (const ipc_address_t &); diff --git a/src/ipc_connecter.cpp b/src/ipc_connecter.cpp index 89ead5fa..8d3ba324 100644 --- a/src/ipc_connecter.cpp +++ b/src/ipc_connecter.cpp @@ -30,8 +30,7 @@ #include "precompiled.hpp" #include "ipc_connecter.hpp" -#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS \ - && !defined ZMQ_HAVE_VXWORKS +#if defined ZMQ_HAVE_IPC #include #include @@ -44,11 +43,14 @@ #include "ipc_address.hpp" #include "session_base.hpp" +#ifdef _MSC_VER +#include +#else #include #include #include #include - +#endif zmq::ipc_connecter_t::ipc_connecter_t (class io_thread_t *io_thread_, class session_base_t *session_, @@ -127,12 +129,19 @@ int zmq::ipc_connecter_t::open () if (rc == 0) return 0; - // Translate other error codes indicating asynchronous connect has been - // launched to a uniform EINPROGRESS. + // Translate other error codes indicating asynchronous connect has been + // launched to a uniform EINPROGRESS. +#ifdef ZMQ_HAVE_WINDOWS + const int last_error = WSAGetLastError (); + if (last_error == WSAEINPROGRESS || last_error == WSAEWOULDBLOCK) + errno = EINPROGRESS; + else + errno = wsa_error_to_errno (last_error); +#else if (rc == -1 && errno == EINTR) { errno = EINPROGRESS; - return -1; } +#endif // Forward the error. return -1; diff --git a/src/ipc_connecter.hpp b/src/ipc_connecter.hpp index 3209b0c6..863e364a 100644 --- a/src/ipc_connecter.hpp +++ b/src/ipc_connecter.hpp @@ -30,8 +30,7 @@ #ifndef __IPC_CONNECTER_HPP_INCLUDED__ #define __IPC_CONNECTER_HPP_INCLUDED__ -#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS \ - && !defined ZMQ_HAVE_VXWORKS +#if defined ZMQ_HAVE_IPC #include "fd.hpp" #include "stream_connecter_base.hpp" diff --git a/src/ipc_listener.cpp b/src/ipc_listener.cpp index 4e20f437..df44eb5c 100644 --- a/src/ipc_listener.cpp +++ b/src/ipc_listener.cpp @@ -30,8 +30,7 @@ #include "precompiled.hpp" #include "ipc_listener.hpp" -#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS \ - && !defined ZMQ_HAVE_VXWORKS +#if defined ZMQ_HAVE_IPC #include @@ -45,11 +44,26 @@ #include "socket_base.hpp" #include "address.hpp" +#ifdef _MSC_VER +#ifdef ZMQ_IOTHREAD_POLLER_USE_SELECT +#error On Windows, IPC does not work with POLLER=select, use POLLER=epoll instead, or disable IPC transport +#endif + +#include +#include + +#define S_ISDIR(m) (((m) &S_IFMT) == S_IFDIR) + +#define rmdir _rmdir +#define unlink _unlink + +#else #include #include #include #include #include +#endif #ifdef ZMQ_HAVE_LOCAL_PEERCRED #include @@ -69,10 +83,26 @@ const char *zmq::ipc_listener_t::tmp_env_vars[] = { 0 // Sentinel }; - int zmq::ipc_listener_t::create_wildcard_address (std::string &path_, std::string &file_) { +#if defined ZMQ_HAVE_WINDOWS + char buffer[MAX_PATH]; + + { + const errno_t rc = tmpnam_s (buffer); + errno_assert (rc == 0); + } + + // TODO or use CreateDirectoryA and specify permissions? + const int rc = _mkdir (buffer); + if (rc != 0) { + return -1; + } + + path_.assign (buffer); + file_ = path_ + "/socket"; +#else std::string tmp_path; // If TMPDIR, TEMPDIR, or TMP are available and are directories, create @@ -102,7 +132,7 @@ int zmq::ipc_listener_t::create_wildcard_address (std::string &path_, std::vector buffer (tmp_path.length () + 1); strcpy (&buffer[0], tmp_path.c_str ()); -#ifdef HAVE_MKDTEMP +#if defined HAVE_MKDTEMP // Create the directory. POSIX requires that mkdtemp() creates the // directory with 0700 permissions, meaning the only possible race // with socket creation could be the same user. However, since @@ -123,6 +153,7 @@ int zmq::ipc_listener_t::create_wildcard_address (std::string &path_, ::close (fd); file_.assign (&buffer[0]); +#endif #endif return 0; @@ -202,7 +233,7 @@ int zmq::ipc_listener_t::set_local_address (const char *addr_) } else { // Create a listening socket. _s = open_socket (AF_UNIX, SOCK_STREAM, 0); - if (_s == -1) { + if (_s == retired_fd) { if (!_tmp_socket_dirname.empty ()) { // We need to preserve errno to return to the user int tmp_errno = errno; @@ -242,9 +273,14 @@ error: int zmq::ipc_listener_t::close () { zmq_assert (_s != retired_fd); - int fd_for_event = _s; + fd_t fd_for_event = _s; +#ifdef ZMQ_HAVE_WINDOWS + int rc = closesocket (_s); + wsa_assert (rc != SOCKET_ERROR); +#else int rc = ::close (_s); errno_assert (rc == 0); +#endif _s = retired_fd; @@ -352,12 +388,27 @@ zmq::fd_t zmq::ipc_listener_t::accept () #if defined ZMQ_HAVE_SOCK_CLOEXEC && defined HAVE_ACCEPT4 fd_t sock = ::accept4 (_s, NULL, NULL, SOCK_CLOEXEC); #else - fd_t sock = ::accept (_s, NULL, NULL); + struct sockaddr_storage ss; + memset (&ss, 0, sizeof (ss)); +#if defined ZMQ_HAVE_HPUX || defined ZMQ_HAVE_VXWORKS + int ss_len = sizeof (ss); +#else + socklen_t ss_len = sizeof (ss); #endif - if (sock == -1) { + + fd_t sock = + ::accept (_s, reinterpret_cast (&ss), &ss_len); +#endif + if (sock == retired_fd) { +#if defined ZMQ_HAVE_WINDOWS + const int last_error = WSAGetLastError (); + wsa_assert (last_error == WSAEWOULDBLOCK || last_error == WSAECONNRESET + || last_error == WSAEMFILE || last_error == WSAENOBUFS); +#else errno_assert (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR || errno == ECONNABORTED || errno == EPROTO || errno == ENFILE); +#endif return retired_fd; } diff --git a/src/ipc_listener.hpp b/src/ipc_listener.hpp index 165b8394..ddda500e 100644 --- a/src/ipc_listener.hpp +++ b/src/ipc_listener.hpp @@ -30,8 +30,7 @@ #ifndef __ZMQ_IPC_LISTENER_HPP_INCLUDED__ #define __ZMQ_IPC_LISTENER_HPP_INCLUDED__ -#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS \ - && !defined ZMQ_HAVE_VXWORKS +#if defined ZMQ_HAVE_IPC #include @@ -77,7 +76,7 @@ class ipc_listener_t : public stream_listener_base_t bool _has_file; // Name of the temporary directory (if any) that has the - // the UNIX domain socket + // UNIX domain socket std::string _tmp_socket_dirname; // Name of the file associated with the UNIX domain address. diff --git a/src/session_base.cpp b/src/session_base.cpp index 1812afbb..325f8e69 100644 --- a/src/session_base.cpp +++ b/src/session_base.cpp @@ -576,8 +576,7 @@ zmq::session_base_t::connecter_factory_entry_t connecter_factory_entry_t (protocol_name::wss, &zmq::session_base_t::create_connecter_wss), #endif -#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS \ - && !defined ZMQ_HAVE_VXWORKS +#if defined ZMQ_HAVE_IPC connecter_factory_entry_t (protocol_name::ipc, &zmq::session_base_t::create_connecter_ipc), #endif @@ -668,8 +667,7 @@ zmq::own_t *zmq::session_base_t::create_connecter_tipc (io_thread_t *io_thread_, } #endif -#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS \ - && !defined ZMQ_HAVE_VXWORKS +#if defined ZMQ_HAVE_IPC zmq::own_t *zmq::session_base_t::create_connecter_ipc (io_thread_t *io_thread_, bool wait_) { diff --git a/src/socket_base.cpp b/src/socket_base.cpp index 05c77f43..bcfe0aff 100644 --- a/src/socket_base.cpp +++ b/src/socket_base.cpp @@ -330,8 +330,7 @@ int zmq::socket_base_t::check_protocol (const std::string &protocol_) const { // First check out whether the protocol is something we are aware of. if (protocol_ != protocol_name::inproc -#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS \ - && !defined ZMQ_HAVE_VXWORKS +#if defined ZMQ_HAVE_IPC && protocol_ != protocol_name::ipc #endif && protocol_ != protocol_name::tcp @@ -666,8 +665,7 @@ int zmq::socket_base_t::bind (const char *endpoint_uri_) } #endif -#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS \ - && !defined ZMQ_HAVE_VXWORKS +#if defined ZMQ_HAVE_IPC if (protocol == protocol_name::ipc) { ipc_listener_t *listener = new (std::nothrow) ipc_listener_t (io_thread, this, options); @@ -920,8 +918,7 @@ int zmq::socket_base_t::connect (const char *endpoint_uri_) } #endif -#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS \ - && !defined ZMQ_HAVE_VXWORKS +#if defined ZMQ_HAVE_IPC else if (protocol == protocol_name::ipc) { paddr->resolved.ipc_addr = new (std::nothrow) ipc_address_t (); alloc_assert (paddr->resolved.ipc_addr); diff --git a/src/zmq.cpp b/src/zmq.cpp index 787e80bb..380cf1e3 100644 --- a/src/zmq.cpp +++ b/src/zmq.cpp @@ -1449,7 +1449,7 @@ int zmq_device (int /* type */, void *frontend_, void *backend_) int zmq_has (const char *capability_) { -#if !defined(ZMQ_HAVE_WINDOWS) && !defined(ZMQ_HAVE_OPENVMS) +#if defined(ZMQ_HAVE_IPC) if (strcmp (capability_, zmq::protocol_name::ipc) == 0) return true; #endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b0f15534..e81549e7 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -95,12 +95,17 @@ else() message(STATUS "capsh not found, skipping tests that require CAP_NET_ADMIN") endif() -if(NOT WIN32) +if(ZMQ_HAVE_IPC) list(APPEND tests test_ipc_wildcard test_pair_ipc - test_rebind_ipc test_reqrep_ipc + test_rebind_ipc + ) +endif() + +if(NOT WIN32) + list(APPEND tests test_proxy test_proxy_hwm test_proxy_single_socket diff --git a/tests/test_rebind_ipc.cpp b/tests/test_rebind_ipc.cpp index 41830c95..61736eed 100644 --- a/tests/test_rebind_ipc.cpp +++ b/tests/test_rebind_ipc.cpp @@ -34,7 +34,7 @@ SETUP_TEARDOWN_TESTCONTEXT void test_rebind_ipc () { - char my_endpoint[32]; + char my_endpoint[MAX_SOCKET_STRING]; make_random_ipc_endpoint (my_endpoint); void *sb0 = test_context_socket (ZMQ_PUSH); diff --git a/tests/test_reconnect_ivl.cpp b/tests/test_reconnect_ivl.cpp index 4e15795f..8044abcb 100644 --- a/tests/test_reconnect_ivl.cpp +++ b/tests/test_reconnect_ivl.cpp @@ -58,7 +58,7 @@ void test_reconnect_ivl_against_pair_socket (const char *my_endpoint_, test_context_socket_close (sc); } -#if !defined(ZMQ_HAVE_WINDOWS) && !defined(ZMQ_HAVE_GNU) +#if defined(ZMQ_HAVE_IPC) && !defined(ZMQ_HAVE_GNU) void test_reconnect_ivl_ipc (void) { char my_endpoint[256]; diff --git a/tests/testutil_unity.cpp b/tests/testutil_unity.cpp index 854388ae..d31ba3a9 100644 --- a/tests/testutil_unity.cpp +++ b/tests/testutil_unity.cpp @@ -31,7 +31,9 @@ #include #include -#ifndef _WIN32 +#ifdef _WIN32 +#include +#else #include #endif @@ -288,9 +290,24 @@ void bind_loopback_tipc (void *socket_, char *my_endpoint_, size_t len_) test_bind (socket_, "tipc://<*>", my_endpoint_, len_); } -#if !defined(ZMQ_HAVE_WINDOWS) && !defined(ZMQ_HAVE_GNU) +#if defined(ZMQ_HAVE_IPC) && !defined(ZMQ_HAVE_GNU) void make_random_ipc_endpoint (char *out_endpoint_) { +#ifdef ZMQ_HAVE_WINDOWS + char random_file[MAX_PATH]; + + { + const errno_t rc = tmpnam_s (random_file); + TEST_ASSERT_EQUAL (0, rc); + } + + // TODO or use CreateDirectoryA and specify permissions? + const int rc = _mkdir (random_file); + TEST_ASSERT_EQUAL (0, rc); + + strcat (random_file, "/ipc"); + +#else char random_file[16]; strcpy (random_file, "tmpXXXXXX"); @@ -301,6 +318,7 @@ void make_random_ipc_endpoint (char *out_endpoint_) int fd = mkstemp (random_file); TEST_ASSERT_TRUE (fd != -1); close (fd); +#endif #endif strcpy (out_endpoint_, "ipc://"); diff --git a/tests/testutil_unity.hpp b/tests/testutil_unity.hpp index e3d80d89..a682a49e 100644 --- a/tests/testutil_unity.hpp +++ b/tests/testutil_unity.hpp @@ -256,7 +256,7 @@ void bind_loopback_ipc (void *socket_, char *my_endpoint_, size_t len_); // Binds to an ipc endpoint using the tipc wildcard address. void bind_loopback_tipc (void *socket_, char *my_endpoint_, size_t len_); -#if !defined(ZMQ_HAVE_WINDOWS) && !defined(ZMQ_HAVE_GNU) +#if defined(ZMQ_HAVE_IPC) && !defined(ZMQ_HAVE_GNU) // utility function to create a random IPC endpoint, similar to what a ipc://* // wildcard binding does, but in a way it can be reused for multiple binds // TODO also add a len parameter here