When more then one peer connected to a ZMQ_PAIR socket,
an application aborted due to assertion failure.
This patch changes the ZMQ_PAIR socket behaviour so that
it rejects any further connection requests.
Before this patch, the stream engine terminated itself
whenever it had detected an IO error. If this happened
when sending a message, the engine lost all
in-flight messages, messages waiting to be decoded,
and the last decoded message that had not been accepted,
if there was one.
The new behaviour is to terminate the engine only after
the input error has been detected and the last decoded
I believe there was a conception that zmq_connect() and zmq_bind() will be called
only at the socket creation time and therefore don't need it.
Now it is not true anymore.
1. when we call zmq_bind()/zmq_connect() to create endpoint
we send ourselfs(through launch_child()) command to process_own(endpoint)
(and add it to own_t::owned)
in the application thread we could call zmq_unbind() / zmq_disconnect() _BEFORE_
we run process_own() in ZMQ thread and in this situation we will be unable to find it in
own_t::owned. in other words own_t::owned.find(endpoint) will not be deleted but it will be deleted from
socket_base_t::endpoints.
2. when you zmq_unbind() the lisnening TCP/IPC socket was terminated only in destructor...
so the whole ZMQ_LINGER time listening TCP/IPC socket was able to accept() new connections
but unable to handle them.
this all geting even worse since unfortunately zmq has a bug and '*_listener_t' object not terminated
untill the socket's zmq_close().
AT LEAST FOR PUSH SOCKETS.
Everything is ok for SUB sockets.
Easy to reproduce without my fix:
zmq_socket(PUSH)
zmq_bind(tcp);
// connect to it from PULL socket
zmq_unbind(tcp);
sleep(forever)
// netstat -anp | grep 'tcp listening socket'
With my fix you could see that after zmq_unbind(tcp) all previously connected tcp sessions
will not be finished untill the zmq_close(socket) regardless of ZMQ_LINGER value.
(*_listener_t terminates all owned session_base_t(connect=false) and they call pipe_t::terminate()
which in turn should call session_base_t::terminated() but this never happens)
make[2]: Entering directory `/home/laotse/src/abs/zeromq-git/src/libzmq-build/src'
CXX libzmq_la-address.lo
address.cpp: In destructor 'zmq::address_t::~address_t()':
address.cpp:41:29: error: deleting object of polymorphic class type 'zmq::tcp_address_t' which has non-virtual destructor might cause undefined behaviour [-Werror=delete-non-virtual-dtor]
cc1plus: all warnings being treated as errors
socket. Thus, it is shared between subsequent calls
to xs_recv (and xs_send). That in turn significantly
limits the number of invocations of getimeofday (or similar)
when timeouts are used and recv/send is called in a
tight loop.
Assign arbitrary number of filters that will be applied for each new TCP transport
connection on a listening socket.
If no filters applied, then TCP transport allows connections from any ip.
If at least one filter is applied then new connection source ip should be matched.
To clear all filters call zmq_setsockopt(socket, ZMQ_TCP_ACCEPT_FILTER, NULL, 0).
Filter is a null-terminated string with ipv6 or ipv4 CIDR.
For example:
localhost
127.0.0.1
mail.ru/24
::1
::1/128
3ffe:1::
3ffe:1::/56
Returns -1 if the filter couldn't be assigned(format error or ipv6 filter with ZMQ_IPV4ONLY set)
P.S.
The only thing that worries me is that I had to re-enable 'default assign by reference constructor/operator'
for 'tcp_address_t' (and for my inherited class tcp_address_mask_t) to store it in std::vector in 'options_t'...
The CreateEvent function requests EVENT_ALL_ACCESS access rights
when the event object already exists. This causes problems
when the event object is created from a service.
The solution is to call OpenEvent function when the CreateEvent
failed due to access control.
The proper solution would be to use CreateEventEx function, but
this one is not available on Windows XP.
The scoket implementation for inproc transfer failed to flush
identity message. The result was that the identity message
was not delivered until after the user sent the first message.
The identity message was never delivered if the user
used the socket only to receive messages.
The current implementaion of router socket does not
handle the full pipe and unroutable messages properly.
Namely, in those cases, the socket could route some
message parts into a wrong connection.
The check_write method does not use the passed message.
The parameter was needed to implement the swap.
As the swap is not supported anymore, it is safe to remove this parameter.
The problem is that even though the AI_V4MAPPED flag is defined
on FreeBSD, the getaddrinfo function does not support it and
returns EAI_BADFLAGS.
The patch also sets the flag on Windows if it is defined there.
This is true for Windows Vista and later.
Fixes issue #331.
Previously, sockets were still "valid" after being closed and only marked
as invalid when destroyed. This meant programs could access closed sockets.
Now the socket is marked "invalid" when closed.