Skip to content

Commit c4d0146

Browse files
committed
problem: udp doesn't enforce correct usage of bind/connect
solution: enforce that dish and gram can only bind and radio can only connect
1 parent 0db70e2 commit c4d0146

File tree

4 files changed

+88
-12
lines changed

4 files changed

+88
-12
lines changed

src/socket_base.cpp

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -556,16 +556,74 @@ int zmq::socket_base_t::bind (const char *addr_)
556556
return rc;
557557
}
558558

559-
if (protocol == "pgm" || protocol == "epgm" || protocol == "norm" || protocol == "udp") {
559+
if (protocol == "pgm" || protocol == "epgm" || protocol == "norm") {
560560
// For convenience's sake, bind can be used interchangeable with
561-
// connect for PGM, EPGM, NORM and UDP transports.
561+
// connect for PGM, EPGM, NORM transports.
562562
EXIT_MUTEX ();
563563
rc = connect (addr_);
564564
if (rc != -1)
565565
options.connected = true;
566566
return rc;
567567
}
568568

569+
if (protocol == "udp") {
570+
if (!(options.type == ZMQ_DGRAM || options.type == ZMQ_DISH)) {
571+
errno = ENOCOMPATPROTO;
572+
EXIT_MUTEX ();
573+
return -1;
574+
}
575+
576+
// Choose the I/O thread to run the session in.
577+
io_thread_t *io_thread = choose_io_thread (options.affinity);
578+
if (!io_thread) {
579+
errno = EMTHREAD;
580+
EXIT_MUTEX ();
581+
return -1;
582+
}
583+
584+
address_t *paddr = new (std::nothrow) address_t (protocol, address, this->get_ctx ());
585+
alloc_assert (paddr);
586+
587+
paddr->resolved.udp_addr = new (std::nothrow) udp_address_t ();
588+
alloc_assert (paddr->resolved.udp_addr);
589+
rc = paddr->resolved.udp_addr->resolve (address.c_str(), true);
590+
if (rc != 0) {
591+
LIBZMQ_DELETE(paddr);
592+
EXIT_MUTEX ();
593+
return -1;
594+
}
595+
596+
session_base_t *session = session_base_t::create (io_thread, true, this,
597+
options, paddr);
598+
errno_assert (session);
599+
600+
pipe_t *newpipe = NULL;
601+
602+
// Create a bi-directional pipe.
603+
object_t *parents [2] = {this, session};
604+
pipe_t *new_pipes [2] = {NULL, NULL};
605+
606+
int hwms [2] = {options.sndhwm, options.rcvhwm};
607+
bool conflates [2] = {false, false};
608+
rc = pipepair (parents, new_pipes, hwms, conflates);
609+
errno_assert (rc == 0);
610+
611+
// Attach local end of the pipe to the socket object.
612+
attach_pipe (new_pipes [0], true);
613+
newpipe = new_pipes [0];
614+
615+
// Attach remote end of the pipe to the session object later on.
616+
session->attach_pipe (new_pipes [1]);
617+
618+
// Save last endpoint URI
619+
paddr->to_string (last_endpoint);
620+
621+
add_endpoint (addr_, (own_t *) session, newpipe);
622+
623+
EXIT_MUTEX ();
624+
return 0;
625+
}
626+
569627
// Remaining transports require to be run in an I/O thread, so at this
570628
// point we'll choose one.
571629
io_thread_t *io_thread = choose_io_thread (options.affinity);
@@ -881,9 +939,15 @@ int zmq::socket_base_t::connect (const char *addr_)
881939
#endif
882940

883941
if (protocol == "udp") {
942+
if (options.type != ZMQ_RADIO) {
943+
errno = ENOCOMPATPROTO;
944+
EXIT_MUTEX ();
945+
return -1;
946+
}
947+
884948
paddr->resolved.udp_addr = new (std::nothrow) udp_address_t ();
885949
alloc_assert (paddr->resolved.udp_addr);
886-
rc = paddr->resolved.udp_addr->resolve (address.c_str(), (options.type == ZMQ_DISH || options.type == ZMQ_DGRAM));
950+
rc = paddr->resolved.udp_addr->resolve (address.c_str(), false);
887951
if (rc != 0) {
888952
LIBZMQ_DELETE(paddr);
889953
EXIT_MUTEX ();
@@ -1284,7 +1348,7 @@ int zmq::socket_base_t::recv (msg_t *msg_, int flags_)
12841348
int zmq::socket_base_t::close ()
12851349
{
12861350
ENTER_MUTEX ();
1287-
1351+
12881352
// Remove all existing signalers for thread safe sockets
12891353
if (thread_safe)
12901354
((mailbox_safe_t*)mailbox)->clear_signalers();

src/udp_address.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ zmq::udp_address_t::~udp_address_t ()
5555
{
5656
}
5757

58-
int zmq::udp_address_t::resolve (const char *name_, bool receiver_)
58+
int zmq::udp_address_t::resolve (const char *name_, bool bind_)
5959
{
6060
// Find the ':' at end that separates address from the port number.
6161
const char *delimiter = strrchr (name_, ':');
@@ -78,8 +78,8 @@ int zmq::udp_address_t::resolve (const char *name_, bool receiver_)
7878
dest_address.sin_family = AF_INET;
7979
dest_address.sin_port = htons (port);
8080

81-
// Only when the udp is receiver we allow * as the address
82-
if (addr_str == "*" && receiver_)
81+
// Only when the udp should bind we allow * as the address
82+
if (addr_str == "*" && bind_)
8383
dest_address.sin_addr.s_addr = htons (INADDR_ANY);
8484
else
8585
dest_address.sin_addr.s_addr = inet_addr (addr_str.c_str ());
@@ -106,9 +106,9 @@ int zmq::udp_address_t::resolve (const char *name_, bool receiver_)
106106
return -1;
107107
}
108108

109-
// If a receiver and not a multicast, the dest address
109+
// If a should bind and not a multicast, the dest address
110110
// is actually the bind address
111-
if (receiver_ && !is_mutlicast)
111+
if (bind_ && !is_mutlicast)
112112
bind_address = dest_address;
113113
else {
114114
bind_address.sin_family = AF_INET;

tests/test_dgram.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,19 @@ int main (void)
6060
void *sender = zmq_socket (ctx, ZMQ_DGRAM);
6161
void *listener = zmq_socket (ctx, ZMQ_DGRAM);
6262

63-
int rc = zmq_bind (listener, "udp://*:5556");
63+
// Connecting dgram shoudl fail
64+
int rc = zmq_connect (listener, "udp://127.0.0.1:5556");
65+
assert (rc == -1);
66+
67+
rc = zmq_bind (listener, "udp://*:5556");
6468
assert (rc == 0);
6569

6670
rc = zmq_bind (sender, "udp://*:5557");
6771
assert (rc == 0);
6872

6973
str_send_to (sender, "Is someone there ?", "127.0.0.1:5556");
7074

71-
str_recv_from (listener, &message_string, &address);
75+
str_recv_from (listener, &message_string, &address);
7276
assert (strcmp(message_string, "Is someone there ?") == 0);
7377
assert (strcmp(address, "127.0.0.1:5557") == 0);
7478
free (message_string);

tests/test_udp.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,17 @@ int main (void)
9595
void *radio = zmq_socket (ctx, ZMQ_RADIO);
9696
void *dish = zmq_socket (ctx, ZMQ_DISH);
9797

98-
int rc = zmq_bind (dish, "udp://*:5556");
98+
// Connecting dish should fail
99+
int rc = zmq_connect (dish, "udp://127.0.0.1:5556");
100+
assert (rc == -1);
101+
102+
rc = zmq_bind (dish, "udp://*:5556");
99103
assert (rc == 0);
100104

105+
// Bind radio should fail
106+
rc = zmq_bind (radio, "udp://*:5556");
107+
assert (rc == -1);
108+
101109
rc = zmq_connect (radio, "udp://127.0.0.1:5556");
102110
assert (rc == 0);
103111

0 commit comments

Comments
 (0)