Exemple #1
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;
}
int main()
{
    const int msgsize = 8193;
    char sndbuf[msgsize] = "\xde\xad\xbe\xef";
    unsigned char rcvbuf[msgsize];

    int server_sock = socket(AF_INET, SOCK_STREAM, 0);
    assert(server_sock!=-1);
    int enable = 1;
    int rc = setsockopt (server_sock, SOL_SOCKET, SO_REUSEADDR, (char *) &enable, sizeof(enable));
    assert(rc!=-1);

    struct sockaddr_in saddr;
    memset(&saddr, 0, sizeof(saddr));
    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = INADDR_ANY;
    saddr.sin_port = htons(12345);

    rc = bind(server_sock, (struct sockaddr *)&saddr, sizeof(saddr));
    assert(rc!=-1);
    rc = listen(server_sock, 1);
    assert(rc!=-1);

    void *zctx = zmq_ctx_new();
    assert(zctx);
    void *zsock = zmq_socket(zctx, ZMQ_STREAM);
    assert(zsock);
    rc = zmq_connect(zsock, "tcp://127.0.0.1:12345");
    assert(rc!=-1);

    int client_sock = accept(server_sock, NULL, NULL);
    assert(client_sock!=-1);

    rc = close(server_sock);
    assert(rc!=-1);

    rc = send(client_sock, sndbuf, msgsize, 0);
    assert(rc==msgsize);

    zmq_msg_t msg;
    zmq_msg_init(&msg);

    int rcvbytes = 0;
    while (rcvbytes==0) // skip connection notification, if any
    {
        rc = zmq_msg_recv(&msg, zsock, 0);  // peerid
        assert(rc!=-1);
        assert(zmq_msg_more(&msg));
        rcvbytes = zmq_msg_recv(&msg, zsock, 0);
        assert(rcvbytes!=-1);
        assert(!zmq_msg_more(&msg));
    }

    // for this test, we only collect the first chunk
    // since the corruption already occurs in the first chunk
    memcpy(rcvbuf, zmq_msg_data(&msg), zmq_msg_size(&msg));

    zmq_msg_close(&msg);
    zmq_close(zsock);
    close(client_sock);

    zmq_ctx_destroy(zctx);

    assert(rcvbytes >= 4);

    // notice that only the 1st byte gets corrupted
    assert(rcvbuf[3]==0xef);
    assert(rcvbuf[2]==0xbe);
    assert(rcvbuf[1]==0xad);
    assert(rcvbuf[0]==0xde);

    (void)(rc); // avoid -Wunused-but-set-variable warning in release build
}
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;
}
Exemple #4
0
 inline size_t size ()
 {
     return zmq_msg_size (this);
 }
Exemple #5
0
 size_t size() const { return zmq_msg_size(const_cast<zmq_msg_t*>(&msg_)); }
