int main(int, char**)
{
    setup_test_environment();

    void* context = zmq_ctx_new ();
    void* sockets [2];
    int rc = 0;

    sockets [SERVER] = zmq_socket (context, ZMQ_STREAM);
    rc = zmq_bind (sockets [SERVER], "tcp://0.0.0.0:6666");
    assert (rc == 0);

    sockets [CLIENT] = zmq_socket (context, ZMQ_STREAM);
    rc = zmq_connect (sockets [CLIENT], "tcp://localhost:6666");
    assert (rc == 0);

    // wait for connect notification
    // Server: Grab the 1st frame (peer identity).
    zmq_msg_t peer_frame;
    rc = zmq_msg_init (&peer_frame);
    assert (rc == 0);
    rc = zmq_msg_recv (&peer_frame, sockets [SERVER], 0);
    assert (rc != -1);
    assert(zmq_msg_size (&peer_frame) > 0);
    assert (has_more (sockets [SERVER]));

    // Server: Grab the 2nd frame (actual payload).
    zmq_msg_t data_frame;
    rc = zmq_msg_init (&data_frame);
    assert (rc == 0);
    rc = zmq_msg_recv (&data_frame, sockets [SERVER], 0);
    assert (rc != -1);
    assert(zmq_msg_size (&data_frame) == 0);

    // Client: Grab the 1st frame (peer identity).
    rc = zmq_msg_init (&peer_frame);
    assert (rc == 0);
    rc = zmq_msg_recv (&peer_frame, sockets [CLIENT], 0);
    assert (rc != -1);
    assert(zmq_msg_size (&peer_frame) > 0);
    assert (has_more (sockets [CLIENT]));

    // Client: Grab the 2nd frame (actual payload).
    rc = zmq_msg_init (&data_frame);
    assert (rc == 0);
    rc = zmq_msg_recv (&data_frame, sockets [CLIENT], 0);
    assert (rc != -1);
    assert(zmq_msg_size (&data_frame) == 0);

    // Send initial message.
    char blob_data [256];
    size_t blob_size = sizeof(blob_data);
    rc = zmq_getsockopt (sockets [CLIENT], ZMQ_IDENTITY, blob_data, &blob_size);
    assert (rc != -1);
    assert(blob_size > 0);
    zmq_msg_t msg;
    rc = zmq_msg_init_size (&msg, blob_size);
    assert (rc == 0);
    memcpy (zmq_msg_data (&msg), blob_data, blob_size);
    rc = zmq_msg_send (&msg, sockets [dialog [0].turn], ZMQ_SNDMORE);
    assert (rc != -1);
    rc = zmq_msg_close (&msg);
    assert (rc == 0);
    rc = zmq_msg_init_size (&msg, strlen(dialog [0].text));
    assert (rc == 0);
    memcpy (zmq_msg_data (&msg), dialog [0].text, strlen(dialog [0].text));
    rc = zmq_msg_send (&msg, sockets [dialog [0].turn], ZMQ_SNDMORE);
    assert (rc != -1);
    rc = zmq_msg_close (&msg);
    assert (rc == 0);

    // TODO: make sure this loop doesn't loop forever if something is wrong
    //       with the test (or the implementation).

    int step = 0;
    while (step < steps) {
        // Wait until something happens.
        zmq_pollitem_t items [] = {
            { sockets [SERVER], 0, ZMQ_POLLIN, 0 },
            { sockets [CLIENT], 0, ZMQ_POLLIN, 0 },
        };
        int rc = zmq_poll (items, 2, 100);
        assert (rc >= 0);

        printf ("Event received for step %d.\n", step);

        // Check for data received by the server.
        if (items [SERVER].revents & ZMQ_POLLIN) {
            assert (dialog [step].turn == CLIENT);

            // Grab the 1st frame (peer identity).
            zmq_msg_t peer_frame;
            rc = zmq_msg_init (&peer_frame);
	    assert (rc == 0);
            rc = zmq_msg_recv (&peer_frame, sockets [SERVER], 0);
	    assert (rc != -1);
	    assert(zmq_msg_size (&peer_frame) > 0);
            assert (has_more (sockets [SERVER]));

            // Grab the 2nd frame (actual payload).
            zmq_msg_t data_frame;
            rc = zmq_msg_init (&data_frame);
	    assert (rc == 0);
            rc = zmq_msg_recv (&data_frame, sockets [SERVER], 0);
	    assert (rc != -1);

            // Make sure payload matches what we expect.
            const char * const data = (const char*)zmq_msg_data (&data_frame);
            const int size = zmq_msg_size (&data_frame);
            // 0-length frame is a disconnection notification.  The server
            // should receive it as the last step in the dialogue.
            if (size == 0) {
                printf ("server received disconnection notification!\n");
		++step;
                assert (step == steps);
            }
            else {
                printf ("server received %d bytes.\n", size);
		fprintf(stderr, "size = %d, len = %ld\n", size, strlen(dialog [step].text));
		assert((size_t)size == strlen(dialog [step].text));
		int cmp = memcmp(dialog [step].text, data, size);
		assert (cmp == 0);

		++step;

                assert (step < steps);

                // Prepare the response.
                rc = zmq_msg_close (&data_frame);
		assert (rc == 0);
                rc = zmq_msg_init_size (&data_frame,
					strlen (dialog [step].text));
		assert (rc == 0);
                memcpy (zmq_msg_data (&data_frame), dialog [step].text,
			zmq_msg_size (&data_frame));

                // Send the response.
                printf ("server sending %d bytes.\n",
			(int)zmq_msg_size (&data_frame));
                rc = zmq_msg_send (&peer_frame, sockets [SERVER], ZMQ_SNDMORE);
		assert (rc != -1);
                rc = zmq_msg_send (&data_frame, sockets [SERVER], ZMQ_SNDMORE);
		assert (rc != -1);
            }

            // Release resources.
            rc = zmq_msg_close (&peer_frame);
	    assert (rc == 0);
            rc = zmq_msg_close (&data_frame);
	    assert (rc == 0);
        }

        // Check for data received by the client.
        if (items [CLIENT].revents & ZMQ_POLLIN) {
            assert (dialog [step].turn == SERVER);

            // Grab the 1st frame (peer identity).
            zmq_msg_t peer_frame;
            rc = zmq_msg_init (&peer_frame);
	    assert (rc == 0);
            rc = zmq_msg_recv (&peer_frame, sockets [CLIENT], 0);
	    assert (rc != -1);
	    assert(zmq_msg_size (&peer_frame) > 0);
            assert (has_more (sockets [CLIENT]));

            // Grab the 2nd frame (actual payload).
            zmq_msg_t data_frame;
            rc = zmq_msg_init (&data_frame);
	    assert (rc == 0);
            rc = zmq_msg_recv (&data_frame, sockets [CLIENT], 0);
	    assert (rc != -1);
	    assert(zmq_msg_size (&data_frame) > 0);

            // Make sure payload matches what we expect.
            const char * const data = (const char*)zmq_msg_data (&data_frame);
            const int size = zmq_msg_size (&data_frame);
	    fprintf(stderr, "size = %d, len = %ld\n", size, strlen(dialog [step].text));
	    assert((size_t)size == strlen(dialog [step].text));
            int cmp = memcmp(dialog [step].text, data, size);
            assert (cmp == 0);

            printf ("client received %d bytes.\n", size);

            ++step;

            // Prepare the response (next line in the dialog).
            assert (step < steps);
            rc = zmq_msg_close (&data_frame);
	    assert (rc == 0);
            rc = zmq_msg_init_size (&data_frame, strlen (dialog [step].text));
	    assert (rc == 0);
            memcpy (zmq_msg_data (&data_frame), dialog [step].text, zmq_msg_size (&data_frame));

            // Send the response.
            printf ("client sending %d bytes.\n", (int)zmq_msg_size (&data_frame));
            rc = zmq_msg_send (&peer_frame, sockets [CLIENT], ZMQ_SNDMORE);
	    assert (rc != -1);
            rc = zmq_msg_send (&data_frame, sockets [CLIENT], ZMQ_SNDMORE);
	    assert (rc != -1);

            // Release resources.
            rc = zmq_msg_close (&peer_frame);
	    assert (rc == 0);
            rc = zmq_msg_close (&data_frame);
	    assert (rc == 0);
        }
    }
    assert (step == steps);

    printf ("Done, exiting now.\n");
    rc = zmq_close (sockets [CLIENT]);
    assert (rc == 0);
    rc = zmq_close (sockets [SERVER]);
    assert (rc == 0);
    rc = zmq_ctx_term (context);
    assert (rc == 0);
    return 0;
}
int main (int, char **)
{
    setup_test_environment ();

    size_t len = MAX_SOCKET_STRING;
    char bind_endpoint[MAX_SOCKET_STRING];
    char connect_endpoint[MAX_SOCKET_STRING];
    void *context = zmq_ctx_new ();
    void *sockets[2];
    int rc = 0;

    sockets[SERVER] = zmq_socket (context, ZMQ_STREAM);
    int enabled = 1;
    rc = zmq_setsockopt (sockets[SERVER], ZMQ_STREAM_NOTIFY, &enabled,
                         sizeof (enabled));
    assert (rc == 0);
    rc = zmq_bind (sockets[SERVER], "tcp://0.0.0.0:*");
    assert (rc == 0);
    rc =
      zmq_getsockopt (sockets[SERVER], ZMQ_LAST_ENDPOINT, bind_endpoint, &len);
    assert (rc == 0);

    //  Apparently Windows can't connect to 0.0.0.0. A better fix would be welcome.
#ifdef ZMQ_HAVE_WINDOWS
    sprintf (connect_endpoint, "tcp://127.0.0.1:%s",
             strrchr (bind_endpoint, ':') + 1);
#else
    strcpy (connect_endpoint, bind_endpoint);
#endif

    sockets[CLIENT] = zmq_socket (context, ZMQ_STREAM);
    rc = zmq_setsockopt (sockets[CLIENT], ZMQ_STREAM_NOTIFY, &enabled,
                         sizeof (enabled));
    assert (rc == 0);
    rc = zmq_connect (sockets[CLIENT], connect_endpoint);
    assert (rc == 0);

    // wait for connect notification
    // Server: Grab the 1st frame (peer routing id).
    zmq_msg_t peer_frame;
    rc = zmq_msg_init (&peer_frame);
    assert (rc == 0);
    rc = zmq_msg_recv (&peer_frame, sockets[SERVER], 0);
    assert (rc != -1);
    assert (zmq_msg_size (&peer_frame) > 0);
    assert (has_more (sockets[SERVER]));
    rc = zmq_msg_close (&peer_frame);
    assert (rc == 0);

    // Server: Grab the 2nd frame (actual payload).
    zmq_msg_t data_frame;
    rc = zmq_msg_init (&data_frame);
    assert (rc == 0);
    rc = zmq_msg_recv (&data_frame, sockets[SERVER], 0);
    assert (rc != -1);
    assert (zmq_msg_size (&data_frame) == 0);
    rc = zmq_msg_close (&data_frame);
    assert (rc == 0);

    // Client: Grab the 1st frame (peer routing id).
    rc = zmq_msg_init (&peer_frame);
    assert (rc == 0);
    rc = zmq_msg_recv (&peer_frame, sockets[CLIENT], 0);
    assert (rc != -1);
    assert (zmq_msg_size (&peer_frame) > 0);
    assert (has_more (sockets[CLIENT]));
    rc = zmq_msg_close (&peer_frame);
    assert (rc == 0);

    // Client: Grab the 2nd frame (actual payload).
    rc = zmq_msg_init (&data_frame);
    assert (rc == 0);
    rc = zmq_msg_recv (&data_frame, sockets[CLIENT], 0);
    assert (rc != -1);
    assert (zmq_msg_size (&data_frame) == 0);
    rc = zmq_msg_close (&data_frame);
    assert (rc == 0);

    // Send initial message.
    char blob_data[256];
    size_t blob_size = sizeof (blob_data);
    rc =
      zmq_getsockopt (sockets[CLIENT], ZMQ_ROUTING_ID, blob_data, &blob_size);
    assert (rc != -1);
    assert (blob_size > 0);
    zmq_msg_t msg;
    rc = zmq_msg_init_size (&msg, blob_size);
    assert (rc == 0);
    memcpy (zmq_msg_data (&msg), blob_data, blob_size);
    rc = zmq_msg_send (&msg, sockets[dialog[0].turn], ZMQ_SNDMORE);
    assert (rc != -1);
    rc = zmq_msg_close (&msg);
    assert (rc == 0);
    rc = zmq_msg_init_size (&msg, strlen (dialog[0].text));
    assert (rc == 0);
    memcpy (zmq_msg_data (&msg), dialog[0].text, strlen (dialog[0].text));
    rc = zmq_msg_send (&msg, sockets[dialog[0].turn], ZMQ_SNDMORE);
    assert (rc != -1);
    rc = zmq_msg_close (&msg);
    assert (rc == 0);

    // TODO: make sure this loop doesn't loop forever if something is wrong
    //       with the test (or the implementation).

    int step = 0;
    while (step < steps) {
        // Wait until something happens.
        zmq_pollitem_t items[] = {
          {sockets[SERVER], 0, ZMQ_POLLIN, 0},
          {sockets[CLIENT], 0, ZMQ_POLLIN, 0},
        };
        int rc = zmq_poll (items, 2, 100);
        assert (rc >= 0);

        // Check for data received by the server.
        if (items[SERVER].revents & ZMQ_POLLIN) {
            assert (dialog[step].turn == CLIENT);

            // Grab the 1st frame (peer routing id).
            zmq_msg_t peer_frame;
            rc = zmq_msg_init (&peer_frame);
            assert (rc == 0);
            rc = zmq_msg_recv (&peer_frame, sockets[SERVER], 0);
            assert (rc != -1);
            assert (zmq_msg_size (&peer_frame) > 0);
            assert (has_more (sockets[SERVER]));

            // Grab the 2nd frame (actual payload).
            zmq_msg_t data_frame;
            rc = zmq_msg_init (&data_frame);
            assert (rc == 0);
            rc = zmq_msg_recv (&data_frame, sockets[SERVER], 0);
            assert (rc != -1);

            // Make sure payload matches what we expect.
            const char *const data = (const char *) zmq_msg_data (&data_frame);
            const size_t size = zmq_msg_size (&data_frame);
            // 0-length frame is a disconnection notification.  The server
            // should receive it as the last step in the dialogue.
            if (size == 0) {
                ++step;
                assert (step == steps);
            } else {
                assert (size == strlen (dialog[step].text));
                int cmp = memcmp (dialog[step].text, data, size);
                assert (cmp == 0);

                ++step;

                assert (step < steps);

                // Prepare the response.
                rc = zmq_msg_close (&data_frame);
                assert (rc == 0);
                rc =
                  zmq_msg_init_size (&data_frame, strlen (dialog[step].text));
                assert (rc == 0);
                memcpy (zmq_msg_data (&data_frame), dialog[step].text,
                        zmq_msg_size (&data_frame));

                // Send the response.
                rc = zmq_msg_send (&peer_frame, sockets[SERVER], ZMQ_SNDMORE);
                assert (rc != -1);
                rc = zmq_msg_send (&data_frame, sockets[SERVER], ZMQ_SNDMORE);
                assert (rc != -1);
            }

            // Release resources.
            rc = zmq_msg_close (&peer_frame);
            assert (rc == 0);
            rc = zmq_msg_close (&data_frame);
            assert (rc == 0);
        }

        // Check for data received by the client.
        if (items[CLIENT].revents & ZMQ_POLLIN) {
            assert (dialog[step].turn == SERVER);

            // Grab the 1st frame (peer routing id).
            zmq_msg_t peer_frame;
            rc = zmq_msg_init (&peer_frame);
            assert (rc == 0);
            rc = zmq_msg_recv (&peer_frame, sockets[CLIENT], 0);
            assert (rc != -1);
            assert (zmq_msg_size (&peer_frame) > 0);
            assert (has_more (sockets[CLIENT]));

            // Grab the 2nd frame (actual payload).
            zmq_msg_t data_frame;
            rc = zmq_msg_init (&data_frame);
            assert (rc == 0);
            rc = zmq_msg_recv (&data_frame, sockets[CLIENT], 0);
            assert (rc != -1);
            assert (zmq_msg_size (&data_frame) > 0);

            // Make sure payload matches what we expect.
            const char *const data = (const char *) zmq_msg_data (&data_frame);
            const size_t size = zmq_msg_size (&data_frame);
            assert (size == strlen (dialog[step].text));
            int cmp = memcmp (dialog[step].text, data, size);
            assert (cmp == 0);

            ++step;

            // Prepare the response (next line in the dialog).
            assert (step < steps);
            rc = zmq_msg_close (&data_frame);
            assert (rc == 0);
            rc = zmq_msg_init_size (&data_frame, strlen (dialog[step].text));
            assert (rc == 0);
            memcpy (zmq_msg_data (&data_frame), dialog[step].text,
                    zmq_msg_size (&data_frame));

            // Send the response.
            rc = zmq_msg_send (&peer_frame, sockets[CLIENT], ZMQ_SNDMORE);
            assert (rc != -1);
            rc = zmq_msg_send (&data_frame, sockets[CLIENT], ZMQ_SNDMORE);
            assert (rc != -1);

            // Release resources.
            rc = zmq_msg_close (&peer_frame);
            assert (rc == 0);
            rc = zmq_msg_close (&data_frame);
            assert (rc == 0);
        }
    }
    assert (step == steps);
    rc = zmq_close (sockets[CLIENT]);
    assert (rc == 0);
    rc = zmq_close (sockets[SERVER]);
    assert (rc == 0);
    rc = zmq_ctx_term (context);
    assert (rc == 0);
    return 0;
}
Example #3
0
/**
 * Called by Java's Socket::getLongSockopt(int option).
 */
