Commit 1bb982ec authored by Richard Newton's avatar Richard Newton

Merge branch 'master' of https://github.com/zeromq/libzmq

parents f06bf8d2 3b628fd8
...@@ -22,6 +22,7 @@ autom4te.cache ...@@ -22,6 +22,7 @@ autom4te.cache
.*~ .*~
tools/curve_keygen.o tools/curve_keygen.o
tools/curve_keygen tools/curve_keygen
tests/test_issue_566
tests/test_ctx_destroy tests/test_ctx_destroy
tests/test_term_endpoint tests/test_term_endpoint
tests/test_system tests/test_system
...@@ -68,6 +69,7 @@ tests/test_inproc_connect ...@@ -68,6 +69,7 @@ tests/test_inproc_connect
tests/test_linger tests/test_linger
tests/test_security_null tests/test_security_null
tests/test_security_plain tests/test_security_plain
tests/test_abstract_ipc
tests/test*.log tests/test*.log
tests/test*.trs tests/test*.trs
src/platform.hpp* src/platform.hpp*
......
...@@ -6,8 +6,11 @@ language: c ...@@ -6,8 +6,11 @@ language: c
before_script: before_script:
# libsodium # libsodium
# Commit 8d0942 broke installation (sodium.h not found) so for now
# we're checking out the last good commit.
- git clone git://github.com/jedisct1/libsodium.git - git clone git://github.com/jedisct1/libsodium.git
- cd libsodium - cd libsodium
- git checkout e2a30a
- ./autogen.sh - ./autogen.sh
- ./configure && make check - ./configure && make check
- sudo make install - sudo make install
......
...@@ -20,6 +20,7 @@ Ben Gray <ben@benjamg.com> ...@@ -20,6 +20,7 @@ Ben Gray <ben@benjamg.com>
Bernd Prager <bernd@prager.ws> Bernd Prager <bernd@prager.ws>
Bernd Melchers <melchers@ZEDAT.FU-Berlin.DE> Bernd Melchers <melchers@ZEDAT.FU-Berlin.DE>
Bob Beaty <rbeaty@peak6.com> Bob Beaty <rbeaty@peak6.com>
Brandon Carpenter <hashstat@yahoo.com>
Brian Buchanan <bwb@holo.org> Brian Buchanan <bwb@holo.org>
Brett Cameron <Brett.Cameron@hp.com> Brett Cameron <Brett.Cameron@hp.com>
Burak Arslan <burak-github@arskom.com.tr> Burak Arslan <burak-github@arskom.com.tr>
......
...@@ -610,14 +610,15 @@ set(tests ...@@ -610,14 +610,15 @@ set(tests
test_sub_forward test_sub_forward
test_term_endpoint test_term_endpoint
test_timeo test_timeo
test_inproc_connect) test_inproc_connect
test_issue_566)
if(NOT WIN32) if(NOT WIN32)
list(APPEND tests list(APPEND tests
test_monitor test_monitor
test_pair_ipc test_pair_ipc
test_reqrep_ipc test_reqrep_ipc
test_stream) test_stream)
endif() endif()
foreach(test ${tests}) foreach(test ${tests})
add_executable(${test} tests/${test}.cpp) add_executable(${test} tests/${test}.cpp)
......
0MQ version 4.1.0, released on 2014/xx/xx 0MQ version 4.0.1 stable, released on 2013/10/08
========================================= ================================================
Changes
-------
* Updated CURVE mechanism to track revised RFC 27 (INITIATE vouch).
The INITIATE command vouch box is Box[C',S](C->S') instead of
Box[C'](C->S), to reduce the risk of client impersonation, as per
https://codesinchaos.wordpress.com/2012/09/09/curvecp-1/.
* Fixed LIBZMQ-567, adding abstract namespaces for IPC sockets on Linux.
Converts an initial strudel or "at sign" (@) in the Unix socket path to
a NULL character ('\0') indicating that the socket uses the abstract
namespace instead of the filesystem namespace. For instance, binding a
socket to 'ipc://@/tmp/tester' will not create a file associated with
the socket whereas binding to 'ipc:///tmp/tester' will create the file
/tmp/tester. See issue 567 for more information.
* Added zmq_z85_encode and zmq_z85_decode to core libzmq API.
* Added zmq_curve_keypair to core libzmq API.
* Bumped library ABI version to 4:0:1.
Bug fixes
---------
* Fixed some build/test errors on OS/X + Clang++.
* Fixed LIBZMQ-565, typo in code.
* Fixed LIBZMQ-566, dealer-to-router connections sometimes failing.
* Fixed builds for AIX, MSVC 2008, OS/X with clang++, Solaris.
* Improved CURVE handshake error handling.
0MQ version 4.0.0 (RC1), released on 2013/09/20 0MQ version 4.0.0 (RC1), released on 2013/09/20
......
...@@ -73,7 +73,7 @@ AC_ARG_WITH([libsodium], ...@@ -73,7 +73,7 @@ AC_ARG_WITH([libsodium],
if test "x$zmq_search_libsodium" = "xyes"; then if test "x$zmq_search_libsodium" = "xyes"; then
if test -r "${with_libsodium}/include/sodium.h"; then if test -r "${with_libsodium}/include/sodium.h"; then
CXXFLAGS="-I${with_libsodium}/include ${CXXFLAGS}" CPPFLAGS="-I${with_libsodium}/include ${CPPFLAGS}"
LDFLAGS="-L${with_libsodium}/lib ${LDFLAGS}" LDFLAGS="-L${with_libsodium}/lib ${LDFLAGS}"
fi fi
fi fi
...@@ -86,7 +86,7 @@ AC_ARG_WITH([libsodium-include-dir], ...@@ -86,7 +86,7 @@ AC_ARG_WITH([libsodium-include-dir],
if test "x$zmq_search_libsodium_include" = "xyes"; then if test "x$zmq_search_libsodium_include" = "xyes"; then
if test -r "${with_libsodium_include_dir}/sodium.h"; then if test -r "${with_libsodium_include_dir}/sodium.h"; then
CXXFLAGS="-I${with_libsodium_include_dir}/include ${CXXFLAGS}" CPPFLAGS="-I${with_libsodium_include_dir}/include ${CPPFLAGS}"
fi fi
fi fi
...@@ -102,11 +102,6 @@ if test "x$zmq_search_libsodium_lib" = "xyes"; then ...@@ -102,11 +102,6 @@ if test "x$zmq_search_libsodium_lib" = "xyes"; then
fi fi
fi fi
# Checks for libraries
AC_CHECK_LIB([pthread], [pthread_create])
AC_CHECK_LIB([rt], [clock_gettime])
AC_CHECK_LIB([sodium], [sodium_init],,AC_MSG_WARN(libsodium is needed for CURVE security))
# Set pedantic # Set pedantic
libzmq_pedantic="yes" libzmq_pedantic="yes"
...@@ -119,6 +114,7 @@ libzmq_dso_visibility="yes" ...@@ -119,6 +114,7 @@ libzmq_dso_visibility="yes"
# Platform specific checks # Platform specific checks
libzmq_on_mingw32="no" libzmq_on_mingw32="no"
libzmq_on_android="no" libzmq_on_android="no"
libzmq_on_linux="no"
# Set some default features required by 0MQ code. # Set some default features required by 0MQ code.
CPPFLAGS="-D_REENTRANT -D_THREAD_SAFE $CPPFLAGS" CPPFLAGS="-D_REENTRANT -D_THREAD_SAFE $CPPFLAGS"
...@@ -134,6 +130,7 @@ case "${host_os}" in ...@@ -134,6 +130,7 @@ case "${host_os}" in
CPPFLAGS="-D_GNU_SOURCE $CPPFLAGS" CPPFLAGS="-D_GNU_SOURCE $CPPFLAGS"
fi fi
AC_DEFINE(ZMQ_HAVE_LINUX, 1, [Have Linux OS]) AC_DEFINE(ZMQ_HAVE_LINUX, 1, [Have Linux OS])
libzmq_on_linux="yes"
case "${host_os}" in case "${host_os}" in
*android*) *android*)
...@@ -161,6 +158,9 @@ case "${host_os}" in ...@@ -161,6 +158,9 @@ case "${host_os}" in
if test "x$solaris_has_atomic" = "xno"; then if test "x$solaris_has_atomic" = "xno"; then
AC_DEFINE(ZMQ_FORCE_MUTEXES, 1, [Force to use mutexes]) AC_DEFINE(ZMQ_FORCE_MUTEXES, 1, [Force to use mutexes])
fi fi
# ssp library is required for libsodium on Solaris-like systems
LDFLAGS="-lssp $LDFLAGS"
CPPFLAGS="$CPPFLAGS -Wno-long-long"
;; ;;
*freebsd*) *freebsd*)
# Define on FreeBSD to enable all library features # Define on FreeBSD to enable all library features
...@@ -254,6 +254,11 @@ case "${host_os}" in ...@@ -254,6 +254,11 @@ case "${host_os}" in
;; ;;
esac esac
# Checks for libraries
AC_CHECK_LIB([pthread], [pthread_create])
AC_CHECK_LIB([rt], [clock_gettime])
AC_CHECK_LIB([sodium], [sodium_init],,AC_MSG_WARN(libsodium is needed for CURVE security))
# #
# Check if the compiler supports -fvisibility=hidden flag. MinGW32 uses __declspec # Check if the compiler supports -fvisibility=hidden flag. MinGW32 uses __declspec
# #
...@@ -425,6 +430,7 @@ AC_LANG_POP([C++]) ...@@ -425,6 +430,7 @@ AC_LANG_POP([C++])
AM_CONDITIONAL(BUILD_PGM, test "x$libzmq_pgm_ext" = "xyes") AM_CONDITIONAL(BUILD_PGM, test "x$libzmq_pgm_ext" = "xyes")
AM_CONDITIONAL(ON_MINGW, test "x$libzmq_on_mingw32" = "xyes") AM_CONDITIONAL(ON_MINGW, test "x$libzmq_on_mingw32" = "xyes")
AM_CONDITIONAL(ON_ANDROID, test "x$libzmq_on_android" = "xyes") AM_CONDITIONAL(ON_ANDROID, test "x$libzmq_on_android" = "xyes")
AM_CONDITIONAL(ON_LINUX, test "x$libzmq_on_linux" = "xyes")
# Checks for library functions. # Checks for library functions.
AC_TYPE_SIGNAL AC_TYPE_SIGNAL
......
...@@ -9,7 +9,7 @@ MAN3 = zmq_bind.3 zmq_unbind.3 zmq_connect.3 zmq_disconnect.3 zmq_close.3 \ ...@@ -9,7 +9,7 @@ MAN3 = zmq_bind.3 zmq_unbind.3 zmq_connect.3 zmq_disconnect.3 zmq_close.3 \
zmq_socket.3 zmq_socket_monitor.3 zmq_poll.3 \ zmq_socket.3 zmq_socket_monitor.3 zmq_poll.3 \
zmq_errno.3 zmq_strerror.3 zmq_version.3 zmq_proxy.3 \ zmq_errno.3 zmq_strerror.3 zmq_version.3 zmq_proxy.3 \
zmq_sendmsg.3 zmq_recvmsg.3 zmq_init.3 zmq_term.3 \ zmq_sendmsg.3 zmq_recvmsg.3 zmq_init.3 zmq_term.3 \
zmq_z85_encode.3 zmq_z85_decode.3 zmq_z85_encode.3 zmq_z85_decode.3 zmq_curve_keypair.3
MAN7 = zmq.7 zmq_tcp.7 zmq_pgm.7 zmq_epgm.7 zmq_inproc.7 zmq_ipc.7 \ MAN7 = zmq.7 zmq_tcp.7 zmq_pgm.7 zmq_epgm.7 zmq_inproc.7 zmq_ipc.7 \
zmq_null.7 zmq_plain.7 zmq_curve.7 zmq_null.7 zmq_plain.7 zmq_curve.7
......
...@@ -194,6 +194,15 @@ Plain-text authentication using username and password:: ...@@ -194,6 +194,15 @@ Plain-text authentication using username and password::
Elliptic curve authentication and encryption:: Elliptic curve authentication and encryption::
linkzmq:zmq_curve[7] linkzmq:zmq_curve[7]
Generate a CURVE keypair in armored text format:
linkzmq:zmq_curve_keypair[3]
Convert an armored key into a 32-byte binary key:
linkzmq:zmq_z85_decode[3]
Convert a 32-byte binary CURVE key to an armored text string:
linkzmq:zmq_z85_encode[3]
ERROR HANDLING ERROR HANDLING
-------------- --------------
......
...@@ -54,7 +54,7 @@ EXAMPLE ...@@ -54,7 +54,7 @@ EXAMPLE
.Setting a limit on the number of sockets .Setting a limit on the number of sockets
---- ----
void *context = zmq_ctx_new (); void *context = zmq_ctx_new ();
zmq_ctx_get (context, ZMQ_MAX_SOCKETS, 256); zmq_ctx_set (context, ZMQ_MAX_SOCKETS, 256);
int max_sockets = zmq_ctx_get (context, ZMQ_MAX_SOCKETS); int max_sockets = zmq_ctx_get (context, ZMQ_MAX_SOCKETS);
assert (max_sockets == 256); assert (max_sockets == 256);
---- ----
......
zmq_curve_keypair(3)
====================
NAME
----
zmq_curve_keypair - generate a new CURVE keypair
SYNOPSIS
--------
*int zmq_curve_keypair (char *z85_public_key, char *z85_secret_key);*
DESCRIPTION
-----------
The _zmq_curve_keypair()_ function shall return a newly generated random
keypair consisting of a public key and a secret key. The caller provides
two buffers, each at least 41 octets large, in which this method will
store the keys. The keys are encoded using linkzmq:zmq_z85_encode[3].
RETURN VALUE
------------
The _zmq_curve_keypair()_ function shall return 0 if successful, else it
shall return `-1` and set 'errno' to one of the values defined below.
ERRORS
------
*ENOTSUP*::
The libzmq library was not built with cryptographic support (libsodium).
EXAMPLE
-------
.Generating a new CURVE keypair
----
char public_key [41];
char secret_key [41];
int rc = crypto_box_keypair (public_key, secret_key);
assert (rc == 0);
----
SEE ALSO
--------
linkzmq:zmq_z85_decode[3]
linkzmq:zmq_z85_encode[3]
linkzmq:zmq_curve[7]
AUTHORS
-------
This page was written by the 0MQ community. To make a change please
read the 0MQ Contribution Policy at <http://www.zeromq.org/docs:contributing>.
...@@ -120,8 +120,8 @@ Default value:: 0 ...@@ -120,8 +120,8 @@ Default value:: 0
Applicable socket types:: N/A Applicable socket types:: N/A
ZMQ_IDENTITY: Set socket identity ZMQ_IDENTITY: Retrieve socket identity
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The 'ZMQ_IDENTITY' option shall retrieve the identity of the specified 'socket'. The 'ZMQ_IDENTITY' option shall retrieve the identity of the specified 'socket'.
Socket identity is used only by request/reply pattern. Namely, it can be used Socket identity is used only by request/reply pattern. Namely, it can be used
in tandem with ROUTER socket to route messages to the peer with specific in tandem with ROUTER socket to route messages to the peer with specific
...@@ -134,7 +134,7 @@ starting with binary zero are reserved for use by 0MQ infrastructure. ...@@ -134,7 +134,7 @@ starting with binary zero are reserved for use by 0MQ infrastructure.
Option value type:: binary data Option value type:: binary data
Option value unit:: N/A Option value unit:: N/A
Default value:: NULL Default value:: NULL
Applicable socket types:: all Applicable socket types:: ZMQ_REP, ZMQ_REQ, ZMQ_ROUTER, ZMQ_DEALER.
ZMQ_RATE: Retrieve multicast data rate ZMQ_RATE: Retrieve multicast data rate
......
...@@ -48,6 +48,11 @@ NOTE: the endpoint pathname must be writable by the process. When the endpoint ...@@ -48,6 +48,11 @@ NOTE: the endpoint pathname must be writable by the process. When the endpoint
starts with '/', e.g., `ipc:///pathname`, this will be an _absolute_ pathname. starts with '/', e.g., `ipc:///pathname`, this will be an _absolute_ pathname.
If the endpoint specifies a directory that does not exist, the bind shall fail. If the endpoint specifies a directory that does not exist, the bind shall fail.
NOTE: on Linux only, when the endpoint pathname starts with `@`, the abstract
namespace shall be used. The abstract namespace is independent of the
filesystem and if a process attempts to bind an endpoint already bound by a
process, it will fail. See unix(7) for details.
Connecting a socket Connecting a socket
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
When connecting a 'socket' to a peer address using _zmq_connect()_ with the When connecting a 'socket' to a peer address using _zmq_connect()_ with the
......
...@@ -31,6 +31,10 @@ _zmq_msg_ family of functions. ...@@ -31,6 +31,10 @@ _zmq_msg_ family of functions.
CAUTION: The deallocation function 'ffn' needs to be thread-safe, since it CAUTION: The deallocation function 'ffn' needs to be thread-safe, since it
will be called from an arbitrary thread. will be called from an arbitrary thread.
CAUTION: If the deallocation function is not provided, the allocated memory
will not be freed, and this may cause a memory leak.
CAUTION: The functions _zmq_msg_init()_, _zmq_msg_init_data()_ and CAUTION: The functions _zmq_msg_init()_, _zmq_msg_init_data()_ and
_zmq_msg_init_size()_ are mutually exclusive. Never initialize the same _zmq_msg_init_size()_ are mutually exclusive. Never initialize the same
'zmq_msg_t' twice. 'zmq_msg_t' twice.
......
...@@ -150,7 +150,7 @@ results shall be undefined. ...@@ -150,7 +150,7 @@ results shall be undefined.
Option value type:: binary data Option value type:: binary data
Option value unit:: N/A Option value unit:: N/A
Default value:: NULL Default value:: NULL
Applicable socket types:: all Applicable socket types:: ZMQ_REQ, ZMQ_REP, ZMQ_ROUTER, ZMQ_DEALER.
ZMQ_RATE: Set multicast data rate ZMQ_RATE: Set multicast data rate
......
...@@ -31,7 +31,6 @@ EXAMPLE ...@@ -31,7 +31,6 @@ EXAMPLE
------- -------
.Decoding a CURVE key .Decoding a CURVE key
---- ----
#include <sodium.h>
char decoded [] = "rq:rM>}U?@Lns47E1%kR.o@n%FcmmsL/@{H8]yf7"; char decoded [] = "rq:rM>}U?@Lns47E1%kR.o@n%FcmmsL/@{H8]yf7";
uint8_t public_key [32]; uint8_t public_key [32];
zmq_z85_decode (public_key, decoded); zmq_z85_decode (public_key, decoded);
...@@ -41,6 +40,7 @@ zmq_z85_decode (public_key, decoded); ...@@ -41,6 +40,7 @@ zmq_z85_decode (public_key, decoded);
SEE ALSO SEE ALSO
-------- --------
linkzmq:zmq_z85_decode[3] linkzmq:zmq_z85_decode[3]
linkzmq:zmq_curve_keypair[3]
linkzmq:zmq_curve[7] linkzmq:zmq_curve[7]
......
...@@ -47,6 +47,7 @@ puts (encoded); ...@@ -47,6 +47,7 @@ puts (encoded);
SEE ALSO SEE ALSO
-------- --------
linkzmq:zmq_z85_decode[3] linkzmq:zmq_z85_decode[3]
linkzmq:zmq_curve_keypair[3]
linkzmq:zmq_curve[7] linkzmq:zmq_curve[7]
......
...@@ -15,6 +15,14 @@ ...@@ -15,6 +15,14 @@
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*************************************************************************
NOTE to contributors. This file comprises the principal public contract
for ZeroMQ API users (along with zmq_utils.h). Any change to this file
supplied in a stable release SHOULD not break existing applications.
In practice this means that the value of constants must not change, and
that old values may not be reused for new constants.
*************************************************************************
*/ */
#ifndef __ZMQ_H_INCLUDED__ #ifndef __ZMQ_H_INCLUDED__
......
...@@ -61,8 +61,22 @@ extern "C" { ...@@ -61,8 +61,22 @@ extern "C" {
# endif # endif
#endif #endif
/* These functions are documented by man pages */
/* Encode data with Z85 encoding. Returns encoded data */
ZMQ_EXPORT char *zmq_z85_encode (char *dest, uint8_t *data, size_t size);
/* Decode data with Z85 encoding. Returns decoded data */
ZMQ_EXPORT uint8_t *zmq_z85_decode (uint8_t *dest, char *string);
/* Generate z85-encoded public and private keypair with libsodium. */
/* Returns 0 on success. */
ZMQ_EXPORT int zmq_curve_keypair (char *z85_public_key, char *z85_secret_key);
typedef void (zmq_thread_fn) (void*); typedef void (zmq_thread_fn) (void*);
/* These functions are not documented by man pages */
/* Helper functions are used by perf tests so that they don't have to care */ /* Helper functions are used by perf tests so that they don't have to care */
/* about minutiae of time-related functions on different OS platforms. */ /* about minutiae of time-related functions on different OS platforms. */
......
...@@ -74,14 +74,12 @@ zmq::ctx_t::~ctx_t () ...@@ -74,14 +74,12 @@ zmq::ctx_t::~ctx_t ()
delete io_threads [i]; delete io_threads [i];
// Deallocate the reaper thread object. // Deallocate the reaper thread object.
if (reaper) delete reaper;
delete reaper;
// Deallocate the array of mailboxes. No special work is // Deallocate the array of mailboxes. No special work is
// needed as mailboxes themselves were deallocated with their // needed as mailboxes themselves were deallocated with their
// corresponding io_thread/socket objects. // corresponding io_thread/socket objects.
if (slots) free (slots);
free (slots);
// Remove the tag, so that the object is considered dead. // Remove the tag, so that the object is considered dead.
tag = ZMQ_CTX_TAG_VALUE_BAD; tag = ZMQ_CTX_TAG_VALUE_BAD;
......
...@@ -132,8 +132,8 @@ namespace zmq ...@@ -132,8 +132,8 @@ namespace zmq
sockets_t sockets; sockets_t sockets;
// List of unused thread slots. // List of unused thread slots.
typedef std::vector <uint32_t> emtpy_slots_t; typedef std::vector <uint32_t> empty_slots_t;
emtpy_slots_t empty_slots; empty_slots_t empty_slots;
// If true, zmq_init has been called but no socket has been created // If true, zmq_init has been called but no socket has been created
// yet. Launching of I/O threads is delayed. // yet. Launching of I/O threads is delayed.
......
...@@ -371,7 +371,7 @@ int zmq::curve_server_t::process_initiate (msg_t *msg_) ...@@ -371,7 +371,7 @@ int zmq::curve_server_t::process_initiate (msg_t *msg_)
// Check cookie plain text is as expected [C' + s'] // Check cookie plain text is as expected [C' + s']
if (memcmp (cookie_plaintext + crypto_secretbox_ZEROBYTES, cn_client, 32) if (memcmp (cookie_plaintext + crypto_secretbox_ZEROBYTES, cn_client, 32)
|| memcmp (cookie_plaintext + crypto_secretbox_ZEROBYTES + 32, cn_secret, 32)) { || memcmp (cookie_plaintext + crypto_secretbox_ZEROBYTES + 32, cn_secret, 32)) {
errno = EAGAIN; errno = EPROTO;
return -1; return -1;
} }
......
...@@ -41,11 +41,11 @@ namespace zmq ...@@ -41,11 +41,11 @@ namespace zmq
// This method is called by the session to signalise that more // This method is called by the session to signalise that more
// messages can be written to the pipe. // messages can be written to the pipe.
virtual void activate_in () = 0; virtual void restart_input () = 0;
// This method is called by the session to signalise that there // This method is called by the session to signalise that there
// are messages to send available. // are messages to send available.
virtual void activate_out () = 0; virtual void restart_output () = 0;
virtual void zap_msg_available () = 0; virtual void zap_msg_available () = 0;
}; };
......
...@@ -51,9 +51,20 @@ int zmq::ipc_address_t::resolve (const char *path_) ...@@ -51,9 +51,20 @@ int zmq::ipc_address_t::resolve (const char *path_)
errno = ENAMETOOLONG; errno = ENAMETOOLONG;
return -1; return -1;
} }
#if defined ZMQ_HAVE_LINUX
if (path_[0] == '@' && !path_[1]) {
errno = EINVAL;
return -1;
}
#endif
address.sun_family = AF_UNIX; address.sun_family = AF_UNIX;
strcpy (address.sun_path, path_); strcpy (address.sun_path, path_);
#if defined ZMQ_HAVE_LINUX
/* Abstract sockets on Linux start with '\0' */
if (path_[0] == '@')
*address.sun_path = '\0';
#endif
return 0; return 0;
} }
...@@ -65,7 +76,15 @@ int zmq::ipc_address_t::to_string (std::string &addr_) ...@@ -65,7 +76,15 @@ int zmq::ipc_address_t::to_string (std::string &addr_)
} }
std::stringstream s; std::stringstream s;
#if !defined ZMQ_HAVE_LINUX
s << "ipc://" << address.sun_path; s << "ipc://" << address.sun_path;
#else
s << "ipc://";
if (!address.sun_path[0] && address.sun_path[1])
s << "@" << address.sun_path + 1;
else
s << address.sun_path;
#endif
addr_ = s.str (); addr_ = s.str ();
return 0; return 0;
} }
...@@ -77,6 +96,10 @@ const sockaddr *zmq::ipc_address_t::addr () const ...@@ -77,6 +96,10 @@ const sockaddr *zmq::ipc_address_t::addr () const
socklen_t zmq::ipc_address_t::addrlen () const socklen_t zmq::ipc_address_t::addrlen () const
{ {
#if defined ZMQ_HAVE_LINUX
if (!address.sun_path[0] && address.sun_path[1])
return (socklen_t) strlen(address.sun_path + 1) + sizeof (sa_family_t) + 1;
#endif
return (socklen_t) sizeof (address); return (socklen_t) sizeof (address);
} }
......
...@@ -54,8 +54,7 @@ zmq::mtrie_t::~mtrie_t () ...@@ -54,8 +54,7 @@ zmq::mtrie_t::~mtrie_t ()
else else
if (count > 1) { if (count > 1) {
for (unsigned short i = 0; i != count; ++i) for (unsigned short i = 0; i != count; ++i)
if (next.table [i]) delete next.table [i];
delete next.table [i];
free (next.table); free (next.table);
} }
} }
......
...@@ -286,7 +286,7 @@ int zmq::options_t::setsockopt (int option_, const void *optval_, ...@@ -286,7 +286,7 @@ int zmq::options_t::setsockopt (int option_, const void *optval_,
break; break;
case ZMQ_ZAP_DOMAIN: case ZMQ_ZAP_DOMAIN:
if (optvallen_ >= 0 && optvallen_ < 256) { if (optvallen_ < 256) {
zap_domain.assign ((const char *) optval_, optvallen_); zap_domain.assign ((const char *) optval_, optvallen_);
return 0; return 0;
} }
......
...@@ -102,12 +102,12 @@ void zmq::pgm_receiver_t::terminate () ...@@ -102,12 +102,12 @@ void zmq::pgm_receiver_t::terminate ()
delete this; delete this;
} }
void zmq::pgm_receiver_t::activate_out () void zmq::pgm_receiver_t::restart_output ()
{ {
drop_subscriptions (); drop_subscriptions ();
} }
void zmq::pgm_receiver_t::activate_in () void zmq::pgm_receiver_t::restart_input ()
{ {
zmq_assert (session != NULL); zmq_assert (session != NULL);
zmq_assert (active_tsi != NULL); zmq_assert (active_tsi != NULL);
......
...@@ -57,8 +57,8 @@ namespace zmq ...@@ -57,8 +57,8 @@ namespace zmq
void plug (zmq::io_thread_t *io_thread_, void plug (zmq::io_thread_t *io_thread_,
zmq::session_base_t *session_); zmq::session_base_t *session_);
void terminate (); void terminate ();
void activate_in (); void restart_input ();
void activate_out (); void restart_output ();
void zap_msg_available () {} void zap_msg_available () {}
// i_poll_events interface implementation. // i_poll_events interface implementation.
......
...@@ -119,13 +119,13 @@ void zmq::pgm_sender_t::terminate () ...@@ -119,13 +119,13 @@ void zmq::pgm_sender_t::terminate ()
delete this; delete this;
} }
void zmq::pgm_sender_t::activate_out () void zmq::pgm_sender_t::restart_output ()
{ {
set_pollout (handle); set_pollout (handle);
out_event (); out_event ();
} }
void zmq::pgm_sender_t::activate_in () void zmq::pgm_sender_t::restart_input ()
{ {
zmq_assert (false); zmq_assert (false);
} }
......
...@@ -56,8 +56,8 @@ namespace zmq ...@@ -56,8 +56,8 @@ namespace zmq
void plug (zmq::io_thread_t *io_thread_, void plug (zmq::io_thread_t *io_thread_,
zmq::session_base_t *session_); zmq::session_base_t *session_);
void terminate (); void terminate ();
void activate_in (); void restart_input ();
void activate_out (); void restart_output ();
void zap_msg_available () {} void zap_msg_available () {}
// i_poll_events interface implementation. // i_poll_events interface implementation.
......
...@@ -96,8 +96,7 @@ zmq::session_base_t::~session_base_t () ...@@ -96,8 +96,7 @@ zmq::session_base_t::~session_base_t ()
if (engine) if (engine)
engine->terminate (); engine->terminate ();
if (addr) delete addr;
delete addr;
} }
void zmq::session_base_t::attach_pipe (pipe_t *pipe_) void zmq::session_base_t::attach_pipe (pipe_t *pipe_)
...@@ -244,7 +243,7 @@ void zmq::session_base_t::read_activated (pipe_t *pipe_) ...@@ -244,7 +243,7 @@ void zmq::session_base_t::read_activated (pipe_t *pipe_)
} }
if (likely (pipe_ == pipe)) if (likely (pipe_ == pipe))
engine->activate_out (); engine->restart_output ();
else else
engine->zap_msg_available (); engine->zap_msg_available ();
} }
...@@ -258,7 +257,7 @@ void zmq::session_base_t::write_activated (pipe_t *pipe_) ...@@ -258,7 +257,7 @@ void zmq::session_base_t::write_activated (pipe_t *pipe_)
} }
if (engine) if (engine)
engine->activate_in (); engine->restart_input ();
} }
void zmq::session_base_t::hiccuped (pipe_t *) void zmq::session_base_t::hiccuped (pipe_t *)
......
...@@ -74,8 +74,8 @@ zmq::stream_engine_t::stream_engine_t (fd_t fd_, const options_t &options_, ...@@ -74,8 +74,8 @@ zmq::stream_engine_t::stream_engine_t (fd_t fd_, const options_t &options_,
io_error (false), io_error (false),
subscription_required (false), subscription_required (false),
mechanism (NULL), mechanism (NULL),
input_paused (false), input_stopped (false),
output_paused (false), output_stopped (false),
socket (NULL) socket (NULL)
{ {
int rc = tx_msg.init (); int rc = tx_msg.init ();
...@@ -114,12 +114,9 @@ zmq::stream_engine_t::~stream_engine_t () ...@@ -114,12 +114,9 @@ zmq::stream_engine_t::~stream_engine_t ()
int rc = tx_msg.close (); int rc = tx_msg.close ();
errno_assert (rc == 0); errno_assert (rc == 0);
if (encoder != NULL) delete encoder;
delete encoder; delete decoder;
if (decoder != NULL) delete mechanism;
delete decoder;
if (mechanism != NULL)
delete mechanism;
} }
void zmq::stream_engine_t::plug (io_thread_t *io_thread_, void zmq::stream_engine_t::plug (io_thread_t *io_thread_,
...@@ -207,7 +204,7 @@ void zmq::stream_engine_t::in_event () ...@@ -207,7 +204,7 @@ void zmq::stream_engine_t::in_event ()
zmq_assert (decoder); zmq_assert (decoder);
// If there has been an I/O error, stop polling. // If there has been an I/O error, stop polling.
if (input_paused) { if (input_stopped) {
rm_fd (handle); rm_fd (handle);
io_error = true; io_error = true;
return; return;
...@@ -255,7 +252,7 @@ void zmq::stream_engine_t::in_event () ...@@ -255,7 +252,7 @@ void zmq::stream_engine_t::in_event ()
error (); error ();
return; return;
} }
input_paused = true; input_stopped = true;
reset_pollin (handle); reset_pollin (handle);
} }
...@@ -294,7 +291,7 @@ void zmq::stream_engine_t::out_event () ...@@ -294,7 +291,7 @@ void zmq::stream_engine_t::out_event ()
// If there is no data to send, stop polling for output. // If there is no data to send, stop polling for output.
if (outsize == 0) { if (outsize == 0) {
output_paused = true; output_stopped = true;
reset_pollout (handle); reset_pollout (handle);
return; return;
} }
...@@ -331,14 +328,14 @@ void zmq::stream_engine_t::out_event () ...@@ -331,14 +328,14 @@ void zmq::stream_engine_t::out_event ()
terminate (); terminate ();
} }
void zmq::stream_engine_t::activate_out () void zmq::stream_engine_t::restart_output ()
{ {
if (unlikely (io_error)) if (unlikely (io_error))
return; return;
if (likely (output_paused)) { if (likely (output_stopped)) {
set_pollout (handle); set_pollout (handle);
output_paused = false; output_stopped = false;
} }
// Speculative write: The assumption is that at the moment new message // Speculative write: The assumption is that at the moment new message
...@@ -348,9 +345,9 @@ void zmq::stream_engine_t::activate_out () ...@@ -348,9 +345,9 @@ void zmq::stream_engine_t::activate_out ()
out_event (); out_event ();
} }
void zmq::stream_engine_t::activate_in () void zmq::stream_engine_t::restart_input ()
{ {
zmq_assert (input_paused); zmq_assert (input_stopped);
zmq_assert (session != NULL); zmq_assert (session != NULL);
zmq_assert (decoder != NULL); zmq_assert (decoder != NULL);
...@@ -382,7 +379,7 @@ void zmq::stream_engine_t::activate_in () ...@@ -382,7 +379,7 @@ void zmq::stream_engine_t::activate_in ()
if (rc == -1 || io_error) if (rc == -1 || io_error)
error (); error ();
else { else {
input_paused = false; input_stopped = false;
set_pollin (handle); set_pollin (handle);
session->flush (); session->flush ();
...@@ -483,6 +480,13 @@ bool zmq::stream_engine_t::handshake () ...@@ -483,6 +480,13 @@ bool zmq::stream_engine_t::handshake ()
// header data away. // header data away.
const size_t header_size = options.identity_size + 1 >= 255 ? 10 : 2; const size_t header_size = options.identity_size + 1 >= 255 ? 10 : 2;
unsigned char tmp [10], *bufferp = tmp; unsigned char tmp [10], *bufferp = tmp;
// Prepare the identity message and load it into encoder.
// Then consume bytes we have already sent to the peer.
const int rc = tx_msg.init_size (options.identity_size);
zmq_assert (rc == 0);
memcpy (tx_msg.data (), options.identity, options.identity_size);
encoder->load_msg (&tx_msg);
size_t buffer_size = encoder->encode (&bufferp, header_size); size_t buffer_size = encoder->encode (&bufferp, header_size);
zmq_assert (buffer_size == header_size); zmq_assert (buffer_size == header_size);
...@@ -617,8 +621,8 @@ int zmq::stream_engine_t::process_handshake_command (msg_t *msg_) ...@@ -617,8 +621,8 @@ int zmq::stream_engine_t::process_handshake_command (msg_t *msg_)
if (rc == 0) { if (rc == 0) {
if (mechanism->is_handshake_complete ()) if (mechanism->is_handshake_complete ())
mechanism_ready (); mechanism_ready ();
if (output_paused) if (output_stopped)
activate_out (); restart_output ();
} }
return rc; return rc;
...@@ -633,10 +637,10 @@ void zmq::stream_engine_t::zap_msg_available () ...@@ -633,10 +637,10 @@ void zmq::stream_engine_t::zap_msg_available ()
error (); error ();
return; return;
} }
if (input_paused) if (input_stopped)
activate_in (); restart_input ();
if (output_paused) if (output_stopped)
activate_out (); restart_output ();
} }
void zmq::stream_engine_t::mechanism_ready () void zmq::stream_engine_t::mechanism_ready ()
...@@ -652,6 +656,7 @@ void zmq::stream_engine_t::mechanism_ready () ...@@ -652,6 +656,7 @@ void zmq::stream_engine_t::mechanism_ready ()
return; return;
} }
errno_assert (rc == 0); errno_assert (rc == 0);
session->flush ();
} }
read_msg = &stream_engine_t::pull_and_encode; read_msg = &stream_engine_t::pull_and_encode;
...@@ -738,7 +743,7 @@ int zmq::stream_engine_t::write (const void *data_, size_t size_) ...@@ -738,7 +743,7 @@ int zmq::stream_engine_t::write (const void *data_, size_t size_)
// we'll get an error (this may happen during the speculative write). // we'll get an error (this may happen during the speculative write).
if (nbytes == SOCKET_ERROR && WSAGetLastError () == WSAEWOULDBLOCK) if (nbytes == SOCKET_ERROR && WSAGetLastError () == WSAEWOULDBLOCK)
return 0; return 0;
// Signalise peer failure. // Signalise peer failure.
if (nbytes == SOCKET_ERROR && ( if (nbytes == SOCKET_ERROR && (
WSAGetLastError () == WSAENETDOWN || WSAGetLastError () == WSAENETDOWN ||
......
...@@ -60,8 +60,8 @@ namespace zmq ...@@ -60,8 +60,8 @@ namespace zmq
void plug (zmq::io_thread_t *io_thread_, void plug (zmq::io_thread_t *io_thread_,
zmq::session_base_t *session_); zmq::session_base_t *session_);
void terminate (); void terminate ();
void activate_in (); void restart_input ();
void activate_out (); void restart_output ();
void zap_msg_available (); void zap_msg_available ();
// i_poll_events interface implementation. // i_poll_events interface implementation.
...@@ -179,10 +179,10 @@ namespace zmq ...@@ -179,10 +179,10 @@ namespace zmq
mechanism_t *mechanism; mechanism_t *mechanism;
// True iff the engine couldn't consume the last decoded message. // True iff the engine couldn't consume the last decoded message.
bool input_paused; bool input_stopped;
// True iff the engine doesn't have any message to encode. // True iff the engine doesn't have any message to encode.
bool output_paused; bool output_stopped;
// Socket // Socket
zmq::socket_base_t *socket; zmq::socket_base_t *socket;
......
...@@ -48,8 +48,7 @@ zmq::trie_t::~trie_t () ...@@ -48,8 +48,7 @@ zmq::trie_t::~trie_t ()
else else
if (count > 1) { if (count > 1) {
for (unsigned short i = 0; i != count; ++i) for (unsigned short i = 0; i != count; ++i)
if (next.table [i]) delete next.table [i];
delete next.table [i];
free (next.table); free (next.table);
} }
} }
......
...@@ -72,8 +72,7 @@ namespace zmq ...@@ -72,8 +72,7 @@ namespace zmq
} }
chunk_t *sc = spare_chunk.xchg (NULL); chunk_t *sc = spare_chunk.xchg (NULL);
if (sc) free (sc);
free (sc);
} }
// Returns reference to the front element of the queue. // Returns reference to the front element of the queue.
...@@ -156,8 +155,7 @@ namespace zmq ...@@ -156,8 +155,7 @@ namespace zmq
// so for cache reasons we'll get rid of the spare and // so for cache reasons we'll get rid of the spare and
// use 'o' as the spare. // use 'o' as the spare.
chunk_t *cs = spare_chunk.xchg (o); chunk_t *cs = spare_chunk.xchg (o);
if (cs) free (cs);
free (cs);
} }
} }
......
...@@ -30,6 +30,10 @@ ...@@ -30,6 +30,10 @@
#else #else
#include "windows.hpp" #include "windows.hpp"
#endif #endif
#ifdef HAVE_LIBSODIUM
# include <sodium.h>
#endif
void zmq_sleep (int seconds_) void zmq_sleep (int seconds_)
{ {
...@@ -100,10 +104,14 @@ static uint8_t decoder [96] = { ...@@ -100,10 +104,14 @@ static uint8_t decoder [96] = {
// Encode a binary frame as a string; destination string MUST be at least // Encode a binary frame as a string; destination string MUST be at least
// size * 5 / 4 bytes long plus 1 byte for the null terminator. Returns // size * 5 / 4 bytes long plus 1 byte for the null terminator. Returns
// dest. Size must be a multiple of 4. // dest. Size must be a multiple of 4.
// Returns NULL and sets errno = EINVAL for invalid input.
char *zmq_z85_encode (char *dest, uint8_t *data, size_t size) char *zmq_z85_encode (char *dest, uint8_t *data, size_t size)
{ {
assert (size % 4 == 0); if (size % 4 != 0) {
errno = EINVAL;
return NULL;
}
unsigned int char_nbr = 0; unsigned int char_nbr = 0;
unsigned int byte_nbr = 0; unsigned int byte_nbr = 0;
uint32_t value = 0; uint32_t value = 0;
...@@ -125,15 +133,20 @@ char *zmq_z85_encode (char *dest, uint8_t *data, size_t size) ...@@ -125,15 +133,20 @@ char *zmq_z85_encode (char *dest, uint8_t *data, size_t size)
return dest; return dest;
} }
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// Decode an encoded string into a binary frame; dest must be at least // Decode an encoded string into a binary frame; dest must be at least
// strlen (string) * 4 / 5 bytes long. Returns dest. strlen (string) // strlen (string) * 4 / 5 bytes long. Returns dest. strlen (string)
// must be a multiple of 5. // must be a multiple of 5.
// Returns NULL and sets errno = EINVAL for invalid input.
uint8_t *zmq_z85_decode (uint8_t *dest, char *string) uint8_t *zmq_z85_decode (uint8_t *dest, char *string)
{ {
assert (strlen (string) % 5 == 0);
if (strlen (string) % 5 != 0) {
errno = EINVAL;
return NULL;
}
unsigned int byte_nbr = 0; unsigned int byte_nbr = 0;
unsigned int char_nbr = 0; unsigned int char_nbr = 0;
uint32_t value = 0; uint32_t value = 0;
...@@ -153,3 +166,34 @@ uint8_t *zmq_z85_decode (uint8_t *dest, char *string) ...@@ -153,3 +166,34 @@ uint8_t *zmq_z85_decode (uint8_t *dest, char *string)
assert (byte_nbr == strlen (string) * 4 / 5); assert (byte_nbr == strlen (string) * 4 / 5);
return dest; return dest;
} }
// --------------------------------------------------------------------------
// Generate a public/private keypair with libsodium.
// Generated keys will be 40 byte z85-encoded strings.
// Returns 0 on success, -1 on failure, setting errno.
// Sets errno = ENOTSUP in the absence of libsodium.
int zmq_curve_keypair (char* z85_public_key, char *z85_secret_key)
{
#ifdef HAVE_LIBSODIUM
# if crypto_box_PUBLICKEYBYTES != 32 \
|| crypto_box_SECRETKEYBYTES != 32
# error "libsodium not built correctly"
# endif
uint8_t public_key [32];
uint8_t secret_key [32];
int rc = crypto_box_keypair (public_key, secret_key);
// is there a sensible errno to set here?
if (rc) return rc;
zmq_z85_encode (z85_public_key, public_key, 32);
zmq_z85_encode (z85_secret_key, secret_key, 32);
return 0;
#else // requires libsodium
errno = ENOTSUP;
return -1;
#endif
}
...@@ -37,7 +37,9 @@ noinst_PROGRAMS = test_system \ ...@@ -37,7 +37,9 @@ noinst_PROGRAMS = test_system \
test_req_correlate \ test_req_correlate \
test_req_relaxed \ test_req_relaxed \
test_conflate \ test_conflate \
test_inproc_connect test_inproc_connect \
test_issue_566 \
test_abstract_ipc
if !ON_MINGW if !ON_MINGW
noinst_PROGRAMS += test_shutdown_stress \ noinst_PROGRAMS += test_shutdown_stress \
...@@ -82,6 +84,8 @@ test_req_correlate_SOURCES = test_req_correlate.cpp ...@@ -82,6 +84,8 @@ test_req_correlate_SOURCES = test_req_correlate.cpp
test_req_relaxed_SOURCES = test_req_relaxed.cpp test_req_relaxed_SOURCES = test_req_relaxed.cpp
test_conflate_SOURCES = test_conflate.cpp test_conflate_SOURCES = test_conflate.cpp
test_inproc_connect_SOURCES = test_inproc_connect.cpp test_inproc_connect_SOURCES = test_inproc_connect.cpp
test_issue_566_SOURCES = test_issue_566.cpp
test_abstract_ipc_SOURCES = test_abstract_ipc.cpp
if !ON_MINGW if !ON_MINGW
test_shutdown_stress_SOURCES = test_shutdown_stress.cpp test_shutdown_stress_SOURCES = test_shutdown_stress.cpp
test_pair_ipc_SOURCES = test_pair_ipc.cpp testutil.hpp test_pair_ipc_SOURCES = test_pair_ipc.cpp testutil.hpp
...@@ -93,3 +97,7 @@ endif ...@@ -93,3 +97,7 @@ endif
# Run the test cases # Run the test cases
TESTS = $(noinst_PROGRAMS) TESTS = $(noinst_PROGRAMS)
XFAIL_TESTS = test_linger XFAIL_TESTS = test_linger
if !ON_LINUX
XFAIL_TESTS += test_abstract_ipc
endif
/*
Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file
This file is part of 0MQ.
0MQ is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
0MQ is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
int main (void)
{
setup_test_environment();
void *ctx = zmq_ctx_new ();
assert (ctx);
void *sb = zmq_socket (ctx, ZMQ_PAIR);
assert (sb);
int rc = zmq_bind (sb, "ipc://@/tmp/tester");
assert (rc == 0);
char endpoint[200];
size_t size = sizeof(endpoint);
rc = zmq_getsockopt (sb, ZMQ_LAST_ENDPOINT, endpoint, &size);
assert (rc == 0);
rc = strncmp(endpoint, "ipc://@/tmp/tester", size);
assert (rc == 0);
void *sc = zmq_socket (ctx, ZMQ_PAIR);
assert (sc);
rc = zmq_connect (sc, "ipc://@/tmp/tester");
assert (rc == 0);
bounce (sb, sc);
rc = zmq_close (sc);
assert (rc == 0);
rc = zmq_close (sb);
assert (rc == 0);
rc = zmq_ctx_term (ctx);
assert (rc == 0);
return 0 ;
}
/*
Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file
This file is part of 0MQ.
0MQ is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
0MQ is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testutil.hpp"
// Issue 566 describes a problem in libzmq v4.0.0 where a dealer to router
// connection would fail randomly. The test works when the two sockets are
// on the same context, and failed when they were on separate contexts.
// Fixed by https://github.com/zeromq/libzmq/commit/be25cf.
int main (void)
{
setup_test_environment();
void *ctx1 = zmq_ctx_new ();
assert (ctx1);
void *ctx2 = zmq_ctx_new ();
assert (ctx2);
void *router = zmq_socket (ctx1, ZMQ_ROUTER);
int on = 1;
int rc = zmq_setsockopt (router, ZMQ_ROUTER_MANDATORY, &on, sizeof (on));
assert (rc == 0);
rc = zmq_bind (router, "tcp://127.0.0.1:5555");
assert (rc != -1);
// Repeat often enough to be sure this works as it should
for (int cycle = 0; cycle < 100; cycle++) {
// Create dealer with unique explicit identity
// We assume the router learns this out-of-band
void *dealer = zmq_socket (ctx2, ZMQ_DEALER);
char identity [10];
sprintf (identity, "%09d", cycle);
rc = zmq_setsockopt (dealer, ZMQ_IDENTITY, identity, 10);
assert (rc == 0);
int rcvtimeo = 1000;
rc = zmq_setsockopt (dealer, ZMQ_RCVTIMEO, &rcvtimeo, sizeof (int));
assert (rc == 0);
rc = zmq_connect (dealer, "tcp://127.0.0.1:5555");
assert (rc == 0);
// Router will try to send to dealer, at short intervals.
// It typically takes 2-5 msec for the connection to establish
// on a loopback interface, but we'll allow up to one second
// before failing the test (e.g. for running on a debugger or
// a very slow system).
for (int attempt = 0; attempt < 500; attempt++) {
zmq_poll (0, 0, 2);
rc = zmq_send (router, identity, 10, ZMQ_SNDMORE);
if (rc == -1 && errno == EHOSTUNREACH)
continue;
assert (rc == 10);
rc = zmq_send (router, "HELLO", 5, 0);
assert (rc == 5);
break;
}
uint8_t buffer [5];
rc = zmq_recv (dealer, buffer, 5, 0);
assert (rc == 5);
assert (memcmp (buffer, "HELLO", 5) == 0);
close_zero_linger (dealer);
}
zmq_close (router);
zmq_ctx_destroy (ctx1);
zmq_ctx_destroy (ctx2);
return 0;
}
...@@ -19,11 +19,11 @@ ...@@ -19,11 +19,11 @@
#include "testutil.hpp" #include "testutil.hpp"
// Test keys from the zmq_curve man page // We'll generate random test keys at startup
static char client_public [] = "Yne@$w-vo<fVvi]a<NY6T1ed:M$fCG*[IaLV{hID"; static char client_public [41];
static char client_secret [] = "D:)Q[IlAW!ahhC2ac:9*A}h:p?([4%wOTJ%JR%cs"; static char client_secret [41];
static char server_public [] = "rq:rM>}U?@Lns47E1%kR.o@n%FcmmsL/@{H8]yf7"; static char server_public [41];
static char server_secret [] = "JTKVSB%%)wK0E.X)V>+}o?pNmC{O&4W4b!Ni{Lh6"; static char server_secret [41];
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// Encode a binary frame as a string; destination string MUST be at least // Encode a binary frame as a string; destination string MUST be at least
...@@ -86,6 +86,13 @@ int main (void) ...@@ -86,6 +86,13 @@ int main (void)
printf ("libsodium not installed, skipping CURVE test\n"); printf ("libsodium not installed, skipping CURVE test\n");
return 0; return 0;
#endif #endif
// Generate new keypairs for this test
int rc = zmq_curve_keypair (client_public, client_secret);
assert (rc == 0);
rc = zmq_curve_keypair (server_public, server_secret);
assert (rc == 0);
setup_test_environment (); setup_test_environment ();
void *ctx = zmq_ctx_new (); void *ctx = zmq_ctx_new ();
assert (ctx); assert (ctx);
...@@ -95,7 +102,7 @@ int main (void) ...@@ -95,7 +102,7 @@ int main (void)
// where child thread does not start up fast enough. // where child thread does not start up fast enough.
void *handler = zmq_socket (ctx, ZMQ_REP); void *handler = zmq_socket (ctx, ZMQ_REP);
assert (handler); assert (handler);
int rc = zmq_bind (handler, "inproc://zeromq.zap.01"); rc = zmq_bind (handler, "inproc://zeromq.zap.01");
assert (rc == 0); assert (rc == 0);
void *zap_thread = zmq_threadstart (&zap_handler, handler); void *zap_thread = zmq_threadstart (&zap_handler, handler);
...@@ -175,8 +182,9 @@ int main (void) ...@@ -175,8 +182,9 @@ int main (void)
// Check CURVE security with bogus client credentials // Check CURVE security with bogus client credentials
// This must be caught by the ZAP handler // This must be caught by the ZAP handler
char bogus_public [] = "8)<]6{NT{}=MZBsH)i%l0k}y*^i#80n-Yf{I8Z+P"; char bogus_public [41];
char bogus_secret [] = "[m9E0TW2Mf?Ke3K>fuBGCrkBpc6aJbj4jv4451Nx"; char bogus_secret [41];
zmq_curve_keypair (bogus_public, bogus_secret);
client = zmq_socket (ctx, ZMQ_DEALER); client = zmq_socket (ctx, ZMQ_DEALER);
assert (client); assert (client);
......
...@@ -57,6 +57,8 @@ void test_fair_queue_in (void *ctx) ...@@ -57,6 +57,8 @@ void test_fair_queue_in (void *ctx)
s_send_seq (rep, "A", SEQ_END); s_send_seq (rep, "A", SEQ_END);
s_recv_seq (reqs [0], "A", SEQ_END); s_recv_seq (reqs [0], "A", SEQ_END);
// TODO: following test fails randomly on some boxes
#ifdef SOMEONE_FIXES_THIS
// send N requests // send N requests
for (size_t peer = 0; peer < services; ++peer) { for (size_t peer = 0; peer < services; ++peer) {
char * str = strdup("A"); char * str = strdup("A");
...@@ -69,12 +71,13 @@ void test_fair_queue_in (void *ctx) ...@@ -69,12 +71,13 @@ void test_fair_queue_in (void *ctx)
for (size_t peer = 0; peer < services; ++peer) { for (size_t peer = 0; peer < services; ++peer) {
char * str = strdup("A"); char * str = strdup("A");
str [0] += peer; str [0] += peer;
// Test fails here
s_recv_seq (rep, str, SEQ_END); s_recv_seq (rep, str, SEQ_END);
s_send_seq (rep, str, SEQ_END); s_send_seq (rep, str, SEQ_END);
s_recv_seq (reqs [peer], str, SEQ_END); s_recv_seq (reqs [peer], str, SEQ_END);
free (str); free (str);
} }
#endif
close_zero_linger (rep); close_zero_linger (rep);
for (size_t peer = 0; peer < services; ++peer) for (size_t peer = 0; peer < services; ++peer)
......
...@@ -102,7 +102,6 @@ test_stream_to_dealer (void) ...@@ -102,7 +102,6 @@ test_stream_to_dealer (void)
assert (rc >= 0); assert (rc >= 0);
bytes_read += rc; bytes_read += rc;
} }
assert (rc == 97);
// First two bytes are major and minor version numbers. // First two bytes are major and minor version numbers.
assert (buffer [0] == 3); // ZMTP/3.0 assert (buffer [0] == 3); // ZMTP/3.0
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#include "testutil.hpp" #include "testutil.hpp"
#if defined (ZMQ_HAVE_WINDOWS) #if defined (ZMQ_HAVE_WINDOWS)
# include <WinSock2.h> # include <winsock2.h>
# include <stdexcept> # include <stdexcept>
#else #else
# include <sys/socket.h> # include <sys/socket.h>
......
...@@ -31,8 +31,10 @@ ...@@ -31,8 +31,10 @@
#include <string> #include <string>
#if defined _WIN32 #if defined _WIN32
# include <crtdbg.h> # if defined _MSC_VER
# pragma warning(disable:4996) # include <crtdbg.h>
# pragma warning(disable:4996)
# endif
#else #else
# include <unistd.h> # include <unistd.h>
# include <signal.h> # include <signal.h>
...@@ -249,9 +251,11 @@ void close_zero_linger (void *socket) ...@@ -249,9 +251,11 @@ void close_zero_linger (void *socket)
void setup_test_environment() void setup_test_environment()
{ {
#if defined _WIN32 #if defined _WIN32
# if defined _MSC_VER
_set_abort_behavior( 0, _WRITE_ABORT_MSG); _set_abort_behavior( 0, _WRITE_ABORT_MSG);
_CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE ); _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR ); _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR );
# endif
#endif #endif
} }
......
...@@ -4,6 +4,6 @@ INCLUDES = -I$(top_srcdir)/include ...@@ -4,6 +4,6 @@ INCLUDES = -I$(top_srcdir)/include
bin_PROGRAMS = curve_keygen bin_PROGRAMS = curve_keygen
curve_keygen_LDADD = $(top_srcdir)/src/libzmq.la curve_keygen_LDADD = $(top_builddir)/src/libzmq.la
curve_keygen_SOURCES = curve_keygen.c curve_keygen_SOURCES = curve_keygen.c
...@@ -24,19 +24,13 @@ ...@@ -24,19 +24,13 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <assert.h>
#include <platform.hpp>
#include <zmq.h>
#include <zmq_utils.h> #include <zmq_utils.h>
#ifdef HAVE_LIBSODIUM
# include <sodium.h>
#endif
int main (void) int main (void)
{ {
#ifdef HAVE_LIBSODIUM
# if crypto_box_PUBLICKEYBYTES != 32 \
|| crypto_box_SECRETKEYBYTES != 32
# error "libsodium not built correctly"
# endif
puts ("This tool generates a CurveZMQ keypair, as two printable strings you can"); puts ("This tool generates a CurveZMQ keypair, as two printable strings you can");
puts ("use in configuration files or source code. The encoding uses Z85, which"); puts ("use in configuration files or source code. The encoding uses Z85, which");
puts ("is a base-85 format that is described in 0MQ RFC 32, and which has an"); puts ("is a base-85 format that is described in 0MQ RFC 32, and which has an");
...@@ -44,23 +38,21 @@ int main (void) ...@@ -44,23 +38,21 @@ int main (void)
puts ("always works with the secret key held by one party and the public key"); puts ("always works with the secret key held by one party and the public key");
puts ("distributed (securely!) to peers wishing to connect to it."); puts ("distributed (securely!) to peers wishing to connect to it.");
uint8_t public_key [32]; char public_key [41];
uint8_t secret_key [32]; char secret_key [41];
int rc = zmq_curve_keypair (public_key, secret_key);
if (rc != 0) {
if (zmq_errno () == ENOTSUP) {
puts ("To use curve_keygen, please install libsodium and then rebuild libzmq.");
}
exit (1);
}
int rc = crypto_box_keypair (public_key, secret_key);
assert (rc == 0);
char encoded [41];
zmq_z85_encode (encoded, public_key, 32);
puts ("\n== CURVE PUBLIC KEY =="); puts ("\n== CURVE PUBLIC KEY ==");
puts (encoded); puts (public_key);
zmq_z85_encode (encoded, secret_key, 32);
puts ("\n== CURVE SECRET KEY =="); puts ("\n== CURVE SECRET KEY ==");
puts (encoded); puts (secret_key);
#else
puts ("To build curve_keygen, please install libsodium and then rebuild libzmq.");
#endif
exit (0); exit (0);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment