Commit 2566c02a authored by Pieter Hintjens's avatar Pieter Hintjens

Problem: CLIENT and SERVER don't check SNDMORE

These sockets don't handle multipart data, so if callers send it,
they drop frames, and things break silently.

Solution: if the caller tries to use ZMQ_SNDMORE, return -1 and
set errno to EINVAL.
parent ae3b2734
...@@ -67,6 +67,8 @@ ERRORS ...@@ -67,6 +67,8 @@ ERRORS
Non-blocking mode was requested and the message cannot be sent at the moment. Non-blocking mode was requested and the message cannot be sent at the moment.
*ENOTSUP*:: *ENOTSUP*::
The _zmq_msg_send()_ operation is not supported by this socket type. The _zmq_msg_send()_ operation is not supported by this socket type.
*EINVAL*::
The sender tried to send multipart data, which the socket type does not allow.
*EFSM*:: *EFSM*::
The _zmq_msg_send()_ operation cannot be performed on this socket at the moment The _zmq_msg_send()_ operation cannot be performed on this socket at the moment
due to the socket not being in the appropriate state. This error may occur with due to the socket not being in the appropriate state. This error may occur with
......
...@@ -58,6 +58,8 @@ ERRORS ...@@ -58,6 +58,8 @@ ERRORS
Non-blocking mode was requested and the message cannot be sent at the moment. Non-blocking mode was requested and the message cannot be sent at the moment.
*ENOTSUP*:: *ENOTSUP*::
The _zmq_send()_ operation is not supported by this socket type. The _zmq_send()_ operation is not supported by this socket type.
*EINVAL*::
The sender tried to send multipart data, which the socket type does not allow.
*EFSM*:: *EFSM*::
The _zmq_send()_ operation cannot be performed on this socket at the moment The _zmq_send()_ operation cannot be performed on this socket at the moment
due to the socket not being in the appropriate state. This error may occur with due to the socket not being in the appropriate state. This error may occur with
......
...@@ -63,6 +63,8 @@ ERRORS ...@@ -63,6 +63,8 @@ ERRORS
Non-blocking mode was requested and the message cannot be sent at the moment. Non-blocking mode was requested and the message cannot be sent at the moment.
*ENOTSUP*:: *ENOTSUP*::
The _zmq_sendmsg()_ operation is not supported by this socket type. The _zmq_sendmsg()_ operation is not supported by this socket type.
*EINVAL*::
The sender tried to send multipart data, which the socket type does not allow.
*EFSM*:: *EFSM*::
The _zmq_sendmsg()_ operation cannot be performed on this socket at the moment The _zmq_sendmsg()_ operation cannot be performed on this socket at the moment
due to the socket not being in the appropriate state. This error may occur with due to the socket not being in the appropriate state. This error may occur with
......
...@@ -54,6 +54,11 @@ void zmq::client_t::xattach_pipe (pipe_t *pipe_, bool subscribe_to_all_) ...@@ -54,6 +54,11 @@ void zmq::client_t::xattach_pipe (pipe_t *pipe_, bool subscribe_to_all_)
int zmq::client_t::xsend (msg_t *msg_) int zmq::client_t::xsend (msg_t *msg_)
{ {
// CLIENT sockets do not allow multipart data (ZMQ_SNDMORE)
if (msg_->flags () & msg_t::more) {
errno = EINVAL;
return -1;
}
return lb.sendpipe (msg_, NULL); return lb.sendpipe (msg_, NULL);
} }
......
...@@ -93,6 +93,11 @@ void zmq::server_t::xwrite_activated (pipe_t *pipe_) ...@@ -93,6 +93,11 @@ void zmq::server_t::xwrite_activated (pipe_t *pipe_)
int zmq::server_t::xsend (msg_t *msg_) int zmq::server_t::xsend (msg_t *msg_)
{ {
// SERVER sockets do not allow multipart data (ZMQ_SNDMORE)
if (msg_->flags () & msg_t::more) {
errno = EINVAL;
return -1;
}
// Find the pipe associated with the routing stored in the message. // Find the pipe associated with the routing stored in the message.
uint32_t routing_id = msg_->get_routing_id (); uint32_t routing_id = msg_->get_routing_id ();
outpipes_t::iterator it = outpipes.find (routing_id); outpipes_t::iterator it = outpipes.find (routing_id);
...@@ -108,7 +113,6 @@ int zmq::server_t::xsend (msg_t *msg_) ...@@ -108,7 +113,6 @@ int zmq::server_t::xsend (msg_t *msg_)
errno = EHOSTUNREACH; errno = EHOSTUNREACH;
return -1; return -1;
} }
bool ok = it->second.pipe->write (msg_); bool ok = it->second.pipe->write (msg_);
if (unlikely (!ok)) { if (unlikely (!ok)) {
// Message failed to send - we must close it ourselves. // Message failed to send - we must close it ourselves.
...@@ -118,7 +122,6 @@ int zmq::server_t::xsend (msg_t *msg_) ...@@ -118,7 +122,6 @@ int zmq::server_t::xsend (msg_t *msg_)
else else
it->second.pipe->flush (); it->second.pipe->flush ();
// Detach the message from the data buffer. // Detach the message from the data buffer.
int rc = msg_->init (); int rc = msg_->init ();
errno_assert (rc == 0); errno_assert (rc == 0);
......
This diff is collapsed.
...@@ -347,7 +347,7 @@ static int ...@@ -347,7 +347,7 @@ static int
s_sendmsg (zmq::socket_base_t *s_, zmq_msg_t *msg_, int flags_) s_sendmsg (zmq::socket_base_t *s_, zmq_msg_t *msg_, int flags_)
{ {
int sz = (int) zmq_msg_size (msg_); int sz = (int) zmq_msg_size (msg_);
int rc = s_->send ((zmq::msg_t*) msg_, flags_); int rc = s_->send ((zmq::msg_t *) msg_, flags_);
if (unlikely (rc < 0)) if (unlikely (rc < 0))
return -1; return -1;
return sz; return sz;
...@@ -393,7 +393,7 @@ int zmq_send_const (void *s_, const void *buf_, size_t len_, int flags_) ...@@ -393,7 +393,7 @@ int zmq_send_const (void *s_, const void *buf_, size_t len_, int flags_)
return -1; return -1;
} }
zmq_msg_t msg; zmq_msg_t msg;
int rc = zmq_msg_init_data (&msg, (void*)buf_, len_, NULL, NULL); int rc = zmq_msg_init_data (&msg, (void *)buf_, len_, NULL, NULL);
if (rc != 0) if (rc != 0)
return -1; return -1;
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
int main (void) int main (void)
{ {
setup_test_environment(); setup_test_environment ();
void *ctx = zmq_ctx_new (); void *ctx = zmq_ctx_new ();
assert (ctx); assert (ctx);
...@@ -51,36 +51,43 @@ int main (void) ...@@ -51,36 +51,43 @@ int main (void)
char *data = (char *) zmq_msg_data (&msg); char *data = (char *) zmq_msg_data (&msg);
data [0] = 1; data [0] = 1;
rc = zmq_msg_send(&msg, client, 0); rc = zmq_msg_send (&msg, client, ZMQ_SNDMORE);
assert (rc == -1);
rc = zmq_msg_send (&msg, client, 0);
assert (rc == 1); assert (rc == 1);
rc = zmq_msg_init (&msg); rc = zmq_msg_init (&msg);
assert (rc == 0); assert (rc == 0);
rc = zmq_msg_recv (&msg, server, 0); rc = zmq_msg_recv (&msg, server, 0);
assert (rc == 1); assert (rc == 1);
uint32_t routing_id = zmq_msg_routing_id (&msg); uint32_t routing_id = zmq_msg_routing_id (&msg);
assert (routing_id != 0); assert (routing_id != 0);
rc = zmq_msg_close(&msg); rc = zmq_msg_close (&msg);
assert (rc == 0); assert (rc == 0);
rc = zmq_msg_init_size (&msg, 1); rc = zmq_msg_init_size (&msg, 1);
assert (rc == 0); assert (rc == 0);
data = (char *)zmq_msg_data(&msg); data = (char *)zmq_msg_data (&msg);
data[0] = 2; data[0] = 2;
rc = zmq_msg_set_routing_id(&msg, routing_id); rc = zmq_msg_set_routing_id (&msg, routing_id);
assert (rc == 0); assert (rc == 0);
rc = zmq_msg_send (&msg, server, ZMQ_SNDMORE);
assert (rc == -1);
rc = zmq_msg_send(&msg, server, 0); rc = zmq_msg_send (&msg, server, 0);
assert (rc == 1); assert (rc == 1);
rc = zmq_msg_recv(&msg, client, 0); rc = zmq_msg_recv (&msg, client, 0);
assert (rc == 1); assert (rc == 1);
rc = zmq_msg_close(&msg); rc = zmq_msg_close (&msg);
assert (rc == 0); assert (rc == 0);
rc = zmq_close (server); rc = zmq_close (server);
......
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