JNIEXPORT jlong JNICALL Java_org_zeromq_ZMQ_00024Socket_getLongSockopt (JNIEnv *env,
                                                                        jobject obj,
                                                                        jint option)
{
    switch (option) {
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,0,0)
    case ZMQ_BACKLOG:
    case ZMQ_MAXMSGSIZE:
    case ZMQ_SNDHWM:
    case ZMQ_RCVHWM:
    case ZMQ_MULTICAST_HOPS:
#else
    case ZMQ_HWM:
    case ZMQ_SWAP:
    case ZMQ_MCAST_LOOP:
#endif
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(2,2,0)
    case ZMQ_RCVTIMEO:
    case ZMQ_SNDTIMEO:
#endif
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(2,1,10)
    case ZMQ_RECONNECT_IVL:
    case ZMQ_RECONNECT_IVL_MAX:
#endif
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(2,1,0)
    case ZMQ_TYPE:
    case ZMQ_FD:
    case ZMQ_EVENTS:
    case ZMQ_LINGER:
#endif
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,2,0)
    case ZMQ_TCP_KEEPALIVE:
    case ZMQ_TCP_KEEPALIVE_IDLE:
    case ZMQ_TCP_KEEPALIVE_CNT:
    case ZMQ_TCP_KEEPALIVE_INTVL:
    case ZMQ_IPV4ONLY:
#endif
    case ZMQ_AFFINITY:
    case ZMQ_RATE:
    case ZMQ_RECOVERY_IVL:
    case ZMQ_SNDBUF:
    case ZMQ_RCVBUF:
    case ZMQ_RCVMORE:
        {
            void *s = get_socket (env, obj);
            jlong ret = 0;
            int rc = 0;
            int err = 0;
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,2,0)
            if(
                   (option == ZMQ_TCP_KEEPALIVE)
                || (option == ZMQ_TCP_KEEPALIVE_IDLE)
                || (option == ZMQ_TCP_KEEPALIVE_CNT)
                || (option == ZMQ_TCP_KEEPALIVE_INTVL)
                || (option == ZMQ_IPV4ONLY)
            ) {
                int optval = 0;
                size_t optvallen = sizeof(optval);
                rc = zmq_getsockopt (s, option, &optval, &optvallen);
                ret = (jlong) optval;
            } else
