static void try_security_mechanism (client_t *self) { char *login = fmq_config_resolve (self->config, "security/plain/login", "guest"); char *password = fmq_config_resolve (self->config, "security/plain/password", ""); zframe_t *frame = fmq_sasl_plain_encode (login, password); fmq_msg_mechanism_set (self->request, "PLAIN"); fmq_msg_response_set (self->request, frame); }
static void client_config_self (client_t *self) { // Get standard client configuration self->heartbeat = atoi ( fmq_config_resolve (self->config, "client/heartbeat", "1")) * 1000; }
// Apply configuration tree: // * apply client configuration // * print any echo items in top-level sections // * apply sections that match methods static void client_apply_config (client_t *self) { // Apply echo commands and class methods fmq_config_t *section = fmq_config_child (self->config); while (section) { fmq_config_t *entry = fmq_config_child (section); while (entry) { if (streq (fmq_config_name (entry), "echo")) zclock_log (fmq_config_value (entry)); entry = fmq_config_next (entry); } if (streq (fmq_config_name (section), "subscribe")) { char *path = fmq_config_resolve (section, "path", "?"); // Store subscription along with any previous ones // Check we don't already have a subscription for this path self->sub = (sub_t *) zlist_first (self->subs); while (self->sub) { if (streq (path, self->sub->path)) return; self->sub = (sub_t *) zlist_next (self->subs); } // Subscription path must start with '/' // We'll do better error handling later assert (*path == '/'); // New subscription, store it for later replay char *inbox = fmq_config_resolve (self->config, "client/inbox", ".inbox"); self->sub = sub_new (self, inbox, path); zlist_append (self->subs, self->sub); } else if (streq (fmq_config_name (section), "set_inbox")) { char *path = fmq_config_resolve (section, "path", "?"); fmq_config_path_set (self->config, "client/inbox", path); } else if (streq (fmq_config_name (section), "set_resync")) { long enabled = atoi (fmq_config_resolve (section, "enabled", "")); // Request resynchronization from server fmq_config_path_set (self->config, "client/resync", enabled? "1" :"0"); } section = fmq_config_next (section); } client_config_self (self); }
static void client_apply_config (client_t *self) { // Get standard client configuration self->heartbeat = atoi ( fmq_config_resolve (self->config, "client/heartbeat", "1")) * 1000; // Apply echo commands and class methods fmq_config_t *section = fmq_config_child (self->config); while (section) { fmq_config_t *entry = fmq_config_child (section); while (entry) { if (streq (fmq_config_name (entry), "echo")) puts (fmq_config_value (entry)); entry = fmq_config_next (entry); } if (streq (fmq_config_name (section), "subscribe")) { char *path = fmq_config_resolve (section, "path", "?"); // Store subscription along with any previous ones // Check we don't already have a subscription for this path sub_t *sub = (sub_t *) zlist_first (self->subs); while (sub) { if (streq (path, sub->path)) return; sub = (sub_t *) zlist_next (self->subs); } // Subscription path must start with '/' // We'll do better error handling later assert (*path == '/'); // New subscription, so store it for later replay sub = sub_new (self, path); zlist_append (self->subs, sub); // If we're connected, then also send to server if (self->connected) { fmq_msg_path_set (self->request, path); self->next_event = subscribe_event; } } section = fmq_config_next (section); } }
static void format_icanhaz_command (client_t *self, server_t *server) { fmq_msg_path_set (server->request, self->sub->path); // If client app wants full resync, send cache to server if (atoi (fmq_config_resolve (self->config, "client/resync", "0")) == 1) { fmq_msg_options_insert (server->request, "RESYNC", "1"); fmq_msg_cache_set (server->request, sub_cache (self->sub)); } }
static void process_the_patch (client_t *self, server_t *server) { char *inbox = fmq_config_resolve (self->config, "client/inbox", ".inbox"); char *filename = fmq_msg_filename (server->reply); // Filenames from server must start with slash, which we skip assert (*filename == '/'); filename++; if (fmq_msg_operation (server->reply) == FMQ_MSG_FILE_CREATE) { if (server->file == NULL) { server->file = fmq_file_new (inbox, filename); if (fmq_file_output (server->file)) { // File not writeable, skip patch fmq_file_destroy (&server->file); return; } } // Try to write, ignore errors in this version zframe_t *frame = fmq_msg_chunk (server->reply); fmq_chunk_t *chunk = fmq_chunk_new (zframe_data (frame), zframe_size (frame)); if (fmq_chunk_size (chunk) > 0) { fmq_file_write (server->file, chunk, fmq_msg_offset (server->reply)); server->credit -= fmq_chunk_size (chunk); } else { // Zero-sized chunk means end of file, so report back to caller zstr_sendm (self->pipe, "DELIVER"); zstr_sendm (self->pipe, filename); zstr_sendf (self->pipe, "%s/%s", inbox, filename); fmq_file_destroy (&server->file); } fmq_chunk_destroy (&chunk); } else if (fmq_msg_operation (server->reply) == FMQ_MSG_FILE_DELETE) { zclock_log ("I: delete %s/%s", inbox, filename); fmq_file_t *file = fmq_file_new (inbox, filename); fmq_file_remove (file); fmq_file_destroy (&file); } }
static void process_the_patch (client_t *self) { char *inbox = fmq_config_resolve (self->config, "client/inbox", ".inbox"); char *filename = fmq_msg_filename (self->reply); if (fmq_msg_operation (self->reply) == FMQ_MSG_FILE_CREATE) { if (self->file == NULL) { zclock_log ("I: create %s", filename); self->file = fmq_file_new (inbox, filename); if (fmq_file_output (self->file)) { // File not writeable, skip patch fmq_file_destroy (&self->file); return; } } // Try to write, ignore errors in this version zframe_t *frame = fmq_msg_chunk (self->reply); fmq_chunk_t *chunk = fmq_chunk_new (zframe_data (frame), zframe_size (frame)); if (fmq_chunk_size (chunk) > 0) { fmq_file_write (self->file, chunk, fmq_msg_offset (self->reply)); self->credit -= fmq_chunk_size (chunk); } else // Zero-sized chunk means end of file fmq_file_destroy (&self->file); fmq_chunk_destroy (&chunk); } else if (fmq_msg_operation (self->reply) == FMQ_MSG_FILE_DELETE) { zclock_log ("I: delete %s", filename); fmq_file_t *file = fmq_file_new (inbox, filename); fmq_file_remove (file); fmq_file_destroy (&file); } }
// Process message from pipe static void client_control_message (client_t *self) { zmsg_t *msg = zmsg_recv (self->pipe); char *method = zmsg_popstr (msg); if (streq (method, "SUBSCRIBE")) { char *path = zmsg_popstr (msg); // Store subscription along with any previous ones // Check we don't already have a subscription for this path self->sub = (sub_t *) zlist_first (self->subs); while (self->sub) { if (streq (path, self->sub->path)) return; self->sub = (sub_t *) zlist_next (self->subs); } // Subscription path must start with '/' // We'll do better error handling later assert (*path == '/'); // New subscription, store it for later replay char *inbox = fmq_config_resolve (self->config, "client/inbox", ".inbox"); self->sub = sub_new (self, inbox, path); zlist_append (self->subs, self->sub); free (path); } else if (streq (method, "SET INBOX")) { char *path = zmsg_popstr (msg); fmq_config_path_set (self->config, "client/inbox", path); free (path); } else if (streq (method, "SET RESYNC")) { char *enabled_string = zmsg_popstr (msg); long enabled = atoi (enabled_string); free (enabled_string); // Request resynchronization from server fmq_config_path_set (self->config, "client/resync", enabled? "1" :"0"); } else if (streq (method, "CONFIG")) { char *config_file = zmsg_popstr (msg); fmq_config_destroy (&self->config); self->config = fmq_config_load (config_file); if (self->config) client_apply_config (self); else { printf ("E: cannot load config file '%s'\n", config_file); self->config = fmq_config_new ("root", NULL); } free (config_file); } else if (streq (method, "SETOPTION")) { char *path = zmsg_popstr (msg); char *value = zmsg_popstr (msg); fmq_config_path_set (self->config, path, value); client_config_self (self); free (path); free (value); } else if (streq (method, "STOP")) { zstr_send (self->pipe, "OK"); self->stopped = true; } else if (streq (method, "CONNECT")) { char *endpoint = zmsg_popstr (msg); if (self->nbr_servers < MAX_SERVERS) { server_t *server = server_new (self->ctx, endpoint); self->servers [self->nbr_servers++] = server; self->dirty = true; client_server_execute (self, server, initialize_event); } else printf ("E: too many server connections (max %d)\n", MAX_SERVERS); free (endpoint); } free (method); zmsg_destroy (&msg); }