Exemple #6
0
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);
  }
}
Exemple #7
0
int zmq::xrep_t::xsend (zmq_msg_t *msg_, int flags_)
{
    //  If this is the first part of the message it's the identity of the
    //  peer to send the message to.
    if (!more_out) {
        zmq_assert (!current_out);

        //  If we have malformed message (prefix with no subsequent message)
        //  then just silently ignore it.
        if (msg_->flags & ZMQ_MSG_MORE) {

            more_out = true;

            //  Find the pipe associated with the identity stored in the prefix.
            //  If there's no such pipe just silently ignore the message.
            blob_t identity ((unsigned char*) zmq_msg_data (msg_),
                zmq_msg_size (msg_));
            outpipes_t::iterator it = outpipes.find (identity);

            if (it != outpipes.end ()) {
                current_out = it->second.writer;
                zmq_msg_t empty;
                int rc = zmq_msg_init (&empty);
                zmq_assert (rc == 0);
                if (!current_out->check_write (&empty)) {
                    it->second.active = false;
                    more_out = false;
                    current_out = NULL;
                }
                rc = zmq_msg_close (&empty);
                zmq_assert (rc == 0);
            }
        }

        int rc = zmq_msg_close (msg_);
        zmq_assert (rc == 0);
        rc = zmq_msg_init (msg_);
        zmq_assert (rc == 0);
        return 0;
    }

    //  Check whether this is the last part of the message.
    more_out = msg_->flags & ZMQ_MSG_MORE;

    //  Push the message into the pipe. If there's no out pipe, just drop it.
    if (current_out) {
        bool ok = current_out->write (msg_);
        zmq_assert (ok);
        if (!more_out) {
            current_out->flush ();
            current_out = NULL;
        }
    }
    int rc = zmq_msg_close (msg_);
    zmq_assert (rc == 0);

    //  Detach the message from the data buffer.
    rc = zmq_msg_init (msg_);
    zmq_assert (rc == 0);

    return 0;
}
Exemple #8
0
int
xrap_traffic_recv (xrap_traffic_t *self, zsock_t *input)
{
    assert (input);

    if (zsock_type (input) == ZMQ_ROUTER) {
        zframe_destroy (&self->routing_id);
        self->routing_id = zframe_recv (input);
        if (!self->routing_id || !zsock_rcvmore (input)) {
            zsys_warning ("xrap_traffic: no routing ID");
            return -1;          //  Interrupted or malformed
        }
    }
    zmq_msg_t frame;
    zmq_msg_init (&frame);
    int size = zmq_msg_recv (&frame, zsock_resolve (input), 0);
    if (size == -1) {
        zsys_warning ("xrap_traffic: interrupted");
        goto malformed;         //  Interrupted
    }
    //  Get and check protocol signature
    self->needle = (byte *) zmq_msg_data (&frame);
    self->ceiling = self->needle + zmq_msg_size (&frame);

    uint16_t signature;
    GET_NUMBER2 (signature);
    if (signature != (0xAAA0 | 9)) {
        zsys_warning ("xrap_traffic: invalid signature");
        //  TODO: discard invalid messages and loop, and return
        //  -1 only on interrupt
        goto malformed;         //  Interrupted
    }
    //  Get message id and parse per message type
    GET_NUMBER1 (self->id);

    switch (self->id) {
        case XRAP_TRAFFIC_CONNECTION_OPEN:
            {
                char protocol [256];
                GET_STRING (protocol);
                if (strneq (protocol, "MALAMUTE")) {
                    zsys_warning ("xrap_traffic: protocol is invalid");
                    goto malformed;
                }
            }
            {
                uint16_t version;
                GET_NUMBER2 (version);
                if (version != 1) {
                    zsys_warning ("xrap_traffic: version is invalid");
                    goto malformed;
                }
            }
            GET_STRING (self->address);
            break;

        case XRAP_TRAFFIC_CONNECTION_PING:
            break;

        case XRAP_TRAFFIC_CONNECTION_PONG:
            break;

        case XRAP_TRAFFIC_CONNECTION_CLOSE:
            break;

        case XRAP_TRAFFIC_XRAP_SEND:
            GET_NUMBER4 (self->timeout);
            //  Get zero or more remaining frames
            zmsg_destroy (&self->content);
            if (zsock_rcvmore (input))
                self->content = zmsg_recv (input);
            else
                self->content = zmsg_new ();
            break;

        case XRAP_TRAFFIC_XRAP_OFFER:
            GET_STRING (self->route);
            GET_STRING (self->method);
            break;

        case XRAP_TRAFFIC_XRAP_DELIVER:
            if (self->needle + ZUUID_LEN > (self->ceiling)) {
                zsys_warning ("xrap_traffic: sender is invalid");
                goto malformed;
            }
            zuuid_destroy (&self->sender);
            self->sender = zuuid_new_from (self->needle);
            self->needle += ZUUID_LEN;
            //  Get zero or more remaining frames
            zmsg_destroy (&self->content);
            if (zsock_rcvmore (input))
                self->content = zmsg_recv (input);
            else
                self->content = zmsg_new ();
            break;

        case XRAP_TRAFFIC_OK:
            GET_NUMBER2 (self->status_code);
            GET_STRING (self->status_reason);
            break;

        case XRAP_TRAFFIC_FAIL:
            GET_NUMBER2 (self->status_code);
            GET_STRING (self->status_reason);
            break;

        case XRAP_TRAFFIC_ERROR:
            GET_NUMBER2 (self->status_code);
            GET_STRING (self->status_reason);
            break;

        default:
            zsys_warning ("xrap_traffic: bad message ID");
            goto malformed;
    }
    //  Successful return
    zmq_msg_close (&frame);
    return 0;

    //  Error returns
    malformed:
        zsys_warning ("xrap_traffic: xrap_traffic malformed message, fail");
        zmq_msg_close (&frame);
        return -1;              //  Invalid message
}
Exemple #9
0
int main(int argc, char **argv)
{
    int connect_rv, rv, msg_size;
    char *path, *message;
    void *context, *socket;
    zmq_msg_t request, reply;

    if (argc != 2) {
        printf("Usage: unwatch_dir <PATH>\n");
        return 1;
    }

    /* You'll probably want to make sure the path is valid here. */
    path = argv[1];

    context = zmq_init(1);
    socket = zmq_socket(context, ZMQ_REQ);
    connect_rv = zmq_connect(socket, "tcp://127.0.0.1:5559");

    if (connect_rv != 0) {
        printf("Failed to connect ZeroMQ socket: %s\n",
               zmq_strerror(errno));
        return 1;
    }

    /* Request */
    asprintf(&message, "{\"call\":\"unwatch\",\"path\":\"%s\"}", path);
    zmq_msg_init_size(&request, strlen(message));
    strncpy(zmq_msg_data(&request), message, strlen(message));
    free(message);

    rv = zmq_send(socket, &request, 0);
    zmq_msg_close(&request);
    if (rv != 0) {
        printf("Failed to send message to server: %s\n",
               zmq_strerror(errno));
        return 1;
    }

    /* Reply */
    zmq_msg_init(&reply);
    rv = zmq_recv(socket, &reply, 0);
    if (rv != 0) {
        printf("Failed to receive message from server: %s\n",
               zmq_strerror(errno));
        return 1;
    }

    msg_size = zmq_msg_size(&reply);
    message = malloc(msg_size + 1);
    memcpy(message, zmq_msg_data(&reply), msg_size);
    zmq_msg_close(&reply);
    message[msg_size] = '\0';

    printf("Got reply: %s\n", message);

    free(message);
    zmq_close(socket);
    zmq_term(context);

    return 0;
}
Exemple #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;
}
Exemple #11
0
/**
 * Receive data from socket
 * Based on code in  https://github.com/zeromq/jzmq/blob/master/src/Socket.cpp
 */
