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));