zcert_t * zcert_new_from (byte *public_key, byte *secret_key) { zcert_t *self = (zcert_t *) zmalloc (sizeof (zcert_t)); if (!self) return NULL; assert (public_key); assert (secret_key); self->metadata = zhash_new (); if (self->metadata) { zhash_autofree (self->metadata); memcpy (self->public_key, public_key, 32); memcpy (self->secret_key, secret_key, 32); #if (ZMQ_VERSION_MAJOR == 4) zmq_z85_encode (self->public_txt, self->public_key, 32); zmq_z85_encode (self->secret_txt, self->secret_key, 32); #else strcpy (self->public_txt, FORTY_ZEROES); strcpy (self->secret_txt, FORTY_ZEROES); #endif } else zcert_destroy (&self); return self; }
int zhash_load (zhash_t *self, char *filename) { assert (self); zhash_autofree (self); FILE *handle = fopen (filename, "r"); if (!handle) return -1; // Failed to create file char buffer [1024]; while (fgets (buffer, 1024, handle)) { // Skip lines starting with "#" if (buffer [0] == '#') continue; // Buffer may end in newline, which we don't want if (buffer [strlen (buffer) - 1] == '\n') buffer [strlen (buffer) - 1] = 0; // Split at equals, if any char *equals = strchr (buffer, '='); if (!equals) break; // Some error, stop parsing it *equals++ = 0; zhash_update (self, buffer, equals); } fclose (handle); return 0; }
static agent_t * s_agent_new (zctx_t *ctx, void *control) { agent_t *self = (agent_t *) zmalloc (sizeof (agent_t)); self->ctx = ctx; self->control = control; self->router = zsocket_new (ctx, ZMQ_ROUTER); // Connect our data socket to caller's endpoint self->data = zsocket_new (ctx, ZMQ_PAIR); char *endpoint = zstr_recv (self->control); int rc = zsocket_connect (self->data, "%s", endpoint); assert (rc != -1); free (endpoint); // Create new client codec using cert from API byte public_key [32]; byte secret_key [32]; rc = zmq_recv (self->control, public_key, 32, 0); assert (rc == 32); rc = zmq_recv (self->control, secret_key, 32, 0); assert (rc == 32); self->cert = zcert_new_from (public_key, secret_key); self->metadata = zhash_new (); zhash_autofree (self->metadata); self->clients = zhash_new (); self->max_clients = 100; self->max_pending = 10; self->client_ttl = 3600; // 60 minutes self->pending_ttl = 60; // 60 seconds return self; }
static zyre_node_t * zyre_node_new (zctx_t *ctx, void *pipe) { zyre_node_t *self = (zyre_node_t *) zmalloc (sizeof (zyre_node_t)); self->ctx = ctx; self->pipe = pipe; self->inbox = zsocket_new (ctx, ZMQ_ROUTER); if (self->inbox == NULL) { free (self); return NULL; // Interrupted 0MQ call } self->port = zsocket_bind (self->inbox, "tcp://*:*"); if (self->port < 0) { free (self); return NULL; // Interrupted 0MQ call } self->beacon = zbeacon_new (self->ctx, ZRE_DISCOVERY_PORT); if (!self->beacon) { free (self); return NULL; // Exhausted process sockets } self->uuid = zuuid_new (); self->peers = zhash_new (); self->peer_groups = zhash_new (); self->own_groups = zhash_new (); self->headers = zhash_new (); zhash_autofree (self->headers); return self; }
static zyre_node_t * zyre_node_new (zsock_t *pipe, void *args) { zyre_node_t *self = (zyre_node_t *) zmalloc (sizeof (zyre_node_t)); self->inbox = zsock_new (ZMQ_ROUTER); if (self->inbox == NULL) { free (self); return NULL; // Could not create new socket } // Use ZMQ_ROUTER_HANDOVER so that when a peer disconnects and // then reconnects, the new client connection is treated as the // canonical one, and any old trailing commands are discarded. zsock_set_router_handover (self->inbox, 1); self->pipe = pipe; self->outbox = (zsock_t *) args; self->poller = zpoller_new (self->pipe, NULL); self->beacon_port = ZRE_DISCOVERY_PORT; self->interval = 0; // Use default self->uuid = zuuid_new (); self->peers = zhash_new (); self->peer_groups = zhash_new (); self->own_groups = zhash_new (); self->headers = zhash_new (); zhash_autofree (self->headers); // Default name for node is first 6 characters of UUID: // the shorter string is more readable in logs self->name = (char *) zmalloc (7); memcpy (self->name, zuuid_str (self->uuid), 6); return self; }
static agent_t * agent_new (zctx_t *ctx, void *pipe) { void *inbox = zsocket_new (ctx, ZMQ_ROUTER); if (!inbox) // Interrupted return NULL; agent_t *self = (agent_t *) zmalloc (sizeof (agent_t)); self->ctx = ctx; self->pipe = pipe; self->udp = zre_udp_new (ZRE_DISCOVERY_PORT); self->inbox = inbox; self->host = zre_udp_host (self->udp); self->port = zsocket_bind (self->inbox, "tcp://*:*"); sprintf (self->endpoint, "%s:%d", self->host, self->port); if (self->port < 0) { // Interrupted zre_udp_destroy (&self->udp); free (self); return NULL; } self->uuid = zre_uuid_new (); self->identity = strdup (zre_uuid_str (self->uuid)); self->peers = zhash_new (); self->peer_groups = zhash_new (); self->own_groups = zhash_new (); self->headers = zhash_new (); zhash_autofree (self->headers); self->log = zre_log_new (self->endpoint); // Set up content distribution network: Each server binds to an // ephemeral port and publishes a temporary directory that acts // as the outbox for this node. // sprintf (self->fmq_outbox, "%s/send/%s", s_tmpdir (), self->identity); zfile_mkdir (self->fmq_outbox); sprintf (self->fmq_inbox, "%s/recv/%s", s_tmpdir (), self->identity); zfile_mkdir (self->fmq_inbox); self->fmq_server = fmq_server_new (); self->fmq_service = fmq_server_bind (self->fmq_server, "tcp://*:*"); fmq_server_publish (self->fmq_server, self->fmq_outbox, "/"); fmq_server_set_anonymous (self->fmq_server, true); char publisher [32]; sprintf (publisher, "tcp://%s:%d", self->host, self->fmq_service); zhash_update (self->headers, "X-FILEMQ", publisher); // Client will connect as it discovers new nodes self->fmq_client = fmq_client_new (); fmq_client_set_inbox (self->fmq_client, self->fmq_inbox); fmq_client_set_resync (self->fmq_client, true); fmq_client_subscribe (self->fmq_client, "/"); return self; }
int zhash_load (zhash_t *self, const char *filename) { assert (self); zhash_autofree (self); // Whether or not file exists, we'll track the filename and last // modification date (0 for unknown files), so that zhash_refresh () // will always work after zhash_load (), to load a newly-created // file. // Take copy of filename in case self->filename is same string. char *filename_copy = strdup (filename); if (filename_copy) { free (self->filename); self->filename = filename_copy; self->modified = zsys_file_modified (self->filename); FILE *handle = fopen (self->filename, "r"); if (handle) { char *buffer = (char *) zmalloc (1024); if (buffer) { while (fgets (buffer, 1024, handle)) { // Skip lines starting with "#" or that do not look like // name=value data. char *equals = strchr (buffer, '='); if (buffer [0] == '#' || equals == buffer || !equals) continue; // Buffer may end in newline, which we don't want if (buffer [strlen (buffer) - 1] == '\n') buffer [strlen (buffer) - 1] = 0; *equals++ = 0; zhash_update (self, buffer, equals); } free (buffer); } else { fclose (handle); return -1; // Out of memory } fclose (handle); } else return -1; // Failed to open file for reading } else return -1; // Out of memory return 0; }
zhash_t * zhash_unpack (zframe_t *frame) { zhash_t *self = zhash_new (); if (!self) return NULL; assert (frame); if (zframe_size (frame) < 4) return self; // Arguable... byte *needle = zframe_data (frame); byte *ceiling = needle + zframe_size (frame); size_t nbr_items = ntohl (*(uint32_t *) needle); needle += 4; while (nbr_items && needle < ceiling) { // Get key as string size_t key_size = *needle++; if (needle + key_size <= ceiling) { char key [256]; memcpy (key, needle, key_size); key [key_size] = 0; needle += key_size; // Get value as longstr if (needle + 4 <= ceiling) { size_t value_size = ntohl (*(uint32_t *) needle); needle += 4; // Be wary of malformed frames if (needle + value_size <= ceiling) { char *value = (char *) malloc (value_size + 1); memcpy (value, needle, value_size); value [value_size] = 0; needle += value_size; // Hash takes ownership of value if (zhash_insert (self, key, value)) { zhash_destroy (&self); break; } } } } } // Hash will free values in destructor if (self) zhash_autofree (self); return self; }
void zre_msg_headers_insert (zre_msg_t *self, const char *key, const char *format, ...) { // Format into newly allocated string assert (self); va_list argptr; va_start (argptr, format); char *string = zsys_vprintf (format, argptr); va_end (argptr); // Store string in hash table if (!self->headers) { self->headers = zhash_new (); zhash_autofree (self->headers); } zhash_update (self->headers, key, string); free (string); }
void zre_msg_headers_insert (zre_msg_t *self, char *key, char *format, ...) { // Format string into buffer assert (self); va_list argptr; va_start (argptr, format); char *string = (char *) malloc (STRING_MAX + 1); assert (string); vsnprintf (string, STRING_MAX, format, argptr); va_end (argptr); // Store string in hash table if (!self->headers) { self->headers = zhash_new (); zhash_autofree (self->headers); } zhash_update (self->headers, key, string); }
zhash_t * zdir_cache (zdir_t *self) { assert (self); // Load any previous cache from disk zhash_t *cache = zhash_new (); if (!cache) return NULL; zhash_autofree (cache); char *cache_file = (char *) zmalloc (strlen (self->path) + strlen ("/.cache") + 1); if (!cache_file) { zhash_destroy (&cache); return NULL; } sprintf (cache_file, "%s/.cache", self->path); zhash_load (cache, cache_file); // Recalculate digest for any new files zfile_t **files = zdir_flatten (self); uint index; for (index = 0;; index++) { zfile_t *file = files [index]; if (!file) break; const char *filename = zfile_filename (file, self->path); if (zhash_lookup (cache, zfile_filename (file, self->path)) == NULL) { int rc = zhash_insert (cache, filename, (void *) zfile_digest (file)); if (rc != 0) { zhash_destroy (&cache); break; } } } freen (files); // Save cache to disk for future reference if (cache) zhash_save (cache, cache_file); freen (cache_file); return cache; }
zhash_t * zhash_dup (zhash_t *self) { if (!self) return NULL; zhash_t *copy = zhash_new (); zhash_autofree (copy); if (copy) { uint index; for (index = 0; index != self->limit; index++) { item_t *item = self->items [index]; while (item) { zhash_insert (copy, item->key, item->value); item = item->next; } } } return copy; }
zcert_t * zcert_new (void) { zcert_t *self = (zcert_t *) zmalloc (sizeof (zcert_t)); assert (self); // Initialize metadata, even if keys aren't working self->metadata = zhash_new (); zhash_autofree (self->metadata); #if (ZMQ_VERSION_MAJOR == 4) int rc = zmq_curve_keypair (self->public_txt, self->secret_txt); assert (rc == 0); zmq_z85_decode (self->public_key, self->public_txt); zmq_z85_decode (self->secret_key, self->secret_txt); #else strcpy (self->public_txt, "0000000000000000000000000000000000000000"); strcpy (self->secret_txt, "0000000000000000000000000000000000000000"); #endif return self; }
zcert_t * zcert_new_from (byte *public_key, byte *secret_key) { zcert_t *self = (zcert_t *) zmalloc (sizeof (zcert_t)); assert (self); assert (public_key); assert (secret_key); self->metadata = zhash_new (); zhash_autofree (self->metadata); memcpy (self->public_key, public_key, 32); memcpy (self->secret_key, secret_key, 32); #if (ZMQ_VERSION_MAJOR == 4) zmq_z85_encode (self->public_txt, self->public_key, 32); zmq_z85_encode (self->secret_txt, self->secret_key, 32); #else strcpy (self->public_txt, "0000000000000000000000000000000000000000"); strcpy (self->secret_txt, "0000000000000000000000000000000000000000"); #endif return self; }
zhash_t * zhash_dup_v2 (zhash_t *self) { if (!self) return NULL; zhash_t *copy = zhash_new (); if (copy) { zhash_autofree (copy); uint index; size_t limit = primes [self->prime_index]; for (index = 0; index < limit; index++) { item_t *item = self->items [index]; while (item) { if (zhash_insert (copy, item->key, item->value)) { zhash_destroy (©); break; } item = item->next; } } } return copy; }
void zhash_test (int verbose) { printf (" * zhash: "); // @selftest zhash_t *hash = zhash_new (); assert (hash); assert (zhash_size (hash) == 0); // Insert some items int rc; rc = zhash_insert (hash, "DEADBEEF", "dead beef"); assert (rc == 0); rc = zhash_insert (hash, "ABADCAFE", "a bad cafe"); assert (rc == 0); rc = zhash_insert (hash, "C0DEDBAD", "coded bad"); assert (rc == 0); rc = zhash_insert (hash, "DEADF00D", "dead food"); assert (rc == 0); assert (zhash_size (hash) == 4); // Look for existing items char *item; item = (char *) zhash_lookup (hash, "DEADBEEF"); assert (streq (item, "dead beef")); item = (char *) zhash_lookup (hash, "ABADCAFE"); assert (streq (item, "a bad cafe")); item = (char *) zhash_lookup (hash, "C0DEDBAD"); assert (streq (item, "coded bad")); item = (char *) zhash_lookup (hash, "DEADF00D"); assert (streq (item, "dead food")); // Look for non-existent items item = (char *) zhash_lookup (hash, "foo"); assert (item == NULL); // Try to insert duplicate items rc = zhash_insert (hash, "DEADBEEF", "foo"); assert (rc == -1); item = (char *) zhash_lookup (hash, "DEADBEEF"); assert (streq (item, "dead beef")); // Some rename tests // Valid rename, key is now LIVEBEEF rc = zhash_rename (hash, "DEADBEEF", "LIVEBEEF"); assert (rc == 0); item = (char *) zhash_lookup (hash, "LIVEBEEF"); assert (streq (item, "dead beef")); // Trying to rename an unknown item to a non-existent key rc = zhash_rename (hash, "WHATBEEF", "NONESUCH"); assert (rc == -1); // Trying to rename an unknown item to an existing key rc = zhash_rename (hash, "WHATBEEF", "LIVEBEEF"); assert (rc == -1); item = (char *) zhash_lookup (hash, "LIVEBEEF"); assert (streq (item, "dead beef")); // Trying to rename an existing item to another existing item rc = zhash_rename (hash, "LIVEBEEF", "ABADCAFE"); assert (rc == -1); item = (char *) zhash_lookup (hash, "LIVEBEEF"); assert (streq (item, "dead beef")); item = (char *) zhash_lookup (hash, "ABADCAFE"); assert (streq (item, "a bad cafe")); // Test keys method zlist_t *keys = zhash_keys (hash); assert (zlist_size (keys) == 4); zlist_destroy (&keys); // Test dup method zhash_t *copy = zhash_dup (hash); assert (zhash_size (copy) == 4); item = (char *) zhash_lookup (copy, "LIVEBEEF"); assert (item); assert (streq (item, "dead beef")); zhash_destroy (©); // Test pack/unpack methods zframe_t *frame = zhash_pack (hash); copy = zhash_unpack (frame); zframe_destroy (&frame); assert (zhash_size (copy) == 4); item = (char *) zhash_lookup (copy, "LIVEBEEF"); assert (item); assert (streq (item, "dead beef")); zhash_destroy (©); // Test foreach rc = zhash_foreach (hash, test_foreach, hash); assert (rc == 0); rc = zhash_foreach (hash, test_foreach_error, hash); assert (rc == -1); // Test save and load zhash_comment (hash, "This is a test file"); zhash_comment (hash, "Created by %s", "czmq_selftest"); zhash_save (hash, ".cache"); copy = zhash_new (); zhash_load (copy, ".cache"); item = (char *) zhash_lookup (copy, "LIVEBEEF"); assert (item); assert (streq (item, "dead beef")); zhash_destroy (©); zsys_file_delete (".cache"); // Delete a item zhash_delete (hash, "LIVEBEEF"); item = (char *) zhash_lookup (hash, "LIVEBEEF"); assert (item == NULL); assert (zhash_size (hash) == 3); // Check that the queue is robust against random usage struct { char name [100]; bool exists; } testset [200]; memset (testset, 0, sizeof (testset)); int testmax = 200, testnbr, iteration; srandom ((unsigned) time (NULL)); for (iteration = 0; iteration < 25000; iteration++) { testnbr = randof (testmax); if (testset [testnbr].exists) { item = (char *) zhash_lookup (hash, testset [testnbr].name); assert (item); zhash_delete (hash, testset [testnbr].name); testset [testnbr].exists = false; } else { sprintf (testset [testnbr].name, "%x-%x", rand (), rand ()); if (zhash_insert (hash, testset [testnbr].name, "") == 0) testset [testnbr].exists = true; } } // Test 10K lookups for (iteration = 0; iteration < 10000; iteration++) item = (char *) zhash_lookup (hash, "DEADBEEFABADCAFE"); // Destructor should be safe to call twice zhash_destroy (&hash); zhash_destroy (&hash); assert (hash == NULL); // Test autofree; automatically copies and frees string values hash = zhash_new (); zhash_autofree (hash); char value [255]; strcpy (value, "This is a string"); rc = zhash_insert (hash, "key1", value); assert (rc == 0); strcpy (value, "Ring a ding ding"); rc = zhash_insert (hash, "key2", value); assert (rc == 0); assert (streq ((char *) zhash_lookup (hash, "key1"), "This is a string")); assert (streq ((char *) zhash_lookup (hash, "key2"), "Ring a ding ding")); zhash_destroy (&hash); // @end printf ("OK\n"); }
/// // Set hash for automatic value destruction void QZhash::autofree () { zhash_autofree (self); }
diag_t jz_msg_validate (JzMsg *self) { g_assert (self); if (self->signature != JZ_MSG_SIGNATURE) return d_invalid_signature; else if (self->version != 1) return d_unknown_version; else if (self->id < 0 || self->id >= JZ_MSG_COUNT) return d_unknown_message_type; #if 0 // Try to keep this alphabetized else if (self->id == JZ_MSG_CALL_ACCEPTED || self->id == JZ_MSG_CALL_REQUEST || self->id == JZ_MSG_CLEAR_REQUEST) { if (self->lcn <= 0 || self->lcn > JZ_MSG_MAX_LCN) return d_invalid_lcn; } else if (self->id == JZ_MSG_CALL_ACCEPTED || self->id == JZ_MSG_CALL_REQUEST ) { if (packet_rngchk (self->packet) < 0) return d_invalid_packet_facility; else if (packet_rngchk (self->packet) > 0) return d_invalid_packet_facility; else if (tput_rngchk (self->throughput) < 0) return d_invalid_throughput_facility; else if (tput_rngchk (self->throughput) > 0) return d_invalid_throughput_facility; else if (window_rngchk (self->window) < 0) return d_invalid_window_facility; else if (window_rngchk (self->window) > 0) return d_invalid_window_facility; } else if (self->id == JZ_MSG_CALL_ACCEPTED || self->id == JZ_MSG_CALL_REQUEST ) { if (!address_validate(self->called_address)) return d_invalid_called_address; } else if (self->id == JZ_MSG_CALL_ACCEPTED || self->id == JZ_MSG_CALL_REQUEST || self->id == JZ_MSG_CLEAR_CONFIRMATION || self->id == JZ_MSG_CONNECT ) { if (!address_validate(self->calling_address)) return d_invalid_calling_address; } else if (self->id == JZ_MSG_CALL_ACCEPTED || self->id == JZ_MSG_CALL_REQUEST) { // Zero-length data frames are OK!! if (self->data->len > JZ_MSG_MAX_CALL_REQUEST_DATA_SIZE) return d_data_too_long; } else if (self->id == JZ_MSG_DATA) { // zero-length data frames are not allowed!! if (self->data->len == 0) return d_data_too_short; else if (self->data->len > JZ_MSG_MAX_DATA_SIZE) return d_data_too_long; } else if (self->id == JZ_MSG_CLEAR_REQUEST || self->id == JZ_MSG_DIAGNOSTIC || self->id == JZ_MSG_RESET_REQUEST) { if (!cause_validate (self->cause)) return d_invalid_cause; if (!diag_validate (self->diagnostic)) return d_invalid_diagnostic; } else if (self->id == JZ_MSG_DATA) { if (!q_validate (self->q)) return d_invalid_q; else if (seq_rngchk (self->ps) != 0) return d_invalid_ps; } else if (self->id == JZ_MSG_DATA || self->id == JZ_MSG_RR || self->id == JZ_MSG_RNR) { if (seq_rngchk (self->pr) != 0) return d_invalid_pr; } else if (self->id == JZ_MSG_CONNECT) { if (!iodir_validate (self->iodir)) return d_invalid_directionality_facility; else if (self->hostname != NULL) { if (!g_utf8_validate (self->hostname, -1, NULL) || g_utf8_strlen (self->hostname, -1) > JZ_MSG_MAX_HOSTNAME_LENGTH) return d_invalid_hostname; } } #if 0 case JZ_MSG_DIRECTORY: GET_NUMBER1 (hash_size); self->workers = zhash_new (); zhash_autofree (self->workers); while (hash_size--) { char *string; GET_STRING (string); char *value = strchr (string, '='); if (value) *value++ = 0; zhash_insert (self->workers, string, value); free (string); } #endif #endif return d_ok; }
JzMsg * jz_msg_new_from_data (gpointer buf, gsize len) { g_assert (buf); JzMsg *self = g_new0(JzMsg, 1); self->data = g_byte_array_new (); size_t string_size; size_t frame_length; g_assert (len > JZ_MSG_ENVELOPE_SIZE); // Get and check protocol signature self->needle = buf; // Initially we don't know enough to properly set the ceiling self->ceiling = buf + len; GET_NUMBER4 (self->signature); g_assert (self->signature == JZ_MSG_SIGNATURE); // Get message id and parse per message type GET_NUMBER4 (frame_length); // Now that we have a frame size, we can properly set the ceiling guint32 padding = JZ_MSG_PADDING_LENGTH (frame_length); self->ceiling = buf + JZ_MSG_ENVELOPE_SIZE + frame_length + padding; GET_NUMBER1 (self->version); GET_NUMBER1 (self->id); GET_NUMBER2 (self->lcn); if (self->version != 1) { self->invalidity = d_unknown_version; goto malformed; } switch (self->id) { case JZ_MSG_DATA: GET_NUMBER1 (self->q); GET_NUMBER2 (self->pr); GET_NUMBER2 (self->ps); g_byte_array_set_size (self->data, 0); GET_RAW (self->data); break; case JZ_MSG_RR: GET_NUMBER2 (self->pr); break; case JZ_MSG_RNR: GET_NUMBER2 (self->pr); break; case JZ_MSG_CALL_REQUEST: // Address block g_free (self->calling_address); GET_STRING (self->calling_address); g_free (self->called_address); GET_STRING (self->called_address); // Facilities GET_NUMBER1 (self->packet); GET_NUMBER2 (self->window); GET_NUMBER1 (self->throughput); // User data g_byte_array_set_size (self->data, 0); GET_RAW (self->data); break; case JZ_MSG_CALL_ACCEPTED: // Address block g_free (self->calling_address); GET_STRING (self->calling_address); g_free (self->called_address); GET_STRING (self->called_address); // Facilities GET_NUMBER1 (self->packet); GET_NUMBER2 (self->window); GET_NUMBER1 (self->throughput); // User data g_byte_array_set_size (self->data, 0); GET_RAW (self->data); break; case JZ_MSG_CLEAR_REQUEST: GET_NUMBER1 (self->cause); GET_NUMBER1 (self->diagnostic); break; case JZ_MSG_CLEAR_CONFIRMATION: break; case JZ_MSG_RESET_REQUEST: GET_NUMBER1 (self->cause); GET_NUMBER1 (self->diagnostic); break; case JZ_MSG_RESET_CONFIRMATION: break; case JZ_MSG_CONNECT: g_free (self->calling_address); GET_STRING (self->calling_address); GET_NUMBER1 (self->iodir); break; case JZ_MSG_CONNECT_INDICATION: break; case JZ_MSG_DISCONNECT: break; case JZ_MSG_DISCONNECT_INDICATION: break; case JZ_MSG_DIAGNOSTIC: GET_NUMBER1 (self->diagnostic); GET_NUMBER1 (self->diagnostic_version); GET_NUMBER1 (self->diagnostic_id); GET_NUMBER2 (self->diagnostic_lcn); break; case JZ_MSG_DIRECTORY_REQUEST: break; case JZ_MSG_DIRECTORY: #if 0 GET_NUMBER1 (hash_size); self->workers = zhash_new (); zhash_autofree (self->workers); while (hash_size--) { char *string; GET_STRING (string); char *value = strchr (string, '='); if (value) *value++ = 0; zhash_insert (self->workers, string, value); free (string); } #endif break; case JZ_MSG_ENQ: break; case JZ_MSG_ACK: break; case JZ_MSG_RESTART_REQUEST: GET_NUMBER1 (self->cause); GET_NUMBER1 (self->diagnostic); break; case JZ_MSG_RESTART_CONFIRMATION: break; default: self->invalidity = d_unknown_message_type; goto malformed; } for (int i = 0; i < padding; i ++) { guint8 padding; GET_NUMBER1 (padding); } GET_NUMBER4 (self->crc); // Successful unpacking self->packed_size = self->needle - (guint8 *) buf; // If the message is shorter than expected if (self->packed_size < JZ_MSG_ENVELOPE_SIZE + frame_length + padding) { g_critical ("message payload smaller than envelope '%s'\n", id_name (self->id)); self->valid = FALSE; self->invalidity = d_packet_too_long; } else self->valid = TRUE; return self; // Error returns malformed: g_critical ("malformed message '%s'\n", id_name (self->id)); self->valid = FALSE; self->packed_size = self->needle - (guint8 *) buf; return self; premature: g_critical ("message payload too big for envelope '%s'\n", id_name (self->id)); self->invalidity = d_packet_too_short; self->packed_size = self->needle - (guint8 *) buf; return self; }
zre_msg_t * zre_msg_recv (void *input) { assert (input); zre_msg_t *self = zre_msg_new (0); zframe_t *frame = NULL; size_t string_size; size_t list_size; size_t hash_size; // Read valid message frame from socket; we loop over any // garbage data we might receive from badly-connected peers while (true) { // If we're reading from a ROUTER socket, get address if (zsocket_type (input) == ZMQ_ROUTER) { zframe_destroy (&self->address); self->address = zframe_recv (input); if (!self->address) goto empty; // Interrupted if (!zsocket_rcvmore (input)) goto malformed; } // Read and parse command in frame frame = zframe_recv (input); if (!frame) goto empty; // Interrupted // Get and check protocol signature self->needle = zframe_data (frame); self->ceiling = self->needle + zframe_size (frame); uint16_t signature; GET_NUMBER2 (signature); if (signature == (0xAAA0 | 1)) break; // Valid signature // Protocol assertion, drop message while (zsocket_rcvmore (input)) { zframe_destroy (&frame); frame = zframe_recv (input); } zframe_destroy (&frame); } // Get message id and parse per message type GET_NUMBER1 (self->id); switch (self->id) { case ZRE_MSG_HELLO: GET_NUMBER2 (self->sequence); free (self->ipaddress); GET_STRING (self->ipaddress); GET_NUMBER2 (self->mailbox); GET_NUMBER1 (list_size); self->groups = zlist_new (); zlist_autofree (self->groups); while (list_size--) { char *string; GET_STRING (string); zlist_append (self->groups, string); free (string); } GET_NUMBER1 (self->status); GET_NUMBER1 (hash_size); self->headers = zhash_new (); zhash_autofree (self->headers); while (hash_size--) { char *string; GET_STRING (string); char *value = strchr (string, '='); if (value) *value++ = 0; zhash_insert (self->headers, string, value); free (string); } break; case ZRE_MSG_WHISPER: GET_NUMBER2 (self->sequence); // Get next frame, leave current untouched if (!zsocket_rcvmore (input)) goto malformed; self->content = zframe_recv (input); break; case ZRE_MSG_SHOUT: GET_NUMBER2 (self->sequence); free (self->group); GET_STRING (self->group); // Get next frame, leave current untouched if (!zsocket_rcvmore (input)) goto malformed; self->content = zframe_recv (input); break; case ZRE_MSG_JOIN: GET_NUMBER2 (self->sequence); free (self->group); GET_STRING (self->group); GET_NUMBER1 (self->status); break; case ZRE_MSG_LEAVE: GET_NUMBER2 (self->sequence); free (self->group); GET_STRING (self->group); GET_NUMBER1 (self->status); break; case ZRE_MSG_PING: GET_NUMBER2 (self->sequence); break; case ZRE_MSG_PING_OK: GET_NUMBER2 (self->sequence); break; default: goto malformed; } // Successful return zframe_destroy (&frame); return self; // Error returns malformed: printf ("E: malformed message '%d'\n", self->id); empty: zframe_destroy (&frame); zre_msg_destroy (&self); return (NULL); }
void ztns_test (bool verbose) { printf (" * ztns: "); // Strings ztns_t *tnetstr = ztns_new (); char *data_str = "Hello World!"; char *tnetstr_str = "12:Hello World!,"; int rc = ztns_append_str (tnetstr, data_str); assert (0 == rc); assert (streq (ztns_get (tnetstr), tnetstr_str)); char * index = tnetstr_str; char *result_str = (char *)ztns_parse (&index); assert (streq (index, "")); assert (streq (result_str, data_str)); free (result_str); ztns_destroy (&tnetstr); tnetstr = ztns_new (); char *data_empty_str = ""; char *tnetstr_empty_str = "0:,"; rc = ztns_append_str (tnetstr, data_empty_str); assert (0 == rc); assert (streq (ztns_get (tnetstr), tnetstr_empty_str)); index = tnetstr_empty_str; result_str = (char *)ztns_parse (&index); assert (streq (index, "")); assert (streq (result_str, data_empty_str)); free (result_str); ztns_destroy (&tnetstr); tnetstr = ztns_new (); char *data_tnet_str = "12:Hello World!,"; tnetstr_str = "16:12:Hello World!,,"; rc = ztns_append_str (tnetstr, data_tnet_str); assert (0 == rc); assert (streq (ztns_get (tnetstr), tnetstr_str)); index = tnetstr_str; result_str = (char *)ztns_parse (&index); assert (streq (index, "")); assert (streq (result_str, data_tnet_str)); free (result_str); ztns_destroy (&tnetstr); // Numbers tnetstr = ztns_new (); long long data_llong = 34; char *tnetstr_llong = "2:34#"; rc = ztns_append_llong (tnetstr, data_llong); assert (0 == rc); assert (streq (ztns_get (tnetstr), tnetstr_llong)); index = tnetstr_llong; long long *result_llong = (long long *)ztns_parse (&index); assert (streq (index, "")); assert (data_llong == *result_llong); free (result_llong); ztns_destroy (&tnetstr); tnetstr = ztns_new (); rc = ztns_append_llong (tnetstr, LLONG_MAX); assert (0 == rc); index = ztns_get (tnetstr); result_llong = (long long *)ztns_parse (&index); assert (streq (index, "")); assert (LLONG_MAX == *result_llong); free (result_llong); ztns_destroy (&tnetstr); tnetstr = ztns_new (); rc = ztns_append_llong (tnetstr, LLONG_MIN); assert (0 == rc); index = ztns_get (tnetstr); result_llong = (long long *)ztns_parse (&index); assert (streq (index, "")); assert (LLONG_MIN == *result_llong); free (result_llong); ztns_destroy (&tnetstr); char *tnetstr_llong_max_plus_one = "19:9223372036854775808#"; index = tnetstr_llong_max_plus_one; result_llong = (long long *)ztns_parse (&index); assert (NULL == result_llong); char *tnetstr_llong_min_minus_one = "20:-9223372036854775809#"; index = tnetstr_llong_min_minus_one; result_llong = (long long *)ztns_parse (&index); assert (NULL == result_llong); char *tnetstr_float_not_llong = "8:15.75331#"; index = tnetstr_float_not_llong; result_llong = (long long *)ztns_parse (&index); assert (NULL == result_llong); // Floats // ### These are a bastard to test and until there's a real use // I've got better things to do with my time //tnetstr = ztns_new (); //float data_float = 15.75331; //char *tnetstr_float = "8:15.75331^"; //rc = ztns_append_float (tnetstr, data_float); //assert (0 == rc); //assert (streq (ztns_get (tnetstr), tnetstr_float)); //index = tnetstr_float; //float *result_float = (float *)ztns_parse (&index); //assert (streq (index, "")); //assert (data_float == *result_float); //free (result_float); //ztns_destroy (&tnetstr); // Booleans tnetstr = ztns_new (); bool data_bool = true; char *tnetstr_bool = "4:true!"; rc = ztns_append_bool (tnetstr, data_bool); assert (0 == rc); assert (streq (ztns_get (tnetstr), tnetstr_bool)); index = tnetstr_bool; bool *result_bool = (bool *)ztns_parse (&index); assert (streq (index, "")); assert (data_bool == *result_bool); free (result_bool); ztns_destroy (&tnetstr); // NULL tnetstr = ztns_new (); char *tnetstr_null = "0:~"; rc = ztns_append_null (tnetstr); assert (streq (ztns_get (tnetstr), tnetstr_null)); index = tnetstr_null; void *result_null = ztns_parse (&index); assert (streq (index, "")); assert (NULL == result_null); ztns_destroy (&tnetstr); // Dictionaries zhash_t *dict = zhash_new (); zhash_t *empty_hash = zhash_new (); zlist_t *empty_list = zlist_new (); zhash_insert (dict, "STRING", data_str); zhash_insert (dict, "INTEGER", &data_llong); zhash_insert (dict, "BOOLEAN", &data_bool); zhash_insert (dict, "HASH", empty_hash); zhash_freefn (dict, "HASH", &s_zhash_free_fn); zhash_insert (dict, "LIST", empty_list); zhash_freefn (dict, "LIST", &s_zlist_free_fn); tnetstr = ztns_new (); rc = ztns_append_dict (tnetstr, dict, &s_tnetstr_foreach_dict_fn_test); assert (0 == rc); zhash_destroy (&dict); index = ztns_get (tnetstr); zhash_t *result_dict = (zhash_t *)ztns_parse (&index); assert (streq (index, "")); assert (NULL != result_dict); zhash_autofree (result_dict); char *item_str = (char *)zhash_lookup (result_dict, "STRING"); assert (streq (data_str, item_str)); long long *item_llong = (long long *)zhash_lookup (result_dict, "INTEGER"); assert (*item_llong == data_llong); bool *item_bool = (bool *)zhash_lookup (result_dict, "BOOLEAN"); assert (*item_bool == data_bool); zhash_t *item_hash = (zhash_t *)zhash_lookup (result_dict, "HASH"); assert (0 == zhash_size (item_hash)); zlist_t *item_list = (zlist_t *)zhash_lookup (result_dict, "LIST"); assert (0 == zlist_size (item_list)); zhash_destroy (&result_dict); ztns_destroy (&tnetstr); // Lists zlist_t *list = zlist_new (); empty_hash = zhash_new (); empty_list = zlist_new (); zlist_append (list, data_str); zlist_append (list, &data_llong); zlist_append (list, &data_bool); zlist_append (list, empty_hash); zlist_freefn (list, empty_hash, &s_zhash_free_fn, true); zlist_append (list, empty_list); zlist_freefn (list, empty_list, &s_zlist_free_fn, true); tnetstr = ztns_new (); rc = ztns_append_list (tnetstr, list, &s_tnetstr_foreach_list_fn_test); assert (0 == rc); zlist_destroy (&list); index = ztns_get (tnetstr); zlist_t *result_list = (zlist_t *)ztns_parse (&index); assert (streq (index, "")); assert (NULL != result_list); item_str = (char *)zlist_pop (result_list); assert (streq (data_str, item_str)); free (item_str); item_llong = (long long *)zlist_pop (result_list); assert (*item_llong == data_llong); free (item_llong); item_bool = (bool *)zlist_pop (result_list); assert (*item_bool == data_bool); free (item_bool); item_hash = (zhash_t *)zlist_pop (result_list); assert (0 == zhash_size (item_hash)); zhash_destroy (&item_hash); item_list = (zlist_t *)zlist_pop (result_list); assert (0 == zlist_size (item_list)); zlist_destroy (&item_list); zlist_destroy (&result_list); ztns_destroy (&tnetstr); printf ("OK\n"); }
zre_msg_t * zre_msg_decode (zmsg_t **msg_p, int socket_type) { assert (msg_p); zmsg_t *msg = *msg_p; if (msg == NULL) return NULL; zre_msg_t *self = zre_msg_new (0); // If message came from a router socket, first frame is routing_id if (socket_type == ZMQ_ROUTER) { self->routing_id = zmsg_pop (msg); // If message was not valid, forget about it if (!self->routing_id || !zmsg_next (msg)) { zre_msg_destroy (&self); return (NULL); // Malformed or empty } } // Read and parse command in frame zframe_t *frame = zmsg_pop (msg); if (!frame) goto empty; // Malformed or empty // Get and check protocol signature self->needle = zframe_data (frame); self->ceiling = self->needle + zframe_size (frame); uint16_t signature; GET_NUMBER2 (signature); if (signature != (0xAAA0 | 1)) goto empty; // Invalid signature // Get message id and parse per message type GET_NUMBER1 (self->id); switch (self->id) { case ZRE_MSG_HELLO: GET_NUMBER2 (self->sequence); GET_STRING (self->ipaddress); GET_NUMBER2 (self->mailbox); { size_t list_size; GET_NUMBER4 (list_size); self->groups = zlist_new (); zlist_autofree (self->groups); while (list_size--) { char *string; GET_LONGSTR (string); zlist_append (self->groups, string); free (string); } } GET_NUMBER1 (self->status); { size_t hash_size; GET_NUMBER4 (hash_size); self->headers = zhash_new (); zhash_autofree (self->headers); while (hash_size--) { char *key, *value; GET_STRING (key); GET_LONGSTR (value); zhash_insert (self->headers, key, value); free (key); free (value); } } break; case ZRE_MSG_WHISPER: GET_NUMBER2 (self->sequence); // Get zero or more remaining frames, leaving current // frame untouched self->content = zmsg_new (); while (zmsg_size (msg)) zmsg_add (self->content, zmsg_pop (msg)); break; case ZRE_MSG_SHOUT: GET_NUMBER2 (self->sequence); GET_STRING (self->group); // Get zero or more remaining frames, leaving current // frame untouched self->content = zmsg_new (); while (zmsg_size (msg)) zmsg_add (self->content, zmsg_pop (msg)); break; case ZRE_MSG_JOIN: GET_NUMBER2 (self->sequence); GET_STRING (self->group); GET_NUMBER1 (self->status); break; case ZRE_MSG_LEAVE: GET_NUMBER2 (self->sequence); GET_STRING (self->group); GET_NUMBER1 (self->status); break; case ZRE_MSG_PING: GET_NUMBER2 (self->sequence); break; case ZRE_MSG_PING_OK: GET_NUMBER2 (self->sequence); break; default: goto malformed; } // Successful return zframe_destroy (&frame); zmsg_destroy (msg_p); return self; // Error returns malformed: printf ("E: malformed message '%d'\n", self->id); empty: zframe_destroy (&frame); zmsg_destroy (msg_p); zre_msg_destroy (&self); return (NULL); }
int zproto_example_recv (zproto_example_t *self, zsock_t *input) { assert (input); if (zsock_type (input) == ZMQ_ROUTER) { zframe_destroy (&self->routing_id); self->routing_id = zframe_recv (input); if (!self->routing_id || !zsock_rcvmore (input)) { zsys_warning ("zproto_example: no routing ID"); return -1; // Interrupted or malformed } } zmq_msg_t frame; zmq_msg_init (&frame); int size = zmq_msg_recv (&frame, zsock_resolve (input), 0); if (size == -1) { zsys_warning ("zproto_example: interrupted"); goto malformed; // Interrupted } // Get and check protocol signature self->needle = (byte *) zmq_msg_data (&frame); self->ceiling = self->needle + zmq_msg_size (&frame); uint16_t signature; GET_NUMBER2 (signature); if (signature != (0xAAA0 | 0)) { zsys_warning ("zproto_example: invalid signature"); // TODO: discard invalid messages and loop, and return // -1 only on interrupt goto malformed; // Interrupted } // Get message id and parse per message type GET_NUMBER1 (self->id); switch (self->id) { case ZPROTO_EXAMPLE_LOG: GET_NUMBER2 (self->sequence); { uint16_t version; GET_NUMBER2 (version); if (version != 3) { zsys_warning ("zproto_example: version is invalid"); goto malformed; } } GET_NUMBER1 (self->level); GET_NUMBER1 (self->event); GET_NUMBER2 (self->node); GET_NUMBER2 (self->peer); GET_NUMBER8 (self->time); GET_STRING (self->host); GET_LONGSTR (self->data); break; case ZPROTO_EXAMPLE_STRUCTURES: GET_NUMBER2 (self->sequence); { size_t list_size; GET_NUMBER4 (list_size); self->aliases = zlist_new (); zlist_autofree (self->aliases); while (list_size--) { char *string = NULL; GET_LONGSTR (string); zlist_append (self->aliases, string); free (string); } } { size_t hash_size; GET_NUMBER4 (hash_size); self->headers = zhash_new (); zhash_autofree (self->headers); while (hash_size--) { char key [256]; char *value = NULL; GET_STRING (key); GET_LONGSTR (value); zhash_insert (self->headers, key, value); free (value); } } break; case ZPROTO_EXAMPLE_BINARY: GET_NUMBER2 (self->sequence); GET_OCTETS (self->flags, 4); { size_t chunk_size; GET_NUMBER4 (chunk_size); if (self->needle + chunk_size > (self->ceiling)) { zsys_warning ("zproto_example: public_key is missing data"); goto malformed; } zchunk_destroy (&self->public_key); self->public_key = zchunk_new (self->needle, chunk_size); self->needle += chunk_size; } if (self->needle + ZUUID_LEN > (self->ceiling)) { zsys_warning ("zproto_example: identifier is invalid"); goto malformed; } zuuid_destroy (&self->identifier); self->identifier = zuuid_new_from (self->needle); self->needle += ZUUID_LEN; // Get next frame off socket if (!zsock_rcvmore (input)) { zsys_warning ("zproto_example: address is missing"); goto malformed; } zframe_destroy (&self->address); self->address = zframe_recv (input); // Get zero or more remaining frames zmsg_destroy (&self->content); if (zsock_rcvmore (input)) self->content = zmsg_recv (input); else self->content = zmsg_new (); break; case ZPROTO_EXAMPLE_TYPES: GET_NUMBER2 (self->sequence); GET_STRING (self->client_forename); GET_STRING (self->client_surname); GET_STRING (self->client_mobile); GET_STRING (self->client_email); GET_STRING (self->supplier_forename); GET_STRING (self->supplier_surname); GET_STRING (self->supplier_mobile); GET_STRING (self->supplier_email); break; default: zsys_warning ("zproto_example: bad message ID"); goto malformed; } // Successful return zmq_msg_close (&frame); return 0; // Error returns malformed: zsys_warning ("zproto_example: zproto_example malformed message, fail"); zmq_msg_close (&frame); return -1; // Invalid message }
int 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 }