void test_req_message_format (void *ctx)
{
    void *req = zmq_socket (ctx, ZMQ_REQ);
    assert (req);

    void *router = zmq_socket (ctx, ZMQ_ROUTER);
    assert (router);

    int rc = zmq_bind (req, bind_address);
    assert (rc == 0);
    size_t len = MAX_SOCKET_STRING;
    rc = zmq_getsockopt (req, ZMQ_LAST_ENDPOINT, connect_address, &len);
    assert (rc == 0);

    rc = zmq_connect (router, connect_address);
    assert (rc == 0);

    // Send a multi-part request.
    s_send_seq (req, "ABC", "DEF", SEQ_END);

    zmq_msg_t msg;
    zmq_msg_init (&msg);

    // Receive peer identity
    rc = zmq_msg_recv (&msg, router, 0);
    assert (rc != -1);
    assert (zmq_msg_size (&msg) > 0);
    zmq_msg_t peer_id_msg;
    zmq_msg_init (&peer_id_msg);
    zmq_msg_copy (&peer_id_msg, &msg);

    int more = 0;
    size_t more_size = sizeof (more);
    rc = zmq_getsockopt (router, ZMQ_RCVMORE, &more, &more_size);
    assert (rc == 0);
    assert (more);

    // Receive the rest.
    s_recv_seq (router, 0, "ABC", "DEF", SEQ_END);

    // Send back a single-part reply.
    rc = zmq_msg_send (&peer_id_msg, router, ZMQ_SNDMORE);
    assert (rc != -1);
    s_send_seq (router, 0, "GHI", SEQ_END);

    // Receive reply.
    s_recv_seq (req, "GHI", SEQ_END);

    rc = zmq_msg_close (&msg);
    assert (rc == 0);

    rc = zmq_msg_close (&peer_id_msg);
    assert (rc == 0);

    close_zero_linger (req);
    close_zero_linger (router);

    // Wait for disconnects.
    msleep (SETTLE_TIME);
}
Exemple #2
0
void test_envelope (void *ctx)
{
    void *rep = zmq_socket (ctx, ZMQ_REP);
    assert (rep);

    int rc = zmq_bind (rep, bind_address);
    assert (rc == 0);

    void *dealer = zmq_socket (ctx, ZMQ_DEALER);
    assert (dealer);

    rc = zmq_connect (dealer, connect_address);
    assert (rc == 0);

    // minimal envelope
    s_send_seq (dealer, 0, "A", SEQ_END);
    s_recv_seq (rep, "A", SEQ_END);
    s_send_seq (rep, "A", SEQ_END);
    s_recv_seq (dealer, 0, "A", SEQ_END);

    // big envelope
    s_send_seq (dealer, "X", "Y", 0, "A", SEQ_END);
    s_recv_seq (rep, "A", SEQ_END);
    s_send_seq (rep, "A", SEQ_END);
    s_recv_seq (dealer, "X", "Y", 0, "A", SEQ_END);

    close_zero_linger (rep);
    close_zero_linger (dealer);

    // Wait for disconnects.
    rc = zmq_poll (0, 0, 100);
    assert (rc == 0);
}
Exemple #3
0
void test_fair_queue_in (void *ctx)
{
    void *receiver = zmq_socket (ctx, ZMQ_DEALER);
    assert (receiver);

    int timeout = 250;
    int rc = zmq_setsockopt (receiver, ZMQ_RCVTIMEO, &timeout, sizeof (int));
    assert (rc == 0);

    rc = zmq_bind (receiver, bind_address);
    assert (rc == 0);

    const size_t services = 5;
    void *senders [services];
    for (size_t peer = 0; peer < services; ++peer) {
        senders [peer] = zmq_socket (ctx, ZMQ_DEALER);
        assert (senders [peer]);

        rc = zmq_setsockopt (senders [peer], ZMQ_RCVTIMEO, &timeout, sizeof (int));
        assert (rc == 0);

        rc = zmq_connect (senders [peer], connect_address);
        assert (rc == 0);
    }

    zmq_msg_t msg;
    rc = zmq_msg_init (&msg);
    assert (rc == 0);

    s_send_seq (senders [0], "A", SEQ_END);
    s_recv_seq (receiver, "A", SEQ_END);

    s_send_seq (senders [0], "A", SEQ_END);
    s_recv_seq (receiver, "A", SEQ_END);

    // send our requests
    for (size_t peer = 0; peer < services; ++peer)
        s_send_seq (senders [peer], "B", SEQ_END);

    // Wait for data.
    rc = zmq_poll (0, 0, 50);
    assert (rc == 0);

    // handle the requests
    for (size_t peer = 0; peer < services; ++peer)
        s_recv_seq (receiver, "B", SEQ_END);

    rc = zmq_msg_close (&msg);
    assert (rc == 0);

    close_zero_linger (receiver);

    for (size_t peer = 0; peer < services; ++peer)
        close_zero_linger (senders [peer]);

    // Wait for disconnects.
    rc = zmq_poll (0, 0, 100);
    assert (rc == 0);
}
Exemple #4
0
void test_push_round_robin_out (void *ctx)
{
    void *push = zmq_socket (ctx, ZMQ_PUSH);
    assert (push);

    int rc = zmq_bind (push, bind_address);
    assert (rc == 0);

    const size_t services = 5;
    void *pulls [services];
    for (size_t peer = 0; peer < services; ++peer) {
        pulls [peer] = zmq_socket (ctx, ZMQ_PULL);
        assert (pulls [peer]);

        int timeout = 100;
        rc = zmq_setsockopt (pulls [peer], ZMQ_RCVTIMEO, &timeout, sizeof (int));
        assert (rc == 0);

        rc = zmq_connect (pulls [peer], connect_address);
        assert (rc == 0);
    }

    // Wait for connections.
    rc = zmq_poll (0, 0, 100);
    assert (rc == 0);

    // Send 2N messages
    for (size_t peer = 0; peer < services; ++peer)
        s_send_seq (push, "ABC", SEQ_END);
    for (size_t peer = 0; peer < services; ++peer)
        s_send_seq (push, "DEF", SEQ_END);

    // Expect every PULL got one of each
    for (size_t peer = 0; peer < services; ++peer) {
        s_recv_seq (pulls [peer], "ABC", SEQ_END);
        s_recv_seq (pulls [peer], "DEF", SEQ_END);
    }

    close_zero_linger (push);

    for (size_t peer = 0; peer < services; ++peer)
        close_zero_linger (pulls [peer]);

    // Wait for disconnects.
    rc = zmq_poll (0, 0, 100);
    assert (rc == 0);
}
void test_round_robin_out (void *ctx)
{
    void *req = zmq_socket (ctx, ZMQ_REQ);
    assert (req);

    int rc = zmq_bind (req, bind_address);
    assert (rc == 0);
    size_t len = MAX_SOCKET_STRING;
    rc = zmq_getsockopt (req, ZMQ_LAST_ENDPOINT, connect_address, &len);
    assert (rc == 0);

    const size_t services = 5;
    void *rep [services];
    for (size_t peer = 0; peer < services; peer++) {
        rep [peer] = zmq_socket (ctx, ZMQ_REP);
        assert (rep [peer]);

        int timeout = 250;
        rc = zmq_setsockopt (rep [peer], ZMQ_RCVTIMEO, &timeout, sizeof (int));
        assert (rc == 0);

        rc = zmq_connect (rep [peer], connect_address);
        assert (rc == 0);
    }
    //  We have to give the connects time to finish otherwise the requests 
    //  will not properly round-robin. We could alternatively connect the
    //  REQ sockets to the REP sockets.
    msleep (SETTLE_TIME);
    
    // Send our peer-replies, and expect every REP it used once in order
    for (size_t peer = 0; peer < services; peer++) {
        s_send_seq (req, "ABC", SEQ_END);
        s_recv_seq (rep [peer], "ABC", SEQ_END);
        s_send_seq (rep [peer], "DEF", SEQ_END);
        s_recv_seq (req, "DEF", SEQ_END);
    }

    close_zero_linger (req);
    for (size_t peer = 0; peer < services; peer++)
        close_zero_linger (rep [peer]);

    // Wait for disconnects.
    msleep (SETTLE_TIME);
}
Exemple #6
0
void test_round_robin_out (void *ctx)
{
    void *req = zmq_socket (ctx, ZMQ_REQ);
    assert (req);

    int rc = zmq_bind (req, bind_address);
    assert (rc == 0);

    const size_t services = 5;
    void *rep [services];
    for (size_t peer = 0; peer < services; peer++) {
        rep [peer] = zmq_socket (ctx, ZMQ_REP);
        assert (rep [peer]);

        int timeout = 100;
        rc = zmq_setsockopt (rep [peer], ZMQ_RCVTIMEO, &timeout, sizeof (int));
        assert (rc == 0);

        rc = zmq_connect (rep [peer], connect_address);
        assert (rc == 0);
    }
    //  We have to give the connects time to finish otherwise the requests 
    //  will not properly round-robin. We could alternatively connect the
    //  REQ sockets to the REP sockets.
    struct timespec t = { 0, 250 * 1000000 };
    nanosleep (&t, NULL);
    
    // Send our peer-replies, and expect every REP it used once in order
    for (size_t peer = 0; peer < services; peer++) {
        s_send_seq (req, "ABC", SEQ_END);
        s_recv_seq (rep [peer], "ABC", SEQ_END);
        s_send_seq (rep [peer], "DEF", SEQ_END);
        s_recv_seq (req, "DEF", SEQ_END);
    }

    close_zero_linger (req);
    for (size_t peer = 0; peer < services; peer++)
        close_zero_linger (rep [peer]);

    // Wait for disconnects.
    rc = zmq_poll (0, 0, 100);
    assert (rc == 0);
}
Exemple #7
0
void test_round_robin_out (void *ctx)
{
    void *dealer = zmq_socket (ctx, ZMQ_DEALER);
    assert (dealer);

    int rc = zmq_bind (dealer, bind_address);
    assert (rc == 0);

    const size_t services = 5;
    void *rep [services];
    for (size_t peer = 0; peer < services; ++peer) {
        rep [peer] = zmq_socket (ctx, ZMQ_REP);
        assert (rep [peer]);

        int timeout = 250;
        rc = zmq_setsockopt (rep [peer], ZMQ_RCVTIMEO, &timeout, sizeof (int));
        assert (rc == 0);

        rc = zmq_connect (rep [peer], connect_address);
        assert (rc == 0);
    }

    // Wait for connections.
    rc = zmq_poll (0, 0, 100);
    assert (rc == 0);

    // Send all requests
    for (size_t i = 0; i < services; ++i)
        s_send_seq (dealer, 0, "ABC", SEQ_END);

    // Expect every REP got one message
    zmq_msg_t msg;
    zmq_msg_init (&msg);

    for (size_t peer = 0; peer < services; ++peer)
        s_recv_seq (rep [peer], "ABC", SEQ_END);

    rc = zmq_msg_close (&msg);
    assert (rc == 0);

    close_zero_linger (dealer);

    for (size_t peer = 0; peer < services; ++peer)
        close_zero_linger (rep [peer]);

    // Wait for disconnects.
    rc = zmq_poll (0, 0, 100);
    assert (rc == 0);
}
Exemple #8
0
void test_destroy_queue_on_disconnect (void *ctx)
{
    void *A = zmq_socket (ctx, ZMQ_DEALER);
    assert (A);

    int rc = zmq_bind (A, bind_address);
    assert (rc == 0);

    void *B = zmq_socket (ctx, ZMQ_DEALER);
    assert (B);

    rc = zmq_connect (B, connect_address);
    assert (rc == 0);

    // Send a message in both directions
    s_send_seq (A, "ABC", SEQ_END);
    s_send_seq (B, "DEF", SEQ_END);

    rc = zmq_disconnect (B, connect_address);
    assert (rc == 0);

    // Disconnect may take time and need command processing.
    zmq_pollitem_t poller [2] = { { A, 0, 0, 0 }, { B, 0, 0, 0 } };
    rc = zmq_poll (poller, 2, 100);
    assert (rc == 0);
    rc = zmq_poll (poller, 2, 100);
    assert (rc == 0);

    // No messages should be available, sending should fail.
    zmq_msg_t msg;
    zmq_msg_init (&msg);

    rc = zmq_send (A, 0, 0, ZMQ_DONTWAIT);
    assert (rc == -1);
    assert (errno == EAGAIN);

    rc = zmq_msg_recv (&msg, A, ZMQ_DONTWAIT);
    assert (rc == -1);
    assert (errno == EAGAIN);

    // After a reconnect of B, the messages should still be gone
    rc = zmq_connect (B, connect_address);
    assert (rc == 0);

    rc = zmq_msg_recv (&msg, A, ZMQ_DONTWAIT);
    assert (rc == -1);
    assert (errno == EAGAIN);

    rc = zmq_msg_recv (&msg, B, ZMQ_DONTWAIT);
    assert (rc == -1);
    assert (errno == EAGAIN);

    rc = zmq_msg_close (&msg);
    assert (rc == 0);

    close_zero_linger (A);
    close_zero_linger (B);

    // Wait for disconnects.
    rc = zmq_poll (0, 0, 100);
    assert (rc == 0);
}
Exemple #9
0
void test_req_only_listens_to_current_peer (void *ctx)
{
    void *req = zmq_socket (ctx, ZMQ_REQ);
    assert (req);

    int rc = zmq_setsockopt(req, ZMQ_IDENTITY, "A", 2);
    assert (rc == 0);

    rc = zmq_bind (req, bind_address);
    assert (rc == 0);

    const size_t services = 3;
    void *router [services];
    
    for (size_t i = 0; i < services; ++i) {
        router [i] = zmq_socket (ctx, ZMQ_ROUTER);
        assert (router [i]);

        int timeout = 100;
        rc = zmq_setsockopt (router [i], ZMQ_RCVTIMEO, &timeout, sizeof (timeout));
        assert (rc == 0);

        int enabled = 1;
        rc = zmq_setsockopt (router [i], ZMQ_ROUTER_MANDATORY, &enabled, sizeof (enabled));
        assert (rc == 0);

        rc = zmq_connect (router [i], connect_address);
        assert (rc == 0);
    }

    // Wait for connects to finish.
    rc = zmq_poll (0, 0, 100);
    assert (rc == 0);

    for (size_t i = 0; i < services; ++i) {
        // There still is a race condition when a stale peer's message
        // arrives at the REQ just after a request was sent to that peer.
        // To avoid that happening in the test, sleep for a bit.
        rc = zmq_poll (0, 0, 10);
        assert (rc == 0);

        s_send_seq (req, "ABC", SEQ_END);

        // Receive on router i
        s_recv_seq (router [i], "A", 0, "ABC", SEQ_END);

        // Send back replies on all routers
        for (size_t j = 0; j < services; ++j) {
            const char *replies [] = { "WRONG", "GOOD" };
            const char *reply = replies [i == j ? 1 : 0];
            s_send_seq (router [j], "A", 0, reply, SEQ_END);
        }

        // Receive only the good reply
        s_recv_seq (req, "GOOD", SEQ_END);
    }

    close_zero_linger (req);
    for (size_t i = 0; i < services; ++i)
        close_zero_linger (router [i]);

    // Wait for disconnects.
    rc = zmq_poll (0, 0, 100);
    assert (rc == 0);
}
Exemple #10
0
void test_fair_queue_in (void *ctx)
{
    void *rep = zmq_socket (ctx, ZMQ_REP);
    assert (rep);

    int timeout = 100;
    int rc = zmq_setsockopt (rep, ZMQ_RCVTIMEO, &timeout, sizeof (int));
    assert (rc == 0);

    rc = zmq_bind (rep, bind_address);
    assert (rc == 0);

    const size_t services = 5;
    void *reqs [services];
    for (size_t peer = 0; peer < services; ++peer) {
        reqs [peer] = zmq_socket (ctx, ZMQ_REQ);
        assert (reqs [peer]);

        rc = zmq_setsockopt (reqs [peer], ZMQ_RCVTIMEO, &timeout, sizeof (int));
        assert (rc == 0);

        rc = zmq_connect (reqs [peer], connect_address);
        assert (rc == 0);
    }

    s_send_seq (reqs [0], "A", SEQ_END);
    s_recv_seq (rep, "A", SEQ_END);
    s_send_seq (rep, "A", SEQ_END);
    s_recv_seq (reqs [0], "A", SEQ_END);

    s_send_seq (reqs [0], "A", SEQ_END);
    s_recv_seq (rep, "A", SEQ_END);
    s_send_seq (rep, "A", SEQ_END);
    s_recv_seq (reqs [0], "A", SEQ_END);

    // send N requests
    for (size_t peer = 0; peer < services; ++peer) {
        char * str = strdup("A");
        str [0] += peer;
        s_send_seq (reqs [peer], str, SEQ_END);
        free (str);
    }

    // handle N requests
    for (size_t peer = 0; peer < services; ++peer) {
        char * str = strdup("A");
        str [0] += peer;
        s_recv_seq (rep, str, SEQ_END);
        s_send_seq (rep, str, SEQ_END);
        s_recv_seq (reqs [peer], str, SEQ_END);
        free (str);
    }

    close_zero_linger (rep);

    for (size_t peer = 0; peer < services; ++peer)
        close_zero_linger (reqs [peer]);

    // Wait for disconnects.
    rc = zmq_poll (0, 0, 100);
    assert (rc == 0);
}
Exemple #11
0
void test_fair_queue_in (void *ctx)
{
    void *receiver = zmq_socket (ctx, ZMQ_ROUTER);
    assert (receiver);

    int timeout = 100;
    int rc = zmq_setsockopt (receiver, ZMQ_RCVTIMEO, &timeout, sizeof (int));
    assert (rc == 0);

    rc = zmq_bind (receiver, bind_address);
    assert (rc == 0);

    const size_t services = 5;
    void *senders [services];
    for (size_t peer = 0; peer < services; ++peer) {
        senders [peer] = zmq_socket (ctx, ZMQ_DEALER);
        assert (senders [peer]);

        rc = zmq_setsockopt (senders [peer], ZMQ_RCVTIMEO, &timeout, sizeof (int));
        assert (rc == 0);

        char *str = strdup("A");
        str [0] += peer;
        rc = zmq_setsockopt (senders [peer], ZMQ_IDENTITY, str, 2);
        assert (rc == 0);
        free (str);

        rc = zmq_connect (senders [peer], connect_address);
        assert (rc == 0);
    }

    zmq_msg_t msg;
    rc = zmq_msg_init (&msg);
    assert (rc == 0);

    s_send_seq (senders [0], "M", SEQ_END);
    s_recv_seq (receiver, "A", "M", SEQ_END);

    s_send_seq (senders [0], "M", SEQ_END);
    s_recv_seq (receiver, "A", "M", SEQ_END);

    int sum = 0;

    // send N requests
    for (size_t peer = 0; peer < services; ++peer) {
        s_send_seq (senders [peer], "M", SEQ_END);
        sum += 'A' + peer;
    }

    assert (sum == services * 'A' + services * (services - 1) / 2);

    // handle N requests
    for (size_t peer = 0; peer < services; ++peer) {
        rc = zmq_msg_recv (&msg, receiver, 0);
        assert (rc == 2);
        const char *id = (const char *)zmq_msg_data (&msg);
        sum -= id [0];

        s_recv_seq (receiver, "M", SEQ_END);
    }

    assert (sum == 0);

    rc = zmq_msg_close (&msg);
    assert (rc == 0);

    close_zero_linger (receiver);

    for (size_t peer = 0; peer < services; ++peer)
        close_zero_linger (senders [peer]);

    // Wait for disconnects.
    rc = zmq_poll (0, 0, 100);
    assert (rc == 0);
}
Exemple #12
0
void test_destroy_queue_on_disconnect (void *ctx)
{
    void *A = zmq_socket (ctx, ZMQ_ROUTER);
    assert (A);

    int enabled = 1;
    int rc = zmq_setsockopt (A, ZMQ_ROUTER_MANDATORY, &enabled, sizeof(enabled));
    assert (rc == 0);

    rc = zmq_bind (A, "inproc://d");
    assert (rc == 0);

    void *B = zmq_socket (ctx, ZMQ_DEALER);
    assert (B);

    rc = zmq_setsockopt (B, ZMQ_IDENTITY, "B", 2);
    assert (rc == 0);

    rc = zmq_connect (B, "inproc://d");
    assert (rc == 0);

    // Send a message in both directions
    s_send_seq (A, "B", "ABC", SEQ_END);
    s_send_seq (B, "DEF", SEQ_END);

    rc = zmq_disconnect (B, "inproc://d");
    assert (rc == 0);

    // Disconnect may take time and need command processing.
    zmq_pollitem_t poller[2] = { { A, 0, 0, 0 }, { B, 0, 0, 0 } };
    rc = zmq_poll (poller, 2, 100);
    assert (rc == 0);

    // No messages should be available, sending should fail.
    zmq_msg_t msg;
    zmq_msg_init (&msg);

    rc = zmq_send (A, "B", 2, ZMQ_SNDMORE | ZMQ_DONTWAIT);
    assert (rc == -1);
    assert (errno == EHOSTUNREACH);

    rc = zmq_msg_recv (&msg, A, ZMQ_DONTWAIT);
    assert (rc == -1);
    assert (errno == EAGAIN);

    // After a reconnect of B, the messages should still be gone
    rc = zmq_connect (B, "inproc://d");
    assert (rc == 0);

    rc = zmq_msg_recv (&msg, A, ZMQ_DONTWAIT);
    assert (rc == -1);
    assert (errno == EAGAIN);

    rc = zmq_msg_recv (&msg, B, ZMQ_DONTWAIT);
    assert (rc == -1);
    assert (errno == EAGAIN);

    rc = zmq_msg_close (&msg);
    assert (rc == 0);

    rc = zmq_close (A);
    assert (rc == 0);

    rc = zmq_close (B);
    assert (rc == 0);
}
Exemple #13
0
void test_fair_queue_in (void *ctx)
{
    void *receiver = zmq_socket (ctx, ZMQ_ROUTER);
    assert (receiver);

    int timeout = 100;
    int rc = zmq_setsockopt (receiver, ZMQ_RCVTIMEO, &timeout, sizeof(int));
    assert (rc == 0);

    rc = zmq_bind (receiver, "inproc://a");
    assert (rc == 0);

    const size_t N = 5;
    void *senders[N];
    for (size_t i = 0; i < N; ++i)
    {
        senders[i] = zmq_socket (ctx, ZMQ_DEALER);
        assert (senders[i]);

        rc = zmq_setsockopt (senders[i], ZMQ_RCVTIMEO, &timeout, sizeof(int));
        assert (rc == 0);

        char *str = strdup("A");
        str[0] += i;
        rc = zmq_setsockopt (senders[i], ZMQ_IDENTITY, str, 2);
        assert (rc == 0);
        free (str);

        rc = zmq_connect (senders[i], "inproc://a");
        assert (rc == 0);
    }

    zmq_msg_t msg;
    rc = zmq_msg_init (&msg);
    assert (rc == 0);

    s_send_seq (senders[0], "M", SEQ_END);
    s_recv_seq (receiver, "A", "M", SEQ_END);

    s_send_seq (senders[0], "M", SEQ_END);
    s_recv_seq (receiver, "A", "M", SEQ_END);

    // send N requests
    for (size_t i = 0; i < N; ++i)
    {
        s_send_seq (senders[i], "M", SEQ_END);
    }

    // handle N requests
    for (size_t i = 0; i < N; ++i)
    {
        char *str = strdup("A");
        str[0] += i;
        s_recv_seq (receiver, str, "M", SEQ_END);
        free (str);
    }

    rc = zmq_msg_close (&msg);
    assert (rc == 0);

    rc = zmq_close (receiver);
    assert (rc == 0);

    for (size_t i = 0; i < N; ++i)
    {
        rc = zmq_close (senders[i]);
        assert (rc == 0);
    }
}
Exemple #14
0
void test_pull_fair_queue_in (void *ctx)
{
    void *pull = zmq_socket (ctx, ZMQ_PULL);
    assert (pull);

    int rc = zmq_bind (pull, bind_address);
    assert (rc == 0);

    const size_t services = 5;
    void *pushs [services];
    for (size_t peer = 0; peer < services; ++peer)
    {
        pushs [peer] = zmq_socket (ctx, ZMQ_PUSH);
        assert (pushs [peer]);

        rc = zmq_connect (pushs [peer], connect_address);
        assert (rc == 0);
    }

    // Wait for connections.
    msleep (SETTLE_TIME);

    int first_half = 0;
    int second_half = 0;

    // Send 2N messages
    for (size_t peer = 0; peer < services; ++peer) {
        char *str = strdup("A");

        str [0] += peer;
        s_send_seq (pushs [peer], str, SEQ_END);
        first_half += str [0];

        str [0] += services;
        s_send_seq (pushs [peer], str, SEQ_END);
        second_half += str [0];

        free (str);
    }

    // Wait for data.
    msleep (SETTLE_TIME);

    zmq_msg_t msg;
    rc = zmq_msg_init (&msg);
    assert (rc == 0);

    // Expect to pull one from each first
    for (size_t peer = 0; peer < services; ++peer) {
        rc = zmq_msg_recv (&msg, pull, 0);
        assert (rc == 2);
        const char *str = (const char *)zmq_msg_data (&msg);
        first_half -= str [0];
    }
    assert (first_half == 0);

    // And then get the second batch
    for (size_t peer = 0; peer < services; ++peer) {
        rc = zmq_msg_recv (&msg, pull, 0);
        assert (rc == 2);
        const char *str = (const char *)zmq_msg_data (&msg);
        second_half -= str [0];
    }
    assert (second_half == 0);

    rc = zmq_msg_close (&msg);
    assert (rc == 0);

    close_zero_linger (pull);

    for (size_t peer = 0; peer < services; ++peer)
        close_zero_linger (pushs [peer]);

    // Wait for disconnects.
    msleep (SETTLE_TIME);
}
Exemple #15
0
void test_destroy_queue_on_disconnect (void *ctx)
{
    void *A = zmq_socket (ctx, ZMQ_PUSH);
    assert (A);

    int hwm = 1;
    int rc = zmq_setsockopt (A, ZMQ_SNDHWM, &hwm, sizeof (hwm));
    assert (rc == 0);

    rc = zmq_bind (A, bind_address);
    assert (rc == 0);

    void *B = zmq_socket (ctx, ZMQ_PULL);
    assert (B);

    rc = zmq_setsockopt (B, ZMQ_RCVHWM, &hwm, sizeof (hwm));
    assert (rc == 0);

    rc = zmq_connect (B, connect_address);
    assert (rc == 0);

    // Send two messages, one should be stuck in A's outgoing queue, the other
    // arrives at B.
    s_send_seq (A, "ABC", SEQ_END);
    s_send_seq (A, "DEF", SEQ_END);

    // Both queues should now be full, indicated by A blocking on send.
    rc = zmq_send (A, 0, 0, ZMQ_DONTWAIT);
    assert (rc == -1);
    assert (errno == EAGAIN);

    rc = zmq_disconnect (B, connect_address);
    assert (rc == 0);

    // Disconnect may take time and need command processing.
    zmq_pollitem_t poller [2] = { { A, 0, 0, 0 }, { B, 0, 0, 0 } };
    rc = zmq_poll (poller, 2, 100);
    assert (rc == 0);
    rc = zmq_poll (poller, 2, 100);
    assert (rc == 0);

    zmq_msg_t msg;
    rc = zmq_msg_init (&msg);
    assert (rc == 0);

    // Can't receive old data on B.
    rc = zmq_msg_recv (&msg, B, ZMQ_DONTWAIT);
    assert (rc == -1);
    assert (errno == EAGAIN);

    // Sending fails.
    rc = zmq_send (A, 0, 0, ZMQ_DONTWAIT);
    assert (rc == -1);
    assert (errno == EAGAIN);

    // Reconnect B
    rc = zmq_connect (B, connect_address);
    assert (rc == 0);

    // Still can't receive old data on B.
    rc = zmq_msg_recv (&msg, B, ZMQ_DONTWAIT);
    assert (rc == -1);
    assert (errno == EAGAIN);

    // two messages should be sendable before the queues are filled up.
    s_send_seq (A, "ABC", SEQ_END);
    s_send_seq (A, "DEF", SEQ_END);

    rc = zmq_send (A, 0, 0, ZMQ_DONTWAIT);
    assert (rc == -1);
    assert (errno == EAGAIN);

    rc = zmq_msg_close (&msg);
    assert (rc == 0);

    close_zero_linger (A);
    close_zero_linger (B);

    // Wait for disconnects.
    msleep (SETTLE_TIME);
}
Exemple #16
0
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);

    void *req = zmq_socket (ctx, ZMQ_REQ);
    assert (req);

    void *router = zmq_socket (ctx, ZMQ_ROUTER);
    assert (router);

    int enabled = 1;
    int rc = zmq_setsockopt (req, ZMQ_REQ_CORRELATE, &enabled, sizeof (int));
    assert (rc == 0);

    int rcvtimeo = 100;
    rc = zmq_setsockopt (req, ZMQ_RCVTIMEO, &rcvtimeo, sizeof (int));
    assert (rc == 0);

    rc = zmq_bind (router, "tcp://127.0.0.1:*");
    assert (rc == 0);
    rc = zmq_getsockopt (router, ZMQ_LAST_ENDPOINT, my_endpoint, &len);
    assert (rc == 0);

    rc = zmq_connect (req, my_endpoint);
    assert (rc == 0);

    // Send a multi-part request.
    s_send_seq (req, "ABC", "DEF", SEQ_END);

    zmq_msg_t msg;
    zmq_msg_init (&msg);

    // Receive peer routing id
    rc = zmq_msg_recv (&msg, router, 0);
    assert (rc != -1);
    assert (zmq_msg_size (&msg) > 0);
    zmq_msg_t peer_id_msg;
    zmq_msg_init (&peer_id_msg);
    zmq_msg_copy (&peer_id_msg, &msg);

    int more = 0;
    size_t more_size = sizeof (more);
    rc = zmq_getsockopt (router, ZMQ_RCVMORE, &more, &more_size);
    assert (rc == 0);
    assert (more);

    // Receive request id 1
    rc = zmq_msg_recv (&msg, router, 0);
    assert (rc != -1);
    assert (zmq_msg_size (&msg) == sizeof (uint32_t));
    uint32_t req_id = *static_cast<uint32_t *> (zmq_msg_data (&msg));
    zmq_msg_t req_id_msg;
    zmq_msg_init (&req_id_msg);
    zmq_msg_copy (&req_id_msg, &msg);

    more = 0;
    more_size = sizeof (more);
    rc = zmq_getsockopt (router, ZMQ_RCVMORE, &more, &more_size);
    assert (rc == 0);
    assert (more);

    // Receive the rest.
    s_recv_seq (router, 0, "ABC", "DEF", SEQ_END);

    uint32_t bad_req_id = req_id + 1;

    // Send back a bad reply: wrong req id, 0, data
    zmq_msg_copy (&msg, &peer_id_msg);
    rc = zmq_msg_send (&msg, router, ZMQ_SNDMORE);
    assert (rc != -1);
    zmq_msg_init_data (&msg, &bad_req_id, sizeof (uint32_t), NULL, NULL);
    rc = zmq_msg_send (&msg, router, ZMQ_SNDMORE);
    assert (rc != -1);
    s_send_seq (router, 0, "DATA", SEQ_END);

    // Send back a good reply: good req id, 0, data
    zmq_msg_copy (&msg, &peer_id_msg);
    rc = zmq_msg_send (&msg, router, ZMQ_SNDMORE);
    assert (rc != -1);
    zmq_msg_copy (&msg, &req_id_msg);
    rc = zmq_msg_send (&msg, router, ZMQ_SNDMORE);
    assert (rc != -1);
    s_send_seq (router, 0, "GHI", SEQ_END);

    // Receive reply. If bad reply got through, we wouldn't see
    // this particular data.
    s_recv_seq (req, "GHI", SEQ_END);

    rc = zmq_msg_close (&msg);
    assert (rc == 0);

    rc = zmq_msg_close (&peer_id_msg);
    assert (rc == 0);

    rc = zmq_msg_close (&req_id_msg);
    assert (rc == 0);

    close_zero_linger (req);
    close_zero_linger (router);

    rc = zmq_ctx_term (ctx);
    assert (rc == 0);

    return 0;
}