#endif
            {
                uint64_t optval = 0; 
                size_t optvallen = sizeof(optval);
                rc = zmq_getsockopt (s, option, &optval, &optvallen);
                ret = (jlong) optval;
            }
            err = zmq_errno();

            if (rc != 0) {
                raise_exception (env, err);
                return 0L;
            }
            return ret;
        }
    default:
        raise_exception (env, EINVAL);
        return 0L;
    }
}
Example #4
0
void test_stream_2_stream ()
{
    void *rbind, *rconn1;
    int ret;
    char buff[256];
    char msg[] = "hi 1";
    const char *bindip = "tcp://127.0.0.1:*";
    int disabled = 0;
    int zero = 0;
    size_t len = MAX_SOCKET_STRING;
    char my_endpoint[MAX_SOCKET_STRING];
    void *ctx = zmq_ctx_new ();

    //  Set up listener STREAM.
    rbind = zmq_socket (ctx, ZMQ_STREAM);
    assert (rbind);
    ret =
      zmq_setsockopt (rbind, ZMQ_STREAM_NOTIFY, &disabled, sizeof (disabled));
    assert (ret == 0);
    ret = zmq_setsockopt (rbind, ZMQ_LINGER, &zero, sizeof (zero));
    assert (0 == ret);
    ret = zmq_bind (rbind, bindip);
    assert (0 == ret);
    ret = zmq_getsockopt (rbind, ZMQ_LAST_ENDPOINT, my_endpoint, &len);
    assert (0 == ret);

    //  Set up connection stream.
    rconn1 = zmq_socket (ctx, ZMQ_STREAM);
    assert (rconn1);
    ret = zmq_setsockopt (rconn1, ZMQ_LINGER, &zero, sizeof (zero));
    assert (0 == ret);

    //  Do the connection.
    ret = zmq_setsockopt (rconn1, ZMQ_CONNECT_ROUTING_ID, "conn1", 6);
    assert (0 == ret);
    ret = zmq_connect (rconn1, my_endpoint);

    /*  Uncomment to test assert on duplicate routing id.
    //  Test duplicate connect attempt.
    ret = zmq_setsockopt (rconn1, ZMQ_CONNECT_ROUTING_ID, "conn1", 6);
    assert (0 == ret);
    ret = zmq_connect (rconn1, bindip);
    assert (0 == ret);
*/
    //  Send data to the bound stream.
    ret = zmq_send (rconn1, "conn1", 6, ZMQ_SNDMORE);
    assert (6 == ret);
    ret = zmq_send (rconn1, msg, 5, 0);
    assert (5 == ret);

    //  Accept data on the bound stream.
    ret = zmq_recv (rbind, buff, 256, 0);
    assert (ret);
    assert (0 == buff[0]);
    ret = zmq_recv (rbind, buff + 128, 128, 0);
    assert (5 == ret);
    assert ('h' == buff[128]);

    // Handle close of the socket.
    ret = zmq_unbind (rbind, my_endpoint);
    assert (0 == ret);
    ret = zmq_close (rbind);
    assert (0 == ret);
    ret = zmq_close (rconn1);
    assert (0 == ret);

    zmq_ctx_destroy (ctx);
}
bool get_routing_id (void *socket, char *data, size_t *size)
{
    int rc = zmq_getsockopt (socket, ZMQ_ROUTING_ID, data, size);
    return rc == 0;
}
Example #6
0
int zmq_poll (zmq_pollitem_t *items_, int nitems_, long timeout_)
{
#if defined ZMQ_HAVE_POLLER
    // if poller is present, use that if there is at least 1 thread-safe socket,
    // otherwise fall back to the previous implementation as it's faster.
    for (int i = 0; i != nitems_; i++) {
        if (items_[i].socket
            && as_socket_base_t (items_[i].socket)->is_thread_safe ()) {
            return zmq_poller_poll (items_, nitems_, timeout_);
        }
    }
#endif // ZMQ_HAVE_POLLER
#if defined ZMQ_POLL_BASED_ON_POLL || defined ZMQ_POLL_BASED_ON_SELECT
    if (unlikely (nitems_ < 0)) {
        errno = EINVAL;
        return -1;
    }
    if (unlikely (nitems_ == 0)) {
        if (timeout_ == 0)
            return 0;
#if defined ZMQ_HAVE_WINDOWS
        Sleep (timeout_ > 0 ? timeout_ : INFINITE);
        return 0;
#elif defined ZMQ_HAVE_VXWORKS
        struct timespec ns_;
        ns_.tv_sec = timeout_ / 1000;
        ns_.tv_nsec = timeout_ % 1000 * 1000000;
        return nanosleep (&ns_, 0);
#else
        return usleep (timeout_ * 1000);
#endif
    }
    if (!items_) {
        errno = EFAULT;
        return -1;
    }

    zmq::clock_t clock;
    uint64_t now = 0;
    uint64_t end = 0;
#if defined ZMQ_POLL_BASED_ON_POLL
    zmq::fast_vector_t<pollfd, ZMQ_POLLITEMS_DFLT> pollfds (nitems_);

    //  Build pollset for poll () system call.
    for (int i = 0; i != nitems_; i++) {
        //  If the poll item is a 0MQ socket, we poll on the file descriptor
        //  retrieved by the ZMQ_FD socket option.
        if (items_[i].socket) {
            size_t zmq_fd_size = sizeof (zmq::fd_t);
            if (zmq_getsockopt (items_[i].socket, ZMQ_FD, &pollfds[i].fd,
                                &zmq_fd_size)
                == -1) {
                return -1;
            }
            pollfds[i].events = items_[i].events ? POLLIN : 0;
        }
        //  Else, the poll item is a raw file descriptor. Just convert the
        //  events to normal POLLIN/POLLOUT for poll ().
        else {
            pollfds[i].fd = items_[i].fd;
            pollfds[i].events =
              (items_[i].events & ZMQ_POLLIN ? POLLIN : 0)
              | (items_[i].events & ZMQ_POLLOUT ? POLLOUT : 0)
              | (items_[i].events & ZMQ_POLLPRI ? POLLPRI : 0);
        }
    }
#else
    //  Ensure we do not attempt to select () on more than FD_SETSIZE
    //  file descriptors.
    //  TODO since this function is called by a client, we could return errno EINVAL/ENOMEM/... here
    zmq_assert (nitems_ <= FD_SETSIZE);

    zmq::optimized_fd_set_t pollset_in (nitems_);
    FD_ZERO (pollset_in.get ());
    zmq::optimized_fd_set_t pollset_out (nitems_);
    FD_ZERO (pollset_out.get ());
    zmq::optimized_fd_set_t pollset_err (nitems_);
    FD_ZERO (pollset_err.get ());

    zmq::fd_t maxfd = 0;

    //  Build the fd_sets for passing to select ().
    for (int i = 0; i != nitems_; i++) {
        //  If the poll item is a 0MQ socket we are interested in input on the
        //  notification file descriptor retrieved by the ZMQ_FD socket option.
        if (items_[i].socket) {
            size_t zmq_fd_size = sizeof (zmq::fd_t);
            zmq::fd_t notify_fd;
            if (zmq_getsockopt (items_[i].socket, ZMQ_FD, &notify_fd,
                                &zmq_fd_size)
                == -1)
                return -1;
            if (items_[i].events) {
                FD_SET (notify_fd, pollset_in.get ());
                if (maxfd < notify_fd)
                    maxfd = notify_fd;
            }
        }
        //  Else, the poll item is a raw file descriptor. Convert the poll item
        //  events to the appropriate fd_sets.
        else {
            if (items_[i].events & ZMQ_POLLIN)
                FD_SET (items_[i].fd, pollset_in.get ());
            if (items_[i].events & ZMQ_POLLOUT)
                FD_SET (items_[i].fd, pollset_out.get ());
            if (items_[i].events & ZMQ_POLLERR)
                FD_SET (items_[i].fd, pollset_err.get ());
            if (maxfd < items_[i].fd)
                maxfd = items_[i].fd;
        }
    }

    zmq::optimized_fd_set_t inset (nitems_);
    zmq::optimized_fd_set_t outset (nitems_);
    zmq::optimized_fd_set_t errset (nitems_);
#endif

    bool first_pass = true;
    int nevents = 0;

    while (true) {
#if defined ZMQ_POLL_BASED_ON_POLL

        //  Compute the timeout for the subsequent poll.
        zmq::timeout_t timeout =
          zmq::compute_timeout (first_pass, timeout_, now, end);

        //  Wait for events.
        {
            int rc = poll (&pollfds[0], nitems_, timeout);
            if (rc == -1 && errno == EINTR) {
                return -1;
            }
            errno_assert (rc >= 0);
        }
        //  Check for the events.
        for (int i = 0; i != nitems_; i++) {
            items_[i].revents = 0;

            //  The poll item is a 0MQ socket. Retrieve pending events
            //  using the ZMQ_EVENTS socket option.
            if (items_[i].socket) {
                size_t zmq_events_size = sizeof (uint32_t);
                uint32_t zmq_events;
                if (zmq_getsockopt (items_[i].socket, ZMQ_EVENTS, &zmq_events,
                                    &zmq_events_size)
                    == -1) {
                    return -1;
                }
                if ((items_[i].events & ZMQ_POLLOUT)
                    && (zmq_events & ZMQ_POLLOUT))
                    items_[i].revents |= ZMQ_POLLOUT;
                if ((items_[i].events & ZMQ_POLLIN)
                    && (zmq_events & ZMQ_POLLIN))
                    items_[i].revents |= ZMQ_POLLIN;
            }
            //  Else, the poll item is a raw file descriptor, simply convert
            //  the events to zmq_pollitem_t-style format.
            else {
                if (pollfds[i].revents & POLLIN)
                    items_[i].revents |= ZMQ_POLLIN;
                if (pollfds[i].revents & POLLOUT)
                    items_[i].revents |= ZMQ_POLLOUT;
                if (pollfds[i].revents & POLLPRI)
                    items_[i].revents |= ZMQ_POLLPRI;
                if (pollfds[i].revents & ~(POLLIN | POLLOUT | POLLPRI))
                    items_[i].revents |= ZMQ_POLLERR;
            }

            if (items_[i].revents)
                nevents++;
        }

#else

        //  Compute the timeout for the subsequent poll.
        timeval timeout;
        timeval *ptimeout;
        if (first_pass) {
            timeout.tv_sec = 0;
            timeout.tv_usec = 0;
            ptimeout = &timeout;
        } else if (timeout_ < 0)
            ptimeout = NULL;
        else {
            timeout.tv_sec = static_cast<long> ((end - now) / 1000);
            timeout.tv_usec = static_cast<long> ((end - now) % 1000 * 1000);
            ptimeout = &timeout;
        }

        //  Wait for events. Ignore interrupts if there's infinite timeout.
        while (true) {
            memcpy (inset.get (), pollset_in.get (),
                    zmq::valid_pollset_bytes (*pollset_in.get ()));
            memcpy (outset.get (), pollset_out.get (),
                    zmq::valid_pollset_bytes (*pollset_out.get ()));
            memcpy (errset.get (), pollset_err.get (),
                    zmq::valid_pollset_bytes (*pollset_err.get ()));
#if defined ZMQ_HAVE_WINDOWS
            int rc =
              select (0, inset.get (), outset.get (), errset.get (), ptimeout);
            if (unlikely (rc == SOCKET_ERROR)) {
                errno = zmq::wsa_error_to_errno (WSAGetLastError ());
                wsa_assert (errno == ENOTSOCK);
                return -1;
            }
#else
            int rc = select (maxfd + 1, inset.get (), outset.get (),
                             errset.get (), ptimeout);
            if (unlikely (rc == -1)) {
                errno_assert (errno == EINTR || errno == EBADF);
                return -1;
            }
#endif
            break;
        }

        //  Check for the events.
        for (int i = 0; i != nitems_; i++) {
            items_[i].revents = 0;

            //  The poll item is a 0MQ socket. Retrieve pending events
            //  using the ZMQ_EVENTS socket option.
            if (items_[i].socket) {
                size_t zmq_events_size = sizeof (uint32_t);
                uint32_t zmq_events;
                if (zmq_getsockopt (items_[i].socket, ZMQ_EVENTS, &zmq_events,
                                    &zmq_events_size)
                    == -1)
                    return -1;
                if ((items_[i].events & ZMQ_POLLOUT)
                    && (zmq_events & ZMQ_POLLOUT))
                    items_[i].revents |= ZMQ_POLLOUT;
                if ((items_[i].events & ZMQ_POLLIN)
                    && (zmq_events & ZMQ_POLLIN))
                    items_[i].revents |= ZMQ_POLLIN;
            }
            //  Else, the poll item is a raw file descriptor, simply convert
            //  the events to zmq_pollitem_t-style format.
            else {
                if (FD_ISSET (items_[i].fd, inset.get ()))
                    items_[i].revents |= ZMQ_POLLIN;
                if (FD_ISSET (items_[i].fd, outset.get ()))
                    items_[i].revents |= ZMQ_POLLOUT;
                if (FD_ISSET (items_[i].fd, errset.get ()))
                    items_[i].revents |= ZMQ_POLLERR;
            }

            if (items_[i].revents)
                nevents++;
        }
#endif

        //  If timeout is zero, exit immediately whether there are events or not.
        if (timeout_ == 0)
            break;

        //  If there are events to return, we can exit immediately.
        if (nevents)
            break;

        //  At this point we are meant to wait for events but there are none.
        //  If timeout is infinite we can just loop until we get some events.
        if (timeout_ < 0) {
            if (first_pass)
                first_pass = false;
            continue;
        }

        //  The timeout is finite and there are no events. In the first pass
        //  we get a timestamp of when the polling have begun. (We assume that
        //  first pass have taken negligible time). We also compute the time
        //  when the polling should time out.
        if (first_pass) {
            now = clock.now_ms ();
            end = now + timeout_;
            if (now == end)
                break;
            first_pass = false;
            continue;
        }

        //  Find out whether timeout have expired.
        now = clock.now_ms ();
        if (now >= end)
            break;
    }

    return nevents;
#else
    //  Exotic platforms that support neither poll() nor select().
    errno = ENOTSUP;
    return -1;
#endif
}
Example #7
0
void test_router_2_router (bool named_)
{
    void *rbind, *rconn1;
    int ret;
    char buff[256];
    char msg[] = "hi 1";
    const char *bindip = "tcp://127.0.0.1:*";
    int zero = 0;
    size_t len = MAX_SOCKET_STRING;
    char my_endpoint[MAX_SOCKET_STRING];
    void *ctx = zmq_ctx_new ();

    //  Create bind socket.
    rbind = zmq_socket (ctx, ZMQ_ROUTER);
    assert (rbind);
    ret = zmq_setsockopt (rbind, ZMQ_LINGER, &zero, sizeof (zero));
    assert (0 == ret);
    ret = zmq_bind (rbind, bindip);
    assert (0 == ret);
    ret = zmq_getsockopt (rbind, ZMQ_LAST_ENDPOINT, my_endpoint, &len);
    assert (0 == ret);

    //  Create connection socket.
    rconn1 = zmq_socket (ctx, ZMQ_ROUTER);
    assert (rconn1);
    ret = zmq_setsockopt (rconn1, ZMQ_LINGER, &zero, sizeof (zero));
    assert (0 == ret);

    //  If we're in named mode, set some identities.
    if (named_) {
        ret = zmq_setsockopt (rbind, ZMQ_ROUTING_ID, "X", 1);
        ret = zmq_setsockopt (rconn1, ZMQ_ROUTING_ID, "Y", 1);
    }

    //  Make call to connect using a connect_routing_id.
    ret = zmq_setsockopt (rconn1, ZMQ_CONNECT_ROUTING_ID, "conn1", 6);
    assert (0 == ret);
    ret = zmq_connect (rconn1, my_endpoint);
    assert (0 == ret);
    /*  Uncomment to test assert on duplicate routing id
    //  Test duplicate connect attempt.
    ret = zmq_setsockopt (rconn1, ZMQ_CONNECT_ROUTING_ID, "conn1", 6);
    assert (0 == ret);
    ret = zmq_connect (rconn1, bindip);
    assert (0 == ret);
*/
    //  Send some data.
    ret = zmq_send (rconn1, "conn1", 6, ZMQ_SNDMORE);
    assert (6 == ret);
    ret = zmq_send (rconn1, msg, 5, 0);
    assert (5 == ret);

    //  Receive the name.
    ret = zmq_recv (rbind, buff, 256, 0);
    if (named_)
        assert (ret && 'Y' == buff[0]);
    else
        assert (ret && 0 == buff[0]);

    //  Receive the data.
    ret = zmq_recv (rbind, buff + 128, 128, 0);
    assert (5 == ret && 'h' == buff[128]);

    //  Send some data back.
    if (named_) {
        ret = zmq_send (rbind, buff, 1, ZMQ_SNDMORE);
        assert (1 == ret);
    } else {
        ret = zmq_send (rbind, buff, 5, ZMQ_SNDMORE);
        assert (5 == ret);
    }
    ret = zmq_send_const (rbind, "ok", 3, 0);
    assert (3 == ret);

    //  If bound socket identity naming a problem, we'll likely see something funky here.
    ret = zmq_recv (rconn1, buff, 256, 0);
    assert ('c' == buff[0] && 6 == ret);
    ret = zmq_recv (rconn1, buff + 128, 128, 0);
    assert (3 == ret && 'o' == buff[128]);

    ret = zmq_unbind (rbind, my_endpoint);
    assert (0 == ret);
    ret = zmq_close (rbind);
    assert (0 == ret);
    ret = zmq_close (rconn1);
    assert (0 == ret);

    zmq_ctx_destroy (ctx);
}
Example #8
0
int main(int argc, char* argv[])
{
	if (argc >= 2)
		g_sn = argv[1];
	if (argc >= 3)
		g_sip = argv[2];
	if (argc >= 4)
		g_port_req = atoi(argv[3]);
	if (argc >= 5)
		g_port_sub = atoi(argv[4]);

	std::cout << "Device SN: \t" << g_sn << std::endl;
	std::cout << "Server IP: \t" << g_sip << std::endl;
	std::cout << "Port_REQ: \t" << g_port_req << std::endl;
	std::cout << "Port_SUB: \t" << g_port_sub << std::endl;

	enet_initialize();
	
	uv_loop_t *loop = uv_default_loop();

#ifndef RDC_LINUX_SYS
	std::string plugin_folder = GetModuleFilePath() + "\\plugins";
#else
	//std::string plugin_folder = GetModuleFilePath() + "/plugins";
	std::string plugin_folder = "plugins";
#endif
	g_PluginLoader.Load(plugin_folder.c_str());

	g_StreamMgr = new StreamMgr(loop);
	g_StreamMgr->Init();

	void * ctx;
	ctx = zmq_ctx_new();
	assert(ctx);
	int rc = create_req_socket(ctx);
	if (rc != 0)
		exit(EXIT_FAILURE);
	rc = Login();
	if (rc != 0) {
		if (rc == -99) {
			printf("Device SN not authed!\n");
#ifndef RDC_LINUX_SYS
			Sleep(5000);
#else
			sleep(5);
#endif
		}
		exit(EXIT_FAILURE);
	}
	rc = create_sub_socket(ctx);
	if (rc != 0)
		exit(EXIT_FAILURE);
	
	uv_poll_t poll_sub;
	uv_os_sock_t socket;
	size_t len = sizeof(uv_os_sock_t);
	zmq_getsockopt(g_sub_socket, ZMQ_FD, &socket, &len);
	rc = uv_poll_init_socket(loop, &poll_sub, socket);
	assert(rc == 0);
	poll_sub.data = g_sub_socket;
	rc = uv_poll_start(&poll_sub, UV_READABLE, proccss_sub_msg);
	assert(rc == 0);

	uv_timer_t timer;
	rc = uv_timer_init(loop, &timer);
	assert(rc == 0);
	rc = uv_timer_start(&timer, Heartbeat_Timer, 1000, 20 * 1000);
	assert(rc == 0);

	//while (true) {
	//	rc = uv_run(loop, UV_RUN_ONCE);
	//}

	uv_run(loop, UV_RUN_DEFAULT);

	rc = Logout();

	uv_timer_stop(&timer);
	uv_poll_stop(&poll_sub);

	zmq_close(g_req_socket);
	zmq_close(g_sub_socket);
	zmq_ctx_term(ctx);
	
	g_StreamMgr->Close();
	delete g_StreamMgr;
	g_PluginLoader.UnLoad();
	enet_deinitialize();
#ifdef _DEBUG
	system("pause");
#endif
    return 0;
}
Example #9
0
File: blaster.c Project: xrl/zmqhs
void recv_msg(void* sock){
  int retval = 0;
  zmq_msg_t msg;

  // Wow, fun bug. You have to set the identity before bind. No changing identity at runtime?
  #define IDENTITY "blaster.c"
  zmq_setsockopt(sock,ZMQ_IDENTITY,IDENTITY,strlen(IDENTITY));
  retval = zmq_bind(sock,operation.destination);

  if(retval != 0){
    switch(errno){
      case EINVAL:
        puts("zmq_bind EINVAL");
        break;
      case EPROTONOSUPPORT:
        puts("zmq_bind EPROTONOSUPPORT");
        break;
      case ENOCOMPATPROTO:
        puts("zmq_bind ENOCOMPATPROTO");
        break;
      case EADDRINUSE:
        puts("zmq_bind EADDRINUSE");
        break;
      case EADDRNOTAVAIL:
        puts("zmq_bind EADDRNOTAVAIL");
        break;
      case ENODEV:
        puts("zmq_bind ENODEV");
        break;
      case ETERM:
        puts("zmq_bind ETERM");
        break;
      case ENOTSOCK:
        puts("zmq_bind ENOTSOCK");
        break;
      case EMTHREAD:
        puts("zmq_bind EMTHREAD");
        break;
      default:
        puts("zmq_bind errno default");
    }
  }

  char identity[256];
  size_t identity_size;
  zmq_getsockopt(sock,ZMQ_IDENTITY,identity,&identity_size);
  printf("Server up (identity %.*s). Waiting for message.\n",(int)identity_size,identity);

  while(1){
    zmq_msg_init(&msg);

    retval = zmq_recv(sock,&msg,0);
    if(retval != 0){
      switch(errno){
        case EAGAIN:
          puts("zmq_connect EAGAIN");
          break;
        case ENOTSUP:
          puts("zmq_connect ENOTSUP");
          break;
        case EFSM:
          puts("zmq_connect EFSM");
          break;
        case ETERM:
          puts("zmq_connect ETERM");
          break;
        case ENOTSOCK:
          puts("zmq_connect ENOTSOCK");
          break;
        case EINTR:
          puts("zmq_connect EINTR");
          break;
        case EFAULT:
        default:
          puts("zmq_recv errno default");
      }
    }

    #ifdef LOGGING
      printf("Message %d '%.*s' (%d bytes)\n",message_count,(int)zmq_msg_size(&msg),zmq_msg_data(&msg),(int)zmq_msg_size(&msg));
      message_count=message_count+1;
    #endif

    deliver_message(sock,10,0);
    zmq_msg_close(&msg);
  }
}
Example #10
0
int uwsgi_proto_zeromq_accept(struct wsgi_request *wsgi_req, int fd) {

	zmq_msg_t message;
	char *req_uuid = NULL;
	size_t req_uuid_len = 0;
	char *req_id = NULL;
	size_t req_id_len = 0;
	char *req_path = NULL;
	size_t req_path_len = 0;
#ifdef UWSGI_JSON
	json_t *root;
	json_error_t error;
#endif
	char *mongrel2_req = NULL;
	size_t mongrel2_req_size = 0;
	int resp_id_len;
	uint32_t events = 0;
	char *message_ptr;
	size_t message_size = 0;
	char *post_data;


#ifdef ZMQ_EVENTS
	size_t events_len = sizeof(uint32_t);
	if (uwsgi.edge_triggered == 0) {
		if (zmq_getsockopt(pthread_getspecific(uwsgi.zmq_pull), ZMQ_EVENTS, &events, &events_len) < 0) {
			uwsgi_error("zmq_getsockopt()");
			uwsgi.edge_triggered = 0;
			return -1;
		}
	}
#endif

	if (events & ZMQ_POLLIN || uwsgi.edge_triggered) {
		wsgi_req->do_not_add_to_async_queue = 1;
		wsgi_req->proto_parser_status = 0;
		zmq_msg_init(&message);
		if (zmq_recv(pthread_getspecific(uwsgi.zmq_pull), &message, uwsgi.zeromq_recv_flag) < 0) {
			if (errno == EAGAIN) {
				uwsgi.edge_triggered = 0;
			}
			else {
				uwsgi_error("zmq_recv()");
			}
			zmq_msg_close(&message);
			return -1;
		}
		uwsgi.edge_triggered = 1;
		message_size = zmq_msg_size(&message);
		//uwsgi_log("%.*s\n", (int) wsgi_req->proto_parser_pos, zmq_msg_data(&message));
		if (message_size > 0xffff) {
			uwsgi_log("too much big message %d\n", message_size);
			zmq_msg_close(&message);
			wsgi_req->do_not_log = 1;
			return -1;
		}

		message_ptr = zmq_msg_data(&message);

		// warning mongrel2_req_size will contains a bad value, but this is not a problem...
		post_data = uwsgi_split4(message_ptr, message_size, ' ', &req_uuid, &req_uuid_len, &req_id, &req_id_len, &req_path, &req_path_len, &mongrel2_req, &mongrel2_req_size);
		if (post_data == NULL) {
			uwsgi_log("cannot parse message (split4 phase)\n");
			zmq_msg_close(&message);
			wsgi_req->do_not_log = 1;
			return -1;
		}

		// fix post_data, mongrel2_req and mongrel2_req_size
		post_data = uwsgi_netstring(mongrel2_req, message_size - (mongrel2_req - message_ptr), &mongrel2_req, &mongrel2_req_size);
		if (post_data == NULL) {
			uwsgi_log("cannot parse message (body netstring phase)\n");
			zmq_msg_close(&message);
			wsgi_req->do_not_log = 1;
			return -1;
		}

		// ok ready to parse tnetstring/json data and build uwsgi request
		if (mongrel2_req[mongrel2_req_size] == '}') {
			if (uwsgi_mongrel2_tnetstring_parse(wsgi_req, mongrel2_req, mongrel2_req_size)) {
				zmq_msg_close(&message);
				wsgi_req->do_not_log = 1;
				return -1;
			}
		}
		else {
#ifdef UWSGI_JSON
#ifdef UWSGI_DEBUG
			uwsgi_log("JSON %d: %.*s\n", mongrel2_req_size, mongrel2_req_size, mongrel2_req);
#endif
			// add a zero to the end of buf
			mongrel2_req[mongrel2_req_size] = 0;
			root = json_loads(mongrel2_req, 0, &error);
			if (!root) {
				uwsgi_log("error parsing JSON data: line %d %s\n", error.line, error.text);
				zmq_msg_close(&message);
				wsgi_req->do_not_log = 1;
				return -1;
			}

			if (uwsgi_mongrel2_json_parse(root, wsgi_req)) {
				json_decref(root);
				zmq_msg_close(&message);
				wsgi_req->do_not_log = 1;
				return -1;
			}

			json_decref(root);
#else
			uwsgi_log("JSON support not enabled (recompile uWSGI with libjansson support, or re-configure mongrel2 with \"protocol='tnetstring'\". skip request\n");
#endif
		}

		// pre-build the mongrel2 response_header
		wsgi_req->proto_parser_buf = uwsgi_malloc(req_uuid_len + 1 + 11 + 1 + req_id_len + 1 + 1);
		memcpy(wsgi_req->proto_parser_buf, req_uuid, req_uuid_len);
		((char *) wsgi_req->proto_parser_buf)[req_uuid_len] = ' ';
		resp_id_len = uwsgi_num2str2(req_id_len, wsgi_req->proto_parser_buf + req_uuid_len + 1);
		((char *) wsgi_req->proto_parser_buf)[req_uuid_len + 1 + resp_id_len] = ':';

		memcpy((char *) wsgi_req->proto_parser_buf + req_uuid_len + 1 + resp_id_len + 1, req_id, req_id_len);

		memcpy((char *) wsgi_req->proto_parser_buf + req_uuid_len + 1 + resp_id_len + 1 + req_id_len, ", ", 2);
		wsgi_req->proto_parser_pos = (uint64_t) req_uuid_len + 1 + resp_id_len + 1 + req_id_len + 1 + 1;

		// handle post data
		if (wsgi_req->post_cl > 0 && !wsgi_req->async_post) {
			if (uwsgi_netstring(post_data, message_size - (post_data - message_ptr), &message_ptr, &wsgi_req->post_cl)) {
#ifdef UWSGI_DEBUG
				uwsgi_log("post_size: %d\n", wsgi_req->post_cl);
#endif
				wsgi_req->async_post = tmpfile();
				if (fwrite(message_ptr, wsgi_req->post_cl, 1, wsgi_req->async_post) != 1) {
					uwsgi_error("fwrite()");
					zmq_msg_close(&message);
					return -1;
				}
				rewind(wsgi_req->async_post);
				wsgi_req->body_as_file = 1;
			}
		}


		zmq_msg_close(&message);

		return 0;
	}

	return -1;
}
static void
test_stream_handshake_timeout_accept (void)
{
    int rc;

    //  Set up our context and sockets
    void *ctx = zmq_ctx_new ();
    assert (ctx);

    //  We use this socket in raw mode, to make a connection and send nothing
    void *stream = zmq_socket (ctx, ZMQ_STREAM);
    assert (stream);

    int zero = 0;
    rc = zmq_setsockopt (stream, ZMQ_LINGER, &zero, sizeof (zero));
    assert (rc == 0);
    rc = zmq_connect (stream, "tcp://localhost:5557");
    assert (rc == 0);

    //  We'll be using this socket to test TCP stream handshake timeout
    void *dealer = zmq_socket (ctx, ZMQ_DEALER);
    assert (dealer);
    rc = zmq_setsockopt (dealer, ZMQ_LINGER, &zero, sizeof (zero));
    assert (rc == 0);
    int val, tenth = 100;
    size_t vsize = sizeof(val);

    // check for the expected default handshake timeout value - 30 sec
    rc = zmq_getsockopt (dealer, ZMQ_HANDSHAKE_IVL, &val, &vsize);
    assert (rc == 0);
    assert (vsize == sizeof(val));
    assert (val == 30000);
    // make handshake timeout faster - 1/10 sec
    rc = zmq_setsockopt (dealer, ZMQ_HANDSHAKE_IVL, &tenth, sizeof (tenth));
    assert (rc == 0);
    vsize = sizeof(val);
    // make sure zmq_setsockopt changed the value
    rc = zmq_getsockopt (dealer, ZMQ_HANDSHAKE_IVL, &val, &vsize);
    assert (rc == 0);
    assert (vsize == sizeof(val));
    assert (val == tenth);

    //  Create and connect a socket for collecting monitor events on dealer
    void *dealer_mon = zmq_socket (ctx, ZMQ_PAIR);
    assert (dealer_mon);

    rc = zmq_socket_monitor (dealer, "inproc://monitor-dealer",
          ZMQ_EVENT_CONNECTED | ZMQ_EVENT_DISCONNECTED | ZMQ_EVENT_ACCEPTED);
    assert (rc == 0);

    //  Connect to the inproc endpoint so we'll get events
    rc = zmq_connect (dealer_mon, "inproc://monitor-dealer");
    assert (rc == 0);

    // bind dealer socket to accept connection from non-sending stream socket
    rc = zmq_bind (dealer, "tcp://127.0.0.1:5557");
    assert (rc == 0);

    // we should get ZMQ_EVENT_ACCEPTED and then ZMQ_EVENT_DISCONNECTED
    int event = get_monitor_event (dealer_mon, NULL, NULL);
    assert (event == ZMQ_EVENT_ACCEPTED);
    event = get_monitor_event (dealer_mon, NULL, NULL);
    assert (event == ZMQ_EVENT_DISCONNECTED);

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

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

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

    rc = zmq_ctx_term (ctx);
    assert (rc == 0);
}
Example #12
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;
}
Example #13
0
static int Lzmq_getsockopt(lua_State *L)
{
    zmq_ptr *s = luaL_checkudata(L, 1, MT_ZMQ_SOCKET);
    int option = luaL_checkint(L, 2);

    size_t optvallen;

    int rc = 0;

    switch (option) {
#if VERSION_2_1
    case ZMQ_FD:
        {
            socket_t optval;
            optvallen = sizeof(socket_t);
            rc = zmq_getsockopt(s->ptr, option, (void *) &optval, &optvallen);
            if (rc == 0) {
                lua_pushinteger(L, (lua_Integer) optval);
                return 1;
            }
        }
        break;
    case ZMQ_EVENTS:
        {
            int32_t optval;
            optvallen = sizeof(int32_t);
            rc = zmq_getsockopt(s->ptr, option, (void *) &optval, &optvallen);
            if (rc == 0) {
                lua_pushinteger(L, (lua_Integer) optval);
                return 1;
            }
        }
        break;
    case ZMQ_TYPE:
    case ZMQ_LINGER:
    case ZMQ_RECONNECT_IVL:
    case ZMQ_BACKLOG:
        {
            int optval;
            optvallen = sizeof(int);
            rc = zmq_getsockopt(s->ptr, option, (void *) &optval, &optvallen);
            if (rc == 0) {
                lua_pushinteger(L, (lua_Integer) optval);
                return 1;
            }
        }
        break;
#endif
    case ZMQ_SWAP:
    case ZMQ_RATE:
    case ZMQ_RECOVERY_IVL:
    case ZMQ_MCAST_LOOP:
    case ZMQ_RCVMORE:
        {
            int64_t optval;
            optvallen = sizeof(int64_t);
            rc = zmq_getsockopt(s->ptr, option, (void *) &optval, &optvallen);
            if (rc == 0) {
                lua_pushinteger(L, (lua_Integer) optval);
                return 1;
            }
        }
        break;
    case ZMQ_IDENTITY:
        {
            char id[256];
            memset((void *)id, '\0', 256);
            optvallen = 256;
            rc = zmq_getsockopt(s->ptr, option, (void *)id, &optvallen);
            id[255] = '\0';
            if (rc == 0) {
                lua_pushstring(L, id);
                return 1;
            }
        }
        break;
    case ZMQ_HWM:
    case ZMQ_AFFINITY:
    case ZMQ_SNDBUF:
    case ZMQ_RCVBUF:
        {
            uint64_t optval;
            optvallen = sizeof(uint64_t);
            rc = zmq_getsockopt(s->ptr, option, (void *) &optval, &optvallen);
            if (rc == 0) {
                lua_pushinteger(L, (lua_Integer) optval);
                return 1;
            }
        }
        break;
    default:
        rc = -1;
        errno = EINVAL;
    }

    if (rc != 0) {
        return Lzmq_push_error(L);
    }

    lua_pushboolean(L, 1);

    return 1;
}
bool get_identity (void* socket, char* data, size_t* size)
{
    int rc = zmq_getsockopt (socket, ZMQ_IDENTITY, data, size);
    return rc == 0;
}
Example #15
0
int zmq_poll (zmq_pollitem_t *items_, int nitems_, long timeout_)
{
#if defined ZMQ_POLL_BASED_ON_POLL
    if (unlikely (nitems_ < 0)) {
        errno = EINVAL;
        return -1;
    }
    if (unlikely (nitems_ == 0)) {
        if (timeout_ == 0)
            return 0;
#if defined ZMQ_HAVE_WINDOWS
        Sleep (timeout_ > 0 ? timeout_ : INFINITE);
        return 0;
#else
        return usleep (timeout_ * 1000);
#endif
    }

    if (!items_) {
        errno = EFAULT;
        return -1;
    }

    zmq::clock_t clock;
    uint64_t now = 0;
    uint64_t end = 0;

    pollfd *pollfds = (pollfd*) malloc (nitems_ * sizeof (pollfd));
    alloc_assert (pollfds);

    //  Build pollset for poll () system call.
    for (int i = 0; i != nitems_; i++) {

        //  If the poll item is a 0MQ socket, we poll on the file descriptor
        //  retrieved by the ZMQ_FD socket option.
        if (items_ [i].socket) {
            size_t zmq_fd_size = sizeof (zmq::fd_t);
            if (zmq_getsockopt (items_ [i].socket, ZMQ_FD, &pollfds [i].fd,
                &zmq_fd_size) == -1) {
                free (pollfds);
                return -1;
            }
            pollfds [i].events = items_ [i].events ? POLLIN : 0;
        }
        //  Else, the poll item is a raw file descriptor. Just convert the
        //  events to normal POLLIN/POLLOUT for poll ().
        else {
            pollfds [i].fd = items_ [i].fd;
            pollfds [i].events =
                (items_ [i].events & ZMQ_POLLIN ? POLLIN : 0) |
                (items_ [i].events & ZMQ_POLLOUT ? POLLOUT : 0);
        }
    }

    bool first_pass = true;
    int nevents = 0;

    while (true) {

         //  Compute the timeout for the subsequent poll.
         int timeout;
         if (first_pass)
             timeout = 0;
         else if (timeout_ < 0)
             timeout = -1;
         else
             timeout = end - now;

        //  Wait for events.
        while (true) {
            int rc = poll (pollfds, nitems_, timeout);
            if (rc == -1 && errno == EINTR) {
                free (pollfds);
                return -1;
            }
            errno_assert (rc >= 0);
            break;
        }

        //  Check for the events.
        for (int i = 0; i != nitems_; i++) {

            items_ [i].revents = 0;

            //  The poll item is a 0MQ socket. Retrieve pending events
            //  using the ZMQ_EVENTS socket option.
            if (items_ [i].socket) {
                size_t zmq_events_size = sizeof (uint32_t);
                uint32_t zmq_events;
                if (zmq_getsockopt (items_ [i].socket, ZMQ_EVENTS, &zmq_events,
                    &zmq_events_size) == -1) {
                    free (pollfds);
                    return -1;
                }
                if ((items_ [i].events & ZMQ_POLLOUT) &&
                      (zmq_events & ZMQ_POLLOUT))
                    items_ [i].revents |= ZMQ_POLLOUT;
                if ((items_ [i].events & ZMQ_POLLIN) &&
                      (zmq_events & ZMQ_POLLIN))
                    items_ [i].revents |= ZMQ_POLLIN;
            }
            //  Else, the poll item is a raw file descriptor, simply convert
            //  the events to zmq_pollitem_t-style format.
            else {
                if (pollfds [i].revents & POLLIN)
                    items_ [i].revents |= ZMQ_POLLIN;
                if (pollfds [i].revents & POLLOUT)
                    items_ [i].revents |= ZMQ_POLLOUT;
                if (pollfds [i].revents & ~(POLLIN | POLLOUT))
                    items_ [i].revents |= ZMQ_POLLERR;
            }

            if (items_ [i].revents)
                nevents++;
        }

        //  If timout is zero, exit immediately whether there are events or not.
        if (timeout_ == 0)
            break;

        //  If there are events to return, we can exit immediately.
        if (nevents)
            break;

        //  At this point we are meant to wait for events but there are none.
        //  If timeout is infinite we can just loop until we get some events.
        if (timeout_ < 0) {
            if (first_pass)
                first_pass = false;
            continue;
        }

        //  The timeout is finite and there are no events. In the first pass
        //  we get a timestamp of when the polling have begun. (We assume that
        //  first pass have taken negligible time). We also compute the time
        //  when the polling should time out.
        if (first_pass) {
            now = clock.now_ms ();
            end = now + timeout_;
            if (now == end)
                break;
            first_pass = false;
            continue;
        }

        //  Find out whether timeout have expired.
        now = clock.now_ms ();
        if (now >= end)
            break;
    }

    free (pollfds);
    return nevents;

#elif defined ZMQ_POLL_BASED_ON_SELECT

    if (unlikely (nitems_ < 0)) {
        errno = EINVAL;
        return -1;
    }
    if (unlikely (nitems_ == 0)) {
        if (timeout_ == 0)
            return 0;
#if defined ZMQ_HAVE_WINDOWS
        Sleep (timeout_ > 0 ? timeout_ : INFINITE);
        return 0;
#else
        return usleep (timeout_ * 1000);
#endif
    }

    if (!items_) {
        errno = EFAULT;
        return -1;
    }

    zmq::clock_t clock;
    uint64_t now = 0;
    uint64_t end = 0;

    //  Ensure we do not attempt to select () on more than FD_SETSIZE
    //  file descriptors.
    zmq_assert (nitems_ <= FD_SETSIZE);

    fd_set pollset_in;
    FD_ZERO (&pollset_in);
    fd_set pollset_out;
    FD_ZERO (&pollset_out);
    fd_set pollset_err;
    FD_ZERO (&pollset_err);

    zmq::fd_t maxfd = 0;

    //  Build the fd_sets for passing to select ().
    for (int i = 0; i != nitems_; i++) {

        //  If the poll item is a 0MQ socket we are interested in input on the
        //  notification file descriptor retrieved by the ZMQ_FD socket option.
        if (items_ [i].socket) {
            size_t zmq_fd_size = sizeof (zmq::fd_t);
            zmq::fd_t notify_fd;
            if (zmq_getsockopt (items_ [i].socket, ZMQ_FD, &notify_fd,
                &zmq_fd_size) == -1)
                return -1;
            if (items_ [i].events) {
                FD_SET (notify_fd, &pollset_in);
                if (maxfd < notify_fd)
                    maxfd = notify_fd;
            }
        }
        //  Else, the poll item is a raw file descriptor. Convert the poll item
        //  events to the appropriate fd_sets.
        else {
            if (items_ [i].events & ZMQ_POLLIN)
                FD_SET (items_ [i].fd, &pollset_in);
            if (items_ [i].events & ZMQ_POLLOUT)
                FD_SET (items_ [i].fd, &pollset_out);
            if (items_ [i].events & ZMQ_POLLERR)
                FD_SET (items_ [i].fd, &pollset_err);
            if (maxfd < items_ [i].fd)
                maxfd = items_ [i].fd;
        }
    }

    bool first_pass = true;
    int nevents = 0;
    fd_set inset, outset, errset;

    while (true) {

        //  Compute the timeout for the subsequent poll.
        timeval timeout;
        timeval *ptimeout;
        if (first_pass) {
            timeout.tv_sec = 0;
            timeout.tv_usec = 0;
            ptimeout = &timeout;
        }
        else if (timeout_ < 0)
            ptimeout = NULL;
        else {
            timeout.tv_sec = (long) ((end - now) / 1000);
            timeout.tv_usec = (long) ((end - now) % 1000 * 1000);
            ptimeout = &timeout;
        }

        //  Wait for events. Ignore interrupts if there's infinite timeout.
        while (true) {
            memcpy (&inset, &pollset_in, sizeof (fd_set));
            memcpy (&outset, &pollset_out, sizeof (fd_set));
            memcpy (&errset, &pollset_err, sizeof (fd_set));
            int rc = select (maxfd + 1, &inset, &outset, &errset, ptimeout);
#if defined ZMQ_HAVE_WINDOWS
            wsa_assert (rc != SOCKET_ERROR);
#else
            if (rc == -1 && errno == EINTR)
                return -1;
            errno_assert (rc >= 0);
#endif
            break;
        }

        //  Check for the events.
        for (int i = 0; i != nitems_; i++) {

            items_ [i].revents = 0;

            //  The poll item is a 0MQ socket. Retrieve pending events
            //  using the ZMQ_EVENTS socket option.
            if (items_ [i].socket) {
                size_t zmq_events_size = sizeof (uint32_t);
                uint32_t zmq_events;
                if (zmq_getsockopt (items_ [i].socket, ZMQ_EVENTS, &zmq_events,
                      &zmq_events_size) == -1)
                    return -1;
                if ((items_ [i].events & ZMQ_POLLOUT) &&
                      (zmq_events & ZMQ_POLLOUT))
                    items_ [i].revents |= ZMQ_POLLOUT;
                if ((items_ [i].events & ZMQ_POLLIN) &&
                      (zmq_events & ZMQ_POLLIN))
                    items_ [i].revents |= ZMQ_POLLIN;
            }
            //  Else, the poll item is a raw file descriptor, simply convert
            //  the events to zmq_pollitem_t-style format.
            else {
                if (FD_ISSET (items_ [i].fd, &inset))
                    items_ [i].revents |= ZMQ_POLLIN;
                if (FD_ISSET (items_ [i].fd, &outset))
                    items_ [i].revents |= ZMQ_POLLOUT;
                if (FD_ISSET (items_ [i].fd, &errset))
                    items_ [i].revents |= ZMQ_POLLERR;
            }

            if (items_ [i].revents)
                nevents++;
        }

        //  If timout is zero, exit immediately whether there are events or not.
        if (timeout_ == 0)
            break;

        //  If there are events to return, we can exit immediately.
        if (nevents)
            break;

        //  At this point we are meant to wait for events but there are none.
        //  If timeout is infinite we can just loop until we get some events.
        if (timeout_ < 0) {
            if (first_pass)
                first_pass = false;
            continue;
        }

        //  The timeout is finite and there are no events. In the first pass
        //  we get a timestamp of when the polling have begun. (We assume that
        //  first pass have taken negligible time). We also compute the time
        //  when the polling should time out.
        if (first_pass) {
            now = clock.now_ms ();
            end = now + timeout_;
            if (now == end)
                break;
            first_pass = false;
            continue;
        }

        //  Find out whether timeout have expired.
        now = clock.now_ms ();
        if (now >= end)
            break;
    }

    return nevents;

#else
    //  Exotic platforms that support neither poll() nor select().
    errno = ENOTSUP;
    return -1;
#endif
}
Example #16
0
void test_multi_connect (const char *address)
{
    size_t len = MAX_SOCKET_STRING;
    char my_endpoint_0[MAX_SOCKET_STRING];
    char my_endpoint_1[MAX_SOCKET_STRING];
    char my_endpoint_2[MAX_SOCKET_STRING];
    char my_endpoint_3[MAX_SOCKET_STRING * 2];
    void *ctx = zmq_ctx_new ();
    assert (ctx);

    int ipv6;
    if (streq (address, "tcp://127.0.0.1:*"))
        ipv6 = 0;
    else if (streq (address, "tcp://[::1]:*"))
        ipv6 = 1;
    else
        assert (false);

    if (ipv6 && !is_ipv6_available ()) {
        zmq_ctx_term (ctx);
        return;
    }

    void *sb0 = zmq_socket (ctx, ZMQ_REP);
    assert (sb0);
    int rc = zmq_setsockopt (sb0, ZMQ_IPV6, &ipv6, sizeof (int));
    assert (rc == 0);
    rc = zmq_bind (sb0, address);
    assert (rc == 0);
    rc = zmq_getsockopt (sb0, ZMQ_LAST_ENDPOINT, my_endpoint_0, &len);
    assert (rc == 0);

    void *sb1 = zmq_socket (ctx, ZMQ_REP);
    assert (sb1);
    rc = zmq_setsockopt (sb1, ZMQ_IPV6, &ipv6, sizeof (int));
    assert (rc == 0);
    rc = zmq_bind (sb1, address);
    assert (rc == 0);
    len = MAX_SOCKET_STRING;
    rc = zmq_getsockopt (sb1, ZMQ_LAST_ENDPOINT, my_endpoint_1, &len);
    assert (rc == 0);

    void *sb2 = zmq_socket (ctx, ZMQ_REP);
    assert (sb2);
    rc = zmq_setsockopt (sb2, ZMQ_IPV6, &ipv6, sizeof (int));
    assert (rc == 0);
    rc = zmq_bind (sb2, address);
    assert (rc == 0);
    len = MAX_SOCKET_STRING;
    rc = zmq_getsockopt (sb2, ZMQ_LAST_ENDPOINT, my_endpoint_2, &len);
    assert (rc == 0);

    void *sc = zmq_socket (ctx, ZMQ_REQ);
    assert (sc);
    rc = zmq_setsockopt (sc, ZMQ_IPV6, &ipv6, sizeof (int));
    assert (rc == 0);
    rc = zmq_connect (sc, my_endpoint_0);
    assert (rc == 0);
    rc = zmq_connect (sc, my_endpoint_1);
    assert (rc == 0);
    if (!ipv6)
        sprintf (my_endpoint_3, "tcp://127.0.0.1:5564;%s",
                 strrchr (my_endpoint_2, '/') + 1);
    else
        sprintf (my_endpoint_3, "tcp://[::1]:5564;%s",
                 strrchr (my_endpoint_2, '/') + 1);
    rc = zmq_connect (sc, my_endpoint_3);
    assert (rc == 0);

    bounce (sb0, sc);
    bounce (sb1, sc);
    bounce (sb2, sc);
    bounce (sb0, sc);
    bounce (sb1, sc);
    bounce (sb2, sc);
    bounce (sb0, sc);

    rc = zmq_disconnect (sc, my_endpoint_0);
    assert (rc == 0);
    rc = zmq_disconnect (sc, my_endpoint_3);
    assert (rc == 0);
    rc = zmq_disconnect (sc, my_endpoint_1);
    assert (rc == 0);

    rc = zmq_unbind (sb0, my_endpoint_0);
    assert (rc == 0);

    rc = zmq_unbind (sb1, my_endpoint_1);
    assert (rc == 0);

    rc = zmq_unbind (sb2, my_endpoint_2);
    assert (rc == 0);

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

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

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

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

    rc = zmq_ctx_term (ctx);
    assert (rc == 0);
}
Example #17
0
int
main (int argc, char **argv)
{
    int i, opt, thread = 1;
    char *command = NULL;
    char *frontendpoint = ZLMB_WORKER_SOCKET, *backendpoint = NULL;
    void *context, *frontend = NULL, *backend = NULL;
    zlmb_worker_t **worker = NULL;
    size_t size;

    const struct option long_options[] = {
        { "endpoint", 1, NULL, 'e' },
        { "command", 1, NULL, 'c' },
        { "thread", 1, NULL, 't' },
        { "syslog", 0, NULL, 's' },
        { "verbose", 0, NULL, 'v' },
        { "help", 0, NULL, 'h' },
        { NULL, 0, NULL, 0 }
    };

    while ((opt = getopt_long(argc, argv,
                              "e:c:t:svh", long_options, NULL)) != -1) {
        switch (opt) {
            case 'e':
                frontendpoint = optarg;
                break;
            case 'c':
                command = optarg;
                break;
            case 't':
                thread = atoi(optarg);
                break;
            case 's':
                _syslog = 1;
                break;
            case 'v':
                _verbose = 1;
                break;
            default:
                _usage(argv[0], NULL);
                return -1;
        }
    }

    _LOG_OPEN(ZLMB_SYSLOG_IDENT);

    _INFO("Connect endpoint: %s\n", frontendpoint);
    _INFO("Execute command: %s\n", command);
    _INFO("Thread count: %d\n", thread);

    context = zmq_ctx_new();
    if (!context) {
        _ERR("ZeroMQ context: %s\n", zmq_strerror(errno));
        _LOG_CLOSE();
        return -1;
    }

    /*
    if (zmq_ctx_set(context, ZMQ_IO_THREADS, 1) == -1) {
        _ERR("%s", zmq_strerror(errno));
        zmq_ctx_destroy(context);
        return -1;
    }

    if (zmq_ctx_set(context, ZMQ_MAX_SOCKETS, 1024) == -1) {
        _ERR("%s",  zmq_strerror(errno));
        zmq_ctx_destroy(context);
        return -1;
    }
    */

    /* backend: command */
    if (command) {
        backend = zmq_socket(context, ZMQ_PUSH);
        if (!backend) {
            _ERR("ZeroMQ backend socket: %s\n", zmq_strerror(errno));
            zmq_ctx_destroy(context);
            _LOG_CLOSE();
            return -1;
        }

        if (zlmb_utils_asprintf(&backendpoint, "%s.%d",
                                ZLMB_WORKER_BACKEND_SOCKET, getpid()) == -1) {
            _ERR("Allocate string backend point.\n");
            zmq_ctx_destroy(context);
            _LOG_CLOSE();
            return -1;
        }

        if (zmq_bind(backend, backendpoint) == -1) {
            _ERR("ZeroMQ backend bind: %s: %s\n",
                 backendpoint, zmq_strerror(errno));
            zmq_close(backend);
            zmq_ctx_destroy(context);
            _LOG_CLOSE();
            return -1;
        }

        _VERBOSE("ZeroMQ backend bind: %s\n", backendpoint);

        /* backend: command thread */
        if (thread <= 0) {
            thread = 1;
        }

        size = sizeof(zlmb_worker_t *) * thread;
        worker = (zlmb_worker_t **)malloc(size);
        if (!worker) {
            _ERR("Memory allocate worker command.\n");
            zmq_close(backend);
            zmq_ctx_destroy(context);
            free(backendpoint);
            _LOG_CLOSE();
            return -1;
        }

        memset(worker, 0, size);

        for (i = 0; i != thread; i++) {
            worker[i] = (zlmb_worker_t *)malloc(sizeof(zlmb_worker_t));
            if (!worker[i]) {
                _ERR("Memory allocate worker command.\n");
                _worker_destroy(worker, thread, 500);
                zmq_close(backend);
                zmq_ctx_destroy(context);
                free(backendpoint);
                return -1;
            }

            worker[i]->thread = 0;
            worker[i]->context = context;
            worker[i]->command = command;
            worker[i]->endpoint = backendpoint;
            worker[i]->argv = argv;
            worker[i]->argc = argc;
            worker[i]->optind = optind;

            if (pthread_create(&(worker[i]->thread), NULL,
                               _worker_command, (void *)worker[i]) == -1) {
                _ERR("Create command worker thread(#%d).\n", i+1);
                _worker_destroy(worker, thread, 500);
                zmq_close(backend);
                zmq_ctx_destroy(context);
                free(backendpoint);
                _LOG_CLOSE();
                return -1;
            }
        }
    }

    /* frontend */
    frontend = zmq_socket(context, ZMQ_PULL);
    if (!frontend) {
        _ERR("ZeroMQ frontend socket: %s\n", zmq_strerror(errno));
        if (worker) {
            _worker_destroy(worker, thread, 500);
            zmq_close(backend);
            free(backendpoint);
        }
        zmq_ctx_destroy(context);
        _LOG_CLOSE();
        return -1;
    }

    if (zmq_connect(frontend, frontendpoint) == -1) {
        _ERR("ZeroMQ frontend connect: %s: %s\n",
             frontendpoint, zmq_strerror(errno));
        if (worker) {
            _worker_destroy(worker, thread, 500);
            zmq_close(backend);
            free(backendpoint);
        }
        zmq_close(frontend);
        zmq_ctx_destroy(context);
        _LOG_CLOSE();
        return -1;
    }

    _VERBOSE("ZeroMQ frontend connect: %s\n", frontendpoint);

    _signals();

    _VERBOSE("ZeroMQ start proxy.\n");

    if (backend) {
        zmq_proxy(frontend, backend, NULL);
    } else {
        zmq_pollitem_t pollitems[] = { { frontend, 0, ZMQ_POLLIN, 0 } };

        _NOTICE("default receive process.\n");

        while (!_interrupted) {
            if (zmq_poll(pollitems, 1, -1) == -1) {
                break;
            }

            if (pollitems[0].revents & ZMQ_POLLIN) {
                int more;
                size_t moresz = sizeof(more);

                _DEBUG("ZeroMQ receive in poll event.\n");

                while (!_interrupted) {
                    zmq_msg_t zmsg;

                    if (zmq_msg_init(&zmsg) != 0) {
                        break;
                    }

                    _DEBUG("ZeroMQ receive message.\n");

                    if (zmq_recvmsg(frontend, &zmsg, 0) == -1) {
                        _ERR("ZeroMQ frontend socket receive: %s\n",
                             zmq_strerror(errno));
                        zmq_msg_close(&zmsg);
                        break;
                    }

                    if (zmq_getsockopt(frontend, ZMQ_RCVMORE,
                                       &more, &moresz) == -1) {
                        _ERR("ZeroMQ frontend socket option receive: %s\n",
                             zmq_strerror(errno));
                        //zmq_msg_close(&zmsg);
                        //break;
                        more = 0;
                    }
#ifndef NDEBUG
                    zlmb_dump_printmsg(stderr, &zmsg);
#endif
                    zmq_msg_close(&zmsg);

                    if (!more) {
                        break;
                    }
                }
            }
        }
    }

    _VERBOSE("ZeroMQ end proxy.\n");

    _VERBOSE("ZeroMQ close sockets.\n");

    zmq_close(frontend);

    if (worker) {
        _worker_destroy(worker, thread, 0);
        zmq_close(backend);
        free(backendpoint);
    }

    _VERBOSE("ZeroMQ destory context.\n");

    zmq_ctx_destroy(context);

    _LOG_CLOSE();

    return 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);
    size_t len = MAX_SOCKET_STRING;
    rc = zmq_getsockopt (req, ZMQ_LAST_ENDPOINT, connect_address, &len);
    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 = 250;
        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.
    msleep (SETTLE_TIME);

    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.
    msleep (SETTLE_TIME);
}
Example #19
0
static void *
_worker_command(void *arg)
{
    zlmb_worker_t *worker = (zlmb_worker_t *)arg;
    zmq_pollitem_t pollitems[] = { { NULL, 0, ZMQ_POLLIN, 0 } };
    void *socket;

    if (!worker || !worker->context || !worker->command) {
        _ERR("Function arguments: %s\n", __FUNCTION__);
        return NULL;
    }

    socket = zmq_socket(worker->context, ZMQ_PULL);
    if (!socket) {
        _ERR("ZeroMQ socket: %s\n", zmq_strerror(errno));
        return NULL;
    }

    if (zmq_connect(socket, worker->endpoint) == -1) {
        _ERR("ZeroMQ socket connect: %s: %s\n",
             worker->endpoint, zmq_strerror(errno));
        zmq_close(socket);
        return NULL;
    }

    _VERBOSE("ZeroMQ socket connect: %s\n", worker->endpoint);

    _VERBOSE("ZeroMQ start worker command proxy.\n");

    pollitems[0].socket = socket;

    _signals();

    while (!_interrupted) {
        if (zmq_poll(pollitems, 1, -1) == -1) {
            break;
        }

        if (pollitems[0].revents & ZMQ_POLLIN) {
            int more;
            size_t moresz = sizeof(more);
            zlmb_spawn_t spawn = { NULL, NULL, NULL, NULL };

            _DEBUG("ZeroMQ receive in poll event.\n");

            spawn.stack = zlmb_stack_init();
            if (!spawn.stack) {
                _ERR("Message stack initilize.\n");
                break;
            }

            while (!_interrupted) {
                zmq_msg_t *zmsg = (zmq_msg_t *)malloc(sizeof(zmq_msg_t));
                if (!zmsg) {
                    break;
                }

                _DEBUG("ZeroMQ receive message.\n");

                if (zmq_msg_init(zmsg) != 0) {
                    break;
                }

                if (zmq_recvmsg(socket, zmsg, 0) == -1) {
                    _ERR("ZeroMQ socket receive: %s\n", zmq_strerror(errno));
                    zmq_msg_close(zmsg);
                    free(zmsg);
                    break;
                }

                if (zmq_getsockopt(socket, ZMQ_RCVMORE, &more, &moresz) == -1) {
                    _ERR("ZeroMQ socket option receive: %s\n",
                         zmq_strerror(errno));
                    more = 0;
                }

                if (zlmb_stack_push(spawn.stack, zmsg) != 0) {
                    _ERR("Message stack push.\n");
                }

                if (!more) {
                    break;
                }
            }

            //env
            _spawn_generate_environ(&spawn);

            //spawn
            _spawn_run(&spawn, worker->command,
                       worker->argc, worker->argv, worker->optind);

            _spawn_destroy(&spawn);
        }
    }

    _VERBOSE("ZeroMQ end worker command proxy.\n");

    zmq_close(socket);

    return NULL;
}
	Bool HawkZmqManager::ProxyZmq(HawkZmq* pFrontend, HawkZmq* pBackend, Bool bBothway, Int32 iTimeout, Bool bOnce)
	{
		HawkAssert(pFrontend && pBackend);
		if (!pFrontend || !pBackend)
			return false;		

		zmq_pollitem_t items[] = 
		{
			{ pFrontend->GetHandle(), 0, 0, 0 },
			{ pBackend->GetHandle(),  0, 0, 0 }
		};
		
		items[0].events = ZMQ_POLLIN;
		if (bBothway)
			items[1].events = ZMQ_POLLIN;

		do
		{
			items[0].revents = 0;
			items[1].revents = 0;

			if (zmq_poll(items, 2, iTimeout) < 0)
				return false;

			if (items[0].revents & ZMQ_POLLIN) 
			{
				zmq_msg_t sMsg;
				if (zmq_msg_init(&sMsg) != HAWK_OK)
					return false;

				while (true) 
				{
					if (zmq_recvmsg(items[0].socket, &sMsg, 0) < 0)
					{
						zmq_msg_close(&sMsg);
						return false;
					}

					Int32  iRecvMore = 0;
					Size_t iLen = sizeof(iRecvMore);
					if (zmq_getsockopt(items[0].socket, ZMQ_RCVMORE, &iRecvMore, &iLen) < 0)
					{
						zmq_msg_close(&sMsg);
						return false;
					}

					if (zmq_sendmsg(items[1].socket, &sMsg, iRecvMore? ZMQ_SNDMORE : 0) < 0)
					{
						zmq_msg_close(&sMsg);
						return false;
					}

					if (iRecvMore == 0)
						break;
				}

				//ÊÍ·ÅÏûÏ¢
				zmq_msg_close(&sMsg);				
			}
		
			if (items[1].revents & ZMQ_POLLIN) 
			{
				zmq_msg_t sMsg;
				if (zmq_msg_init(&sMsg) != HAWK_OK)
					return false;

				while (true) 
				{
					if (zmq_recvmsg(items[1].socket, &sMsg, 0) < 0)
					{
						zmq_msg_close(&sMsg);
						return false;
					}

					Int32  iRecvMore = 0;
					Size_t iLen = sizeof(iRecvMore);
					if (zmq_getsockopt(items[1].socket, ZMQ_RCVMORE, &iRecvMore, &iLen) < 0)
					{
						zmq_msg_close(&sMsg);
						return false;
					}

					if (zmq_sendmsg(items[0].socket, &sMsg, iRecvMore? ZMQ_SNDMORE: 0) < 0)
					{
						zmq_msg_close(&sMsg);
						return false;
					}

					if (iRecvMore == 0)
						break;
				}

				zmq_msg_close(&sMsg);
			}
		}while(!bOnce);
		
		return true;
	}
