const char * zfile_digest (zfile_t *self) { assert (self); if (!self->digest) { if (zfile_input (self) == -1) return NULL; // Problem reading file // Now calculate hash for file data, chunk by chunk size_t blocksz = 65535; off_t offset = 0; self->digest = zdigest_new (); if (!self->digest) return NULL; zchunk_t *chunk = zfile_read (self, blocksz, offset); while (zchunk_size (chunk)) { zdigest_update (self->digest, zchunk_data (chunk), zchunk_size (chunk)); zchunk_destroy (&chunk); // off_t is defined as long (32 bit on Windows, 64 bit otherwise) // This guards against overflow in both contexts. if (blocksz > LONG_MAX - offset) return NULL; offset += (off_t) blocksz; chunk = zfile_read (self, blocksz, offset); } zchunk_destroy (&chunk); fclose (self->handle); self->handle = 0; } return zdigest_string (self->digest); }
static void s_check_directory (s_agent_t *self) { // Get latest snapshot and build a patches list for any changes // All patches are built using a virtual path starting at "/" zdir_t *dir = zdir_new (self->path, NULL); zlist_t *patches = zdir_diff (self->dir, dir, "/"); // Drop old directory and replace with latest version zdir_destroy (&self->dir); self->dir = dir; while (zlist_size (patches)) { zdir_patch_t *patch = (zdir_patch_t *) zlist_pop (patches); if (zdir_patch_op (patch) == patch_create) { // Shout new files to DROPS group // Stupidest possible approach: send whole file as one frame // Truncate file at arbitrary limit of 10MB zfile_t *file = zdir_patch_file (patch); if (zfile_input (file) == 0) { zchunk_t *chunk = zfile_read (file, 10 * 1024 * 1024, 0); assert (chunk); zmsg_t *msg = zmsg_new (); zmsg_addstr (msg, "CREATE"); zmsg_addstr (msg, zdir_patch_vpath (patch)); zmsg_add (msg, zframe_new (zchunk_data (chunk), zchunk_size (chunk))); zchunk_destroy (&chunk); zyre_shout (self->zyre, "DROPS", &msg); } } zdir_patch_destroy (&patch); } zlist_destroy (&patches); }
char * zfile_digest (zfile_t *self) { if (!self->digest) { if (zfile_input (self) == -1) return NULL; // Problem reading file // Now calculate hash for file data, chunk by chunk size_t blocksz = 65535; off_t offset = 0; self->digest = zdigest_new (); zchunk_t *chunk = zfile_read (self, blocksz, offset); while (zchunk_size (chunk)) { zdigest_update (self->digest, zchunk_data (chunk), zchunk_size (chunk)); zchunk_destroy (&chunk); offset += blocksz; chunk = zfile_read (self, blocksz, offset); } zchunk_destroy (&chunk); zfile_close (self); } return zdigest_string (self->digest); }
char * zconfig_str_save (zconfig_t *self) { zchunk_t *chunk = zconfig_chunk_save (self); char *string = strdup ((char *) zchunk_data (chunk)); zchunk_destroy (&chunk); return string; }
JNIEXPORT jbyteArray JNICALL Java_org_zeromq_czmq_Zchunk__1_1data (JNIEnv *env, jclass c, jlong self) { jbyte *data_ = (jbyte *) zchunk_data ((zchunk_t *) (intptr_t) self); jint return_size_ = (jint) zchunk_size ((zchunk_t *) (intptr_t) self); jbyteArray return_data_ = (*env)->NewByteArray (env, return_size_); (*env)->SetByteArrayRegion (env, return_data_, 0, return_size_, (jbyte *) data_); return return_data_; }
static zsync_node_t * zsync_node_new () { int rc; zsync_node_t *self = (zsync_node_t *) zmalloc (sizeof (zsync_node_t)); self->ctx = zctx_new (); assert (self->ctx); self->zyre = zyre_new (self->ctx); assert (self->zyre); // Obtain permanent UUID self->own_uuid = zuuid_new (); if (zsys_file_exists (UUID_FILE)) { // Read uuid from file zfile_t *uuid_file = zfile_new (".", UUID_FILE); int rc = zfile_input (uuid_file); // open file for reading assert (rc == 0); zchunk_t *uuid_chunk = zfile_read (uuid_file, 16, 0); assert (zchunk_size (uuid_chunk) == 16); // make sure read succeeded zuuid_set (self->own_uuid, zchunk_data (uuid_chunk)); zfile_destroy (&uuid_file); } else { // Write uuid to file zfile_t *uuid_file = zfile_new (".", UUID_FILE); rc = zfile_output (uuid_file); // open file for writing assert (rc == 0); zchunk_t *uuid_bin = zchunk_new ( zuuid_data (self->own_uuid), 16); rc = zfile_write (uuid_file, uuid_bin, 0); assert (rc == 0); zfile_destroy (&uuid_file); } // Obtain peers and states self->peers = zlist_new (); if (zsys_file_exists (PEER_STATES_FILE)) { zhash_t *peer_states = zhash_new (); int rc = zhash_load (peer_states, PEER_STATES_FILE); assert (rc == 0); zlist_t *uuids = zhash_keys (peer_states); char *uuid = zlist_first (uuids); while (uuid) { char * state_str = zhash_lookup (peer_states, uuid); uint64_t state; sscanf (state_str, "%"SCNd64, &state); zlist_append (self->peers, zsync_peer_new (uuid, state)); uuid = zlist_next (uuids); } } self->zyre_peers = zhash_new (); self->terminated = false; return self; }
void zchunk_test (bool verbose) { printf (" * zchunk: "); // @selftest zchunk_t *chunk = zchunk_new ("1234567890", 10); assert (chunk); assert (zchunk_size (chunk) == 10); assert (memcmp (zchunk_data (chunk), "1234567890", 10) == 0); zchunk_destroy (&chunk); chunk = zchunk_new (NULL, 10); zchunk_append (chunk, "12345678", 8); zchunk_append (chunk, "90ABCDEF", 8); zchunk_append (chunk, "GHIJKLMN", 8); assert (memcmp (zchunk_data (chunk), "1234567890", 10) == 0); assert (zchunk_size (chunk) == 10); zframe_t *frame = zchunk_pack (chunk); assert(frame); zchunk_t *chunk2 = zchunk_unpack (frame); assert (memcmp (zchunk_data (chunk2), "1234567890", 10) == 0); zframe_destroy(&frame); zchunk_destroy(&chunk2); zchunk_t *copy = zchunk_dup (chunk); assert (memcmp (zchunk_data (copy), "1234567890", 10) == 0); assert (zchunk_size (copy) == 10); zchunk_destroy (©); zchunk_destroy (&chunk); copy = zchunk_new ("1234567890abcdefghij", 20); chunk = zchunk_new (NULL, 8); zchunk_consume (chunk, copy); assert (!zchunk_exhausted (copy)); assert (memcmp (zchunk_data (chunk), "12345678", 8) == 0); zchunk_set (chunk, NULL, 0); zchunk_consume (chunk, copy); assert (!zchunk_exhausted (copy)); assert (memcmp (zchunk_data (chunk), "90abcdef", 8) == 0); zchunk_set (chunk, NULL, 0); zchunk_consume (chunk, copy); assert (zchunk_exhausted (copy)); assert (zchunk_size (chunk) == 4); assert (memcmp (zchunk_data (chunk), "ghij", 4) == 0); zchunk_destroy (©); zchunk_destroy (&chunk); // @end printf ("OK\n"); }
zchunk_t * zconfig_chunk_save (zconfig_t *self) { assert (self); int size = s_config_execute (self, s_config_save, NULL, 0); // Allow an extra byte so we can null-terminate the data zchunk_t *chunk = zchunk_new (NULL, size + 1); if (chunk) { s_config_execute (self, s_config_save, chunk, 0); // This lets us treat the chunk data as a string zchunk_data (chunk) [zchunk_size (chunk)] = 0; } return chunk; }
ssize_t zpipes_client_read (zpipes_client_t *self, void *data, size_t size, int timeout) { assert (self); zpipes_msg_send_read (self->dealer, size, timeout); zpipes_msg_t *reply = zpipes_msg_recv (self->dealer); if (!reply) { self->error = EINTR; return -1; // Interrupted } ssize_t rc = 0; if (zpipes_msg_id (reply) == ZPIPES_MSG_READ_OK) { zchunk_t *chunk = zpipes_msg_chunk (reply); ssize_t bytes = zchunk_size (chunk); assert (bytes <= size); memcpy (data, zchunk_data (chunk), bytes); rc = bytes; } else if (zpipes_msg_id (reply) == ZPIPES_MSG_READ_END) rc = 0; else if (zpipes_msg_id (reply) == ZPIPES_MSG_READ_TIMEOUT) { self->error = EAGAIN; rc = -1; } else if (zpipes_msg_id (reply) == ZPIPES_MSG_READ_FAILED) { // TODO: better error code? // This happens if we close a pipe while there's a pending read self->error = EINTR; rc = -1; } else if (zpipes_msg_id (reply) == ZPIPES_MSG_INVALID) { self->error = EBADF; rc = -1; } zpipes_msg_destroy (&reply); return rc; }
static void pipe_send_data (pipe_t *self, zchunk_t **chunk_p) { assert (self); assert (self->reader); zchunk_t *chunk = *chunk_p; assert (chunk); if (self->reader == REMOTE_NODE) { // Send chunk to remote node reader zmsg_t *msg = zmsg_new (); zmsg_addstr (msg, "DATA"); zmsg_addstr (msg, self->name); zmsg_addmem (msg, zchunk_data (chunk), zchunk_size (chunk)); zyre_whisper (self->server->zyre, self->remote, &msg); zchunk_destroy (chunk_p); } else { client_store_chunk (self->reader, chunk_p); engine_send_event (self->reader, have_data_event); } }
int fmq_msg_send (fmq_msg_t *self, zsock_t *output) { assert (self); assert (output); if (zsock_type (output) == ZMQ_ROUTER) zframe_send (&self->routing_id, output, ZFRAME_MORE + ZFRAME_REUSE); size_t frame_size = 2 + 1; // Signature and message ID switch (self->id) { case FMQ_MSG_OHAI: frame_size += 1 + strlen ("FILEMQ"); frame_size += 2; // version break; case FMQ_MSG_ICANHAZ: frame_size += 4; if (self->path) frame_size += strlen (self->path); frame_size += 4; // Size is 4 octets if (self->options) { self->options_bytes = 0; char *item = (char *) zhash_first (self->options); while (item) { self->options_bytes += 1 + strlen (zhash_cursor (self->options)); self->options_bytes += 4 + strlen (item); item = (char *) zhash_next (self->options); } } frame_size += self->options_bytes; frame_size += 4; // Size is 4 octets if (self->cache) { self->cache_bytes = 0; char *item = (char *) zhash_first (self->cache); while (item) { self->cache_bytes += 1 + strlen (zhash_cursor (self->cache)); self->cache_bytes += 4 + strlen (item); item = (char *) zhash_next (self->cache); } } frame_size += self->cache_bytes; break; case FMQ_MSG_NOM: frame_size += 8; // credit frame_size += 8; // sequence break; case FMQ_MSG_CHEEZBURGER: frame_size += 8; // sequence frame_size += 1; // operation frame_size += 4; if (self->filename) frame_size += strlen (self->filename); frame_size += 8; // offset frame_size += 1; // eof frame_size += 4; // Size is 4 octets if (self->headers) { self->headers_bytes = 0; char *item = (char *) zhash_first (self->headers); while (item) { self->headers_bytes += 1 + strlen (zhash_cursor (self->headers)); self->headers_bytes += 4 + strlen (item); item = (char *) zhash_next (self->headers); } } frame_size += self->headers_bytes; frame_size += 4; // Size is 4 octets if (self->chunk) frame_size += zchunk_size (self->chunk); break; case FMQ_MSG_SRSLY: frame_size += 1 + strlen (self->reason); break; case FMQ_MSG_RTFM: frame_size += 1 + strlen (self->reason); break; } // Now serialize message into the frame zmq_msg_t frame; zmq_msg_init_size (&frame, frame_size); self->needle = (byte *) zmq_msg_data (&frame); PUT_NUMBER2 (0xAAA0 | 3); PUT_NUMBER1 (self->id); size_t nbr_frames = 1; // Total number of frames to send switch (self->id) { case FMQ_MSG_OHAI: PUT_STRING ("FILEMQ"); PUT_NUMBER2 (FMQ_MSG_VERSION); break; case FMQ_MSG_ICANHAZ: if (self->path) { PUT_LONGSTR (self->path); } else PUT_NUMBER4 (0); // Empty string if (self->options) { PUT_NUMBER4 (zhash_size (self->options)); char *item = (char *) zhash_first (self->options); while (item) { PUT_STRING (zhash_cursor (self->options)); PUT_LONGSTR (item); item = (char *) zhash_next (self->options); } } else PUT_NUMBER4 (0); // Empty hash if (self->cache) { PUT_NUMBER4 (zhash_size (self->cache)); char *item = (char *) zhash_first (self->cache); while (item) { PUT_STRING (zhash_cursor (self->cache)); PUT_LONGSTR (item); item = (char *) zhash_next (self->cache); } } else PUT_NUMBER4 (0); // Empty hash break; case FMQ_MSG_NOM: PUT_NUMBER8 (self->credit); PUT_NUMBER8 (self->sequence); break; case FMQ_MSG_CHEEZBURGER: PUT_NUMBER8 (self->sequence); PUT_NUMBER1 (self->operation); if (self->filename) { PUT_LONGSTR (self->filename); } else PUT_NUMBER4 (0); // Empty string PUT_NUMBER8 (self->offset); PUT_NUMBER1 (self->eof); if (self->headers) { PUT_NUMBER4 (zhash_size (self->headers)); char *item = (char *) zhash_first (self->headers); while (item) { PUT_STRING (zhash_cursor (self->headers)); PUT_LONGSTR (item); item = (char *) zhash_next (self->headers); } } else PUT_NUMBER4 (0); // Empty hash if (self->chunk) { PUT_NUMBER4 (zchunk_size (self->chunk)); memcpy (self->needle, zchunk_data (self->chunk), zchunk_size (self->chunk)); self->needle += zchunk_size (self->chunk); } else PUT_NUMBER4 (0); // Empty chunk break; case FMQ_MSG_SRSLY: PUT_STRING (self->reason); break; case FMQ_MSG_RTFM: PUT_STRING (self->reason); break; } // Now send the data frame zmq_msg_send (&frame, zsock_resolve (output), --nbr_frames? ZMQ_SNDMORE: 0); return 0; }
zconfig_t * zconfig_chunk_load (zchunk_t *chunk) { // Parse the chunk line by line zconfig_t *self = zconfig_new ("root", NULL); if (!self) return NULL; bool valid = true; int lineno = 0; char *data_ptr = (char *) zchunk_data (chunk); size_t remaining = zchunk_size (chunk); while (remaining) { // Copy stuff into cur_line; not fastest but safest option // since chunk may not be null terminated, etc. char *eoln = (char *) memchr (data_ptr, '\n', remaining); size_t cur_size; if (eoln) cur_size = eoln - data_ptr; else cur_size = remaining; if (cur_size > 1024) cur_size = 1024; char cur_line [1024 + 1]; memcpy (cur_line, data_ptr, cur_size); cur_line [cur_size] = '\0'; data_ptr = eoln? eoln + 1: NULL; remaining -= cur_size + (eoln? 1: 0); // Trim line size_t length = strlen (cur_line); while (length && isspace ((byte) cur_line [length - 1])) cur_line [--length] = 0; // Collect indentation level and name, if any lineno++; // Handle whole-line comment if present if (cur_line [0] == '#') { if (!self->comments) { self->comments = zlist_new (); assert (self->comments); zlist_autofree (self->comments); } zlist_append (self->comments, cur_line + 1); } char *scanner = cur_line; int level = s_collect_level (&scanner, lineno); if (level == -1) { valid = false; break; } char *name = s_collect_name (&scanner, lineno); if (name == NULL) { valid = false; break; } // If name is not empty, collect property value if (*name) { char *value = s_collect_value (&scanner, lineno); if (value == NULL) valid = false; else { // Navigate to parent for this element zconfig_t *parent = zconfig_at_depth (self, level); if (parent) { zconfig_t *item = zconfig_new (name, parent); assert (item); item->value = value; } else { zclock_log ("E (zconfig): (%d) indentation error", lineno); free (value); valid = false; } } } else if (s_verify_eoln (scanner, lineno)) valid = false; free (name); if (!valid) break; } // Either the whole ZPL stream is valid or none of it is if (!valid) zconfig_destroy (&self); return self; }
static void zhttp_client_actor (zsock_t *pipe, void *args) { curl_global_init (CURL_GLOBAL_ALL); CURLM *multi = curl_multi_init (); CURLSH *share = curl_share_init (); curl_share_setopt (share, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); curl_share_setopt (share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION); curl_share_setopt (share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT); long verbose = (*(bool *) args) ? 1L : 0L; CURLMcode code; SOCKET pipefd = zsock_fd (pipe); struct curl_waitfd waitfd = {pipefd, CURL_WAIT_POLLIN}; // List to hold pending curl handles, in case we are destroy the client // while request are inprogress zlistx_t *pending_handles = zlistx_new (); zlistx_set_destructor (pending_handles, (zlistx_destructor_fn *) curl_destructor); zsock_signal (pipe, 0); bool terminated = false; while (!terminated) { if (!zsock_has_in (pipe)) { code = curl_multi_wait (multi, &waitfd, 1, 1000, NULL); assert (code == CURLM_OK); } if (zsock_has_in (pipe)) { char *command = zstr_recv (pipe); if (!command) break; // Interrupted // All actors must handle $TERM in this way if (streq (command, "$TERM")) terminated = true; else if (streq (command, "GET")) { char *url; zlistx_t *headers; int timeout; void *handler; void *arg; int rc = zsock_recv (pipe, "slipp", &url, &headers, &timeout, &handler, &arg); assert (rc == 0); zchunk_t *response = zchunk_new (NULL, 100); assert (response); struct curl_slist *curl_headers = zlistx_to_slist (headers); CURL *curl = curl_easy_init (); zlistx_add_end (pending_handles, curl); http_request *request = (http_request *) zmalloc (sizeof (http_request)); assert (request); request->handler = handler; request->arg = arg; request->curl = curl; request->response = response; request->headers = curl_headers; request->body = NULL; curl_easy_setopt (curl, CURLOPT_SHARE, share); curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS, (long)timeout); curl_easy_setopt (curl, CURLOPT_VERBOSE, verbose); curl_easy_setopt (curl, CURLOPT_HTTPHEADER, curl_headers); curl_easy_setopt (curl, CURLOPT_URL, url); curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, write_data); curl_easy_setopt (curl, CURLOPT_WRITEDATA, response); curl_easy_setopt (curl, CURLOPT_PRIVATE, request); code = curl_multi_add_handle (multi, curl); assert (code == CURLM_OK); zlistx_destroy (&headers); zstr_free (&url); } else if (streq (command, "POST")) { char *url; zlistx_t *headers; zchunk_t *body; int timeout; void *handler; void *arg; int rc = zsock_recv (pipe, "slcipp", &url, &headers, &body, &timeout, &handler, &arg); assert (rc == 0); zchunk_t *response = zchunk_new (NULL, 100); assert (response); struct curl_slist *curl_headers = zlistx_to_slist (headers); CURL *curl = curl_easy_init (); zlistx_add_end (pending_handles, curl); http_request *request = (http_request *) zmalloc (sizeof (http_request)); assert (request); request->handler = handler; request->arg = arg; request->curl = curl; request->response = response; request->headers = curl_headers; request->body = body; curl_easy_setopt (curl, CURLOPT_SHARE, share); curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS, (long)timeout); curl_easy_setopt (curl, CURLOPT_VERBOSE, verbose); curl_easy_setopt (curl, CURLOPT_POSTFIELDS, zchunk_data (body)); curl_easy_setopt (curl, CURLOPT_POSTFIELDSIZE, zchunk_size (body)); curl_easy_setopt (curl, CURLOPT_HTTPHEADER, curl_headers); curl_easy_setopt (curl, CURLOPT_URL, url); curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, write_data); curl_easy_setopt (curl, CURLOPT_WRITEDATA, response); curl_easy_setopt (curl, CURLOPT_PRIVATE, request); code = curl_multi_add_handle (multi, curl); assert (code == CURLM_OK); zlistx_destroy (&headers); zstr_free (&url); } else { puts ("E: invalid message to actor"); assert (false); } zstr_free (&command); } int still_running; code = curl_multi_perform (multi, &still_running); assert (code == CURLM_OK); int msgq = 0; struct CURLMsg *msg = curl_multi_info_read (multi, &msgq); while (msg) { if (msg->msg == CURLMSG_DONE) { CURL *curl = msg->easy_handle; http_request *request; curl_easy_getinfo (curl, CURLINFO_PRIVATE, &request); long response_code_long; curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &response_code_long); int response_code = (int) response_code_long; if (response_code == 0 && msg->data.result == CURLE_OPERATION_TIMEDOUT) response_code = -1; int rc = zsock_send (pipe, "icpp", response_code, request->response, request->handler, request->arg); assert (rc == 0); curl_multi_remove_handle (multi, curl); // Remove curl from the pending handles and delete it void *handle = zlistx_find (pending_handles, curl); assert (handle); rc = zlistx_delete (pending_handles, handle); assert (rc == 0); } msg = curl_multi_info_read (multi, &msgq); } } zlistx_destroy (&pending_handles); curl_share_cleanup (share); curl_multi_cleanup (multi); curl_global_cleanup (); }
/// // Return chunk data byte * QZchunk::data () { byte * rv = zchunk_data (self); return rv; }
static void get_next_patch_for_client (server_t *self, client_t *client) { // Get next patch for client if we're not doing one already if (client->patch == NULL) client->patch = (zdir_patch_t *) zlist_pop (client->patches); if (client->patch == NULL) { client->next_event = finished_event; return; } // Get virtual path from patch fmq_msg_set_filename (client->reply, zdir_patch_vpath (client->patch)); // We can process a delete patch right away if (zdir_patch_op (client->patch) == patch_delete) { fmq_msg_set_sequence (client->reply, client->sequence++); fmq_msg_set_operation (client->reply, FMQ_MSG_FILE_DELETE); client->next_event = send_delete_event; // No reliability in this version, assume patch delivered safely zdir_patch_destroy (&client->patch); } else if (zdir_patch_op (client->patch) == patch_create) { // Create patch refers to file, open that for input if needed if (client->file == NULL) { client->file = zfile_dup (zdir_patch_file (client->patch)); if (zfile_input (client->file)) { // File no longer available, skip it zdir_patch_destroy (&client->patch); zfile_destroy (&client->file); client->next_event = next_patch_event; return; } client->offset = 0; } // Get next chunk for file zchunk_t *chunk = zfile_read (client->file, CHUNK_SIZE, client->offset); assert (chunk); // Check if we have the credit to send chunk if (zchunk_size (chunk) <= client->credit) { fmq_msg_set_sequence (client->reply, client->sequence++); fmq_msg_set_operation (client->reply, FMQ_MSG_FILE_CREATE); fmq_msg_set_offset (client->reply, client->offset); fmq_msg_set_chunk (client->reply, zframe_new ( zchunk_data (chunk), zchunk_size (chunk))); client->offset += zchunk_size (chunk); client->credit -= zchunk_size (chunk); client->next_event = send_chunk_event; // Zero-sized chunk means end of file if (zchunk_size (chunk) == 0) { zfile_destroy (&client->file); zdir_patch_destroy (&client->patch); } } else client->next_event = no_credit_event; zchunk_destroy (&chunk); } }
void zproto_example_test (bool verbose) { printf (" * zproto_example:"); if (verbose) printf ("\n"); // @selftest // Simple create/destroy test zproto_example_t *self = zproto_example_new (); assert (self); zproto_example_destroy (&self); // Create pair of sockets we can send through // We must bind before connect if we wish to remain compatible with ZeroMQ < v4 zsock_t *output = zsock_new (ZMQ_DEALER); assert (output); int rc = zsock_bind (output, "inproc://selftest-zproto_example"); assert (rc == 0); zsock_t *input = zsock_new (ZMQ_ROUTER); assert (input); rc = zsock_connect (input, "inproc://selftest-zproto_example"); assert (rc == 0); // Encode/send/decode and verify each message type int instance; self = zproto_example_new (); zproto_example_set_id (self, ZPROTO_EXAMPLE_LOG); zproto_example_set_sequence (self, 123); zproto_example_set_level (self, 2); zproto_example_set_event (self, 3); zproto_example_set_node (self, 45536); zproto_example_set_peer (self, 65535); zproto_example_set_time (self, 1427261426); zproto_example_set_host (self, "localhost"); zproto_example_set_data (self, "This is the message to log"); // Send twice zproto_example_send (self, output); zproto_example_send (self, output); for (instance = 0; instance < 2; instance++) { zproto_example_recv (self, input); assert (zproto_example_routing_id (self)); assert (zproto_example_sequence (self) == 123); assert (zproto_example_level (self) == 2); assert (zproto_example_event (self) == 3); assert (zproto_example_node (self) == 45536); assert (zproto_example_peer (self) == 65535); assert (zproto_example_time (self) == 1427261426); assert (streq (zproto_example_host (self), "localhost")); assert (streq (zproto_example_data (self), "This is the message to log")); } zproto_example_set_id (self, ZPROTO_EXAMPLE_STRUCTURES); zproto_example_set_sequence (self, 123); zlist_t *structures_aliases = zlist_new (); zlist_append (structures_aliases, "First alias"); zlist_append (structures_aliases, "Second alias"); zlist_append (structures_aliases, "Third alias"); zproto_example_set_aliases (self, &structures_aliases); zhash_t *structures_headers = zhash_new (); zhash_insert (structures_headers, "endpoint", "tcp://*****:*****@example.com"); zproto_example_set_supplier_forename (self, "Leslie"); zproto_example_set_supplier_surname (self, "Lamport"); zproto_example_set_supplier_mobile (self, "01987654321"); zproto_example_set_supplier_email (self, "*****@*****.**"); // Send twice zproto_example_send (self, output); zproto_example_send (self, output); for (instance = 0; instance < 2; instance++) { zproto_example_recv (self, input); assert (zproto_example_routing_id (self)); assert (zproto_example_sequence (self) == 123); assert (streq (zproto_example_client_forename (self), "Lucius Junius")); assert (streq (zproto_example_client_surname (self), "Brutus")); assert (streq (zproto_example_client_mobile (self), "01234567890")); assert (streq (zproto_example_client_email (self), "*****@*****.**")); assert (streq (zproto_example_supplier_forename (self), "Leslie")); assert (streq (zproto_example_supplier_surname (self), "Lamport")); assert (streq (zproto_example_supplier_mobile (self), "01987654321")); assert (streq (zproto_example_supplier_email (self), "*****@*****.**")); } zproto_example_destroy (&self); zsock_destroy (&input); zsock_destroy (&output); // @end printf ("OK\n"); }
int zproto_example_send (zproto_example_t *self, zsock_t *output) { assert (self); assert (output); if (zsock_type (output) == ZMQ_ROUTER) zframe_send (&self->routing_id, output, ZFRAME_MORE + ZFRAME_REUSE); size_t frame_size = 2 + 1; // Signature and message ID switch (self->id) { case ZPROTO_EXAMPLE_LOG: frame_size += 2; // sequence frame_size += 2; // version frame_size += 1; // level frame_size += 1; // event frame_size += 2; // node frame_size += 2; // peer frame_size += 8; // time frame_size += 1 + strlen (self->host); frame_size += 4; if (self->data) frame_size += strlen (self->data); break; case ZPROTO_EXAMPLE_STRUCTURES: frame_size += 2; // sequence frame_size += 4; // Size is 4 octets if (self->aliases) { char *aliases = (char *) zlist_first (self->aliases); while (aliases) { frame_size += 4 + strlen (aliases); aliases = (char *) zlist_next (self->aliases); } } frame_size += 4; // Size is 4 octets if (self->headers) { self->headers_bytes = 0; char *item = (char *) zhash_first (self->headers); while (item) { self->headers_bytes += 1 + strlen (zhash_cursor (self->headers)); self->headers_bytes += 4 + strlen (item); item = (char *) zhash_next (self->headers); } } frame_size += self->headers_bytes; break; case ZPROTO_EXAMPLE_BINARY: frame_size += 2; // sequence frame_size += 4; // flags frame_size += 4; // Size is 4 octets if (self->public_key) frame_size += zchunk_size (self->public_key); frame_size += ZUUID_LEN; // identifier break; case ZPROTO_EXAMPLE_TYPES: frame_size += 2; // sequence frame_size += 1 + strlen (self->client_forename); frame_size += 1 + strlen (self->client_surname); frame_size += 1 + strlen (self->client_mobile); frame_size += 1 + strlen (self->client_email); frame_size += 1 + strlen (self->supplier_forename); frame_size += 1 + strlen (self->supplier_surname); frame_size += 1 + strlen (self->supplier_mobile); frame_size += 1 + strlen (self->supplier_email); break; } // Now serialize message into the frame zmq_msg_t frame; zmq_msg_init_size (&frame, frame_size); self->needle = (byte *) zmq_msg_data (&frame); PUT_NUMBER2 (0xAAA0 | 0); PUT_NUMBER1 (self->id); bool have_content = false; size_t nbr_frames = 1; // Total number of frames to send switch (self->id) { case ZPROTO_EXAMPLE_LOG: PUT_NUMBER2 (self->sequence); PUT_NUMBER2 (3); PUT_NUMBER1 (self->level); PUT_NUMBER1 (self->event); PUT_NUMBER2 (self->node); PUT_NUMBER2 (self->peer); PUT_NUMBER8 (self->time); PUT_STRING (self->host); if (self->data) { PUT_LONGSTR (self->data); } else PUT_NUMBER4 (0); // Empty string break; case ZPROTO_EXAMPLE_STRUCTURES: PUT_NUMBER2 (self->sequence); if (self->aliases) { PUT_NUMBER4 (zlist_size (self->aliases)); char *aliases = (char *) zlist_first (self->aliases); while (aliases) { PUT_LONGSTR (aliases); aliases = (char *) zlist_next (self->aliases); } } else PUT_NUMBER4 (0); // Empty string array if (self->headers) { PUT_NUMBER4 (zhash_size (self->headers)); char *item = (char *) zhash_first (self->headers); while (item) { PUT_STRING (zhash_cursor (self->headers)); PUT_LONGSTR (item); item = (char *) zhash_next (self->headers); } } else PUT_NUMBER4 (0); // Empty hash break; case ZPROTO_EXAMPLE_BINARY: PUT_NUMBER2 (self->sequence); PUT_OCTETS (self->flags, 4); if (self->public_key) { PUT_NUMBER4 (zchunk_size (self->public_key)); memcpy (self->needle, zchunk_data (self->public_key), zchunk_size (self->public_key)); self->needle += zchunk_size (self->public_key); } else PUT_NUMBER4 (0); // Empty chunk if (self->identifier) zuuid_export (self->identifier, self->needle); else memset (self->needle, 0, ZUUID_LEN); self->needle += ZUUID_LEN; nbr_frames++; nbr_frames += self->content? zmsg_size (self->content): 1; have_content = true; break; case ZPROTO_EXAMPLE_TYPES: PUT_NUMBER2 (self->sequence); PUT_STRING (self->client_forename); PUT_STRING (self->client_surname); PUT_STRING (self->client_mobile); PUT_STRING (self->client_email); PUT_STRING (self->supplier_forename); PUT_STRING (self->supplier_surname); PUT_STRING (self->supplier_mobile); PUT_STRING (self->supplier_email); break; } // Now send the data frame zmq_msg_send (&frame, zsock_resolve (output), --nbr_frames? ZMQ_SNDMORE: 0); // Now send any frame fields, in order if (self->id == ZPROTO_EXAMPLE_BINARY) { // If address isn't set, send an empty frame if (self->address) zframe_send (&self->address, output, ZFRAME_REUSE + (--nbr_frames? ZFRAME_MORE: 0)); else zmq_send (zsock_resolve (output), NULL, 0, (--nbr_frames? ZMQ_SNDMORE: 0)); } // Now send the content if necessary if (have_content) { if (self->content) { zframe_t *frame = zmsg_first (self->content); while (frame) { zframe_send (&frame, output, ZFRAME_REUSE + (--nbr_frames? ZFRAME_MORE: 0)); frame = zmsg_next (self->content); } } else zmq_send (zsock_resolve (output), NULL, 0, 0); } return 0; }
void zconfig_test (bool verbose) { printf (" * zconfig: "); // @selftest const char *SELFTEST_DIR_RW = "src/selftest-rw"; const char *testbasedir = ".test_zconfig"; const char *testfile = "test.cfg"; char *basedirpath = NULL; // subdir in a test, under SELFTEST_DIR_RW char *filepath = NULL; // pathname to testfile in a test, in dirpath basedirpath = zsys_sprintf ("%s/%s", SELFTEST_DIR_RW, testbasedir); assert (basedirpath); filepath = zsys_sprintf ("%s/%s", basedirpath, testfile); assert (filepath); // Make sure old aborted tests do not hinder us zdir_t *dir = zdir_new (basedirpath, NULL); if (dir) { zdir_remove (dir, true); zdir_destroy (&dir); } zsys_file_delete (filepath); zsys_dir_delete (basedirpath); // Create temporary directory for test files zsys_dir_create (basedirpath); zconfig_t *root = zconfig_new ("root", NULL); assert (root); zconfig_t *section, *item; section = zconfig_new ("headers", root); assert (section); item = zconfig_new ("email", section); assert (item); zconfig_set_value (item, "*****@*****.**"); item = zconfig_new ("name", section); assert (item); zconfig_set_value (item, "Justin Kayce"); zconfig_putf (root, "/curve/secret-key", "%s", "Top Secret"); zconfig_set_comment (root, " CURVE certificate"); zconfig_set_comment (root, " -----------------"); assert (zconfig_comments (root)); zconfig_save (root, filepath); zconfig_destroy (&root); root = zconfig_load (filepath); if (verbose) zconfig_save (root, "-"); assert (streq (zconfig_filename (root), filepath)); char *email = zconfig_get (root, "/headers/email", NULL); assert (email); assert (streq (email, "*****@*****.**")); char *passwd = zconfig_get (root, "/curve/secret-key", NULL); assert (passwd); assert (streq (passwd, "Top Secret")); zconfig_savef (root, "%s/%s", basedirpath, testfile); assert (!zconfig_has_changed (root)); int rc = zconfig_reload (&root); assert (rc == 0); assert (!zconfig_has_changed (root)); zconfig_destroy (&root); // Test chunk load/save root = zconfig_new ("root", NULL); assert (root); section = zconfig_new ("section", root); assert (section); item = zconfig_new ("value", section); assert (item); zconfig_set_value (item, "somevalue"); zconfig_t *search = zconfig_locate (root, "section/value"); assert (search == item); zchunk_t *chunk = zconfig_chunk_save (root); assert (strlen ((char *) zchunk_data (chunk)) == 32); char *string = zconfig_str_save (root); assert (string); assert (streq (string, (char *) zchunk_data (chunk))); freen (string); assert (chunk); zconfig_destroy (&root); root = zconfig_chunk_load (chunk); assert (root); char *value = zconfig_get (root, "/section/value", NULL); assert (value); assert (streq (value, "somevalue")); // Test config can't be saved to a file in a path that doesn't // exist or isn't writable rc = zconfig_savef (root, "%s/path/that/doesnt/exist/%s", basedirpath, testfile); assert (rc == -1); zconfig_destroy (&root); zchunk_destroy (&chunk); // Test subtree removal { zconfig_t *root = zconfig_str_load ( "context\n" " iothreads = 1\n" " verbose = 1 # Ask for a trace\n" "main\n" " type = zqueue # ZMQ_DEVICE type\n" " frontend\n" " option\n" " hwm = 1000\n" " swap = 25000000 # 25MB\n" " bind = 'inproc://addr1'\n" " bind = 'ipc://addr2'\n" " backend\n" " bind = inproc://addr3\n" ); zconfig_t *to_delete = zconfig_locate (root, "main/frontend"); assert (to_delete); zconfig_remove (to_delete); char *value = zconfig_get (root, "/main/type", NULL); assert (value); assert (streq (value, "zqueue")); value = zconfig_get (root, "/main/backend/bind", NULL); assert (value); assert (streq (value, "inproc://addr3")); value = zconfig_get (root, "/main/frontend", NULL); assert (value); value = zconfig_get (root, "/main/frontend/option", NULL); assert (value == NULL); value = zconfig_get (root, "/main/frontend/option/swap", NULL); assert (value == NULL); zconfig_destroy (&root); } // Test str_load zconfig_t *config = zconfig_str_load ( "malamute\n" " endpoint = ipc://@/malamute\n" " producer = STREAM\n" " consumer\n" " STREAM2 = .*\n" " STREAM3 = HAM\n" "server\n" " verbose = true\n" ); assert (config); assert (streq (zconfig_get (config, "malamute/endpoint", NULL), "ipc://@/malamute")); assert (streq (zconfig_get (config, "malamute/producer", NULL), "STREAM")); assert (zconfig_locate (config, "malamute/consumer")); zconfig_t *c = zconfig_child (zconfig_locate (config, "malamute/consumer")); assert (c); assert (streq (zconfig_name (c), "STREAM2")); assert (streq (zconfig_value (c), ".*")); c = zconfig_next (c); assert (c); assert (streq (zconfig_name (c), "STREAM3")); assert (streq (zconfig_value (c), "HAM")); c = zconfig_next (c); assert (!c); assert (streq (zconfig_get (config, "server/verbose", NULL), "true")); zconfig_destroy (&config); // Delete all test files dir = zdir_new (basedirpath, NULL); assert (dir); zdir_remove (dir, true); zdir_destroy (&dir); zstr_free (&basedirpath); zstr_free (&filepath); #if defined (__WINDOWS__) zsys_shutdown(); #endif // @end printf ("OK\n"); }
void fmq_msg_test (bool verbose) { printf (" * fmq_msg:"); if (verbose) printf ("\n"); // @selftest // Simple create/destroy test fmq_msg_t *self = fmq_msg_new (); assert (self); fmq_msg_destroy (&self); // Create pair of sockets we can send through // We must bind before connect if we wish to remain compatible with ZeroMQ < v4 zsock_t *output = zsock_new (ZMQ_DEALER); assert (output); int rc = zsock_bind (output, "inproc://selftest-fmq_msg"); assert (rc == 0); zsock_t *input = zsock_new (ZMQ_ROUTER); assert (input); rc = zsock_connect (input, "inproc://selftest-fmq_msg"); assert (rc == 0); // Encode/send/decode and verify each message type int instance; self = fmq_msg_new (); fmq_msg_set_id (self, FMQ_MSG_OHAI); // Send twice fmq_msg_send (self, output); fmq_msg_send (self, output); for (instance = 0; instance < 2; instance++) { fmq_msg_recv (self, input); assert (fmq_msg_routing_id (self)); } fmq_msg_set_id (self, FMQ_MSG_OHAI_OK); // Send twice fmq_msg_send (self, output); fmq_msg_send (self, output); for (instance = 0; instance < 2; instance++) { fmq_msg_recv (self, input); assert (fmq_msg_routing_id (self)); } fmq_msg_set_id (self, FMQ_MSG_ICANHAZ); fmq_msg_set_path (self, "Life is short but Now lasts for ever"); zhash_t *icanhaz_options = zhash_new (); zhash_insert (icanhaz_options, "Name", "Brutus"); fmq_msg_set_options (self, &icanhaz_options); zhash_t *icanhaz_cache = zhash_new (); zhash_insert (icanhaz_cache, "Name", "Brutus"); fmq_msg_set_cache (self, &icanhaz_cache); // Send twice fmq_msg_send (self, output); fmq_msg_send (self, output); for (instance = 0; instance < 2; instance++) { fmq_msg_recv (self, input); assert (fmq_msg_routing_id (self)); assert (streq (fmq_msg_path (self), "Life is short but Now lasts for ever")); zhash_t *options = fmq_msg_get_options (self); assert (zhash_size (options) == 2); assert (streq ((char *) zhash_first (options), "Brutus")); assert (streq ((char *) zhash_cursor (options), "Name")); zhash_destroy (&options); if (instance == 1) zhash_destroy (&icanhaz_options); zhash_t *cache = fmq_msg_get_cache (self); assert (zhash_size (cache) == 2); assert (streq ((char *) zhash_first (cache), "Brutus")); assert (streq ((char *) zhash_cursor (cache), "Name")); zhash_destroy (&cache); if (instance == 1) zhash_destroy (&icanhaz_cache); } fmq_msg_set_id (self, FMQ_MSG_ICANHAZ_OK); // Send twice fmq_msg_send (self, output); fmq_msg_send (self, output); for (instance = 0; instance < 2; instance++) { fmq_msg_recv (self, input); assert (fmq_msg_routing_id (self)); } fmq_msg_set_id (self, FMQ_MSG_NOM); fmq_msg_set_credit (self, 123); fmq_msg_set_sequence (self, 123); // Send twice fmq_msg_send (self, output); fmq_msg_send (self, output); for (instance = 0; instance < 2; instance++) { fmq_msg_recv (self, input); assert (fmq_msg_routing_id (self)); assert (fmq_msg_credit (self) == 123); assert (fmq_msg_sequence (self) == 123); } fmq_msg_set_id (self, FMQ_MSG_CHEEZBURGER); fmq_msg_set_sequence (self, 123); fmq_msg_set_operation (self, 123); fmq_msg_set_filename (self, "Life is short but Now lasts for ever"); fmq_msg_set_offset (self, 123); fmq_msg_set_eof (self, 123); zhash_t *cheezburger_headers = zhash_new (); zhash_insert (cheezburger_headers, "Name", "Brutus"); fmq_msg_set_headers (self, &cheezburger_headers); zchunk_t *cheezburger_chunk = zchunk_new ("Captcha Diem", 12); fmq_msg_set_chunk (self, &cheezburger_chunk); // Send twice fmq_msg_send (self, output); fmq_msg_send (self, output); for (instance = 0; instance < 2; instance++) { fmq_msg_recv (self, input); assert (fmq_msg_routing_id (self)); assert (fmq_msg_sequence (self) == 123); assert (fmq_msg_operation (self) == 123); assert (streq (fmq_msg_filename (self), "Life is short but Now lasts for ever")); assert (fmq_msg_offset (self) == 123); assert (fmq_msg_eof (self) == 123); zhash_t *headers = fmq_msg_get_headers (self); assert (zhash_size (headers) == 2); assert (streq ((char *) zhash_first (headers), "Brutus")); assert (streq ((char *) zhash_cursor (headers), "Name")); zhash_destroy (&headers); if (instance == 1) zhash_destroy (&cheezburger_headers); assert (memcmp (zchunk_data (fmq_msg_chunk (self)), "Captcha Diem", 12) == 0); if (instance == 1) zchunk_destroy (&cheezburger_chunk); } fmq_msg_set_id (self, FMQ_MSG_HUGZ); // Send twice fmq_msg_send (self, output); fmq_msg_send (self, output); for (instance = 0; instance < 2; instance++) { fmq_msg_recv (self, input); assert (fmq_msg_routing_id (self)); } fmq_msg_set_id (self, FMQ_MSG_HUGZ_OK); // Send twice fmq_msg_send (self, output); fmq_msg_send (self, output); for (instance = 0; instance < 2; instance++) { fmq_msg_recv (self, input); assert (fmq_msg_routing_id (self)); } fmq_msg_set_id (self, FMQ_MSG_KTHXBAI); // Send twice fmq_msg_send (self, output); fmq_msg_send (self, output); for (instance = 0; instance < 2; instance++) { fmq_msg_recv (self, input); assert (fmq_msg_routing_id (self)); } fmq_msg_set_id (self, FMQ_MSG_SRSLY); fmq_msg_set_reason (self, "Life is short but Now lasts for ever"); // Send twice fmq_msg_send (self, output); fmq_msg_send (self, output); for (instance = 0; instance < 2; instance++) { fmq_msg_recv (self, input); assert (fmq_msg_routing_id (self)); assert (streq (fmq_msg_reason (self), "Life is short but Now lasts for ever")); } fmq_msg_set_id (self, FMQ_MSG_RTFM); fmq_msg_set_reason (self, "Life is short but Now lasts for ever"); // Send twice fmq_msg_send (self, output); fmq_msg_send (self, output); for (instance = 0; instance < 2; instance++) { fmq_msg_recv (self, input); assert (fmq_msg_routing_id (self)); assert (streq (fmq_msg_reason (self), "Life is short but Now lasts for ever")); } fmq_msg_destroy (&self); zsock_destroy (&input); zsock_destroy (&output); // @end printf ("OK\n"); }
void zconfig_test (bool verbose) { printf (" * zconfig: "); // @selftest // Create temporary directory for test files # define TESTDIR ".test_zconfig" zsys_dir_create (TESTDIR); zconfig_t *root = zconfig_new ("root", NULL); assert (root); zconfig_t *section, *item; section = zconfig_new ("headers", root); assert (section); item = zconfig_new ("email", section); assert (item); zconfig_set_value (item, "*****@*****.**"); item = zconfig_new ("name", section); assert (item); zconfig_set_value (item, "Justin Kayce"); zconfig_putf (root, "/curve/secret-key", "%s", "Top Secret"); zconfig_set_comment (root, " CURVE certificate"); zconfig_set_comment (root, " -----------------"); assert (zconfig_comments (root)); zconfig_save (root, TESTDIR "/test.cfg"); zconfig_destroy (&root); root = zconfig_load (TESTDIR "/test.cfg"); if (verbose) zconfig_save (root, "-"); assert (streq (zconfig_filename (root), TESTDIR "/test.cfg")); char *email = zconfig_get (root, "/headers/email", NULL); assert (email); assert (streq (email, "*****@*****.**")); char *passwd = zconfig_get (root, "/curve/secret-key", NULL); assert (passwd); assert (streq (passwd, "Top Secret")); zconfig_savef (root, "%s/%s", TESTDIR, "test.cfg"); assert (!zconfig_has_changed (root)); int rc = zconfig_reload (&root); assert (rc == 0); assert (!zconfig_has_changed (root)); zconfig_destroy (&root); // Test chunk load/save root = zconfig_new ("root", NULL); assert (root); section = zconfig_new ("section", root); assert (section); item = zconfig_new ("value", section); assert (item); zconfig_set_value (item, "somevalue"); zconfig_t *search = zconfig_locate (root, "section/value"); assert (search == item); zchunk_t *chunk = zconfig_chunk_save (root); assert (strlen ((char *) zchunk_data (chunk)) == 32); char *string = zconfig_str_save (root); assert (string); assert (streq (string, (char *) zchunk_data (chunk))); free (string); assert (chunk); zconfig_destroy (&root); root = zconfig_chunk_load (chunk); assert (root); char *value = zconfig_get (root, "/section/value", NULL); assert (value); assert (streq (value, "somevalue")); // Test config can't be saved to a file in a path that doesn't // exist or isn't writable rc = zconfig_savef (root, "%s/path/that/doesnt/exist/%s", TESTDIR, "test.cfg"); assert (rc == -1); zconfig_destroy (&root); zchunk_destroy (&chunk); // Delete all test files zdir_t *dir = zdir_new (TESTDIR, NULL); assert (dir); zdir_remove (dir, true); zdir_destroy (&dir); // @end printf ("OK\n"); }
void zsync_node_engine (void *args, zctx_t *ctx, void *pipe) { int rc; zsync_node_t *self = zsync_node_new (); self->ctx = ctx; self->zyre = zyre_new (ctx); self->zsync_pipe = pipe; // Join group rc = zyre_join (self->zyre, "ZSYNC"); assert (rc == 0); // Give time to interconnect zclock_sleep (250); zpoller_t *poller = zpoller_new (zyre_socket (self->zyre), self->zsync_pipe, NULL); // Create thread for file management self->file_pipe = zthread_fork (self->ctx, zsync_ftmanager_engine, NULL); zpoller_add (poller, self->file_pipe); // Create thread for credit management self->credit_pipe = zthread_fork (self->ctx, zsync_credit_manager_engine, NULL); zpoller_add (poller, self->credit_pipe); // Start receiving messages printf("[ND] started\n"); while (!zpoller_terminated (poller)) { void *which = zpoller_wait (poller, -1); if (which == zyre_socket (self->zyre)) { zsync_node_recv_from_zyre (self); } else if (which == self->zsync_pipe) { printf("[ND] Recv Agent\n"); zsync_node_recv_from_agent (self); } else if (which == self->file_pipe) { printf("[ND] Recv FT Manager\n"); zsync_ftm_msg_t *msg = zsync_ftm_msg_recv (self->file_pipe); char *receiver = zsync_ftm_msg_receiver (msg); char *zyre_uuid = zsync_node_zyre_uuid (self, receiver); if (zyre_uuid) { char *path = zsync_ftm_msg_path (msg); uint64_t sequence = zsync_ftm_msg_sequence (msg); uint64_t chunk_size = zsync_ftm_msg_chunk_size (msg); uint64_t offset = zsync_ftm_msg_offset (msg); zsync_msg_send_req_chunk (pipe, path, chunk_size, offset); zsync_msg_t *zsmsg = zsync_msg_recv (pipe); zchunk_t *chunk = zsync_msg_chunk (zsmsg); zframe_t *frame = zframe_new (zchunk_data (chunk), zchunk_size (chunk)); zmsg_t *zmsg = zmsg_new (); zs_msg_pack_chunk (zmsg, sequence, path, offset, frame); zyre_whisper (self->zyre, zyre_uuid, &zmsg); zsync_ftm_msg_destroy (&msg); zsync_msg_destroy (&zsmsg); } } else if (which == self->credit_pipe) { printf("[ND] Recv Credit Manager\n"); zsync_credit_msg_t *cmsg = zsync_credit_msg_recv (self->credit_pipe); char *receiver = zsync_credit_msg_receiver (cmsg); char *zyre_uuid = zsync_node_zyre_uuid (self, receiver); if (zyre_uuid) { zmsg_t *credit_msg = zsync_credit_msg_credit (cmsg); assert (rc == 0); zyre_whisper (self->zyre, zyre_uuid, &credit_msg); } zsync_credit_msg_destroy (&cmsg); } if (self->terminated) { break; } } zpoller_destroy (&poller); zsync_node_destroy (&self); printf("[ND] stopped\n"); }