int main (void) { setup_test_environment(); size_t len = MAX_SOCKET_STRING; char my_endpoint[MAX_SOCKET_STRING]; void *ctx = zmq_ctx_new (); assert (ctx); // Spawn ZAP handler // We create and bind ZAP socket in main thread to avoid case // where child thread does not start up fast enough. void *handler = zmq_socket (ctx, ZMQ_REP); assert (handler); int rc = zmq_bind (handler, "inproc://zeromq.zap.01"); assert (rc == 0); void *zap_thread = zmq_threadstart (&zap_handler, handler); void *server = zmq_socket (ctx, ZMQ_DEALER); assert (server); void *client = zmq_socket (ctx, ZMQ_DEALER); assert (client); rc = zmq_setsockopt (server, ZMQ_ZAP_DOMAIN, "DOMAIN", 6); assert (rc == 0); rc = zmq_bind (server, "tcp://127.0.0.1:*"); assert (rc == 0); rc = zmq_getsockopt (server, ZMQ_LAST_ENDPOINT, my_endpoint, &len); assert (rc == 0); rc = zmq_connect (client, my_endpoint); assert (rc == 0); s_send (client, "This is a message"); zmq_msg_t msg; zmq_msg_init (&msg); rc = zmq_msg_recv (&msg, server, 0); assert (rc != -1); assert (streq (zmq_msg_gets (&msg, "Hello"), "World")); assert (streq (zmq_msg_gets (&msg, "Socket-Type"), "DEALER")); assert (streq (zmq_msg_gets (&msg, "User-Id"), "anonymous")); assert (streq (zmq_msg_gets (&msg, "Peer-Address"), "127.0.0.1")); assert (zmq_msg_gets (&msg, "No Such") == NULL); assert (zmq_errno () == EINVAL); zmq_msg_close (&msg); close_zero_linger (client); close_zero_linger (server); // Shutdown rc = zmq_ctx_term (ctx); assert (rc == 0); // Wait until ZAP handler terminates zmq_threadclose (zap_thread); return 0; }
inline const char *gets(const char *property_) { const char *value = zmq_msg_gets(&msg, property_); if (value == NULL) throw error_t(); return value; }
void test_metadata () { char my_endpoint[MAX_SOCKET_STRING]; setup_test_context (); // Spawn ZAP handler // We create and bind ZAP socket in main thread to avoid case // where child thread does not start up fast enough. void *handler = zmq_socket (get_test_context (), ZMQ_REP); TEST_ASSERT_NOT_NULL (handler); TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (handler, "inproc://zeromq.zap.01")); void *zap_thread = zmq_threadstart (&zap_handler, handler); void *server = test_context_socket (ZMQ_DEALER); void *client = test_context_socket (ZMQ_DEALER); TEST_ASSERT_SUCCESS_ERRNO ( zmq_setsockopt (server, ZMQ_ZAP_DOMAIN, "DOMAIN", 6)); bind_loopback_ipv4 (server, my_endpoint, sizeof (my_endpoint)); TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (client, my_endpoint)); s_send (client, "This is a message"); zmq_msg_t msg; zmq_msg_init (&msg); TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&msg, server, 0)); TEST_ASSERT_EQUAL_STRING ("World", zmq_msg_gets (&msg, "Hello")); TEST_ASSERT_EQUAL_STRING ("DEALER", zmq_msg_gets (&msg, "Socket-Type")); TEST_ASSERT_EQUAL_STRING ("anonymous", zmq_msg_gets (&msg, "User-Id")); TEST_ASSERT_EQUAL_STRING ("127.0.0.1", zmq_msg_gets (&msg, "Peer-Address")); TEST_ASSERT_NULL (zmq_msg_gets (&msg, "No Such")); TEST_ASSERT_EQUAL_INT (EINVAL, zmq_errno ()); zmq_msg_close (&msg); test_context_socket_close_zero_linger (client); test_context_socket_close_zero_linger (server); // Shutdown teardown_test_context (); // Wait until ZAP handler terminates zmq_threadclose (zap_thread); }
int zmq_msg_get (const zmq_msg_t *msg_, int property_) { const char* fd_string; switch (property_) { case ZMQ_MORE: return (((zmq::msg_t*) msg_)->flags () & zmq::msg_t::more)? 1: 0; case ZMQ_SRCFD: fd_string = zmq_msg_gets(msg_, "__fd"); if (fd_string == NULL) return (int)-1; return atoi(fd_string); case ZMQ_SHARED: return (((zmq::msg_t*) msg_)->is_cmsg ()) || (((zmq::msg_t*) msg_)->flags () & zmq::msg_t::shared)? 1: 0; default: errno = EINVAL; return -1; } }
static void test_stream_to_dealer () { int rc; char my_endpoint[MAX_SOCKET_STRING]; // We'll be using this socket in raw mode void *stream = test_context_socket (ZMQ_STREAM); int zero = 0; TEST_ASSERT_SUCCESS_ERRNO ( zmq_setsockopt (stream, ZMQ_LINGER, &zero, sizeof (zero))); int enabled = 1; TEST_ASSERT_SUCCESS_ERRNO ( zmq_setsockopt (stream, ZMQ_STREAM_NOTIFY, &enabled, sizeof (enabled))); bind_loopback_ipv4 (stream, my_endpoint, sizeof my_endpoint); // We'll be using this socket as the other peer void *dealer = test_context_socket (ZMQ_DEALER); TEST_ASSERT_SUCCESS_ERRNO ( zmq_setsockopt (dealer, ZMQ_LINGER, &zero, sizeof (zero))); TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (dealer, my_endpoint)); // Send a message on the dealer socket send_string_expect_success (dealer, "Hello", 0); // Connecting sends a zero message // First frame is routing id zmq_msg_t routing_id; TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&routing_id)); TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&routing_id, stream, 0)); TEST_ASSERT_TRUE (zmq_msg_more (&routing_id)); // Verify the existence of Peer-Address metadata char const *peer_address = zmq_msg_gets (&routing_id, "Peer-Address"); TEST_ASSERT_NOT_NULL (peer_address); TEST_ASSERT_EQUAL_STRING ("127.0.0.1", peer_address); // Second frame is zero byte buffer[255]; TEST_ASSERT_EQUAL_INT ( 0, TEST_ASSERT_SUCCESS_ERRNO (zmq_recv (stream, buffer, 255, 0))); // Verify the existence of Peer-Address metadata peer_address = zmq_msg_gets (&routing_id, "Peer-Address"); TEST_ASSERT_NOT_NULL (peer_address); TEST_ASSERT_EQUAL_STRING ("127.0.0.1", peer_address); // Real data follows // First frame is routing id TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&routing_id, stream, 0)); TEST_ASSERT_TRUE (zmq_msg_more (&routing_id)); // Verify the existence of Peer-Address metadata peer_address = zmq_msg_gets (&routing_id, "Peer-Address"); TEST_ASSERT_NOT_NULL (peer_address); TEST_ASSERT_EQUAL_STRING ("127.0.0.1", peer_address); // Second frame is greeting signature recv_array_expect_success (stream, greeting.signature, 0); // Send our own protocol greeting TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_send (&routing_id, stream, ZMQ_SNDMORE)); TEST_ASSERT_EQUAL_INT ( sizeof (greeting), TEST_ASSERT_SUCCESS_ERRNO ( zmq_send (stream, &greeting, sizeof (greeting), 0))); // Now we expect the data from the DEALER socket // We want the rest of greeting along with the Ready command int bytes_read = 0; while (bytes_read < 97) { // First frame is the routing id of the connection (each time) TEST_ASSERT_GREATER_THAN_INT ( 0, TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&routing_id, stream, 0))); TEST_ASSERT_TRUE (zmq_msg_more (&routing_id)); // Second frame contains the next chunk of data TEST_ASSERT_SUCCESS_ERRNO ( rc = zmq_recv (stream, buffer + bytes_read, 255 - bytes_read, 0)); bytes_read += rc; } // First two bytes are major and minor version numbers. TEST_ASSERT_EQUAL_INT (3, buffer[0]); // ZMTP/3.0 TEST_ASSERT_EQUAL_INT (0, buffer[1]); // Mechanism is "NULL" TEST_ASSERT_EQUAL_INT8_ARRAY (buffer + 2, "NULL\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20); TEST_ASSERT_EQUAL_INT8_ARRAY (buffer + 54, "\4\51\5READY", 8); TEST_ASSERT_EQUAL_INT8_ARRAY (buffer + 62, "\13Socket-Type\0\0\0\6DEALER", 22); TEST_ASSERT_EQUAL_INT8_ARRAY (buffer + 84, "\10Identity\0\0\0\0", 13); // Announce we are ready memcpy (buffer, "\4\51\5READY", 8); memcpy (buffer + 8, "\13Socket-Type\0\0\0\6ROUTER", 22); memcpy (buffer + 30, "\10Identity\0\0\0\0", 13); // Send Ready command TEST_ASSERT_GREATER_THAN_INT (0, TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_send ( &routing_id, stream, ZMQ_SNDMORE))); TEST_ASSERT_EQUAL_INT ( 43, TEST_ASSERT_SUCCESS_ERRNO (zmq_send (stream, buffer, 43, 0))); // Now we expect the data from the DEALER socket // First frame is, again, the routing id of the connection TEST_ASSERT_GREATER_THAN_INT ( 0, TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&routing_id, stream, 0))); TEST_ASSERT_TRUE (zmq_msg_more (&routing_id)); // Third frame contains Hello message from DEALER TEST_ASSERT_EQUAL_INT (7, TEST_ASSERT_SUCCESS_ERRNO ( zmq_recv (stream, buffer, sizeof buffer, 0))); // Then we have a 5-byte message "Hello" TEST_ASSERT_EQUAL_INT (0, buffer[0]); // Flags = 0 TEST_ASSERT_EQUAL_INT (5, buffer[1]); // Size = 5 TEST_ASSERT_EQUAL_INT8_ARRAY (buffer + 2, "Hello", 5); // Send "World" back to DEALER TEST_ASSERT_GREATER_THAN_INT (0, TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_send ( &routing_id, stream, ZMQ_SNDMORE))); byte world[] = {0, 5, 'W', 'o', 'r', 'l', 'd'}; TEST_ASSERT_EQUAL_INT ( sizeof (world), TEST_ASSERT_SUCCESS_ERRNO (zmq_send (stream, world, sizeof (world), 0))); // Expect response on DEALER socket recv_string_expect_success (dealer, "World", 0); // Test large messages over STREAM socket #define size 64000 uint8_t msgout[size]; memset (msgout, 0xAB, size); zmq_send (dealer, msgout, size, 0); uint8_t msgin[9 + size]; memset (msgin, 0, 9 + size); bytes_read = 0; while (bytes_read < 9 + size) { // Get routing id frame TEST_ASSERT_GREATER_THAN_INT ( 0, TEST_ASSERT_SUCCESS_ERRNO (zmq_recv (stream, buffer, 256, 0))); // Get next chunk TEST_ASSERT_GREATER_THAN_INT ( 0, TEST_ASSERT_SUCCESS_ERRNO (rc = zmq_recv (stream, msgin + bytes_read, 9 + size - bytes_read, 0))); bytes_read += rc; } for (int byte_nbr = 0; byte_nbr < size; byte_nbr++) { TEST_ASSERT_EQUAL_UINT8 (0xAB, msgin[9 + byte_nbr]); } test_context_socket_close (dealer); test_context_socket_close (stream); }
static void test_stream_to_dealer (void) { int rc; // Set up our context and sockets void *ctx = zmq_ctx_new (); assert (ctx); // We'll be using this socket in raw mode void *stream = zmq_socket (ctx, ZMQ_STREAM); assert (stream); int zero = 0; rc = zmq_setsockopt (stream, ZMQ_LINGER, &zero, sizeof (zero)); assert (rc == 0); int enabled = 1; rc = zmq_setsockopt (stream, ZMQ_STREAM_NOTIFY, &enabled, sizeof (enabled)); assert (rc == 0); rc = zmq_bind (stream, "tcp://127.0.0.1:5556"); assert (rc == 0); // We'll be using this socket as the other peer void *dealer = zmq_socket (ctx, ZMQ_DEALER); assert (dealer); rc = zmq_setsockopt (dealer, ZMQ_LINGER, &zero, sizeof (zero)); assert (rc == 0); rc = zmq_connect (dealer, "tcp://localhost:5556"); // Send a message on the dealer socket rc = zmq_send (dealer, "Hello", 5, 0); assert (rc == 5); // Connecting sends a zero message // First frame is identity zmq_msg_t identity; rc = zmq_msg_init (&identity); assert (rc == 0); rc = zmq_msg_recv (&identity, stream, 0); assert (rc > 0); assert (zmq_msg_more (&identity)); // Verify the existence of Peer-Address metadata char const* peer_address = zmq_msg_gets (&identity, "Peer-Address"); assert (peer_address != 0); assert (streq (peer_address, "127.0.0.1")); // Second frame is zero byte buffer [255]; rc = zmq_recv (stream, buffer, 255, 0); assert (rc == 0); // Verify the existence of Peer-Address metadata peer_address = zmq_msg_gets (&identity, "Peer-Address"); assert (peer_address != 0); assert (streq (peer_address, "127.0.0.1")); // Real data follows // First frame is identity rc = zmq_msg_recv (&identity, stream, 0); assert (rc > 0); assert (zmq_msg_more (&identity)); // Verify the existence of Peer-Address metadata peer_address = zmq_msg_gets (&identity, "Peer-Address"); assert (peer_address != 0); assert (streq (peer_address, "127.0.0.1")); // Second frame is greeting signature rc = zmq_recv (stream, buffer, 255, 0); assert (rc == 10); assert (memcmp (buffer, greeting.signature, 10) == 0); // Send our own protocol greeting rc = zmq_msg_send (&identity, stream, ZMQ_SNDMORE); assert (rc > 0); rc = zmq_send (stream, &greeting, sizeof (greeting), 0); assert (rc == sizeof (greeting)); // Now we expect the data from the DEALER socket // We want the rest of greeting along with the Ready command int bytes_read = 0; while (bytes_read < 97) { // First frame is the identity of the connection (each time) rc = zmq_msg_recv (&identity, stream, 0); assert (rc > 0); assert (zmq_msg_more (&identity)); // Second frame contains the next chunk of data rc = zmq_recv (stream, buffer + bytes_read, 255 - bytes_read, 0); assert (rc >= 0); bytes_read += rc; } // First two bytes are major and minor version numbers. assert (buffer [0] == 3); // ZMTP/3.0 assert (buffer [1] == 0); // Mechanism is "NULL" assert (memcmp (buffer + 2, "NULL\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) == 0); assert (memcmp (buffer + 54, "\4\51\5READY", 8) == 0); assert (memcmp (buffer + 62, "\13Socket-Type\0\0\0\6DEALER", 22) == 0); assert (memcmp (buffer + 84, "\10Identity\0\0\0\0", 13) == 0); // Announce we are ready memcpy (buffer, "\4\51\5READY", 8); memcpy (buffer + 8, "\13Socket-Type\0\0\0\6ROUTER", 22); memcpy (buffer + 30, "\10Identity\0\0\0\0", 13); // Send Ready command rc = zmq_msg_send (&identity, stream, ZMQ_SNDMORE); assert (rc > 0); rc = zmq_send (stream, buffer, 43, 0); assert (rc == 43); // Now we expect the data from the DEALER socket // First frame is, again, the identity of the connection rc = zmq_msg_recv (&identity, stream, 0); assert (rc > 0); assert (zmq_msg_more (&identity)); // Third frame contains Hello message from DEALER rc = zmq_recv (stream, buffer, sizeof buffer, 0); assert (rc == 7); // Then we have a 5-byte message "Hello" assert (buffer [0] == 0); // Flags = 0 assert (buffer [1] == 5); // Size = 5 assert (memcmp (buffer + 2, "Hello", 5) == 0); // Send "World" back to DEALER rc = zmq_msg_send (&identity, stream, ZMQ_SNDMORE); assert (rc > 0); byte world [] = { 0, 5, 'W', 'o', 'r', 'l', 'd' }; rc = zmq_send (stream, world, sizeof (world), 0); assert (rc == sizeof (world)); // Expect response on DEALER socket rc = zmq_recv (dealer, buffer, 255, 0); assert (rc == 5); assert (memcmp (buffer, "World", 5) == 0); rc = zmq_close (dealer); assert (rc == 0); rc = zmq_close (stream); assert (rc == 0); rc = zmq_ctx_term (ctx); assert (rc == 0); }