value hx_zmq_rcv(value socket_handle_, value flags) {
	
	val_check_kind(socket_handle_, k_zmq_socket_handle);
	
	if (!val_is_null(flags) && !val_is_int(flags)) {
		val_throw(alloc_int(EINVAL));
		return alloc_null();
	}
	
	zmq_msg_t message;

    int rc = zmq_msg_init (&message);
    int err = zmq_errno();
    if (rc != 0) {
        val_throw(alloc_int(err));
        return alloc_null();
    }
	
	gc_enter_blocking();
	
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,0,0)	
    rc = zmq_recvmsg (val_data(socket_handle_), &message, val_int(flags));
#else
    rc = zmq_recv (val_data(socket_handle_), &message, val_int(flags));
#endif
	gc_exit_blocking();

    err = zmq_errno();
    if (rc == -1 && err == EAGAIN) {
        rc = zmq_msg_close (&message);
        err = zmq_errno();
        if (rc != 0) {
			val_throw(alloc_int(err));
			return alloc_null();
        }
        return alloc_null();
    }

    if (rc == -1) {
        rc = zmq_msg_close (&message);
        int err1 = zmq_errno();
        if (rc != 0) {
			val_throw(alloc_int(err1));
			return alloc_null();
        }
        val_throw(alloc_int(err));
        return alloc_null();
    }
	
	// Return data to Haxe
	int sz = zmq_msg_size (&message);
    const char* pd = (char *)zmq_msg_data (&message);

	// Create a return buffer byte array, by memcopying the message data, then discard the ZMQ message
	buffer b = alloc_buffer(NULL);
	buffer_append_sub(b,pd,sz);
	rc = zmq_msg_close (&message);
	err = zmq_errno();
	if (rc != 0) {
		val_throw(alloc_int(err));
		return alloc_null();
	}
	return buffer_val(b);
}
Exemple #12
0
Fichier : test.c Projet : melo/pocs
int main (void)
{
    void *context = zmq_init (1);
    pid_t pid = fork();
    
    if (pid) {
      void *responder = zmq_socket (context, ZMQ_REP);
      //  Socket to talk to clients
      zmq_bind (responder, "ipc://xpto.sock");

      while (1) {
          //  Wait for next request from client
          zmq_msg_t request;
          zmq_msg_init (&request);
          zmq_recv (responder, &request, 0);
          
          char payload[10];
          int size = zmq_msg_size(&request);
          memcpy(payload, zmq_msg_data(&request), size);
          payload[size] = '\0';
          if (strncmp(payload, "quit", 4) == 0) {
            printf("[%d] Received '%s', sleep a bit\n", getpid(), payload);
            sleep(4);
            break;
          }
          
          printf ("[%d] Received '%s'\n", getpid(), payload);
          zmq_msg_close (&request);

          //  Do some 'work'
          sleep (1);

          //  Send reply back to client
          zmq_msg_t reply;
          zmq_msg_init_size (&reply, 5);
          memcpy (zmq_msg_data (&reply), "World", 5);
          zmq_send (responder, &reply, 0);
          zmq_msg_close (&reply);
      }
      //  We never get here but if we did, this would be how we end
      printf("[%d] Parent is cleaning up\n", getpid());
      zmq_close (responder);
      zmq_term (context);

      printf("[%d] waiting for child\n", getpid());
      int status;
      int rpid = waitpid(pid, &status, 0);
      printf("[%d] waited for pid %d, got %d status %d\n", getpid(), pid, rpid, status);
      printf("[%d] Parent is exiting\n", getpid());
    }
    else {
      context = zmq_init (1);

      //  Socket to talk to server
      printf ("[%d] Connecting to hello world server...\n", getpid());
      void *requester = zmq_socket (context, ZMQ_REQ);
      zmq_connect (requester, "ipc://xpto.sock");

      int request_nbr;
      zmq_msg_t request;
      for (request_nbr = 0; request_nbr != 2; request_nbr++) {
          zmq_msg_init_size (&request, 5);
          memcpy (zmq_msg_data (&request), "Hello", 5);
          printf ("[%d] Sending Hello %d...\n", getpid(), request_nbr);
          zmq_send (requester, &request, 0);
          zmq_msg_close (&request);

          zmq_msg_t reply;
          zmq_msg_init (&reply);
          zmq_recv (requester, &reply, 0);
          printf ("[%d] Received World %d\n", getpid(), request_nbr);
          zmq_msg_close (&reply);
      }

      zmq_msg_init_size (&request, 4);
      memcpy (zmq_msg_data (&request), "quit", 4);
      printf ("[%d] Sending quit...\n", getpid());
      zmq_send (requester, &request, 0);
      zmq_msg_close (&request);
      
      sleep(1);

      printf("[%d] Child is cleaning up\n", getpid());
      zmq_close (requester);
      zmq_term (context);
      printf("[%d] Child is exiting()\n", getpid());
      exit(0);
    }

    return 0;
}
Exemple #13
0
static int
s_vocket_input (zloop_t *loop, zmq_pollitem_t *item, void *arg)
{
    vocket_t *vocket = (vocket_t *) arg;
    driver_t *driver = vocket->driver;

    //  It's remotely possible we just lost a peering, in which case
    //  don't take the message off the pipe, leave it for next time
    if (zlist_size (vocket->live_peerings) < vocket->min_peerings)
        return 0;

    //  Pull message parts off socket
    assert (item->socket == vocket->msgpipe);
    zmq_msg_t msg;
    zmq_msg_init (&msg);

    Bool more = vocket->more;
    int rc = zmq_recvmsg (vocket->msgpipe, &msg, 0);
    while (rc >= 0) {
        vocket->outpiped++;
        Bool first = !more;
        more = zsockopt_rcvmore (vocket->msgpipe);

        //  Route message to active peerings as appropriate
        if (vocket->routing == VTX_ROUTING_NONE)
            zclock_log ("W: send() not allowed - dropping");
        else
        if (vocket->routing == VTX_ROUTING_REQUEST) {
            //  First part of message
            //  Round-robin to next peering
            if (first) {
                vocket->current_peering = (peering_t *) zlist_pop (vocket->live_peerings);
                zlist_append (vocket->live_peerings, vocket->current_peering);
            }
            peering_t *peering = vocket->current_peering;
            if (peering)
                s_queue_output (peering, &msg, more);
        }
        else
        if (vocket->routing == VTX_ROUTING_REPLY) {
            peering_t *peering = vocket->current_peering;
            if (peering)
                s_queue_output (peering, &msg, more);
        }
        else
        if (vocket->routing == VTX_ROUTING_DEALER) {
            //  First part of message
            //  Round-robin to next peering
            if (first) {
                vocket->current_peering = (peering_t *) zlist_pop (vocket->live_peerings);
                zlist_append (vocket->live_peerings, vocket->current_peering);
            }
            peering_t *peering = vocket->current_peering;
            if (peering)
                s_queue_output (peering, &msg, more);
        }
        else
        if (vocket->routing == VTX_ROUTING_ROUTER) {
            peering_t *peering = vocket->current_peering;
            //  Look-up peering using first message part
            if (first) {
                //  Parse and check schemed identity
                size_t size = zmq_msg_size (&msg);
                char *address = (char *) malloc (size + 1);
                memcpy (address, zmq_msg_data (&msg), size);
                address [size] = 0;

                int scheme_size = strlen (driver->scheme);
                if (memcmp (address, driver->scheme, scheme_size) == 0
                &&  memcmp (address + scheme_size, "://", 3) == 0) {
                    peering = (peering_t *) zhash_lookup (
                        vocket->peering_hash, address + scheme_size + 3);
                    if (!peering || !peering->alive)
                        zclock_log ("W: no route to '%s' - dropping", address);
                    vocket->current_peering = peering;
                }
                else
                    zclock_log ("E: bad address '%s' - dropping", address);
                free (address);
            }
            else
                if (peering)
                    s_queue_output (peering, &msg, more);
        }
        else
        if (vocket->routing == VTX_ROUTING_PUBLISH) {
            //  This is the first part of possibly multi-part message
            //  Subscribe all peerings that are alive
            if (first) {
                peering_t *peering = (peering_t *) zlist_first (vocket->live_peerings);
                while (peering) {
                    peering->subscribed = TRUE;
                    peering = (peering_t *) zlist_next (vocket->live_peerings);
                }
            }

            if (zlist_size (vocket->live_peerings) > 1) {
                //  Duplicate frames to all subscribers
                peering_t *peering = (peering_t *) zlist_first (vocket->live_peerings);
                while (peering) {
                    if (peering->subscribed)
                        s_queue_output (peering, &msg, more);
                    peering = (peering_t *) zlist_next (vocket->live_peerings);
                }
            }
            else
            if (zlist_size (vocket->live_peerings) == 1) {
                //  Send frames straight through to single subscriber
                peering_t *peering = (peering_t *) zlist_first (vocket->live_peerings);
                if (peering->subscribed)
                    s_queue_output (peering, &msg, more);
            }
        }
        else
        if (vocket->routing == VTX_ROUTING_SINGLE) {
            if (first)
                vocket->current_peering = (peering_t *) zlist_first (vocket->live_peerings);
            peering_t *peering = vocket->current_peering;
            if (peering)
                s_queue_output (peering, &msg, more);
        }
        else
            zclock_log ("E: unknown routing mechanism - dropping");

        zmq_msg_close (&msg);
        zmq_msg_init (&msg);
        rc = zmq_recvmsg (vocket->msgpipe, &msg, ZMQ_DONTWAIT);
    }
    //  Save state
    vocket->more = more;

    return 0;
}
Exemple #14
0
int
zproto_example_recv (zproto_example_t *self, zsock_t *input)
{
    assert (input);

    if (zsock_type (input) == ZMQ_ROUTER) {
        zframe_destroy (&self->routing_id);
        self->routing_id = zframe_recv (input);
        if (!self->routing_id || !zsock_rcvmore (input)) {
            zsys_warning ("zproto_example: no routing ID");
            return -1;          //  Interrupted or malformed
        }
    }
    zmq_msg_t frame;
    zmq_msg_init (&frame);
    int size = zmq_msg_recv (&frame, zsock_resolve (input), 0);
    if (size == -1) {
        zsys_warning ("zproto_example: interrupted");
        goto malformed;         //  Interrupted
    }
    //  Get and check protocol signature
    self->needle = (byte *) zmq_msg_data (&frame);
    self->ceiling = self->needle + zmq_msg_size (&frame);

    uint16_t signature;
    GET_NUMBER2 (signature);
    if (signature != (0xAAA0 | 0)) {
        zsys_warning ("zproto_example: invalid signature");
        //  TODO: discard invalid messages and loop, and return
        //  -1 only on interrupt
        goto malformed;         //  Interrupted
    }
    //  Get message id and parse per message type
    GET_NUMBER1 (self->id);

    switch (self->id) {
        case ZPROTO_EXAMPLE_LOG:
            GET_NUMBER2 (self->sequence);
            {
                uint16_t version;
                GET_NUMBER2 (version);
                if (version != 3) {
                    zsys_warning ("zproto_example: version is invalid");
                    goto malformed;
                }
            }
            GET_NUMBER1 (self->level);
            GET_NUMBER1 (self->event);
            GET_NUMBER2 (self->node);
            GET_NUMBER2 (self->peer);
            GET_NUMBER8 (self->time);
            GET_STRING (self->host);
            GET_LONGSTR (self->data);
            break;

        case ZPROTO_EXAMPLE_STRUCTURES:
            GET_NUMBER2 (self->sequence);
            {
                size_t list_size;
                GET_NUMBER4 (list_size);
                self->aliases = zlist_new ();
                zlist_autofree (self->aliases);
                while (list_size--) {
                    char *string = NULL;
                    GET_LONGSTR (string);
                    zlist_append (self->aliases, string);
                    free (string);
                }
            }
            {
                size_t hash_size;
                GET_NUMBER4 (hash_size);
                self->headers = zhash_new ();
                zhash_autofree (self->headers);
                while (hash_size--) {
                    char key [256];
                    char *value = NULL;
                    GET_STRING (key);
                    GET_LONGSTR (value);
                    zhash_insert (self->headers, key, value);
                    free (value);
                }
            }
            break;

        case ZPROTO_EXAMPLE_BINARY:
            GET_NUMBER2 (self->sequence);
            GET_OCTETS (self->flags, 4);
            {
                size_t chunk_size;
                GET_NUMBER4 (chunk_size);
                if (self->needle + chunk_size > (self->ceiling)) {
                    zsys_warning ("zproto_example: public_key is missing data");
                    goto malformed;
                }
                zchunk_destroy (&self->public_key);
                self->public_key = zchunk_new (self->needle, chunk_size);
                self->needle += chunk_size;
            }
            if (self->needle + ZUUID_LEN > (self->ceiling)) {
                zsys_warning ("zproto_example: identifier is invalid");
                goto malformed;
            }
            zuuid_destroy (&self->identifier);
            self->identifier = zuuid_new_from (self->needle);
            self->needle += ZUUID_LEN;
            //  Get next frame off socket
            if (!zsock_rcvmore (input)) {
                zsys_warning ("zproto_example: address is missing");
                goto malformed;
            }
            zframe_destroy (&self->address);
            self->address = zframe_recv (input);
            //  Get zero or more remaining frames
            zmsg_destroy (&self->content);
            if (zsock_rcvmore (input))
                self->content = zmsg_recv (input);
            else
                self->content = zmsg_new ();
            break;

        case ZPROTO_EXAMPLE_TYPES:
            GET_NUMBER2 (self->sequence);
            GET_STRING (self->client_forename);
            GET_STRING (self->client_surname);
            GET_STRING (self->client_mobile);
            GET_STRING (self->client_email);
            GET_STRING (self->supplier_forename);
            GET_STRING (self->supplier_surname);
            GET_STRING (self->supplier_mobile);
            GET_STRING (self->supplier_email);
            break;

        default:
            zsys_warning ("zproto_example: bad message ID");
            goto malformed;
    }
    //  Successful return
    zmq_msg_close (&frame);
    return 0;

    //  Error returns
    malformed:
        zsys_warning ("zproto_example: zproto_example malformed message, fail");
        zmq_msg_close (&frame);
        return -1;              //  Invalid message
}
int main (void)
{
    int rc;
 
    setup_test_environment();
    //  Create the infrastructure
    void *ctx = zmq_ctx_new ();
    assert (ctx);

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

    rc = zmq_bind(rep, "tcp://127.0.0.1:5560");
    assert (rc == 0);

    rc = zmq_connect(req, "tcp://127.0.0.1:5560");
    assert (rc == 0);

    char tmp[MSG_SIZE];
    zmq_send(req, tmp, MSG_SIZE, 0);

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

    zmq_recvmsg(rep, &msg, 0);
    assert(zmq_msg_size(&msg) == MSG_SIZE);
  
	  // get the messages source file descriptor
    int srcFd = zmq_msg_get(&msg, ZMQ_SRCFD);
    assert(srcFd >= 0);

	  // get the remote endpoint
    struct sockaddr_storage ss;
    socklen_t addrlen = sizeof ss;
    rc = getpeername (srcFd, (struct sockaddr*) &ss, &addrlen);
    assert (rc == 0);

    char host [NI_MAXHOST];
    rc = getnameinfo ((struct sockaddr*) &ss, addrlen, host, sizeof host, NULL, 0, NI_NUMERICHOST);
    assert (rc == 0);

	  // assert it is localhost which connected
    assert (strcmp(host, "127.0.0.1") == 0);

    rc = zmq_close (rep);
    assert (rc == 0);
    rc = zmq_close (req);
    assert (rc == 0);

	  // sleep a bit for the socket to be freed
	  usleep(30000);
	
	  // getting name from closed socket will fail
    rc = getpeername (srcFd, (struct sockaddr*) &ss, &addrlen);
    assert (rc == -1);
    assert (errno == EBADF);
    
    rc = zmq_ctx_term (ctx);
    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;
}
Exemple #17
0
int
zgossip_msg_recv (zgossip_msg_t *self, zsock_t *input)
{
    assert (input);

    if (zsock_type (input) == ZMQ_ROUTER) {
        zframe_destroy (&self->routing_id);
        self->routing_id = zframe_recv (input);
        if (!self->routing_id || !zsock_rcvmore (input)) {
            zsys_warning ("zgossip_msg: no routing ID");
            return -1;          //  Interrupted or malformed
        }
    }
    zmq_msg_t frame;
    zmq_msg_init (&frame);
    int size = zmq_msg_recv (&frame, zsock_resolve (input), 0);
    if (size == -1) {
        zsys_warning ("zgossip_msg: interrupted");
        goto malformed;         //  Interrupted
    }
    //  Get and check protocol signature
    self->needle = (byte *) zmq_msg_data (&frame);
    self->ceiling = self->needle + zmq_msg_size (&frame);

    uint16_t signature;
    GET_NUMBER2 (signature);
    if (signature != (0xAAA0 | 0)) {
        zsys_warning ("zgossip_msg: invalid signature");
        //  TODO: discard invalid messages and loop, and return
        //  -1 only on interrupt
        goto malformed;         //  Interrupted
    }
    //  Get message id and parse per message type
    GET_NUMBER1 (self->id);

    switch (self->id) {
    case ZGOSSIP_MSG_HELLO:
    {
        byte version;
        GET_NUMBER1 (version);
        if (version != 1) {
            zsys_warning ("zgossip_msg: version is invalid");
            goto malformed;
        }
    }
    break;

    case ZGOSSIP_MSG_PUBLISH:
    {
        byte version;
        GET_NUMBER1 (version);
        if (version != 1) {
            zsys_warning ("zgossip_msg: version is invalid");
            goto malformed;
        }
    }
    GET_STRING (self->key);
    GET_LONGSTR (self->value);
    GET_NUMBER4 (self->ttl);
    break;

    case ZGOSSIP_MSG_PING:
    {
        byte version;
        GET_NUMBER1 (version);
        if (version != 1) {
            zsys_warning ("zgossip_msg: version is invalid");
            goto malformed;
        }
    }
    break;

    case ZGOSSIP_MSG_PONG:
    {
        byte version;
        GET_NUMBER1 (version);
        if (version != 1) {
            zsys_warning ("zgossip_msg: version is invalid");
            goto malformed;
        }
    }
    break;

    case ZGOSSIP_MSG_INVALID:
    {
        byte version;
        GET_NUMBER1 (version);
        if (version != 1) {
            zsys_warning ("zgossip_msg: version is invalid");
            goto malformed;
        }
    }
    break;

    default:
        zsys_warning ("zgossip_msg: bad message ID");
        goto malformed;
    }
    //  Successful return
    zmq_msg_close (&frame);
    return 0;

    //  Error returns
malformed:
    zsys_warning ("zgossip_msg: zgossip_msg malformed message, fail");
    zmq_msg_close (&frame);
    return -1;              //  Invalid message
}
Exemple #18
0
static int
_spawn_run(zlmb_spawn_t *self, char *command, int argc, char **argv, int opt)
{
    pid_t pid;
    int ret, in[2];
    int i, n = argc - opt;
    char *env[] = { NULL, NULL, NULL, NULL };
    char **arg = NULL;
    posix_spawn_file_actions_t actions;

    if (!self || !command || strlen(command) <= 0) {
        _ERR("Function arguments: %s\n", __FUNCTION__);
        return -1;
    }

    env[0] = self->frame;
    env[1] = self->frame_length;
    env[2] = self->length;

    if (n < 0) {
        n = 0;
    }

    arg = malloc(sizeof(char *) * (n + 2));
    if (arg == NULL) {
        _ERR("Memory allocate args.\n");
        return -1;
    }
    if (n > 0) {
        for (i = 0; i != n; i++) {
            arg[i+1] = argv[opt+i];
        }
    }
    arg[0] = command;
    arg[n+1] = NULL;

    if (pipe(in) == -1) {
        _ERR("Create STDIN pipe.\n");
        return -1;
    }

    if (posix_spawn_file_actions_init(&actions) != 0) {
        _ERR("POSIX spawn file action initilize.\n");
        return -1;
    }

    if (posix_spawn_file_actions_addclose(&actions, in[1]) != 0 ||
        posix_spawn_file_actions_adddup2(&actions, in[0], 0) != 0) {
        _ERR("POSIX spawn file action add.\n");
        posix_spawn_file_actions_destroy(&actions);
        return -1;
    }

    _DEBUG("POSIX spawn run: %s\n", command);

    if (posix_spawnp(&pid, command, &actions, NULL, arg, env) != 0) {
        _ERR("POSIX spawn: %s\n", command);
        posix_spawn_file_actions_destroy(&actions);
        return -1;
    }

    close(in[0]);

    while (zlmb_stack_size(self->stack)) {
        zmq_msg_t *zmsg = zlmb_stack_shift(self->stack);
        if (zmsg) {
            write(in[1], zmq_msg_data(zmsg), zmq_msg_size(zmsg));
            zmq_msg_close(zmsg);
            free(zmsg);
        }
    }

    close(in[1]);

    _DEBUG("POSIX spawn wait(#%d).\n", pid);
    waitpid(pid, &ret, 0);

    posix_spawn_file_actions_destroy(&actions);

    _DEBUG("POSIX spawn finish(#%d).\n", pid);

    if (arg) {
        free(arg);
    }

    return 0;
}
Exemple #19
0
int main(void)
{
    void* zmq_ctx = zmq_ctx_new();
    void* zmq_sock = zmq_socket(zmq_ctx, ZMQ_DEALER);
    zmq_connect(zmq_sock, "tcp://localhost:5555");
 //   int pid = getpid();
    char buf[MSG_SIZE] = {0};
    
    zmq_pollitem_t items[] = 
    {
        {zmq_sock, 0, ZMQ_POLLIN, 0},       // zmq socket
        {0, STDIN_FILENO, ZMQ_POLLIN, 0},   // posix fd: stdin
    };

    int index = 0;
    int nbyte = 0;
    printf("ym65536#");
    fflush(stdout);
    while (1)
    {
        zmq_poll(items, 2, -1);
        if (items[1].revents & ZMQ_POLLIN)
        {
            nbyte = read(STDIN_FILENO, buf, MSG_SIZE);
            nbyte = nbyte > 200 ? 200: nbyte;
 //           sprintf(&buf[nbyte], " id:<%d,%d>", pid, index);

            // send empty msg
            zmq_msg_t blankMsg;
            zmq_msg_init_size(&blankMsg, 0);
            zmq_msg_send(&blankMsg, zmq_sock, ZMQ_SNDMORE);
            zmq_msg_close(&blankMsg);

            // send addr info
/*            zmq_msg_t addrMsg;
            struct addrinfo addr;
            addr.ip = ntohl(inet_addr("10.10.15.15"));
            addr.port = htons(5555);
            addr.pad = 0;
            zmq_msg_init_size(&addrMsg, sizeof(struct addrinfo));
            memcpy(zmq_msg_data(&addrMsg), (char* )&addr, sizeof(addr));
            zmq_msg_send(&addrMsg, zmq_sock, ZMQ_SNDMORE);
            zmq_msg_close(&addrMsg);
*/
            zmq_msg_t request;
            zmq_msg_init_size(&request, strlen(buf));
            memcpy(zmq_msg_data(&request), buf, strlen(buf));
            printf("send request: %s\n", buf);
            zmq_msg_send(&request, zmq_sock, 0);
            zmq_msg_close(&request);
            printf("ym65536#");
            fflush(stdout);
        }
      
        if (items[0].revents & ZMQ_POLLIN) // recv from broker
        {
            // recv empty msg
            zmq_msg_t blankMsg;
            zmq_msg_init(&blankMsg);
            zmq_msg_recv(&blankMsg, zmq_sock, 0);
            printf("recv: msgsize=%d\n", zmq_msg_size(&blankMsg));
            zmq_msg_close(&blankMsg);

            // recv addr info
/*            zmq_msg_t addrMsg;
            struct addrinfo addr;
            zmq_msg_init(&addrMsg);
            zmq_msg_recv(&addrMsg, zmq_sock, 0);
            memcpy((char*)&addr, zmq_msg_data(&addrMsg), sizeof(addr));
            zmq_msg_close(&addrMsg);
            printf("recv: ip:%08x, port:%d\n", addr.ip, addr.port);
*/
            memset(buf, 0, sizeof(buf));
            zmq_msg_t reply;
            zmq_msg_init(&reply);
            zmq_msg_recv(&reply, zmq_sock, 0);
            memcpy(buf, zmq_msg_data(&reply), zmq_msg_size(&reply));
            printf("recv: %s\n", buf);
            zmq_msg_close(&reply);
        }
        index++;
    }

    sleep(1);
    zmq_close(zmq_sock);
    zmq_ctx_destroy(zmq_ctx);

    return 0;
}
Exemple #20
-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);
    }
}