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; }
inline size_t size () { return zmq_msg_size (this); }
size_t size() const { return zmq_msg_size(const_cast<zmq_msg_t*>(&msg_)); }
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); } }
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; }
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 }
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; }
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; }
/** * 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); }
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; }
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; }
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; }
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 }
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; }
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; }
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); } }