diff --git a/CMakeLists.txt b/CMakeLists.txt index c48bdbd7..726864ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -785,6 +785,7 @@ set(cxx-sources gather.cpp ip_resolver.cpp zap_client.cpp + ws_address.cpp ws_connecter.cpp ws_decoder.cpp ws_encoder.cpp @@ -923,6 +924,7 @@ set(cxx-sources vmci_listener.hpp windows.hpp wire.hpp + ws_address.hpp ws_connecter.hpp ws_decoder.hpp ws_encoder.hpp diff --git a/Makefile.am b/Makefile.am index 7c6bdad3..9be3018e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -250,6 +250,8 @@ src_libzmq_la_SOURCES = \ src/vmci_listener.hpp \ src/windows.hpp \ src/wire.hpp \ + src/ws_address.cpp \ + src/ws_address.hpp \ src/ws_connecter.cpp \ src/ws_connecter.hpp \ src/ws_decoder.cpp \ diff --git a/src/address.cpp b/src/address.cpp index 75aeb516..37a006b7 100644 --- a/src/address.cpp +++ b/src/address.cpp @@ -36,6 +36,7 @@ #include "udp_address.hpp" #include "ipc_address.hpp" #include "tipc_address.hpp" +#include "ws_address.hpp" #if defined ZMQ_HAVE_VMCI #include "vmci_address.hpp" @@ -56,10 +57,12 @@ zmq::address_t::address_t (const std::string &protocol_, zmq::address_t::~address_t () { - if (protocol == protocol_name::tcp || protocol == protocol_name::ws) { + if (protocol == protocol_name::tcp) { LIBZMQ_DELETE (resolved.tcp_addr); } else if (protocol == protocol_name::udp) { LIBZMQ_DELETE (resolved.udp_addr); + } else if (protocol == protocol_name::ws) { + LIBZMQ_DELETE (resolved.ws_addr); } #if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS \ && !defined ZMQ_HAVE_VXWORKS @@ -85,6 +88,8 @@ int zmq::address_t::to_string (std::string &addr_) const return resolved.tcp_addr->to_string (addr_); if (protocol == protocol_name::udp && resolved.udp_addr) return resolved.udp_addr->to_string (addr_); + if (protocol == protocol_name::ws && resolved.ws_addr) + return resolved.ws_addr->to_string (addr_); #if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS \ && !defined ZMQ_HAVE_VXWORKS if (protocol == protocol_name::ipc && resolved.ipc_addr) diff --git a/src/address.hpp b/src/address.hpp index 090ce1f6..4bc5c65c 100644 --- a/src/address.hpp +++ b/src/address.hpp @@ -45,6 +45,7 @@ namespace zmq class ctx_t; class tcp_address_t; class udp_address_t; +class ws_address_t; #if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS class ipc_address_t; #endif @@ -92,6 +93,7 @@ struct address_t void *dummy; tcp_address_t *tcp_addr; udp_address_t *udp_addr; + ws_address_t *ws_addr; #if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS \ && !defined ZMQ_HAVE_VXWORKS ipc_address_t *ipc_addr; diff --git a/src/ip_resolver.cpp b/src/ip_resolver.cpp index 4a8283de..d01f82f0 100644 --- a/src/ip_resolver.cpp +++ b/src/ip_resolver.cpp @@ -97,7 +97,8 @@ zmq::ip_resolver_options_t::ip_resolver_options_t () : _nic_name_allowed (false), _ipv6_wanted (false), _port_expected (false), - _dns_allowed (false) + _dns_allowed (false), + _path_allowed (false) { } @@ -141,6 +142,13 @@ zmq::ip_resolver_options_t &zmq::ip_resolver_options_t::allow_dns (bool allow_) return *this; } +zmq::ip_resolver_options_t &zmq::ip_resolver_options_t::allow_path (bool allow_) +{ + _path_allowed = allow_; + + return *this; +} + bool zmq::ip_resolver_options_t::bindable () { return _bindable_wanted; @@ -166,6 +174,11 @@ bool zmq::ip_resolver_options_t::allow_dns () return _dns_allowed; } +bool zmq::ip_resolver_options_t::allow_path () +{ + return _path_allowed; +} + zmq::ip_resolver_t::ip_resolver_t (ip_resolver_options_t opts_) : _options (opts_) { @@ -214,6 +227,13 @@ int zmq::ip_resolver_t::resolve (ip_addr_t *ip_addr_, const char *name_) port = 0; } + // Check if path is allowed in ip address, if allowed it must be truncated + if (_options.allow_path ()) { + size_t pos = addr.find ('/'); + if (pos != std::string::npos) + addr = addr.substr (0, pos); + } + // Trim any square brackets surrounding the address. Used for // IPv6 addresses to remove the confusion with the port // delimiter. diff --git a/src/ip_resolver.hpp b/src/ip_resolver.hpp index af6e932e..f1aafea6 100644 --- a/src/ip_resolver.hpp +++ b/src/ip_resolver.hpp @@ -68,12 +68,14 @@ class ip_resolver_options_t ip_resolver_options_t &ipv6 (bool ipv6_); ip_resolver_options_t &expect_port (bool expect_); ip_resolver_options_t &allow_dns (bool allow_); + ip_resolver_options_t &allow_path (bool allow_); bool bindable (); bool allow_nic_name (); bool ipv6 (); bool expect_port (); bool allow_dns (); + bool allow_path (); private: bool _bindable_wanted; @@ -81,6 +83,7 @@ class ip_resolver_options_t bool _ipv6_wanted; bool _port_expected; bool _dns_allowed; + bool _path_allowed; }; class ip_resolver_t diff --git a/src/socket_base.cpp b/src/socket_base.cpp index 993a2e23..8a35c51d 100644 --- a/src/socket_base.cpp +++ b/src/socket_base.cpp @@ -65,6 +65,7 @@ #include "address.hpp" #include "ipc_address.hpp" #include "tcp_address.hpp" +#include "ws_address.hpp" #include "udp_address.hpp" #include "tipc_address.hpp" #include "mailbox.hpp" @@ -889,46 +890,14 @@ int zmq::socket_base_t::connect (const char *endpoint_uri_) // Defer resolution until a socket is opened paddr->resolved.tcp_addr = NULL; } else if (protocol == protocol_name::ws) { - // Do some basic sanity checks on ws:// address syntax - // - hostname starts with digit or letter, with embedded '-' or '.' - // - IPv6 address may contain hex chars and colons. - // - IPv6 link local address may contain % followed by interface name / zone_id - // (Reference: https://tools.ietf.org/html/rfc4007) - // - IPv4 address may contain decimal digits and dots. - // - Address must end in ":port" where port is *, or numeric - // - Address may contain two parts separated by ':' - // Following code is quick and dirty check to catch obvious errors, - // without trying to be fully accurate. - const char *check = address.c_str (); - if (isalnum (*check) || isxdigit (*check) || *check == '[' - || *check == ':') { - check++; - while (isalnum (*check) || isxdigit (*check) || *check == '.' - || *check == '-' || *check == ':' || *check == '%' - || *check == ';' || *check == '[' || *check == ']' - || *check == '_' || *check == '*') { - check++; - } - } - // Assume the worst, now look for success - rc = -1; - // Did we reach the end of the address safely? - if (*check == 0) { - // Do we have a valid port string? (cannot be '*' in connect - check = strrchr (address.c_str (), ':'); - if (check) { - check++; - if (*check && (isdigit (*check))) - rc = 0; // Valid - } - } - if (rc == -1) { - errno = EINVAL; + paddr->resolved.ws_addr = new (std::nothrow) ws_address_t (); + alloc_assert (paddr->resolved.ws_addr); + rc = paddr->resolved.ws_addr->resolve (address.c_str (), false, + options.ipv6); + if (rc != 0) { LIBZMQ_DELETE (paddr); return -1; } - // Defer resolution until a socket is opened - paddr->resolved.tcp_addr = NULL; } #if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS \ && !defined ZMQ_HAVE_VXWORKS diff --git a/src/ws_address.cpp b/src/ws_address.cpp new file mode 100644 index 00000000..f614e122 --- /dev/null +++ b/src/ws_address.cpp @@ -0,0 +1,159 @@ +/* + Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file + + This file is part of libzmq, the ZeroMQ core engine in C++. + + libzmq is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + As a special exception, the Contributors give you permission to link + this library with independent modules to produce an executable, + regardless of the license terms of these independent modules, and to + copy and distribute the resulting executable under terms of your choice, + provided that you also meet, for each linked independent module, the + terms and conditions of the license of that module. An independent + module is a module which is not derived from or based on this library. + If you modify this library, you must extend this exception to your + version of the library. + + libzmq 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 . +*/ + +#include "precompiled.hpp" +#include +#include + +#include "macros.hpp" +#include "ws_address.hpp" +#include "stdint.hpp" +#include "err.hpp" +#include "ip.hpp" + +#ifndef ZMQ_HAVE_WINDOWS +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#include + +zmq::ws_address_t::ws_address_t () +{ + memset (&_address, 0, sizeof (_address)); +} + +zmq::ws_address_t::ws_address_t (const sockaddr *sa_, socklen_t sa_len_) +{ + zmq_assert (sa_ && sa_len_ > 0); + + memset (&_address, 0, sizeof (_address)); + if (sa_->sa_family == AF_INET + && sa_len_ >= static_cast (sizeof (_address.ipv4))) + memcpy (&_address.ipv4, sa_, sizeof (_address.ipv4)); + else if (sa_->sa_family == AF_INET6 + && sa_len_ >= static_cast (sizeof (_address.ipv6))) + memcpy (&_address.ipv6, sa_, sizeof (_address.ipv6)); + + _path = std::string ("/"); + + char hbuf[NI_MAXHOST]; + const int rc = getnameinfo (addr (), addrlen (), hbuf, sizeof (hbuf), NULL, + 0, NI_NUMERICHOST); + if (rc != 0) + _host = std::string ("localhost"); + + std::ostringstream os; + + if (_address.family () == AF_INET6) + os << std::string ("["); + + os << std::string (hbuf); + + if (_address.family () == AF_INET6) + os << std::string ("]"); + + _host = os.str (); +} + +int zmq::ws_address_t::resolve (const char *name_, bool local_, bool ipv6_) +{ + // find the host part, It's important to use str*r*chr to only get + // the latest colon since IPv6 addresses use colons as delemiters. + const char *delim = strrchr (name_, ':'); + if (delim == NULL) { + errno = EINVAL; + return -1; + } + _host = std::string (name_, delim - name_); + + // find the path part, which is optional + delim = strrchr (name_, '/'); + if (delim) + _path = std::string (delim); + else + _path = std::string ("/"); + + ip_resolver_options_t resolver_opts; + resolver_opts.bindable (local_) + .allow_dns (!local_) + .allow_nic_name (local_) + .ipv6 (ipv6_) + .allow_path (true) + .expect_port (true); + + ip_resolver_t resolver (resolver_opts); + + return resolver.resolve (&_address, name_); +} + +int zmq::ws_address_t::to_string (std::string &addr_) const +{ + std::ostringstream os; + os << std::string ("ws://") << host () << std::string (":") + << _address.port (); + addr_ = os.str (); + + return 0; +} + +const sockaddr *zmq::ws_address_t::addr () const +{ + return _address.as_sockaddr (); +} + +socklen_t zmq::ws_address_t::addrlen () const +{ + return _address.sockaddr_len (); +} + +const char *zmq::ws_address_t::host () const +{ + return _host.c_str (); +} + +const char *zmq::ws_address_t::path () const +{ + return _path.c_str (); +} + +#if defined ZMQ_HAVE_WINDOWS +unsigned short zmq::ws_address_t::family () const +#else +sa_family_t zmq::ws_address_t::family () const +#endif +{ + return _address.family (); +} diff --git a/src/ws_address.hpp b/src/ws_address.hpp new file mode 100644 index 00000000..b74d71dc --- /dev/null +++ b/src/ws_address.hpp @@ -0,0 +1,75 @@ +/* + Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file + + This file is part of libzmq, the ZeroMQ core engine in C++. + + libzmq is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + As a special exception, the Contributors give you permission to link + this library with independent modules to produce an executable, + regardless of the license terms of these independent modules, and to + copy and distribute the resulting executable under terms of your choice, + provided that you also meet, for each linked independent module, the + terms and conditions of the license of that module. An independent + module is a module which is not derived from or based on this library. + If you modify this library, you must extend this exception to your + version of the library. + + libzmq 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 . +*/ + +#ifndef __ZMQ_WS_ADDRESS_HPP_INCLUDED__ +#define __ZMQ_WS_ADDRESS_HPP_INCLUDED__ + +#if !defined ZMQ_HAVE_WINDOWS +#include +#include +#endif + +#include "ip_resolver.hpp" + +namespace zmq +{ +class ws_address_t +{ + public: + ws_address_t (); + ws_address_t (const sockaddr *sa_, socklen_t sa_len_); + + // This function translates textual WS address into an address + // structure. If 'local' is true, names are resolved as local interface + // names. If it is false, names are resolved as remote hostnames. + // If 'ipv6' is true, the name may resolve to IPv6 address. + int resolve (const char *name_, bool local_, bool ipv6_); + + // The opposite to resolve() + int to_string (std::string &addr_) const; + +#if defined ZMQ_HAVE_WINDOWS + unsigned short family () const; +#else + sa_family_t family () const; +#endif + const sockaddr *addr () const; + socklen_t addrlen () const; + + const char *host () const; + const char *path () const; + + private: + ip_addr_t _address; + std::string _host; + std::string _path; +}; +} + +#endif diff --git a/src/ws_connecter.cpp b/src/ws_connecter.cpp index 57a1f639..48724356 100644 --- a/src/ws_connecter.cpp +++ b/src/ws_connecter.cpp @@ -38,7 +38,7 @@ #include "ip.hpp" #include "tcp.hpp" #include "address.hpp" -#include "tcp_address.hpp" +#include "ws_address.hpp" #include "session_base.hpp" #include "ws_engine.hpp" @@ -111,7 +111,7 @@ void zmq::ws_connecter_t::out_event () return; } - create_engine (fd, get_socket_name (fd, socket_end_local)); + create_engine (fd, get_socket_name (fd, socket_end_local)); } void zmq::ws_connecter_t::timer_event (int id_) @@ -167,63 +167,20 @@ int zmq::ws_connecter_t::open () { zmq_assert (_s == retired_fd); - // Resolve the address - if (_addr->resolved.tcp_addr != NULL) { - LIBZMQ_DELETE (_addr->resolved.tcp_addr); - } - - _addr->resolved.tcp_addr = new (std::nothrow) tcp_address_t (); - alloc_assert (_addr->resolved.tcp_addr); + tcp_address_t tcp_addr; _s = tcp_open_socket (_addr->address.c_str (), options, false, true, - _addr->resolved.tcp_addr); - if (_s == retired_fd) { - // TODO we should emit some event in this case! - - LIBZMQ_DELETE (_addr->resolved.tcp_addr); + &tcp_addr); + if (_s == retired_fd) return -1; - } - zmq_assert (_addr->resolved.tcp_addr != NULL); // Set the socket to non-blocking mode so that we get async connect(). unblock_socket (_s); - const tcp_address_t *const tcp_addr = _addr->resolved.tcp_addr; - - int rc; - - // Set a source address for conversations - if (tcp_addr->has_src_addr ()) { - // Allow reusing of the address, to connect to different servers - // using the same source port on the client. - int flag = 1; -#ifdef ZMQ_HAVE_WINDOWS - rc = setsockopt (_s, SOL_SOCKET, SO_REUSEADDR, - reinterpret_cast (&flag), sizeof (int)); - wsa_assert (rc != SOCKET_ERROR); -#elif defined ZMQ_HAVE_VXWORKS - rc = setsockopt (_s, SOL_SOCKET, SO_REUSEADDR, (char *) &flag, - sizeof (int)); - errno_assert (rc == 0); -#else - rc = setsockopt (_s, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof (int)); - errno_assert (rc == 0); -#endif - -#if defined ZMQ_HAVE_VXWORKS - rc = ::bind (_s, (sockaddr *) tcp_addr->src_addr (), - tcp_addr->src_addrlen ()); -#else - rc = ::bind (_s, tcp_addr->src_addr (), tcp_addr->src_addrlen ()); -#endif - if (rc == -1) - return -1; - } - // Connect to the remote peer. #if defined ZMQ_HAVE_VXWORKS - rc = ::connect (_s, (sockaddr *) tcp_addr->addr (), tcp_addr->addrlen ()); + int rc = ::connect (_s, (sockaddr *) tcp_addr.addr (), tcp_addr.addrlen ()); #else - rc = ::connect (_s, tcp_addr->addr (), tcp_addr->addrlen ()); + int rc = ::connect (_s, tcp_addr.addr (), tcp_addr.addrlen ()); #endif // Connect was successful immediately. if (rc == 0) { @@ -307,8 +264,8 @@ void zmq::ws_connecter_t::create_engine (fd_t fd, endpoint_type_connect); // Create the engine object for this connection. - ws_engine_t *engine = - new (std::nothrow) ws_engine_t (fd, options, endpoint_pair, true); + ws_engine_t *engine = new (std::nothrow) + ws_engine_t (fd, options, endpoint_pair, *_addr->resolved.ws_addr, true); alloc_assert (engine); // Attach the engine to the corresponding session object. diff --git a/src/ws_engine.cpp b/src/ws_engine.cpp index 3db9b751..f0197f07 100644 --- a/src/ws_engine.cpp +++ b/src/ws_engine.cpp @@ -69,9 +69,11 @@ encode_base64 (const unsigned char *in, int in_len, char *out, int out_len); zmq::ws_engine_t::ws_engine_t (fd_t fd_, const options_t &options_, const endpoint_uri_pair_t &endpoint_uri_pair_, + ws_address_t &address_, bool client_) : stream_engine_base_t (fd_, options_, endpoint_uri_pair_), _client (client_), + _address (address_), _client_handshake_state (client_handshake_initial), _server_handshake_state (handshake_initial), _header_name_position (0), @@ -109,16 +111,15 @@ void zmq::ws_engine_t::plug_internal () encode_base64 (nonce, 16, _websocket_key, MAX_HEADER_VALUE_LENGTH); assert (size > 0); - size = snprintf ( - (char *) _write_buffer, WS_BUFFER_SIZE, - "GET / HTTP/1.1\r\n" - "Host: server.example.com\r\n" // TODO: we need the address here - "Upgrade: websocket\r\n" - "Connection: Upgrade\r\n" - "Sec-WebSocket-Key: %s\r\n" - "Sec-WebSocket-Protocol: ZWS2.0\r\n" - "Sec-WebSocket-Version: 13\r\n\r\n", - _websocket_key); + size = snprintf ((char *) _write_buffer, WS_BUFFER_SIZE, + "GET %s HTTP/1.1\r\n" + "Host: %s\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Key: %s\r\n" + "Sec-WebSocket-Protocol: ZWS2.0\r\n" + "Sec-WebSocket-Version: 13\r\n\r\n", + _address.path (), _address.host (), _websocket_key); assert (size > 0 && size < WS_BUFFER_SIZE); _outpos = _write_buffer; _outsize = size; diff --git a/src/ws_engine.hpp b/src/ws_engine.hpp index 26af0160..29f6e948 100644 --- a/src/ws_engine.hpp +++ b/src/ws_engine.hpp @@ -34,6 +34,7 @@ #include "address.hpp" #include "msg.hpp" #include "stream_engine_base.hpp" +#include "ws_address.hpp" #define WS_BUFFER_SIZE 8192 @@ -130,6 +131,7 @@ class ws_engine_t : public stream_engine_base_t ws_engine_t (fd_t fd_, const options_t &options_, const endpoint_uri_pair_t &endpoint_uri_pair_, + ws_address_t &address_, bool client_); ~ws_engine_t (); @@ -145,6 +147,7 @@ class ws_engine_t : public stream_engine_base_t bool server_handshake (); bool _client; + ws_address_t _address; ws_client_handshake_state_t _client_handshake_state; ws_server_handshake_state_t _server_handshake_state; diff --git a/src/ws_listener.cpp b/src/ws_listener.cpp index e261752b..0cfb7508 100644 --- a/src/ws_listener.cpp +++ b/src/ws_listener.cpp @@ -100,7 +100,8 @@ std::string zmq::ws_listener_t::get_socket_name (zmq::fd_t fd_, int zmq::ws_listener_t::create_socket (const char *addr_) { - _s = tcp_open_socket (addr_, options, true, true, &_address); + tcp_address_t address; + _s = tcp_open_socket (addr_, options, true, true, &address); if (_s == retired_fd) { return -1; } @@ -133,7 +134,7 @@ int zmq::ws_listener_t::create_socket (const char *addr_) #if defined ZMQ_HAVE_VXWORKS rc = bind (_s, (sockaddr *) _address.addr (), _address.addrlen ()); #else - rc = bind (_s, _address.addr (), _address.addrlen ()); + rc = bind (_s, address.addr (), address.addrlen ()); #endif #ifdef ZMQ_HAVE_WINDOWS if (rc == SOCKET_ERROR) { @@ -173,6 +174,10 @@ int zmq::ws_listener_t::set_local_address (const char *addr_) // socket was already created by the application _s = options.use_fd; } else { + int rc = _address.resolve (addr_, true, options.ipv6); + if (rc != 0) + return -1; + if (create_socket (addr_) == -1) return -1; } @@ -251,8 +256,8 @@ void zmq::ws_listener_t::create_engine (fd_t fd) get_socket_name (fd, socket_end_local), get_socket_name (fd, socket_end_remote), endpoint_type_bind); - ws_engine_t *engine = - new (std::nothrow) ws_engine_t (fd, options, endpoint_pair, false); + ws_engine_t *engine = new (std::nothrow) + ws_engine_t (fd, options, endpoint_pair, _address, false); alloc_assert (engine); // Choose I/O thread to run connecter in. Given that we are already diff --git a/src/ws_listener.hpp b/src/ws_listener.hpp index faa42f14..7f74c4be 100644 --- a/src/ws_listener.hpp +++ b/src/ws_listener.hpp @@ -31,7 +31,7 @@ #define __ZMQ_WS_LISTENER_HPP_INCLUDED__ #include "fd.hpp" -#include "tcp_address.hpp" +#include "ws_address.hpp" #include "stream_listener_base.hpp" namespace zmq @@ -63,7 +63,7 @@ class ws_listener_t : public stream_listener_base_t int create_socket (const char *addr_); // Address to listen on. - tcp_address_t _address; + ws_address_t _address; ws_listener_t (const ws_listener_t &); const ws_listener_t &operator= (const ws_listener_t &); diff --git a/tests/test_ws_transport.cpp b/tests/test_ws_transport.cpp index b1f61aae..cf241afc 100644 --- a/tests/test_ws_transport.cpp +++ b/tests/test_ws_transport.cpp @@ -35,10 +35,11 @@ SETUP_TEARDOWN_TESTCONTEXT void test_roundtrip () { void *sb = test_context_socket (ZMQ_REP); - TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb, "ws://*:5556")); + TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb, "ws://*:5556/roundtrip")); void *sc = test_context_socket (ZMQ_REQ); - TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, "ws://127.0.0.1:5556")); + TEST_ASSERT_SUCCESS_ERRNO ( + zmq_connect (sc, "ws://127.0.0.1:5556/roundtrip")); bounce (sb, sc); @@ -49,10 +50,10 @@ void test_roundtrip () void test_short_message () { void *sb = test_context_socket (ZMQ_REP); - TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb, "ws://*:5557")); + TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb, "ws://*:5557/short")); void *sc = test_context_socket (ZMQ_REQ); - TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, "ws://127.0.0.1:5557")); + TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, "ws://127.0.0.1:5557/short")); zmq_msg_t msg; TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init_size (&msg, 255)); @@ -78,10 +79,10 @@ void test_short_message () void test_large_message () { void *sb = test_context_socket (ZMQ_REP); - TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb, "ws://*:5557")); + TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (sb, "ws://*:5557/large")); void *sc = test_context_socket (ZMQ_REQ); - TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, "ws://127.0.0.1:5557")); + TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sc, "ws://127.0.0.1:5557/large")); zmq_msg_t msg; TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init_size (&msg, 65536));