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 * zchunk_unpack (zframe_t *frame) { assert(frame); assert(zframe_is(frame)); return zchunk_new (zframe_data (frame), zframe_size (frame) ); }
zchunk_t * zchunk_read (FILE *handle, size_t bytes) { assert (handle); zchunk_t *self = zchunk_new (NULL, bytes); self->size = fread (self->data, 1, bytes, handle); return self; }
zchunk_t * zchunk_dup (zchunk_t *self) { assert (self); assert (zchunk_is (self)); return zchunk_new (self->data, self->max_size); }
zconfig_t * zconfig_str_load (const char *string) { zchunk_t *chunk = zchunk_new (string, strlen (string)); zconfig_t *config = zconfig_chunk_load (chunk); zchunk_destroy (&chunk); return config; }
static void server_process_cluster_command ( server_t *self, const char *peer_id, const char *peer_name, zmsg_t *msg, bool unicast) { char *request = zmsg_popstr (msg); char *pipename = zmsg_popstr (msg); zsys_info ("peer=%s command=%s pipe=%s unicast=%d", peer_name, request, pipename? pipename: "-", unicast); // Lookup or create pipe // TODO: remote pipes need cleaning up with some timeout pipe_t *pipe = NULL; if (pipename) { pipe = (pipe_t *) zhash_lookup (self->pipes, pipename); if (!pipe) pipe = pipe_new (self, pipename); } if (pipe && streq (request, "HAVE WRITER")) pipe_attach_remote_writer (pipe, peer_id, unicast); else if (pipe && streq (request, "HAVE READER")) pipe_attach_remote_reader (pipe, peer_id, unicast); else if (pipe && streq (request, "DATA")) { // TODO encode these commands as proper protocol zframe_t *frame = zmsg_pop (msg); zchunk_t *chunk = zchunk_new (zframe_data (frame), zframe_size (frame)); if (pipe->writer == REMOTE_NODE && pipe->reader) { zsys_info ("send %d bytes to pipe", (int) zchunk_size (chunk)); pipe_send_data (pipe, &chunk); } else zsys_info ("discard %d bytes, unroutable", (int) zchunk_size (chunk)); zframe_destroy (&frame); zchunk_destroy (&chunk); } else if (pipe && streq (request, "DROP READER")) pipe_drop_remote_reader (&pipe, peer_id); else if (pipe && streq (request, "DROP WRITER")) pipe_drop_remote_writer (&pipe, peer_id); else if (streq (request, "DUMP")) zyre_dump (self->zyre); else zsys_warning ("bad request %s from %s", request, peer_name); zstr_free (&pipename); zstr_free (&request); }
JNIEXPORT jlong JNICALL Java_org_zeromq_czmq_Zchunk__1_1new (JNIEnv *env, jclass c, jbyteArray data, jlong size) { jbyte *data_ = (byte *) (*env)->GetByteArrayElements (env, data, 0); // Disable CZMQ signal handling; allow Java to deal with it zsys_handler_set (NULL); jlong new_ = (jlong) (intptr_t) zchunk_new (data_, (size_t) size); (*env)->ReleaseByteArrayElements (env, data, (jbyte *) data_, 0); return new_; }
void hydra_post_set_data (hydra_post_t *self, const void *data, size_t size) { assert (self); zstr_free (&self->location); zchunk_destroy (&self->content); self->content = zchunk_new (data, size); strcpy (self->digest, zchunk_digest (self->content)); self->content_size = zchunk_size (self->content); }
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; }
int zfile_test (bool verbose) { printf (" * zfile: "); // @selftest zfile_t *file = zfile_new (".", "bilbo"); assert (streq (zfile_filename (file, "."), "bilbo")); assert (zfile_is_readable (file) == false); zfile_destroy (&file); // Create a test file in some random subdirectory file = zfile_new ("./this/is/a/test", "bilbo"); int rc = zfile_output (file); assert (rc == 0); zchunk_t *chunk = zchunk_new (NULL, 100); zchunk_fill (chunk, 0, 100); // Write 100 bytes at position 1,000,000 in the file rc = zfile_write (file, chunk, 1000000); assert (rc == 0); zfile_close (file); assert (zfile_is_readable (file)); assert (zfile_cursize (file) == 1000100); assert (!zfile_is_stable (file)); zchunk_destroy (&chunk); zclock_sleep (1001); assert (zfile_is_stable (file)); // Check we can read from file rc = zfile_input (file); assert (rc == 0); chunk = zfile_read (file, 1000100, 0); assert (chunk); assert (zchunk_size (chunk) == 1000100); zchunk_destroy (&chunk); // Remove file and directory zdir_t *dir = zdir_new ("./this", NULL); assert (zdir_cursize (dir) == 1000100); zdir_remove (dir, true); assert (zdir_cursize (dir) == 0); zdir_destroy (&dir); // Check we can no longer read from file assert (!zfile_is_readable (file)); rc = zfile_input (file); assert (rc == -1); zfile_destroy (&file); // @end printf ("OK\n"); return 0; }
static parser_state_t* parser_state_new(zconfig_t* config, size_t id) { parser_state_t *state = zmalloc(sizeof(*state)); state->config = config; state->id = id; snprintf(state->me, 16, "parser[%zu]", id); state->pull_socket = parser_pull_socket_new(); state->push_socket = parser_push_socket_new(); state->decompression_buffer = zchunk_new(NULL, INITIAL_DECOMPRESSION_BUFFER_SIZE); return state; }
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; }
static void collect_data_to_send (client_t *self) { zsys_info ("read %d bytes", (int) zpipes_msg_size (self->request)); // Do we have enough data to satisfy the read request? size_t required = zpipes_msg_size (self->request); // If pipe was closed, we'll do a short read with as much // data as we have pending if (required > self->pending && self->pipe == NULL) required = self->pending; if (self->pipe == NULL && self->pending == 0) engine_set_exception (self, pipe_shut_event); else if (self->pending >= required) { // Create a bucket chunk with the required max size zchunk_t *bucket = zchunk_new (NULL, required); // Now fill the bucket with chunks from our queue while (zchunk_size (bucket) < required) { // Get next chunk and consume as much of it as possible zchunk_t *chunk = (zchunk_t *) zlist_pop (self->queue); assert (chunk); zchunk_consume (bucket, chunk); // If chunk is exhausted, destroy it if (zchunk_exhausted (chunk)) zchunk_destroy (&chunk); else { // Push chunk back for next time zlist_push (self->queue, chunk); assert (zchunk_size (bucket) == required); } } zpipes_msg_set_chunk (self->reply, &bucket); self->pending -= required; } else engine_set_exception (self, not_enough_data_event); }
ssize_t zpipes_client_write (zpipes_client_t *self, void *data, size_t size, int timeout) { assert (self); zchunk_t *chunk = zchunk_new (data, size); assert (chunk); zpipes_msg_t *request = zpipes_msg_new (ZPIPES_MSG_WRITE); zpipes_msg_set_chunk (request, &chunk); zpipes_msg_set_timeout (request, timeout); zpipes_msg_send (&request, self->dealer); zpipes_msg_t *reply = zpipes_msg_recv (self->dealer); if (!reply) { self->error = EINTR; return -1; // Interrupted } ssize_t rc = size; if (zpipes_msg_id (reply) == ZPIPES_MSG_WRITE_TIMEOUT) { self->error = EAGAIN; rc = -1; } else if (zpipes_msg_id (reply) == ZPIPES_MSG_WRITE_FAILED) { // TODO: better error code? // This happens if we close a pipe while there's a pending write 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; }
int fmq_msg_recv (fmq_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 ("fmq_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 ("fmq_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 | 3)) { zsys_warning ("fmq_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 FMQ_MSG_OHAI: { char protocol [256]; GET_STRING (protocol); if (strneq (protocol, "FILEMQ")) { zsys_warning ("fmq_msg: protocol is invalid"); goto malformed; } } { uint16_t version; GET_NUMBER2 (version); if (version != FMQ_MSG_VERSION) { zsys_warning ("fmq_msg: version is invalid"); goto malformed; } } break; case FMQ_MSG_OHAI_OK: break; case FMQ_MSG_ICANHAZ: GET_LONGSTR (self->path); { size_t hash_size; GET_NUMBER4 (hash_size); self->options = zhash_new (); zhash_autofree (self->options); while (hash_size--) { char key [256]; char *value = NULL; GET_STRING (key); GET_LONGSTR (value); zhash_insert (self->options, key, value); free (value); } } { size_t hash_size; GET_NUMBER4 (hash_size); self->cache = zhash_new (); zhash_autofree (self->cache); while (hash_size--) { char key [256]; char *value = NULL; GET_STRING (key); GET_LONGSTR (value); zhash_insert (self->cache, key, value); free (value); } } break; case FMQ_MSG_ICANHAZ_OK: break; case FMQ_MSG_NOM: GET_NUMBER8 (self->credit); GET_NUMBER8 (self->sequence); break; case FMQ_MSG_CHEEZBURGER: GET_NUMBER8 (self->sequence); GET_NUMBER1 (self->operation); GET_LONGSTR (self->filename); GET_NUMBER8 (self->offset); GET_NUMBER1 (self->eof); { 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); } } { size_t chunk_size; GET_NUMBER4 (chunk_size); if (self->needle + chunk_size > (self->ceiling)) { zsys_warning ("fmq_msg: chunk is missing data"); goto malformed; } zchunk_destroy (&self->chunk); self->chunk = zchunk_new (self->needle, chunk_size); self->needle += chunk_size; } break; case FMQ_MSG_HUGZ: break; case FMQ_MSG_HUGZ_OK: break; case FMQ_MSG_KTHXBAI: break; case FMQ_MSG_SRSLY: GET_STRING (self->reason); break; case FMQ_MSG_RTFM: GET_STRING (self->reason); break; default: zsys_warning ("fmq_msg: bad message ID"); goto malformed; } // Successful return zmq_msg_close (&frame); return 0; // Error returns malformed: zsys_warning ("fmq_msg: fmq_msg malformed message, fail"); zmq_msg_close (&frame); return -1; // Invalid message }
void zfile_test (bool verbose) { printf (" * zfile: "); // @selftest zfile_t *file = zfile_new (NULL, "bilbo"); assert (streq (zfile_filename (file, "."), "bilbo")); assert (zfile_is_readable (file) == false); zfile_destroy (&file); // Create a test file in some random subdirectory file = zfile_new ("./this/is/a/test", "bilbo"); int rc = zfile_output (file); assert (rc == 0); zchunk_t *chunk = zchunk_new (NULL, 100); zchunk_fill (chunk, 0, 100); // Write 100 bytes at position 1,000,000 in the file rc = zfile_write (file, chunk, 1000000); assert (rc == 0); zchunk_destroy (&chunk); zfile_close (file); assert (zfile_is_readable (file)); assert (zfile_cursize (file) == 1000100); assert (!zfile_is_stable (file)); // Now append one byte to file from outside int handle = open ("./this/is/a/test/bilbo", O_WRONLY | O_TRUNC | O_BINARY, 0); assert (handle >= 0); rc = write (handle, "Hello, World\n", 13); assert (rc == 13); close (handle); assert (zfile_has_changed (file)); zclock_sleep (1001); assert (zfile_has_changed (file)); assert (!zfile_is_stable (file)); zfile_restat (file); assert (zfile_is_stable (file)); assert (streq (zfile_digest (file), "4AB299C8AD6ED14F31923DD94F8B5F5CB89DFB54")); // Check we can read from file rc = zfile_input (file); assert (rc == 0); chunk = zfile_read (file, 1000100, 0); assert (chunk); assert (zchunk_size (chunk) == 13); zchunk_destroy (&chunk); zfile_close (file); // Try some fun with symbolic links zfile_t *link = zfile_new ("./this/is/a/test", "bilbo.ln"); rc = zfile_output (link); assert (rc == 0); fprintf (zfile_handle (link), "./this/is/a/test/bilbo\n"); zfile_destroy (&link); link = zfile_new ("./this/is/a/test", "bilbo.ln"); rc = zfile_input (link); assert (rc == 0); chunk = zfile_read (link, 1000100, 0); assert (chunk); assert (zchunk_size (chunk) == 13); zchunk_destroy (&chunk); zfile_destroy (&link); // Remove file and directory zdir_t *dir = zdir_new ("./this", NULL); assert (zdir_cursize (dir) == 26); zdir_remove (dir, true); assert (zdir_cursize (dir) == 0); zdir_destroy (&dir); // Check we can no longer read from file assert (zfile_is_readable (file)); zfile_restat (file); assert (!zfile_is_readable (file)); rc = zfile_input (file); assert (rc == -1); zfile_destroy (&file); // @end printf ("OK\n"); }
/// // Create a new chunk of the specified size. If you specify the data, it // is copied into the chunk. If you do not specify the data, the chunk is // allocated and left empty, and you can then add data using zchunk_append. QZchunk::QZchunk (const void *data, size_t size, QObject *qObjParent) : QObject (qObjParent) { this->self = zchunk_new (data, size); }
void zhttp_client_test (bool verbose) { #if defined(HAVE_LIBCURL) && defined(ZMQ_STREAM) printf (" * zhttp_client: "); zsock_t *server = zsock_new_stream (NULL); int port = zsock_bind (server, "tcp://127.0.0.1:*"); char url[255]; sprintf (url, "http://127.0.0.1:%d", port); // @selftest // Simple create/destroy test zhttp_client_t *self = zhttp_client_new (verbose); assert (self); // Send the get request bool event = false; zlistx_t *headers = zlistx_new (); zlistx_add_end (headers, "Host: zeromq.org"); zhttp_client_get (self, url, headers, -1, test_handler, &event); zlistx_destroy (&headers); // Receive request on the server zchunk_t *routing_id = recv_http_request (server); // Send the response char* response = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nHello"; zsock_send (server, "cs", routing_id, response); zchunk_destroy (&routing_id); // Receive the response on the http client int rc = zhttp_client_wait (self, -1); assert (rc == 0); zhttp_client_execute (self); assert (event); // Send a POST request event = false; zchunk_t *body = zchunk_new ("World", 5); zhttp_client_post (self, url, NULL, body, -1, test_handler, &event); // Receive request on the server routing_id = recv_http_request (server); // Send the response zsock_send (server, "cs", routing_id, response); zchunk_destroy (&routing_id); // Receive the response on the http client rc = zhttp_client_wait (self, -1); assert (rc == 0); zhttp_client_execute (self); assert (event); // Timeout check event = false; zhttp_client_get (self, url, NULL, 1000, test_handler, &event); rc = zhttp_client_wait (self, 1200); assert (rc == 0); zhttp_client_execute (self); assert (event); // Sending another request, without being answer // Checking the client ability to stop while request are inprogres zhttp_client_get (self, url, NULL, -1, test_handler, NULL); zchunk_destroy (&body); zhttp_client_destroy (&self); zsock_destroy (&server); // @end printf ("OK\n"); #endif }
void zpipes_server_test (bool verbose) { printf (" * zpipes_server: \n"); if (verbose) printf ("\n"); // @selftest // Prepare test cases const char *endpoint = "ipc://@/zpipes/local"; zactor_t *server = zactor_new (zpipes_server, NULL); if (verbose) zstr_send (server, "VERBOSE"); zstr_sendx (server, "BIND", endpoint, NULL); zsock_t *writer = zsock_new_dealer (endpoint); assert (writer); zsock_t *writer2 = zsock_new_dealer (endpoint); assert (writer2); zsock_t *reader = zsock_new_dealer (endpoint); assert (reader); zsock_t *reader2 = zsock_new_dealer (endpoint); assert (reader2); zchunk_t *chunk = zchunk_new ("Hello, World", 12); int32_t timeout = 100; // -------------------------------------------------------------------- // Basic tests // Open writer on pipe zpipes_msg_send_output (writer, "test pipe"); if (s_expect_reply (writer, ZPIPES_MSG_OUTPUT_OK)) assert (false); // Write will timeout if there's no reader zpipes_msg_send_write (writer, chunk, timeout); if (s_expect_reply (writer, ZPIPES_MSG_WRITE_TIMEOUT)) assert (false); // Now open reader on pipe zpipes_msg_send_input (reader, "test pipe"); if (s_expect_reply (reader, ZPIPES_MSG_INPUT_OK)) assert (false); // Read will timeout if there's no data zpipes_msg_send_read (reader, 12, timeout); if (s_expect_reply (reader, ZPIPES_MSG_READ_TIMEOUT)) assert (false); // Write should now be successful zpipes_msg_send_write (writer, chunk, 0); if (s_expect_reply (writer, ZPIPES_MSG_WRITE_OK)) assert (false); // Read should now be successful zpipes_msg_send_read (reader, 12, 0); if (s_expect_reply (reader, ZPIPES_MSG_READ_OK)) assert (false); // Zero read request returns "end of pipe" zpipes_msg_send_read (reader, 0, 0); if (s_expect_reply (reader, ZPIPES_MSG_READ_END)) assert (false); // Close writer zpipes_msg_send_close (writer); if (s_expect_reply (writer, ZPIPES_MSG_CLOSE_OK)) assert (false); // Any read request returns "end of pipe" zpipes_msg_send_read (reader, 12, timeout); if (s_expect_reply (reader, ZPIPES_MSG_READ_END)) assert (false); // Close reader zpipes_msg_send_close (reader); if (s_expect_reply (reader, ZPIPES_MSG_CLOSE_OK)) assert (false); // -------------------------------------------------------------------- // Test pipelining (request queuing & filtering) // Open reader on pipe zpipes_msg_send_input (reader, "test pipe"); if (s_expect_reply (reader, ZPIPES_MSG_INPUT_OK)) assert (false); // Open writer on pipe zpipes_msg_send_output (writer, "test pipe"); if (s_expect_reply (writer, ZPIPES_MSG_OUTPUT_OK)) assert (false); // Pipeline three read requests zpipes_msg_send_read (reader, 12, timeout); zpipes_msg_send_read (reader, 12, timeout); zpipes_msg_send_read (reader, 12, timeout); // First read will return with a timeout if (s_expect_reply (reader, ZPIPES_MSG_READ_TIMEOUT)) assert (false); // Write chunk to pipe zpipes_msg_send_write (writer, chunk, 0); if (s_expect_reply (writer, ZPIPES_MSG_WRITE_OK)) assert (false); // Second read will succeed if (s_expect_reply (reader, ZPIPES_MSG_READ_OK)) assert (false); // Send PING, expect PING-OK back zpipes_msg_send_ping (reader); if (s_expect_reply (reader, ZPIPES_MSG_PING_OK)) assert (false); // Close writer zpipes_msg_send_close (writer); if (s_expect_reply (writer, ZPIPES_MSG_CLOSE_OK)) assert (false); // Third read will report end of pipe if (s_expect_reply (reader, ZPIPES_MSG_READ_END)) assert (false); // Close reader zpipes_msg_send_close (reader); if (s_expect_reply (reader, ZPIPES_MSG_CLOSE_OK)) assert (false); // Read now fails as pipe is closed zpipes_msg_send_read (reader, 12, timeout); if (s_expect_reply (reader, ZPIPES_MSG_INVALID)) assert (false); // Closing an already closed pipe is an error zpipes_msg_send_close (reader); if (s_expect_reply (reader, ZPIPES_MSG_INVALID)) assert (false); // -------------------------------------------------------------------- // Test read/close pipelining // Open reader on pipe zpipes_msg_send_input (reader, "test pipe"); if (s_expect_reply (reader, ZPIPES_MSG_INPUT_OK)) assert (false); // Open writer on pipe zpipes_msg_send_output (writer, "test pipe"); if (s_expect_reply (writer, ZPIPES_MSG_OUTPUT_OK)) assert (false); // Pipeline two read requests zpipes_msg_send_read (reader, 12, timeout); zpipes_msg_send_read (reader, 12, timeout); // Send PING, expect PING-OK back zpipes_msg_send_ping (reader); if (s_expect_reply (reader, ZPIPES_MSG_PING_OK)) assert (false); // Close reader zpipes_msg_send_close (reader); // First read now fails if (s_expect_reply (reader, ZPIPES_MSG_READ_FAILED)) assert (false); if (s_expect_reply (reader, ZPIPES_MSG_CLOSE_OK)) assert (false); // Second read is now invalid if (s_expect_reply (reader, ZPIPES_MSG_INVALID)) assert (false); // Close writer zpipes_msg_send_close (writer); if (s_expect_reply (writer, ZPIPES_MSG_CLOSE_OK)) assert (false); // -------------------------------------------------------------------- // Test reads and writes of different sizes // Open reader on pipe zpipes_msg_send_input (reader, "test pipe"); if (s_expect_reply (reader, ZPIPES_MSG_INPUT_OK)) assert (false); // Open writer on pipe zpipes_msg_send_output (writer, "test pipe"); if (s_expect_reply (writer, ZPIPES_MSG_OUTPUT_OK)) assert (false); // Write chunk to pipe zpipes_msg_send_write (writer, chunk, 0); if (s_expect_reply (writer, ZPIPES_MSG_WRITE_OK)) assert (false); // Close writer zpipes_msg_send_close (writer); if (s_expect_reply (writer, ZPIPES_MSG_CLOSE_OK)) assert (false); // Read back in several steps zpipes_msg_send_read (reader, 1, 0); if (s_expect_reply (reader, ZPIPES_MSG_READ_OK)) assert (false); zpipes_msg_send_read (reader, 2, 0); if (s_expect_reply (reader, ZPIPES_MSG_READ_OK)) assert (false); zpipes_msg_send_read (reader, 3, 0); if (s_expect_reply (reader, ZPIPES_MSG_READ_OK)) assert (false); zpipes_msg_send_read (reader, 3, 0); if (s_expect_reply (reader, ZPIPES_MSG_READ_OK)) assert (false); // We get a short read (3 bytes) zpipes_msg_send_read (reader, 100, 0); if (s_expect_reply (reader, ZPIPES_MSG_READ_OK)) assert (false); // Pipe is now empty zpipes_msg_send_read (reader, 100, 0); if (s_expect_reply (reader, ZPIPES_MSG_READ_END)) assert (false); // Close reader zpipes_msg_send_close (reader); if (s_expect_reply (reader, ZPIPES_MSG_CLOSE_OK)) assert (false); // -------------------------------------------------------------------- // Test connection expiry // Set connection timeout to 200 msecs zstr_sendx (server, "SET", "server/timeout", "200", NULL); // Open reader on pipe zpipes_msg_send_input (reader, "test pipe"); if (s_expect_reply (reader, ZPIPES_MSG_INPUT_OK)) assert (false); // Read will expire, we don't expect any response for this command zpipes_msg_send_read (reader, 12, 0); // Do nothing for long enough for the timeout to hit zclock_sleep (300); // Try again, server should now treat the client as disconnected zpipes_msg_send_read (reader, 12, 0); if (s_expect_reply (reader, ZPIPES_MSG_INVALID)) assert (false); // Now check that disconnection erases pipe contents // Open reader on pipe zpipes_msg_send_input (reader, "test pipe"); if (s_expect_reply (reader, ZPIPES_MSG_INPUT_OK)) assert (false); // Open writer on pipe zpipes_msg_send_output (writer, "test pipe"); if (s_expect_reply (writer, ZPIPES_MSG_OUTPUT_OK)) assert (false); // Write chunk to pipe zpipes_msg_send_write (writer, chunk, 0); if (s_expect_reply (writer, ZPIPES_MSG_WRITE_OK)) assert (false); // Do nothing for long enough for the timeout to hit // Both writer and reader should be disconnected zclock_sleep (300); // Open reader on pipe zpipes_msg_send_input (reader, "test pipe"); if (s_expect_reply (reader, ZPIPES_MSG_INPUT_OK)) assert (false); // Open writer on pipe zpipes_msg_send_output (writer, "test pipe"); if (s_expect_reply (writer, ZPIPES_MSG_OUTPUT_OK)) assert (false); // This read should timeout, as pipe is empty zpipes_msg_send_read (reader, 12, timeout); if (s_expect_reply (reader, ZPIPES_MSG_READ_TIMEOUT)) assert (false); // Close writer zpipes_msg_send_close (writer); if (s_expect_reply (writer, ZPIPES_MSG_CLOSE_OK)) assert (false); // Close reader zpipes_msg_send_close (reader); if (s_expect_reply (reader, ZPIPES_MSG_CLOSE_OK)) assert (false); // -------------------------------------------------------------------- // Test writer closing while reader still active // Open writer on pipe zpipes_msg_send_output (writer, "test pipe"); if (s_expect_reply (writer, ZPIPES_MSG_OUTPUT_OK)) assert (false); // Open reader on pipe zpipes_msg_send_input (reader, "test pipe"); if (s_expect_reply (reader, ZPIPES_MSG_INPUT_OK)) assert (false); // Write one chunk to pipe zpipes_msg_send_write (writer, chunk, 0); if (s_expect_reply (writer, ZPIPES_MSG_WRITE_OK)) assert (false); // Close writer, before reader has read data zpipes_msg_send_close (writer); if (s_expect_reply (writer, ZPIPES_MSG_CLOSE_OK)) assert (false); // Open writer on same pipe name zpipes_msg_send_output (writer, "test pipe"); if (s_expect_reply (writer, ZPIPES_MSG_OUTPUT_OK)) assert (false); // Read should still be successful zpipes_msg_send_read (reader, 12, 0); if (s_expect_reply (reader, ZPIPES_MSG_READ_OK)) assert (false); // Create second reader and open pipe for input zpipes_msg_send_input (reader2, "test pipe"); if (s_expect_reply (reader2, ZPIPES_MSG_INPUT_OK)) assert (false); // Write one chunk to pipe, will go to second instance zpipes_msg_send_write (writer, chunk, 0); if (s_expect_reply (writer, ZPIPES_MSG_WRITE_OK)) assert (false); // Pipe is terminated and empty zpipes_msg_send_read (reader, 0, 0); if (s_expect_reply (reader, ZPIPES_MSG_READ_END)) assert (false); // Reader2 should be successful zpipes_msg_send_read (reader2, 12, 0); if (s_expect_reply (reader2, ZPIPES_MSG_READ_OK)) assert (false); // Close reader zpipes_msg_send_close (reader); if (s_expect_reply (reader, ZPIPES_MSG_CLOSE_OK)) assert (false); // Close writer zpipes_msg_send_close (writer); if (s_expect_reply (writer, ZPIPES_MSG_CLOSE_OK)) assert (false); // Pipe is terminated and empty zpipes_msg_send_read (reader2, 0, 0); if (s_expect_reply (reader2, ZPIPES_MSG_READ_END)) assert (false); // Do that again to be sure it wasn't a coincidence :) zpipes_msg_send_read (reader2, 0, 0); if (s_expect_reply (reader2, ZPIPES_MSG_READ_END)) assert (false); // Close reader2 zpipes_msg_send_close (reader2); if (s_expect_reply (reader2, ZPIPES_MSG_CLOSE_OK)) assert (false); // -------------------------------------------------------------------- // Test reader closing while writer still active // Open writer on pipe zpipes_msg_send_output (writer, "test pipe"); if (s_expect_reply (writer, ZPIPES_MSG_OUTPUT_OK)) assert (false); // Open reader on pipe zpipes_msg_send_input (reader, "test pipe"); if (s_expect_reply (reader, ZPIPES_MSG_INPUT_OK)) assert (false); // Write one chunk to pipe zpipes_msg_send_write (writer, chunk, 0); if (s_expect_reply (writer, ZPIPES_MSG_WRITE_OK)) assert (false); // Read should be successful zpipes_msg_send_read (reader, 12, 0); if (s_expect_reply (reader, ZPIPES_MSG_READ_OK)) assert (false); // Close reader zpipes_msg_send_close (reader); if (s_expect_reply (reader, ZPIPES_MSG_CLOSE_OK)) assert (false); // Write should fail zpipes_msg_send_write (writer, chunk, 0); if (s_expect_reply (writer, ZPIPES_MSG_WRITE_FAILED)) assert (false); // Close writer zpipes_msg_send_close (writer); if (s_expect_reply (writer, ZPIPES_MSG_CLOSE_OK)) assert (false); // -------------------------------------------------------------------- // Two readers or writers on same pipe are not allowed // Open writer on pipe zpipes_msg_send_output (writer, "test pipe"); if (s_expect_reply (writer, ZPIPES_MSG_OUTPUT_OK)) assert (false); // Open second writer on pipe zpipes_msg_send_output (writer2, "test pipe"); if (s_expect_reply (writer2, ZPIPES_MSG_OUTPUT_FAILED)) assert (false); // Open reader on pipe zpipes_msg_send_input (reader, "test pipe"); if (s_expect_reply (reader, ZPIPES_MSG_INPUT_OK)) assert (false); // Open second reader on pipe zpipes_msg_send_input (reader2, "test pipe"); if (s_expect_reply (reader2, ZPIPES_MSG_INPUT_FAILED)) assert (false); // Close reader zpipes_msg_send_close (reader); if (s_expect_reply (reader, ZPIPES_MSG_CLOSE_OK)) assert (false); // Close writer zpipes_msg_send_close (writer); if (s_expect_reply (writer, ZPIPES_MSG_CLOSE_OK)) assert (false); // -------------------------------------------------------------------- // Test short read when writer closes // Open writer on pipe zpipes_msg_send_output (writer, "test pipe"); if (s_expect_reply (writer, ZPIPES_MSG_OUTPUT_OK)) assert (false); // Open reader on pipe zpipes_msg_send_input (reader, "test pipe"); if (s_expect_reply (reader, ZPIPES_MSG_INPUT_OK)) assert (false); // Write one chunk to pipe zpipes_msg_send_write (writer, chunk, 0); if (s_expect_reply (writer, ZPIPES_MSG_WRITE_OK)) assert (false); // Try to read large amount of data, will block zpipes_msg_send_read (reader, 1000, 0); // Close writer zpipes_msg_send_close (writer); if (s_expect_reply (writer, ZPIPES_MSG_CLOSE_OK)) assert (false); // Reader should now return short read if (s_expect_reply (reader, ZPIPES_MSG_READ_OK)) assert (false); // Pipe is terminated and empty zpipes_msg_send_read (reader, 0, 0); if (s_expect_reply (reader, ZPIPES_MSG_READ_END)) assert (false); // Close reader zpipes_msg_send_close (reader); if (s_expect_reply (reader, ZPIPES_MSG_CLOSE_OK)) assert (false); // -------------------------------------------------------------------- zchunk_destroy (&chunk); zactor_destroy (&server); zsock_destroy (&reader); zsock_destroy (&writer); zsock_destroy (&reader2); zsock_destroy (&writer2); // @end printf ("OK\n"); }
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"); }
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"); }
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 }
void zfile_test (bool verbose) { printf (" * zfile: "); // @selftest const char *SELFTEST_DIR_RW = "src/selftest-rw"; const char *testbasedir = "this"; const char *testsubdir = "is/a/test"; const char *testfile = "bilbo"; const char *testlink = "bilbo.ln"; char *basedirpath = NULL; // subdir in a test, under SELFTEST_DIR_RW char *dirpath = NULL; // subdir in a test, under basedirpath char *filepath = NULL; // pathname to testfile in a test, in dirpath char *linkpath = NULL; // pathname to testlink in a test, in dirpath basedirpath = zsys_sprintf ("%s/%s", SELFTEST_DIR_RW, testbasedir); assert (basedirpath); dirpath = zsys_sprintf ("%s/%s", basedirpath, testsubdir); assert (dirpath); filepath = zsys_sprintf ("%s/%s", dirpath, testfile); assert (filepath); linkpath = zsys_sprintf ("%s/%s", dirpath, testlink); assert (linkpath); // This subtest is specifically for NULL as current directory, so // no SELFTEST_DIR_RW here; testfile should have no slashes inside. // Normally tests clean up in zfile_destroy(), but if a selftest run // dies e.g. on assert(), workspace remains dirty. Better clean it up. if (zfile_exists (testfile) ) { if (verbose) zsys_debug ("zfile_test() has to remove ./%s that should not have been here", testfile); zfile_delete (testfile); } zfile_t *file = zfile_new (NULL, testfile); assert (file); assert (streq (zfile_filename (file, "."), testfile)); assert (zfile_is_readable (file) == false); zfile_destroy (&file); // Create a test file in some random subdirectory if (verbose) zsys_debug ("zfile_test() at timestamp %" PRIi64 ": " "Creating new zfile %s", zclock_time(), filepath ); if (zfile_exists (filepath) ) { if (verbose) zsys_debug ("zfile_test() has to remove %s that should not have been here", filepath); zfile_delete (filepath); } file = zfile_new (dirpath, testfile); assert (file); int rc = zfile_output (file); assert (rc == 0); zchunk_t *chunk = zchunk_new (NULL, 100); assert (chunk); zchunk_fill (chunk, 0, 100); // Write 100 bytes at position 1,000,000 in the file if (verbose) zsys_debug ("zfile_test() at timestamp %" PRIi64 ": " "Writing 100 bytes at position 1,000,000 in the file", zclock_time() ); rc = zfile_write (file, chunk, 1000000); if (verbose) zsys_debug ("zfile_test() at timestamp %" PRIi64 ": " "Wrote 100 bytes at position 1,000,000 in the file, result code %d", zclock_time(), rc ); assert (rc == 0); zchunk_destroy (&chunk); zfile_close (file); assert (zfile_is_readable (file)); assert (zfile_cursize (file) == 1000100); if (verbose) zsys_debug ("zfile_test() at timestamp %" PRIi64 ": " "Testing if file is NOT stable (is younger than 1 sec)", zclock_time() ); assert (!zfile_is_stable (file)); if (verbose) zsys_debug ("zfile_test() at timestamp %" PRIi64 ": " "Passed the lag-dependent tests", zclock_time() ); assert (zfile_digest (file)); // Now truncate file from outside int handle = open (filepath, O_WRONLY | O_TRUNC | O_BINARY, 0); assert (handle >= 0); rc = write (handle, "Hello, World\n", 13); assert (rc == 13); close (handle); assert (zfile_has_changed (file)); #ifdef CZMQ_BUILD_DRAFT_API zclock_sleep ((int)zsys_file_stable_age_msec() + 50); #else zclock_sleep (5050); #endif assert (zfile_has_changed (file)); assert (!zfile_is_stable (file)); zfile_restat (file); assert (zfile_is_stable (file)); assert (streq (zfile_digest (file), "4AB299C8AD6ED14F31923DD94F8B5F5CB89DFB54")); // Check we can read from file rc = zfile_input (file); assert (rc == 0); chunk = zfile_read (file, 1000100, 0); assert (chunk); assert (zchunk_size (chunk) == 13); zchunk_destroy (&chunk); zfile_close (file); // Check we can read lines from file rc = zfile_input (file); assert (rc == 0); const char *line = zfile_readln (file); assert (streq (line, "Hello, World")); line = zfile_readln (file); assert (line == NULL); zfile_close (file); // Try some fun with symbolic links zfile_t *link = zfile_new (dirpath, testlink); assert (link); rc = zfile_output (link); assert (rc == 0); fprintf (zfile_handle (link), "%s\n", filepath); zfile_destroy (&link); link = zfile_new (dirpath, testlink); assert (link); rc = zfile_input (link); assert (rc == 0); chunk = zfile_read (link, 1000100, 0); assert (chunk); assert (zchunk_size (chunk) == 13); zchunk_destroy (&chunk); zfile_destroy (&link); // Remove file and directory zdir_t *dir = zdir_new (basedirpath, NULL); assert (dir); assert (zdir_cursize (dir) == 26); zdir_remove (dir, true); assert (zdir_cursize (dir) == 0); zdir_destroy (&dir); // Check we can no longer read from file assert (zfile_is_readable (file)); zfile_restat (file); assert (!zfile_is_readable (file)); rc = zfile_input (file); assert (rc == -1); zfile_destroy (&file); // This set of tests is done, free the strings for reuse zstr_free (&basedirpath); zstr_free (&dirpath); zstr_free (&filepath); zstr_free (&linkpath); const char *eof_checkfile = "eof_checkfile"; filepath = zsys_sprintf ("%s/%s", SELFTEST_DIR_RW, eof_checkfile); assert (filepath); if (zfile_exists (filepath) ) { if (verbose) zsys_debug ("zfile_test() has to remove %s that should not have been here", filepath); zfile_delete (filepath); } zstr_free (&filepath); file = zfile_new (SELFTEST_DIR_RW, eof_checkfile); assert (file); // 1. Write something first rc = zfile_output (file); assert (rc == 0); chunk = zchunk_new ("123456789", 9); assert (chunk); rc = zfile_write (file, chunk, 0); assert (rc == 0); zchunk_destroy (&chunk); zfile_close (file); assert (zfile_cursize (file) == 9); // 2. Read the written something rc = zfile_input (file); assert (rc != -1); // try to read more bytes than there is in the file chunk = zfile_read (file, 1000, 0); assert (zfile_eof(file)); assert (zchunk_streq (chunk, "123456789")); zchunk_destroy (&chunk); // reading is ok chunk = zfile_read (file, 5, 0); assert (!zfile_eof(file)); assert (zchunk_streq (chunk, "12345")); zchunk_destroy (&chunk); // read from non zero offset until the end chunk = zfile_read (file, 5, 5); assert (zfile_eof(file)); assert (zchunk_streq (chunk, "6789")); zchunk_destroy (&chunk); zfile_remove (file); zfile_close (file); zfile_destroy (&file); #ifdef CZMQ_BUILD_DRAFT_API zfile_t *tempfile = zfile_tmp (); assert (tempfile); assert (zfile_filename (tempfile, NULL)); assert (zsys_file_exists (zfile_filename (tempfile, NULL))); zchunk_t *tchunk = zchunk_new ("HELLO", 6); assert (zfile_write (tempfile, tchunk, 0) == 0); zchunk_destroy (&tchunk); char *filename = strdup (zfile_filename (tempfile, NULL)); zfile_destroy (&tempfile); assert (!zsys_file_exists (filename)); zstr_free (&filename); #endif // CZMQ_BUILD_DRAFT_API #if defined (__WINDOWS__) zsys_shutdown(); #endif // @end printf ("OK\n"); }
static void handler (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; long timeout = 30; 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) { int events = zsock_events (pipe); if ((events & ZMQ_POLLIN) == 0) { code = curl_multi_wait (multi, &waitfd, 1, 1000, NULL); assert (code == CURLM_OK); } events = zsock_events (pipe); if (events & ZMQ_POLLIN) { 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; void *userp; int rc = zsock_recv (pipe, "slp", &url, &headers, &userp); assert (rc == 0); zchunk_t *data = zchunk_new (NULL, 100); assert (data); 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->userp = userp; request->curl = curl; request->data = data; request->headers = curl_headers; curl_easy_setopt (curl, CURLOPT_SHARE, share); curl_easy_setopt (curl, CURLOPT_TIMEOUT, 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, data); 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; int rc = zsock_send (pipe, "icp", response_code, request->data, request->userp); 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 (); }
static void zsync_node_recv_from_zyre (zsync_node_t *self) { zsync_peer_t *sender; char *zyre_sender; zuuid_t *sender_uuid; zmsg_t *zyre_in, *zyre_out, *fm_msg; zlist_t *fpaths, *fmetadata; zyre_event_t *event = zyre_event_recv (self->zyre); zyre_sender = zyre_event_sender (event); // get tmp uuid switch (zyre_event_type (event)) { case ZYRE_EVENT_ENTER: printf("[ND] ZS_ENTER: %s\n", zyre_sender); zhash_insert (self->zyre_peers, zyre_sender, NULL); break; case ZYRE_EVENT_JOIN: printf ("[ND] ZS_JOIN: %s\n", zyre_sender); // Obtain own current state zsync_msg_send_req_state (self->zsync_pipe); zsync_msg_t *msg_state = zsync_msg_recv (self->zsync_pipe); assert (zsync_msg_id (msg_state) == ZSYNC_MSG_RES_STATE); uint64_t state = zsync_msg_state (msg_state); // Send GREET message zyre_out = zmsg_new (); zs_msg_pack_greet (zyre_out, zuuid_data (self->own_uuid), state); zyre_whisper (self->zyre, zyre_sender, &zyre_out); break; case ZYRE_EVENT_LEAVE: break; case ZYRE_EVENT_EXIT: /* printf("[ND] ZS_EXIT %s left the house!\n", zyre_sender); sender = zhash_lookup (self->zyre_peers, zyre_sender); if (sender) { // Reset Managers zmsg_t *reset_msg = zmsg_new (); zmsg_addstr (reset_msg, zsync_peer_uuid (sender)); zmsg_addstr (reset_msg, "ABORT"); zmsg_send (&reset_msg, self->file_pipe); reset_msg = zmsg_new (); zmsg_addstr (reset_msg, zsync_peer_uuid (sender)); zmsg_addstr (reset_msg, "ABORT"); zmsg_send (&reset_msg, self->credit_pipe); // Remove Peer from active list zhash_delete (self->zyre_peers, zyre_sender); }*/ break; case ZYRE_EVENT_WHISPER: case ZYRE_EVENT_SHOUT: printf ("[ND] ZS_WHISPER: %s\n", zyre_sender); sender = zhash_lookup (self->zyre_peers, zyre_sender); zyre_in = zyre_event_msg (event); zs_msg_t *msg = zs_msg_unpack (zyre_in); switch (zs_msg_get_cmd (msg)) { case ZS_CMD_GREET: // Get perm uuid sender_uuid = zuuid_new (); zuuid_set (sender_uuid, zs_msg_uuid (msg)); sender = zsync_node_peers_lookup (self, zuuid_str (sender_uuid)); if (!sender) { sender = zsync_peer_new (zuuid_str (sender_uuid), 0x0); zlist_append (self->peers, sender); } assert (sender); zhash_update (self->zyre_peers, zyre_sender, sender); zsync_peer_set_zyre_state (sender, ZYRE_EVENT_JOIN); // Get current state for sender uint64_t remote_current_state = zs_msg_get_state (msg); printf ("[ND] current state: %"PRId64"\n", remote_current_state); // Lookup last known state uint64_t last_state_local = zsync_peer_state (sender); printf ("[ND] last known state: %"PRId64"\n", zsync_peer_state (sender)); // Send LAST_STATE if differs if (remote_current_state >= last_state_local) { zmsg_t *lmsg = zmsg_new (); zs_msg_pack_last_state (lmsg, last_state_local); zyre_whisper (self->zyre, zyre_sender, &lmsg); } break; case ZS_CMD_LAST_STATE: assert (sender); zyre_out = zmsg_new (); // Gets updates from client uint64_t last_state_remote = zs_msg_get_state (msg); zsync_msg_send_req_update (self->zsync_pipe, last_state_remote); zsync_msg_t *msg_upd = zsync_msg_recv (self->zsync_pipe); assert (zsync_msg_id (msg_upd) == ZSYNC_MSG_UPDATE); // Send UPDATE zyre_out = zsync_msg_update_msg (msg_upd); zyre_whisper (self->zyre, zyre_sender, &zyre_out); break; case ZS_CMD_UPDATE: printf ("[ND] UPDATE\n"); assert (sender); uint64_t state = zs_msg_get_state (msg); zsync_peer_set_state (sender, state); zsync_node_save_peers (self); fmetadata = zs_msg_get_fmetadata (msg); zmsg_t *zsync_msg = zmsg_new (); zs_msg_pack_update (zsync_msg, zs_msg_get_state (msg), fmetadata); zsync_msg_send_update (self->zsync_pipe, zsync_peer_uuid (sender), zsync_msg); break; case ZS_CMD_REQUEST_FILES: printf ("[ND] REQUEST FILES\n"); fpaths = zs_msg_fpaths (msg); zmsg_t *fm_msg = zmsg_new (); zmsg_addstr (fm_msg, zsync_peer_uuid (sender)); zmsg_addstr (fm_msg, "REQUEST"); char *fpath = zs_msg_fpaths_first (msg); while (fpath) { zmsg_addstr (fm_msg, fpath); printf("[ND] %s\n", fpath); fpath = zs_msg_fpaths_next (msg); } zmsg_send (&fm_msg, self->file_pipe); break; case ZS_CMD_GIVE_CREDIT: printf("[ND] GIVE CREDIT\n"); fm_msg = zmsg_new (); zmsg_addstr (fm_msg, zsync_peer_uuid (sender)); zmsg_addstr (fm_msg, "CREDIT"); zmsg_addstrf (fm_msg, "%"PRId64, zs_msg_get_credit (msg)); zmsg_send (&fm_msg, self->file_pipe); break; case ZS_CMD_SEND_CHUNK: printf("[ND] SEND_CHUNK (RCV)\n"); // Send receival to credit manager zframe_t *zframe = zs_msg_get_chunk (msg); uint64_t chunk_size = zframe_size (zframe); zsync_credit_msg_send_update (self->credit_pipe, zsync_peer_uuid (sender), chunk_size); // Pass chunk to client byte *data = zframe_data (zframe); zchunk_t *chunk = zchunk_new (data, chunk_size); char *path = zs_msg_get_file_path (msg); uint64_t seq = zs_msg_get_sequence (msg); uint64_t off = zs_msg_get_offset (msg); zsync_msg_send_chunk (self->zsync_pipe, chunk, path, seq, off); break; case ZS_CMD_ABORT: // TODO abort protocol managed file transfer printf("[ND] ABORT\n"); break; default: assert (false); break; } zs_msg_destroy (&msg); break; default: printf("[ND] Error command not found\n"); break; } zyre_event_destroy (&event); }