int main (void)
{
    size_t len = MAX_SOCKET_STRING;
    char my_endpoint_0[MAX_SOCKET_STRING];
    char my_endpoint_1[MAX_SOCKET_STRING];

    setup_test_environment ();

    void *ctx = zmq_ctx_new ();
    assert (ctx);

    //  Create few sockets
    void *vent = zmq_socket (ctx, ZMQ_PUSH);
    assert (vent);
    int rc = zmq_bind (vent, "tcp://127.0.0.1:*");
    assert (rc == 0);
    rc = zmq_getsockopt (vent, ZMQ_LAST_ENDPOINT, my_endpoint_0, &len);
    assert (rc == 0);

    void *sink = zmq_socket (ctx, ZMQ_PULL);
    assert (sink);
    rc = zmq_connect (sink, my_endpoint_0);
    assert (rc == 0);

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

#if defined(ZMQ_SERVER) && defined(ZMQ_CLIENT)
    void *server = zmq_socket (ctx, ZMQ_SERVER);
    assert (server);
    rc = zmq_bind (server, "tcp://127.0.0.1:*");
    assert (rc == 0);
    len = MAX_SOCKET_STRING;
    rc = zmq_getsockopt (server, ZMQ_LAST_ENDPOINT, my_endpoint_1, &len);
    assert (rc == 0);

    void *client = zmq_socket (ctx, ZMQ_CLIENT);
    assert (client);
#endif

    //  Set up poller
    void* poller = zmq_poller_new ();
    zmq_poller_event_t event;

    // waiting on poller with no registered sockets should report error
    rc = zmq_poller_wait(poller, &event, 0);
    assert (rc == -1);
    assert (errno == ETIMEDOUT);

    // register sink
    rc = zmq_poller_add (poller, sink, sink, ZMQ_POLLIN);
    assert (rc == 0);
    
    //  Send a message
    char data[1] = {'H'};
    rc = zmq_send_const (vent, data, 1, 0);
    assert (rc == 1);   

    //  We expect a message only on the sink
    rc = zmq_poller_wait (poller, &event, -1);
    assert (rc == 0);
    assert (event.socket == sink);
    assert (event.user_data == sink);
    rc = zmq_recv (sink, data, 1, 0);
    assert (rc == 1);

    //  We expect timed out
    rc = zmq_poller_wait (poller, &event, 0);
    assert (rc == -1);
    assert (errno == ETIMEDOUT);

    //  Stop polling sink
    rc = zmq_poller_remove (poller, sink);
    assert (rc == 0);

    //  Check we can poll an FD
    rc = zmq_connect (bowl, my_endpoint_0);
    assert (rc == 0);

#if defined _WIN32
    SOCKET fd;
    size_t fd_size = sizeof (SOCKET);
#else 
    int fd;
    size_t fd_size = sizeof (int);
#endif

    rc = zmq_getsockopt (bowl, ZMQ_FD, &fd, &fd_size);
    assert (rc == 0);
    rc = zmq_poller_add_fd (poller, fd, bowl, ZMQ_POLLIN);
    assert (rc == 0);
    rc = zmq_poller_wait (poller, &event, 500);
    assert (rc == 0);
    assert (event.socket == NULL);
    assert (event.fd == fd);
    assert (event.user_data == bowl);
    zmq_poller_remove_fd (poller, fd);

#if defined(ZMQ_SERVER) && defined(ZMQ_CLIENT)
    //  Polling on thread safe sockets
    rc = zmq_poller_add (poller, server, NULL, ZMQ_POLLIN);
    assert (rc == 0);
    rc = zmq_connect (client, my_endpoint_1);
    assert (rc == 0);
    rc = zmq_send_const (client, data, 1, 0);
    assert (rc == 1);
    rc = zmq_poller_wait (poller, &event, 500);
    assert (rc == 0);
    assert (event.socket == server);
    assert (event.user_data == NULL); 
    rc = zmq_recv (server, data, 1, 0);
    assert (rc == 1);    

    //  Polling on pollout
    rc = zmq_poller_modify (poller, server, ZMQ_POLLOUT | ZMQ_POLLIN); 
    assert (rc == 0);
    rc = zmq_poller_wait (poller, &event, 0);
    assert (rc == 0);
    assert (event.socket == server);
    assert (event.user_data == NULL);
    assert (event.events == ZMQ_POLLOUT);

    //  Stop polling server
    rc = zmq_poller_remove (poller, server);
    assert (rc == 0);
#endif

    //  Destory sockets, poller and ctx    
    rc = zmq_close (sink);
    assert (rc == 0);
    rc = zmq_close (vent);
    assert (rc == 0);
    rc = zmq_close (bowl);
    assert (rc == 0);
#if defined(ZMQ_SERVER) && defined(ZMQ_CLIENT)
    rc = zmq_close (server);
    assert (rc == 0);
    rc = zmq_close (client);
    assert (rc == 0);
#endif

    // Test error - null poller pointers
    rc = zmq_poller_destroy (NULL);
    assert (rc == -1 && errno == EFAULT);
    void *null_poller = NULL;
    rc = zmq_poller_destroy (&null_poller);
    assert (rc == -1 && errno == EFAULT);

    rc = zmq_poller_destroy (&poller);
    assert(rc == 0);
    rc = zmq_ctx_term (ctx);
    assert (rc == 0);

    return 0;
}
Example #22
0
static void 
zmqdrv_getsockopt(zmq_drv_t *drv, ErlIOVec *ev)
{
    ErlDrvBinary*   bin   = ev->binv[1];
    char*           bytes = bin->orig_bytes;
    uint32_t        idx   = ntohl(*(uint32_t*)(bytes+1));
    void*           s     = drv->get_zmq_socket(idx);
    zmq_sock_info*  si    = drv->get_socket_info(idx);
    uint32_t        opt   = ntohl (*(uint32_t*)(bytes+sizeof(idx)+1));
    union {
        uint8_t  a[255];
        uint64_t ui64;
        int64_t  i64;
        int      i;
        uint32_t ui;
    } val;
    size_t vallen;

    if (idx > drv->zmq_socket_count || !s || !si) {
        zmqdrv_error_code(drv, ENODEV);
        return;
    }

    zmqdrv_fprintf("setsockopt %p (setting %d options)\r\n", si->socket, (int)n);

    switch (opt) {
        case ZMQ_AFFINITY:
            vallen = sizeof(uint64_t);
            if (zmq_getsockopt(s, opt, &val.ui64, &vallen) < 0)
                zmqdrv_error_code(drv, zmq_errno());
            zmqdrv_ok_int64(drv, driver_caller(drv->port), val.ui64);
            break;
        case ZMQ_BACKLOG:
            vallen = sizeof(int);
            if (zmq_getsockopt(s, opt, &val.i, &vallen) < 0)
                zmqdrv_error_code(drv, zmq_errno());
            zmqdrv_ok_int64(drv, driver_caller(drv->port), val.i);
            break;
        case ZMQ_EVENTS:
            vallen = sizeof(uint32_t);
            if (zmq_getsockopt(s, opt, &val.ui, &vallen) < 0)
                zmqdrv_error_code(drv, zmq_errno());
            zmqdrv_ok_int64(drv, driver_caller(drv->port), val.ui);
            break;
        case ZMQ_FD:
            vallen = sizeof(int);
            if (zmq_getsockopt(s, opt, &val.i, &vallen) < 0)
                zmqdrv_error_code(drv, zmq_errno());
            zmqdrv_ok_int64(drv, driver_caller(drv->port), val.i);
            break;
        case ZMQ_HWM:
            vallen = sizeof(uint64_t);
            if (zmq_getsockopt(s, opt, &val.ui64, &vallen) < 0)
                zmqdrv_error_code(drv, zmq_errno());
            zmqdrv_ok_int64(drv, driver_caller(drv->port), val.ui64);
            break;
        case ZMQ_IDENTITY:
            vallen = sizeof(val);
            if (zmq_getsockopt(s, opt, val.a, &vallen) < 0)
                zmqdrv_error_code(drv, zmq_errno());
            zmqdrv_ok_binary(drv, driver_caller(drv->port), val.a, vallen);
            break;
        case ZMQ_LINGER:
            vallen = sizeof(int);
            if (zmq_getsockopt(s, opt, &val.i, &vallen) < 0)
                zmqdrv_error_code(drv, zmq_errno());
            zmqdrv_ok_bool(drv, driver_caller(drv->port), !!val.i);
            break;
        case ZMQ_MCAST_LOOP:
            vallen = sizeof(int64_t);
            if (zmq_getsockopt(s, opt, &val.i64, &vallen) < 0)
                zmqdrv_error_code(drv, zmq_errno());
            zmqdrv_ok_bool(drv, driver_caller(drv->port), !!val.i64);
            break;
        case ZMQ_RATE:
            vallen = sizeof(int64_t);
            if (zmq_getsockopt(s, opt, &val.i64, &vallen) < 0)
                zmqdrv_error_code(drv, zmq_errno());
            zmqdrv_ok_int64(drv, driver_caller(drv->port), val.i64);
            break;
        case ZMQ_RCVBUF:
            vallen = sizeof(uint64_t);
            if (zmq_getsockopt(s, opt, &val.ui64, &vallen) < 0)
                zmqdrv_error_code(drv, zmq_errno());
            zmqdrv_ok_int64(drv, driver_caller(drv->port), val.ui64);
            break;
        case ZMQ_RCVMORE:
            vallen = sizeof(int64_t);
            if (zmq_getsockopt(s, opt, &val.i64, &vallen) < 0)
                zmqdrv_error_code(drv, zmq_errno());
            zmqdrv_ok_bool(drv, driver_caller(drv->port), !!val.i64);
            break;
        case ZMQ_RECONNECT_IVL:
            vallen = sizeof(int);
            if (zmq_getsockopt(s, opt, &val.i, &vallen) < 0)
                zmqdrv_error_code(drv, zmq_errno());
            zmqdrv_ok_int64(drv, driver_caller(drv->port), val.i);
            break;
        case ZMQ_RECOVERY_IVL:
            vallen = sizeof(int64_t);
            if (zmq_getsockopt(s, opt, &val.i64, &vallen) < 0)
                zmqdrv_error_code(drv, zmq_errno());
            zmqdrv_ok_int64(drv, driver_caller(drv->port), val.i64);
            break;
        case ZMQ_RECOVERY_IVL_MSEC:
            vallen = sizeof(int64_t);
            if (zmq_getsockopt(s, opt, &val.i64, &vallen) < 0)
                zmqdrv_error_code(drv, zmq_errno());
            zmqdrv_ok_int64(drv, driver_caller(drv->port), val.i64);
            break;
        case ZMQ_SNDBUF:
            vallen = sizeof(uint64_t);
            if (zmq_getsockopt(s, opt, &val.ui64, &vallen) < 0)
                zmqdrv_error_code(drv, zmq_errno());
            zmqdrv_ok_int64(drv, driver_caller(drv->port), val.ui64);
            break;
        case ZMQ_SWAP:
            vallen = sizeof(int64_t);
            if (zmq_getsockopt(s, opt, &val.i64, &vallen) < 0)
                zmqdrv_error_code(drv, zmq_errno());
            zmqdrv_ok_int64(drv, driver_caller(drv->port), val.i64);
            break;
        case ZMQ_TYPE:
            vallen = sizeof(int);
            if (zmq_getsockopt(s, opt, &val.i, &vallen) < 0)
                zmqdrv_error_code(drv, zmq_errno());
            zmqdrv_ok_int64(drv, driver_caller(drv->port), val.i);
            break;
        case ZMQ_ACTIVE:
            zmqdrv_ok_bool(drv, driver_caller(drv->port), si->active_mode);
            break;
        default:
            zmqdrv_error(drv, "Option not implemented!");
            return;
    }
}
Example #23
-1
static void
zmqdrv_ready_input(ErlDrvData handle, ErlDrvEvent event)
{
    zmq_drv_t *drv = (zmq_drv_t *)handle;

    // Get 0MQ sockets managed by application thread's signaler
    // identified by "event" fd.
    zmq_fd_sockets_map_t::iterator it = drv->zmq_fd_sockets.find((long)event);

    zmqdrv_fprintf("input ready on [idx=%ld]\r\n", (long)event);

    assert(it != drv->zmq_fd_sockets.end());

    zmq_sock_set_t::iterator si = it->second.begin();

    assert(si != it->second.end());

    for (; si != it->second.end(); ++si) {
        zmq_socket_t   s     = (*si)->socket;
        uint32_t       idx   = (*si)->idx;
        ErlDrvTermData owner = (*si)->owner;
        int            rc    = 0;
        uint32_t       events;
        size_t         events_size = sizeof(events);

        zmq_getsockopt(s, ZMQ_EVENTS, &events, &events_size);

        while (((*si)->active_mode || (*si)->in_caller) && (events & ZMQ_POLLIN)) {
            msg_t msg;

            rc = zmq_recv(s, &msg, ZMQ_NOBLOCK);

            ErlDrvTermData pid = (*si)->active_mode ? owner : (*si)->in_caller;

            if (rc == -1) {
                if (zmq_errno() != EAGAIN) {
                    ErlDrvTermData spec[] =
                        {ERL_DRV_ATOM,  am_zmq,
                         ERL_DRV_UINT,  idx,
                         ERL_DRV_ATOM,  error_atom(zmq_errno()),
                         ERL_DRV_TUPLE, 2,
                         ERL_DRV_TUPLE, 3};
                    driver_send_term(drv->port, owner, spec, sizeof(spec)/sizeof(spec[0]));
                    (*si)->in_caller = 0;
                }
                break;
            }

            if ((*si)->active_mode) {
                // Send message {zmq, Socket, binary()} to the owner pid
                ErlDrvTermData spec[] =
                    {ERL_DRV_ATOM,  am_zmq,
                     ERL_DRV_UINT,  idx,
                     ERL_DRV_BUF2BINARY, (ErlDrvTermData)zmq_msg_data(&msg), zmq_msg_size(&msg),
                     ERL_DRV_TUPLE, 3};
                driver_send_term(drv->port, owner, spec, sizeof(spec)/sizeof(spec[0]));
            } else {
                // Return result {ok, binary()} to the waiting caller's pid
                ErlDrvTermData spec[] = 
                    {ERL_DRV_ATOM,   am_zok,
                     ERL_DRV_BUF2BINARY, (ErlDrvTermData)zmq_msg_data(&msg), zmq_msg_size(&msg),
                     ERL_DRV_TUPLE, 2};
                driver_send_term(drv->port, pid, spec, sizeof(spec)/sizeof(spec[0]));
                (*si)->in_caller = 0;
            }

            // FIXME: add error handling
            zmqdrv_fprintf("received %ld byte message relayed to pid %ld\r\n", zmq_msg_size(&msg), pid);
            zmq_getsockopt(s, ZMQ_EVENTS, &events, &events_size);
        }
    
        zmq_getsockopt(s, ZMQ_EVENTS, &events, &events_size);

        if ((*si)->out_caller != 0 && (events & ZMQ_POLLOUT)) {
            // There was a pending unwritten message on this socket.
            // Try to write it.  If the write succeeds/fails clear the ZMQ_POLLOUT
            // flag and notify the waiting caller of completion of operation.
            rc = zmq_send(s, &(*si)->out_msg, (*si)->out_flags | ZMQ_NOBLOCK);

            zmqdrv_fprintf("resending message %p (size=%ld) on socket %p (ret=%d)\r\n", 
                zmq_msg_data(&(*si)->out_msg), zmq_msg_size(&(*si)->out_msg), s, rc);

            if (rc == 0) {
                zmq_msg_close(&(*si)->out_msg);
                // Unblock the waiting caller's pid by returning result
                zmqdrv_ok(drv, (*si)->out_caller);
                (*si)->out_caller = 0;
            } else if (zmq_errno() != EAGAIN) {
                // Unblock the waiting caller's pid by returning result
                zmq_msg_close(&(*si)->out_msg);
                zmqdrv_socket_error(drv, (*si)->out_caller, idx, zmq_errno());
                (*si)->out_caller = 0;
            }
        }

        zmqdrv_fprintf("--> socket %p events=%d\r\n", s, events);
    }
}