Exemplo n.º 1
0
curvezmq_keypair_t *
curvezmq_keypair_load (void)
{
    curvezmq_keypair_t *self = 
        (curvezmq_keypair_t *) zmalloc (sizeof (curvezmq_keypair_t));
        
    int matches = 0;            //  How many key octets we parsed
    zconfig_t *root = zconfig_load ("secret.key");
    if (root) {
        char *secret_key = zconfig_resolve (root, "secret-key", NULL);
        if (secret_key) {
            int byte_nbr;
            for (byte_nbr = 0; byte_nbr < 32; byte_nbr++)
                matches += sscanf (secret_key + byte_nbr * 2, "%02hhX ", &self->secret_key [byte_nbr]);
        }
        char *public_key = zconfig_resolve (root, "public-key", NULL);
        if (public_key) {
            int byte_nbr;
            for (byte_nbr = 0; byte_nbr < 32; byte_nbr++)
                matches += sscanf (public_key + byte_nbr * 2, "%02hhX ", &self->public_key [byte_nbr]);
        }
    }
    if (matches != 64)
        curvezmq_keypair_destroy (&self);
    zconfig_destroy (&root);
    return self;
}
Exemplo n.º 2
0
JNIEXPORT jlong JNICALL
Java_zconfig__1_1load (JNIEnv *env, jclass c, jstring filename)
{
    char *filename_ = (char *) (*env)->GetStringUTFChars (env, filename, NULL);
    jlong load_ = (jlong) zconfig_load (filename_);
    (*env)->ReleaseStringUTFChars (env, filename, filename_);
    return load_;
}
Exemplo n.º 3
0
zcert_t *
zcert_load (char *format, ...)
{
#if (ZMQ_VERSION_MAJOR == 4)
    assert (format);
    va_list argptr;
    va_start (argptr, format);
    char *filename = zsys_vprintf (format, argptr);
    va_end (argptr);

    //  Try first to load secret certificate, which has both keys
    //  Then fallback to loading public certificate
    char filename_secret [256];
    snprintf (filename_secret, 256, "%s_secret", filename);
    zconfig_t *root = zconfig_load (filename_secret);
    if (!root)
        root = zconfig_load (filename);
        
    zcert_t *self = NULL;
    if (root) {
        char *public_text = zconfig_resolve (root, "/curve/public-key", NULL);
        char *secret_text = zconfig_resolve (root, "/curve/secret-key", NULL);
        if (public_text && strlen (public_text) == 40) {
            byte public_key [32] = { 0 };
            byte secret_key [32] = { 0 };
            zmq_z85_decode (public_key, public_text);
            if (secret_text && strlen (secret_text) == 40)
                zmq_z85_decode (secret_key, secret_text);

            //  Load metadata into certificate
            self = zcert_new_from (public_key, secret_key);
            zconfig_t *metadata = zconfig_locate (root, "/metadata");
            zconfig_t *item = metadata? zconfig_child (metadata): NULL;
            while (item) {
                zcert_set_meta (self, zconfig_name (item), zconfig_value (item));
                item = zconfig_next (item);
            }
        }
    }
    zconfig_destroy (&root);
    zstr_free (&filename);
    return self;
#else   
    return NULL;
#endif
}
Exemplo n.º 4
0
//  Process message from pipe
static void
server_control_message (server_t *self)
{
    zmsg_t *msg = zmsg_recv (self->pipe);
    char *method = zmsg_popstr (msg);
    if (streq (method, "BIND")) {
        char *endpoint = zmsg_popstr (msg);
        self->port = zsocket_bind (self->router, endpoint);
        zstr_sendf (self->pipe, "%d", self->port);
        free (endpoint);
    }
    else
    if (streq (method, "PUBLISH")) {
        char *location = zmsg_popstr (msg);
        char *alias = zmsg_popstr (msg);
        mount_t *mount = mount_new (location, alias);
        zlist_append (self->mounts, mount);          
        free (location);
        free (alias);
    }
    else
    if (streq (method, "SET ANONYMOUS")) {
        char *enabled_string = zmsg_popstr (msg);
        long enabled = atoi (enabled_string);
        free (enabled_string);
        //  Enable anonymous access without a config file                   
        zconfig_put (self->config, "security/anonymous", enabled? "1" :"0");
    }
    else
    if (streq (method, "CONFIG")) {
        char *config_file = zmsg_popstr (msg);
        zconfig_destroy (&self->config);
        self->config = zconfig_load (config_file);
        if (self->config)
            server_apply_config (self);
        else {
            printf ("E: cannot load config file '%s'\n", config_file);
            self->config = zconfig_new ("root", NULL);
        }
        free (config_file);
    }
    else
    if (streq (method, "SETOPTION")) {
        char *path = zmsg_popstr (msg);
        char *value = zmsg_popstr (msg);
        zconfig_put (self->config, path, value);
        server_config_self (self);
        free (path);
        free (value);
    }
    else
    if (streq (method, "STOP")) {
        zstr_send (self->pipe, "OK");
        self->stopped = true;
    }
    free (method);
    zmsg_destroy (&msg);
}
Exemplo n.º 5
0
zconfig_t *
zconfig_loadf (const char *format, ...)
{
    va_list argptr;
    va_start (argptr, format);
    char *filename = zsys_vprintf (format, argptr);
    va_end (argptr);
    if (filename) {
        zconfig_t *config = zconfig_load (filename);
        free (filename);
        return config;
    }
    else
        return NULL;
}
Exemplo n.º 6
0
void
zconfig_test (bool verbose)
{
    printf (" * zconfig: ");
    
    //  @selftest
    //  Create temporary directory for test files
#   define TESTDIR ".test_zconfig"
    zsys_dir_create (TESTDIR);
    
    zconfig_t *root = zconfig_new ("root", NULL);
    zconfig_t *section, *item;
    
    section = zconfig_new ("headers", root);
    item = zconfig_new ("email", section);
    zconfig_set_value (item, "*****@*****.**");
    item = zconfig_new ("name", section);
    zconfig_set_value (item, "Justin Kayce");
    zconfig_put (root, "/curve/secret-key", "Top Secret");
    zconfig_set_comment (root, "   CURVE certificate");
    zconfig_set_comment (root, "   -----------------");
    assert (zconfig_comments (root));
    zconfig_save (root, TESTDIR "/test.cfg");
    zconfig_destroy (&root);
    root = zconfig_load (TESTDIR "/test.cfg");
    if (verbose)
        zconfig_save (root, "-");
        
    char *email = zconfig_resolve (root, "/headers/email", NULL);
    assert (email);
    assert (streq (email, "*****@*****.**"));
    char *passwd = zconfig_resolve (root, "/curve/secret-key", NULL);
    assert (passwd);
    assert (streq (passwd, "Top Secret"));

    zconfig_save (root, TESTDIR "/test.cfg");
    zconfig_destroy (&root);
    
    //  Delete all test files
    zdir_t *dir = zdir_new (TESTDIR, NULL);
    zdir_remove (dir, true);
    zdir_destroy (&dir);
    //  @end

    printf ("OK\n");
}
Exemplo n.º 7
0
int
zconfig_reload (zconfig_t **self_p)
{
    assert (self_p);
    zconfig_t *self = *self_p;

    if (self->file) {
        zconfig_t *copy = zconfig_load (zfile_filename (self->file, NULL));
        if (copy) {
            //  Destroy old tree and install new one
            zconfig_destroy (self_p);
            *self_p = copy;
            return 0;
        }
    }
    return -1;              //  Not successful
}
Exemplo n.º 8
0
int
shelf_test (bool verbose)
{
    printf (" * shelf: ");
    zconfig_t* config = zconfig_load(".testdir/test.cfg");
    assert(config); 
    zpgutil_datasource_t *datasource = zpgutil_datasource_new (config);
    assert (datasource);
    zpgutil_session_t *session = zpgutil_session_new (datasource);
    assert (session);
 
    //  @selftest
    //  Simple create/destroy test
    shelf_t *self = shelf_new (session);
    assert (self);
    book_t *mybook = shelf_add_book (self,"William Shakespeare","Macbeth");
    assert (mybook);
    book_destroy (&mybook);

    int c = shelf_count_books (self);
    assert (c>0);

    shelf_load_books (self);
    book_t *loaded;
    while ( (loaded = shelf_next_book (self)) != NULL)
    {
      book_print (loaded);
      book_destroy (&loaded);
    }
    shelf_destroy (&self);
    //  @end

    zpgutil_session_destroy (&session);
    zpgutil_datasource_destroy (&datasource);
    zconfig_destroy (&config);

    printf ("OK\n");
    return 0;
}
Exemplo n.º 9
0
int main(int argc, char * const *argv)
{
    setvbuf(stdout, NULL, _IOLBF, 0);
    setvbuf(stderr, NULL, _IOLBF, 0);

    process_arguments(argc, argv);

    // load config
    if (!zsys_file_exists(config_file_name)) {
        fprintf(stderr, "[W] missing config file: %s\n", config_file_name);
        config = zconfig_new("", NULL);
    } else if (zsys_file_exists(config_file_name)) {
        // load config
        config_file_init();
        config = zconfig_load((char*)config_file_name);
    }

    // configure graylog endpoint
    if (interface == NULL)
        interface = zconfig_resolve(config, "/graylog/endpoint", DEFAULT_INTERFACE);

    // set inbound high-water-mark
    if (rcv_hwm == -1)
        rcv_hwm = atoi(zconfig_resolve(config, "/logjam/high_water_mark", DEFAULT_RCV_HWM_STR));

    // set outbound high-water-mark
    if (snd_hwm == -1)
        snd_hwm = atoi(zconfig_resolve(config, "/graylog/high_water_mark", DEFAULT_SND_HWM_STR));

    if (!quiet)
        printf("[I] started %s\n"
               "[I] interface %s\n"
               "[I] rcv-hwm:  %d\n"
               "[I] snd-hwm:  %d\n"
               , argv[0], interface, rcv_hwm, snd_hwm);

    return graylog_forwarder_run_controller_loop(config, hosts, subscriptions, rcv_hwm, snd_hwm);
}
Exemplo n.º 10
0
///
//  Load a config tree from a specified ZPL text file; returns a zconfig_t  
//  reference for the root, if the file exists and is readable. Returns NULL
//  if the file does not exist.                                             
QmlZconfig *QmlZconfigAttached::load (const QString &filename) {
    QmlZconfig *qmlSelf = new QmlZconfig ();
    qmlSelf->self = zconfig_load (filename.toUtf8().data());
    return qmlSelf;
};
Exemplo n.º 11
0
void
zconfig_test (bool verbose)
{
    printf (" * zconfig: ");

    //  @selftest
    //  Create temporary directory for test files
#   define TESTDIR ".test_zconfig"
    zsys_dir_create (TESTDIR);

    zconfig_t *root = zconfig_new ("root", NULL);
    assert (root);
    zconfig_t *section, *item;

    section = zconfig_new ("headers", root);
    assert (section);
    item = zconfig_new ("email", section);
    assert (item);
    zconfig_set_value (item, "*****@*****.**");
    item = zconfig_new ("name", section);
    assert (item);
    zconfig_set_value (item, "Justin Kayce");
    zconfig_putf (root, "/curve/secret-key", "%s", "Top Secret");
    zconfig_set_comment (root, "   CURVE certificate");
    zconfig_set_comment (root, "   -----------------");
    assert (zconfig_comments (root));
    zconfig_save (root, TESTDIR "/test.cfg");
    zconfig_destroy (&root);
    root = zconfig_load (TESTDIR "/test.cfg");
    if (verbose)
        zconfig_save (root, "-");
    assert (streq (zconfig_filename (root), TESTDIR "/test.cfg"));

    char *email = zconfig_get (root, "/headers/email", NULL);
    assert (email);
    assert (streq (email, "*****@*****.**"));
    char *passwd = zconfig_get (root, "/curve/secret-key", NULL);
    assert (passwd);
    assert (streq (passwd, "Top Secret"));

    zconfig_savef (root, "%s/%s", TESTDIR, "test.cfg");
    assert (!zconfig_has_changed (root));
    int rc = zconfig_reload (&root);
    assert (rc == 0);
    assert (!zconfig_has_changed (root));
    zconfig_destroy (&root);

    //  Test chunk load/save
    root = zconfig_new ("root", NULL);
    assert (root);
    section = zconfig_new ("section", root);
    assert (section);
    item = zconfig_new ("value", section);
    assert (item);
    zconfig_set_value (item, "somevalue");
    zconfig_t *search = zconfig_locate (root, "section/value");
    assert (search == item);
    zchunk_t *chunk = zconfig_chunk_save (root);
    assert (strlen ((char *) zchunk_data (chunk)) == 32);
    char *string = zconfig_str_save (root);
    assert (string);
    assert (streq (string, (char *) zchunk_data (chunk)));
    free (string);
    assert (chunk);
    zconfig_destroy (&root);

    root = zconfig_chunk_load (chunk);
    assert (root);
    char *value = zconfig_get (root, "/section/value", NULL);
    assert (value);
    assert (streq (value, "somevalue"));

    //  Test config can't be saved to a file in a path that doesn't
    //  exist or isn't writable
    rc = zconfig_savef (root, "%s/path/that/doesnt/exist/%s", TESTDIR, "test.cfg");
    assert (rc == -1);

    zconfig_destroy (&root);
    zchunk_destroy (&chunk);

    //  Delete all test files
    zdir_t *dir = zdir_new (TESTDIR, NULL);
    assert (dir);
    zdir_remove (dir, true);
    zdir_destroy (&dir);
    //  @end

    printf ("OK\n");
}
Exemplo n.º 12
0
int main (int argc, char *argv [])
{
    puts (PRODUCT);
    puts (COPYRIGHT);
    puts (NOWARRANTY);

    int argn = 1;
    bool verbose = false;
    bool force_foreground = false;
    if (argc > argn && streq (argv [argn], "-v")) {
        verbose = true;
        argn++;
    }
    if (argc > argn && streq (argv [argn], "-f")) {
        force_foreground = true;
        argn++;
    }
    if (argc > argn && streq (argv [argn], "-h")) {
        puts ("Usage: malamute [ -v ] [ -f ] [ -h | config-file ]");
        puts ("  Default config-file is 'malamute.cfg'");
        return 0;
    }
    //  Collect configuration file name
    const char *config_file = "malamute.cfg";
    if (argc > argn) {
        config_file = argv [argn];
        argn++;
    }
    zsys_init ();
    // Keep old behavior unless specified otherwise.
    if (!getenv ("ZSYS_LOGSYSTEM")) {
        zsys_set_logsystem(true);
    }
    zsys_set_pipehwm (0);
    zsys_set_sndhwm (0);
    zsys_set_rcvhwm (0);

    //  Load config file for our own use here
    zsys_info ("loading configuration from '%s'...", config_file);
    zconfig_t *config = zconfig_load (config_file);
    if (!config) {
        zsys_info ("'%s' is missing, creating with defaults:", config_file);
        config = zconfig_new ("root", NULL);
        zconfig_put (config, "server/timeout", "5000");
        zconfig_put (config, "server/background", "0");
        zconfig_put (config, "server/workdir", ".");
        zconfig_put (config, "server/verbose", "0");
        zconfig_put (config, "mlm_server/security/mechanism", "null");
        zconfig_put (config, "mlm_server/bind/endpoint", MLM_DEFAULT_ENDPOINT);
        zconfig_print (config);
        zconfig_save (config, config_file);
    }
    //  Do we want to run broker in the background?
    int as_daemon = !force_foreground && atoi (zconfig_resolve (config, "server/background", "0"));
    const char *workdir = zconfig_resolve (config, "server/workdir", ".");
    if (as_daemon) {
        zsys_info ("switching Malamute to background...");
        if (zsys_daemonize (workdir))
            return -1;
    }
    //  Switch to user/group to run process under, if any
    if (zsys_run_as (
        zconfig_resolve (config, "server/lockfile", NULL),
        zconfig_resolve (config, "server/group", NULL),
        zconfig_resolve (config, "server/user", NULL)))
        return -1;

    //  Install authenticator (NULL or PLAIN)
    zactor_t *auth = zactor_new (zauth, NULL);
    assert (auth);

    if (verbose || atoi (zconfig_resolve (config, "server/auth/verbose", "0"))) {
        zstr_sendx (auth, "VERBOSE", NULL);
        zsock_wait (auth);
    }
    //  Do PLAIN password authentication if requested
    const char *passwords = zconfig_resolve (config, "server/auth/plain", NULL);
    if (passwords) {
        zstr_sendx (auth, "PLAIN", passwords, NULL);
        zsock_wait (auth);
    }
    //  Start Malamute server instance
    zactor_t *server = zactor_new (mlm_server, "Malamute");
    if (verbose)
        zstr_send (server, "VERBOSE");
    zstr_sendx (server, "LOAD", config_file, NULL);

    //  Accept and print any message back from server
    while (true) {
        char *message = zstr_recv (server);
        if (message) {
            puts (message);
            free (message);
        }
        else {
            puts ("interrupted");
            break;
        }
    }
    //  Shutdown all services
    zactor_destroy (&server);
    zactor_destroy (&auth);

    //  Destroy config tree
    zconfig_destroy (&config);

#if defined (__WINDOWS__)
    zsys_shutdown ();
#endif

    return 0;
}
Exemplo n.º 13
0
int main(int argc, char * const *argv)
{
    int rc = 0;
    process_arguments(argc, argv);

    setvbuf(stdout, NULL, _IOLBF, 0);
    setvbuf(stderr, NULL, _IOLBF, 0);

    if (!quiet)
        printf("[I] started %s\n"
               "[I] sub-port:    %d\n"
               "[I] push-port:   %d\n"
               "[I] io-threads:  %lu\n"
               "[I] rcv-hwm:  %d\n"
               "[I] snd-hwm:  %d\n"
               , argv[0], pull_port, pub_port, io_threads, rcv_hwm, snd_hwm);

    // load config
    config_file_exists = zsys_file_exists(config_file_name);
    if (config_file_exists) {
        config_file_init();
        config = zconfig_load((char*)config_file_name);
    }

    // set global config
    zsys_init();
    zsys_set_rcvhwm(10000);
    zsys_set_sndhwm(10000);
    zsys_set_pipehwm(1000);
    zsys_set_linger(100);
    zsys_set_io_threads(io_threads);

    // create socket to receive messages on
    zsock_t *receiver = zsock_new(ZMQ_SUB);
    assert_x(receiver != NULL, "sub socket creation failed", __FILE__, __LINE__);
    zsock_set_rcvhwm(receiver, rcv_hwm);

    // bind externally
    char* host = zlist_first(hosts);
    while (host) {
        if (!quiet)
            printf("[I] connecting to: %s\n", host);
        rc = zsock_connect(receiver, "%s", host);
        assert_x(rc == 0, "sub socket connect failed", __FILE__, __LINE__);
        host = zlist_next(hosts);
    }
    tracker = device_tracker_new(hosts, receiver);

    // create socket for publishing
    zsock_t *publisher = zsock_new(ZMQ_PUSH);
    assert_x(publisher != NULL, "pub socket creation failed", __FILE__, __LINE__);
    zsock_set_sndhwm(publisher, snd_hwm);

    rc = zsock_bind(publisher, "tcp://%s:%d", "*", pub_port);
    assert_x(rc == pub_port, "pub socket bind failed", __FILE__, __LINE__);

    // create compressor sockets
    zsock_t *compressor_input = zsock_new(ZMQ_PUSH);
    assert_x(compressor_input != NULL, "compressor input socket creation failed", __FILE__, __LINE__);
    rc = zsock_bind(compressor_input, "inproc://compressor-input");
    assert_x(rc==0, "compressor input socket bind failed", __FILE__, __LINE__);

    zsock_t *compressor_output = zsock_new(ZMQ_PULL);
    assert_x(compressor_output != NULL, "compressor output socket creation failed", __FILE__, __LINE__);
    rc = zsock_bind(compressor_output, "inproc://compressor-output");
    assert_x(rc==0, "compressor output socket bind failed", __FILE__, __LINE__);

    // create compressor agents
    zactor_t *compressors[MAX_COMPRESSORS];
    for (size_t i = 0; i < num_compressors; i++)
        compressors[i] = message_decompressor_new(i);

    // set up event loop
    zloop_t *loop = zloop_new();
    assert(loop);
    zloop_set_verbose(loop, 0);

    // calculate statistics every 1000 ms
    int timer_id = zloop_timer(loop, 1000, 0, timer_event, NULL);
    assert(timer_id != -1);

    // setup handler for the receiver socket
    publisher_state_t publisher_state = {
        .receiver = zsock_resolve(receiver),
        .publisher = zsock_resolve(publisher),
        .compressor_input = zsock_resolve(compressor_input),
        .compressor_output = zsock_resolve(compressor_output),
    };

    // setup handler for compression results
    rc = zloop_reader(loop, compressor_output, read_zmq_message_and_forward, &publisher_state);
    assert(rc == 0);
    zloop_reader_set_tolerant(loop, compressor_output);

    // setup handdler for messages incoming from the outside or rabbit_listener
    rc = zloop_reader(loop, receiver, read_zmq_message_and_forward, &publisher_state);
    assert(rc == 0);
    zloop_reader_set_tolerant(loop, receiver);

    // initialize clock
    global_time = zclock_time();

    // setup subscriptions
    if (subscriptions == NULL || zlist_size(subscriptions) == 0) {
        if (!quiet)
            printf("[I] subscribing to all log messages\n");
        zsock_set_subscribe(receiver, "");
    } else {
        char *subscription = zlist_first(subscriptions);
        while (subscription) {
            if (!quiet)
                printf("[I] subscribing to %s\n", subscription);
            zsock_set_subscribe(receiver, subscription);
            subscription = zlist_next(subscriptions);
        }
        zsock_set_subscribe(receiver, "heartbeat");
    }

    // run the loop
    if (!zsys_interrupted) {
        if (verbose)
            printf("[I] starting main event loop\n");
        bool should_continue_to_run = getenv("CPUPROFILE") != NULL;
        do {
            rc = zloop_start(loop);
            should_continue_to_run &= errno == EINTR && !zsys_interrupted;
            log_zmq_error(rc, __FILE__, __LINE__);
        } while (should_continue_to_run);
        if (verbose)
            printf("[I] main event zloop terminated with return code %d\n", rc);
    }

    zloop_destroy(&loop);
    assert(loop == NULL);

    if (!quiet) {
        printf("[I] received %zu messages\n", received_messages_count);
        printf("[I] shutting down\n");
    }

    zlist_destroy(&hosts);
    zlist_destroy(&subscriptions);
    zsock_destroy(&receiver);
    zsock_destroy(&publisher);
    zsock_destroy(&compressor_input);
    zsock_destroy(&compressor_output);
    device_tracker_destroy(&tracker);
    for (size_t i = 0; i < num_compressors; i++)
        zactor_destroy(&compressors[i]);
    zsys_shutdown();

    if (!quiet)
        printf("[I] terminated\n");

    return rc;
}
Exemplo n.º 14
0
void
zconfig_test (bool verbose)
{
    printf (" * zconfig: ");

    //  @selftest
    //  We create a config of this structure:
    //
    //  root
    //      type = zqueue
    //      frontend
    //          option
    //              swap = 25000000     #  25MB
    //              subscribe = #2
    //              hwm = 1000
    //          bind = tcp://*:5555
    //      backend
    //          bind = tcp://*:5556
    //
    zconfig_t
        *root,
        *type,
        *frontend,
        *option,
        *hwm,
        *swap,
        *subscribe,
        *bind,
        *backend;

    //  Left is first child, next is next sibling
    root     = zconfig_new ("root", NULL);
    type     = zconfig_new ("type", root);
    zconfig_value_set (type, "zqueue");
    frontend = zconfig_new ("frontend", root);
    option   = zconfig_new ("option", frontend);
    swap     = zconfig_new ("swap", option);
    zconfig_value_set (swap, "25000000");
    subscribe = zconfig_new ("subscribe", option);
    zconfig_value_format (subscribe, "#%d", 2);
    hwm      = zconfig_new ("hwm", option);
    zconfig_value_set (hwm, "1000");
    bind     = zconfig_new ("bind", frontend);
    zconfig_value_set (bind, "tcp://*:5555");
    backend  = zconfig_new ("backend", root);
    bind     = zconfig_new ("bind", backend);
    zconfig_value_set (bind, "tcp://*:5556");

    assert (atoi (zconfig_resolve (root, "frontend/option/hwm", "0")) == 1000);
    assert (streq (zconfig_resolve (root, "backend/bind", ""), "tcp://*:5556"));

    zconfig_path_set (root, "frontend/option/hwm", "500");
    assert (atoi (zconfig_resolve (root, "frontend/option/hwm", "0")) == 500);
    zconfig_path_set (root, "frontend/option/lwm", "200");
    assert (atoi (zconfig_resolve (root, "frontend/option/lwm", "0")) == 200);
    
    zconfig_destroy (&root);
    assert (root == NULL);

    //  Test loading from a ZPL file
    zconfig_t *config = zconfig_load ("selftest.cfg");
    assert (config);

    //  Destructor should be safe to call twice
    zconfig_destroy (&config);
    zconfig_destroy (&config);
    assert (config == NULL);
    //  @end

    printf ("OK\n");
}
Exemplo n.º 15
0
bool
GlobalServerStartupInfo_init (
    GlobalServerStartupInfo *self,
    char *confFilePath
) {
    memset (self, 0, sizeof (GlobalServerStartupInfo));

    bool result = true;
    zconfig_t *conf = NULL;
    char *portsArray = NULL;

    // ===================================
    //       Read Global configuration
    // ===================================
    // Open the configuration file
    if (!(conf = zconfig_load (confFilePath))) {
        error ("Cannot read the global configuration file (%s).", confFilePath);
        result = false;
        goto cleanup;
    }

    // Read the CLI serverIP
    if (!(self->ip = strdup (zconfig_resolve (conf, "globalServer/serverIP", NULL)))
    ) {
        warning ("Cannot read correctly the CLI serverIP in the configuration file (%s). ", confFilePath);
        warning ("The default serverIP = %s has been used.", GLOBAL_SERVER_CLI_IP_DEFAULT);
        self->ip = GLOBAL_SERVER_CLI_IP_DEFAULT;
    }

    // Read the CLI port
    if (!(self->cliPort = atoi (zconfig_resolve (conf, "globalServer/port", NULL)))
    ) {
        warning ("Cannot read correctly the CLI port in the configuration file (%s). ", confFilePath);
        warning ("The default port = %d has been used.", GLOBAL_SERVER_CLI_PORT_DEFAULT);
        self->cliPort = GLOBAL_SERVER_CLI_PORT_DEFAULT;
    }

    // ===================================
    //       Read Zone configuration
    // ===================================
    // Read the zone ports array
    if (!(portsArray = zconfig_resolve (conf, "zoneServer/portsArray", NULL))) {
        warning ("Public Zone ports cannot be read for Global Server. Defaults ports have been used : %s", ZONE_SERVER_PORTS_DEFAULT);
        portsArray = ZONE_SERVER_PORTS_DEFAULT;
    }

    // Tokenize the ports array
    char *port = strtok (portsArray, " ");
    while (port != NULL) {
        self->zoneServersCount++;
        port = strtok (NULL, " ");
    }

    if (self->zoneServersCount == 0) {
        error ("Cannot read correctly the zone ports array.");
        result = false;
        goto cleanup;
    }

    // Fill the server ports array
    self->zoneServersPorts = calloc (self->zoneServersCount, sizeof (int));
    for (int portIndex = 0; portIndex < self->zoneServersCount; portIndex++) {
        self->zoneServersPorts[portIndex] = strtoul (portsArray, &portsArray, 10);
        portsArray++;
    }

    // Read the number of zone workers
    if (!(self->zoneWorkersCount = atoi (zconfig_resolve (conf, "zoneServer/workersCount", NULL)))) {
        warning ("Cannot read correctly the zone workers count in the configuration file (%s). ", confFilePath);
        warning ("The default worker count = %d has been used.", ZONE_SERVER_WORKERS_COUNT_DEFAULT);
        self->zoneWorkersCount = ZONE_SERVER_WORKERS_COUNT_DEFAULT;
    }

    char *zoneServersIp;
    // Read the zone server interfaces IP
    if (!(zoneServersIp = zconfig_resolve (conf, "zoneServer/serversIP", NULL))) {
        error ("Cannot read correctly the zone servers interface IP in the configuration file (%s). ", confFilePath);
        result = false;
        goto cleanup;
    }

    int nbZoneServersIp = 0;
    char *routerIp = strtok (zoneServersIp, " ");
    while (routerIp != NULL) {
        routerIp = strtok (NULL, " ");
        nbZoneServersIp++;
    }

    if (nbZoneServersIp != self->zoneServersCount) {
        error ("Number of zone ports different from the number of zone interfaces IP. (%d / %d)",
            nbZoneServersIp, self->zoneServersCount
        );
        result = false;
        goto cleanup;
    }

    // Fill the zone server IPs array
    self->zoneServersIp = calloc (self->zoneServersCount, sizeof (char *));
    for (int ipIndex = 0; ipIndex < self->zoneServersCount; ipIndex++) {
        self->zoneServersIp[ipIndex] = strdup (zoneServersIp);
        zoneServersIp += strlen (zoneServersIp) + 1;
    }

    // ===================================
    //       Read Social configuration
    // ===================================
    // Read the social ports array
    if (!(portsArray = zconfig_resolve (conf, "socialServer/portsArray", NULL))) {
        warning ("Public Social ports cannot be read for Global Server. Defaults ports have been used : %s", SOCIAL_SERVER_PORTS_DEFAULT);
        portsArray = SOCIAL_SERVER_PORTS_DEFAULT;
    }

    // Tokenize the ports array
    port = strtok (portsArray, " ");
    while (port != NULL) {
        self->socialServersCount++;
        port = strtok (NULL, " ");
    }

    if (self->socialServersCount == 0) {
        error ("Cannot read correctly the social ports array.");
        result = false;
        goto cleanup;
    }

    // Fill the server ports array
    self->socialServersPorts = calloc (self->socialServersCount, sizeof (int));
    for (int portIndex = 0; portIndex < self->socialServersCount; portIndex++) {
        self->socialServersPorts[portIndex] = strtoul (portsArray, &portsArray, 10);
        portsArray++;
    }

    // Read the number of social workers
    if (!(self->socialWorkersCount = atoi (zconfig_resolve (conf, "socialServer/workersCount", NULL)))) {
        warning ("Cannot read correctly the social workers count in the configuration file (%s). ", confFilePath);
        warning ("The default worker count = %d has been used.", SOCIAL_SERVER_WORKERS_COUNT_DEFAULT);
        self->socialWorkersCount = SOCIAL_SERVER_WORKERS_COUNT_DEFAULT;
    }

    char *socialServersIp;
    // Read the social server interfaces IP
    if (!(socialServersIp = zconfig_resolve (conf, "socialServer/serversIP", NULL))) {
        error ("Cannot read correctly the social servers interface IP in the configuration file (%s). ", confFilePath);
        result = false;
        goto cleanup;
    }

    int nbSocialServersIp = 0;
    routerIp = strtok (socialServersIp, " ");
    while (routerIp != NULL) {
        routerIp = strtok (NULL, " ");
        nbSocialServersIp++;
    }

    if (nbSocialServersIp != self->socialServersCount) {
        error ("Number of social ports different from the number of social interfaces IP. (%d / %d)",
            nbSocialServersIp, self->socialServersCount
        );
        result = false;
        goto cleanup;
    }

    // Fill the social server IPs array
    self->socialServersIp = calloc (self->socialServersCount, sizeof (char *));
    for (int ipIndex = 0; ipIndex < self->socialServersCount; ipIndex++) {
        self->socialServersIp[ipIndex] = strdup (socialServersIp);
        socialServersIp += strlen (socialServersIp) + 1;
    }

    // ===================================
    //       Read Barrack configuration
    // ===================================
    // Read the ports array
    if (!(portsArray = zconfig_resolve (conf, "barrackServer/portsArray", NULL))) {
        warning ("Ports cannot be read for Barrack Server. Defaults ports have been used : %s", BARRACK_SERVER_PORTS_DEFAULT);
        portsArray = BARRACK_SERVER_PORTS_DEFAULT;
    }

    // Tokenize the ports array
    port = strtok (portsArray, " ");
    while (port != NULL) {
        self->barrackServerPortCount++;
        port = strtok (NULL, " ");
    }

    // Fill the server ports array
    self->barrackServerPort = calloc (self->barrackServerPortCount, sizeof (int));
    for (int portIndex = 0; portIndex < self->barrackServerPortCount; portIndex++) {
        self->barrackServerPort[portIndex] = strtoul (portsArray, &portsArray, 10);
        portsArray++;
    }

    // Read the number of barrack server workers
    if (!(self->barrackWorkersCount = atoi (zconfig_resolve (conf, "barrackServer/workersCount", NULL)))) {
        warning ("Cannot read correctly the barrack workers count in the configuration file (%s). ", confFilePath);
        warning ("The default worker count = %d has been used.", BARRACK_SERVER_WORKERS_COUNT_DEFAULT);
        self->barrackWorkersCount = BARRACK_SERVER_WORKERS_COUNT_DEFAULT;
    }

    // Read the server interface IP
    if (!(self->barrackServerIp = strdup (zconfig_resolve (conf, "barrackServer/serverIP", NULL)))) {
        warning ("Cannot read correctly the barrack interface IP in the configuration file (%s). ", confFilePath);
        warning ("The default IP = %s has been used.", BARRACK_SERVER_FRONTEND_IP_DEFAULT);
        self->barrackServerIp = BARRACK_SERVER_FRONTEND_IP_DEFAULT;
    }

    // ===================================
    //       Read MySQL configuration
    // ===================================
    if (!(self->sqlInfo.hostname = strdup (zconfig_resolve (conf, "database/mysql_host", NULL)))
    ) {
        warning ("Cannot read correctly the MySQL host in the configuration file (%s). ", confFilePath);
        warning ("The default hostname = %s has been used.", MYSQL_HOSTNAME_DEFAULT);
        self->sqlInfo.hostname = MYSQL_HOSTNAME_DEFAULT;
    }
    if (!(self->sqlInfo.login = strdup (zconfig_resolve (conf, "database/mysql_user", NULL)))
    ) {
        warning ("Cannot read correctly the MySQL user in the configuration file (%s). ", confFilePath);
        warning ("The default hostname = %s has been used.", MYSQL_LOGIN_DEFAULT);
        self->sqlInfo.login = MYSQL_LOGIN_DEFAULT;
    }
    if (!(self->sqlInfo.password = strdup (zconfig_resolve (conf, "database/mysql_password", NULL)))
    ) {
        warning ("Cannot read correctly the MySQL password in the configuration file (%s). ", confFilePath);
        warning ("The default hostname = %s has been used.", MYSQL_PASSWORD_DEFAULT);
        self->sqlInfo.password = MYSQL_PASSWORD_DEFAULT;
    }
    if (!(self->sqlInfo.database = strdup (zconfig_resolve (conf, "database/mysql_database", NULL)))
    ) {
        warning ("Cannot read correctly the MySQL database in the configuration file (%s). ", confFilePath);
        warning ("The default hostname = %s has been used.", MYSQL_DATABASE_DEFAULT);
        self->sqlInfo.database = MYSQL_DATABASE_DEFAULT;
    }

    // ===================================
    //       Read Redis configuration
    // ===================================
    if (!(self->redisInfo.hostname = strdup (zconfig_resolve (conf, "redisServer/redis_host", NULL)))
    ) {
        warning ("Cannot read correctly the Redis host in the configuration file (%s). ", confFilePath);
        warning ("The default hostname = %s has been used.", REDIS_HOSTNAME_DEFAULT);
        self->redisInfo.hostname = REDIS_HOSTNAME_DEFAULT;
    }
    if (!(self->redisInfo.port = atoi (zconfig_resolve (conf, "redisServer/redis_port", NULL)))
    ) {
        warning ("Cannot read correctly the Redis port in the configuration file (%s). ", confFilePath);
        warning ("The default hostname = %d has been used.", REDIS_PORT_DEFAULT);
        self->redisInfo.port = REDIS_PORT_DEFAULT;
    }


cleanup:
    // Close the configuration file
    zconfig_destroy (&conf);

    return result;
}
Exemplo n.º 16
0
void
zconfig_test (bool verbose)
{
    printf (" * zconfig: ");

    //  @selftest

    const char *SELFTEST_DIR_RW = "src/selftest-rw";

    const char *testbasedir  = ".test_zconfig";
    const char *testfile = "test.cfg";
    char *basedirpath = NULL;   // subdir in a test, under SELFTEST_DIR_RW
    char *filepath = NULL;      // pathname to testfile in a test, in dirpath

    basedirpath = zsys_sprintf ("%s/%s", SELFTEST_DIR_RW, testbasedir);
    assert (basedirpath);
    filepath = zsys_sprintf ("%s/%s", basedirpath, testfile);
    assert (filepath);

    // Make sure old aborted tests do not hinder us
    zdir_t *dir = zdir_new (basedirpath, NULL);
    if (dir) {
        zdir_remove (dir, true);
        zdir_destroy (&dir);
    }
    zsys_file_delete (filepath);
    zsys_dir_delete  (basedirpath);

    //  Create temporary directory for test files
    zsys_dir_create (basedirpath);

    zconfig_t *root = zconfig_new ("root", NULL);
    assert (root);
    zconfig_t *section, *item;

    section = zconfig_new ("headers", root);
    assert (section);
    item = zconfig_new ("email", section);
    assert (item);
    zconfig_set_value (item, "*****@*****.**");
    item = zconfig_new ("name", section);
    assert (item);
    zconfig_set_value (item, "Justin Kayce");
    zconfig_putf (root, "/curve/secret-key", "%s", "Top Secret");
    zconfig_set_comment (root, "   CURVE certificate");
    zconfig_set_comment (root, "   -----------------");
    assert (zconfig_comments (root));
    zconfig_save (root, filepath);
    zconfig_destroy (&root);
    root = zconfig_load (filepath);
    if (verbose)
        zconfig_save (root, "-");
    assert (streq (zconfig_filename (root), filepath));

    char *email = zconfig_get (root, "/headers/email", NULL);
    assert (email);
    assert (streq (email, "*****@*****.**"));
    char *passwd = zconfig_get (root, "/curve/secret-key", NULL);
    assert (passwd);
    assert (streq (passwd, "Top Secret"));

    zconfig_savef (root, "%s/%s", basedirpath, testfile);
    assert (!zconfig_has_changed (root));
    int rc = zconfig_reload (&root);
    assert (rc == 0);
    assert (!zconfig_has_changed (root));
    zconfig_destroy (&root);

    //  Test chunk load/save
    root = zconfig_new ("root", NULL);
    assert (root);
    section = zconfig_new ("section", root);
    assert (section);
    item = zconfig_new ("value", section);
    assert (item);
    zconfig_set_value (item, "somevalue");
    zconfig_t *search = zconfig_locate (root, "section/value");
    assert (search == item);
    zchunk_t *chunk = zconfig_chunk_save (root);
    assert (strlen ((char *) zchunk_data (chunk)) == 32);
    char *string = zconfig_str_save (root);
    assert (string);
    assert (streq (string, (char *) zchunk_data (chunk)));
    freen (string);
    assert (chunk);
    zconfig_destroy (&root);

    root = zconfig_chunk_load (chunk);
    assert (root);
    char *value = zconfig_get (root, "/section/value", NULL);
    assert (value);
    assert (streq (value, "somevalue"));

    //  Test config can't be saved to a file in a path that doesn't
    //  exist or isn't writable
    rc = zconfig_savef (root, "%s/path/that/doesnt/exist/%s", basedirpath, testfile);
    assert (rc == -1);

    zconfig_destroy (&root);
    zchunk_destroy (&chunk);

    //  Test subtree removal
	{
		zconfig_t *root = zconfig_str_load (
			"context\n"
			"    iothreads = 1\n"
			"    verbose = 1      #   Ask for a trace\n"
			"main\n"
			"    type = zqueue    #  ZMQ_DEVICE type\n"
			"    frontend\n"
			"        option\n"
			"            hwm = 1000\n"
			"            swap = 25000000     #  25MB\n"
			"        bind = 'inproc://addr1'\n"
			"        bind = 'ipc://addr2'\n"
			"    backend\n"
			"        bind = inproc://addr3\n"
		);

        zconfig_t *to_delete = zconfig_locate (root, "main/frontend");
        assert (to_delete);

        zconfig_remove (to_delete);

        char *value = zconfig_get (root, "/main/type", NULL);
        assert (value);
        assert (streq (value, "zqueue"));

        value = zconfig_get (root, "/main/backend/bind", NULL);
        assert (value);
        assert (streq (value, "inproc://addr3"));

        value = zconfig_get (root, "/main/frontend", NULL);
        assert (value);

        value = zconfig_get (root, "/main/frontend/option", NULL);
        assert (value == NULL);

        value = zconfig_get (root, "/main/frontend/option/swap", NULL);
        assert (value == NULL);

        zconfig_destroy (&root);
	}

    // Test str_load
    zconfig_t *config = zconfig_str_load (
        "malamute\n"
        "    endpoint = ipc://@/malamute\n"
        "    producer = STREAM\n"
        "    consumer\n"
        "        STREAM2 = .*\n"
        "        STREAM3 = HAM\n"
        "server\n"
        "    verbose = true\n"
        );
    assert (config);
    assert (streq (zconfig_get (config, "malamute/endpoint", NULL), "ipc://@/malamute"));
    assert (streq (zconfig_get (config, "malamute/producer", NULL), "STREAM"));
    assert (zconfig_locate (config, "malamute/consumer"));

    zconfig_t *c = zconfig_child (zconfig_locate (config, "malamute/consumer"));
    assert (c);
    assert (streq (zconfig_name (c), "STREAM2"));
    assert (streq (zconfig_value (c), ".*"));

    c = zconfig_next (c);
    assert (c);
    assert (streq (zconfig_name (c), "STREAM3"));
    assert (streq (zconfig_value (c), "HAM"));

    c = zconfig_next (c);
    assert (!c);

    assert (streq (zconfig_get (config, "server/verbose", NULL), "true"));

    zconfig_destroy (&config);

    //  Delete all test files
    dir = zdir_new (basedirpath, NULL);
    assert (dir);
    zdir_remove (dir, true);
    zdir_destroy (&dir);

    zstr_free (&basedirpath);
    zstr_free (&filepath);

#if defined (__WINDOWS__)
    zsys_shutdown();
#endif
    //  @end

    printf ("OK\n");
}
Exemplo n.º 17
0
int main (int argc, char *argv [])
{
    puts (PRODUCT);
    puts (COPYRIGHT);
    puts (NOWARRANTY);

    int argn = 1;
    bool verbose = false;
    bool force_foreground = false;
    if (argc > argn && streq (argv [argn], "-v")) {
        verbose = true;
        argn++;
    }
    if (argc > argn && streq (argv [argn], "-f")) {
        force_foreground = true;
        argn++;
    }
    if (argc > argn && streq (argv [argn], "-h")) {
        puts ("Usage: malamute [ -v ] [ -f ] [ -h | config-file ]");
        puts ("  Default config-file is 'malamute.cfg'");
        return 0;
    }
    //  Collect configuration file name
    const char *config_file = "malamute.cfg";
    if (argc > argn) {
        config_file = argv [argn];
        argn++;
    }
    //  Send logging to system facility as well as stdout
    zsys_init ();
    zsys_set_logsystem (true);
    zsys_set_pipehwm (0);
    zsys_set_sndhwm (0);
    zsys_set_rcvhwm (0);

    //  Load config file for our own use here
    zsys_info ("starting Malamute using config in '%s'", config_file);
    zconfig_t *config = zconfig_load (config_file);
    if (config) {
        //  Do we want to run broker in the background?
        int as_daemon = !force_foreground && atoi (zconfig_resolve (config, "server/background", "0"));
        const char *workdir = zconfig_resolve (config, "server/workdir", ".");
        if (as_daemon) {
            zsys_info ("switching Malamute to background...");
            if (zsys_daemonize (workdir))
                return -1;
        }
        //  Switch to user/group to run process under, if any
        if (zsys_run_as (
            zconfig_resolve (config, "server/lockfile", NULL),
            zconfig_resolve (config, "server/group", NULL),
            zconfig_resolve (config, "server/user", NULL)))
            return -1;
    }
    else {
        zsys_error ("cannot load config file '%s'\n", config_file);
        return 1;
    }
    //  Install authenticator (NULL or PLAIN)
    zactor_t *auth = zactor_new (zauth, NULL);
    assert (auth);

    if (verbose || atoi (zconfig_resolve (config, "server/auth/verbose", "0"))) {
        zstr_sendx (auth, "VERBOSE", NULL);
        zsock_wait (auth);
    }
    //  Do PLAIN password authentication if requested
    const char *passwords = zconfig_resolve (config, "server/auth/plain", NULL);
    if (passwords) {
        zstr_sendx (auth, "PLAIN", passwords, NULL);
        zsock_wait (auth);
    }
    //  Start Malamute server instance
    zactor_t *server = zactor_new (mlm_server, "Malamute");
    if (verbose)
        zstr_send (server, "VERBOSE");
    zstr_sendx (server, "LOAD", config_file, NULL);

    //  Accept and print any message back from server
    while (true) {
        char *message = zstr_recv (server);
        if (message) {
            puts (message);
            free (message);
        }
        else {
            puts ("interrupted");
            break;
        }
    }
    //  Shutdown all services
    zactor_destroy (&server);
    zactor_destroy (&auth);

    //  Destroy config tree
    zconfig_destroy (&config);
    return 0;
}
Exemplo n.º 18
0
int zmaster_server_main(int argc, char **argv)
{
    int op;
    char *test_listen = 0;

    parent_pid = getppid();
    test_mode = 1;
    reloading = 0;
    softstopping = 0;
    ev_status = 0;
    ev_listen = 0;
    local_ev_close_do_once = 1;
    signal(SIGPIPE, SIG_IGN);

    if (!zvar_progname) {
        zvar_progname = argv[0];
    }

    zvar_config_init();
    zvar_evbase_init();

    while ((op = getopt(argc, argv, "Ml:c:o:t:dv")) > 0) {
        switch (op) {
        case 'M':
            test_mode = 0;
            break;
        case 'l':
            test_listen = optarg;
            break;
        case 'c':
            zconfig_load(zvar_config, optarg);
            break;
        case 'o':
            {
                char *key, *value;
                key = zstrdup(optarg);
                value = strchr(key, '=');
                if (value) {
                    *value++ = 0;
                }
                zconfig_add(zvar_config, key, value);
                zfree(key);
            }
            break;
        case 't':
            zvar_master_server_listen_type = optarg[0];
            break;
        case 'd':
            zlog_set_level_from_console(ZLOG_DEBUG);
            break;
        case 'v':
            zlog_set_level_from_console(ZLOG_VERBOSE);
            break;
        default:
            zfatal("parameters error");
        }
    }

    zlog_set_level(zlog_parse_level(zconfig_get_str(zvar_config, "zlog_level", "info")));

    register_server(test_listen);

    {
        char *run_user = zconfig_get_str(zvar_config, "zrun_user", 0);
        if (!ZEMPTY(run_user)) {
            if (zchroot_user(0, run_user) < 0) {
                zfatal("change user %s(%m)", run_user);
            }
        }
    }

    if (zmaster_server_before_service) {
        zmaster_server_before_service();
    }

    while (1) {
        zevbase_dispatch(zvar_evbase, 0);
        if (zmaster_server_loop) {
            zmaster_server_loop();
        }
        if (reloading) {
            local_ev_close();
            if (getppid() != parent_pid) {
                break;
            }
        }
        if (softstopping) {
            local_ev_close();
            break;
        }
    }

    local_ev_close();

    if (zmaster_server_before_exit) {
        zmaster_server_before_exit();
    }

    zevtimer_fini(&reload_timer);

    zevbase_free(zvar_evbase);

    return 0;
}
Exemplo n.º 19
0
int main (int argc, char *argv [])
{
    puts (PRODUCT);
    puts (COPYRIGHT);
    puts (NOWARRANTY);

    int argn = 1;
    bool verbose = false;
    if (argn < argc && streq (argv [argn], "-h")) {
        puts ("syntax: hydrad [ directory ]");
        puts (" -- defaults to .hydra in current directory");
        exit (0);
    }
    if (argn < argc && streq (argv [argn], "-v")) {
        verbose = true;
        argn++;
    }
    //  By default, current node runs in .hydra directory; create this if
    //  it's missing (don't create directory passed as argument);
    char *workdir = ".hydra";
    if (argn < argc)
        workdir = argv [argn++];
    else
        zsys_dir_create (workdir);

    //  ----------------------------------------------------------------------
    //  This code eventually goes into a reusable hydra actor class

    //  Switch to working directory
    zsys_info ("hydrad: data store in %s directory", workdir);
    if (zsys_dir_change (workdir)) {
        zsys_error ("hydrad: cannot access %s: %s", workdir, strerror (errno));
        return 1;
    }
    //  Check we are the only process currently running here
    if (zsys_run_as ("hydrad.lock", NULL, NULL)) {
        zsys_error ("hydrad: cannot start process safely, exiting");
        return 1;
    }
    //  Get node identity from config file, or generate new identity
    zconfig_t *config = zconfig_load ("hydra.cfg");
    if (!config) {
        //  Set defaults for Hydra service
        config = zconfig_new ("root", NULL);
        zconfig_put (config, "/server/timeout", "5000");
        zconfig_put (config, "/server/background", "0");
        zconfig_put (config, "/server/verbose", "0");
    }
    char *identity = zconfig_resolve (config, "/hydra/identity", NULL);
    if (!identity) {
        zuuid_t *uuid = zuuid_new ();
        zconfig_put (config, "/hydra/identity", zuuid_str (uuid));
        zconfig_put (config, "/hydra/nickname", "Anonymous");
        zconfig_save (config, "hydra.cfg");
        zuuid_destroy (&uuid);
    }
    //  Create store structure, if necessary
    zsys_dir_create ("content");
    zsys_dir_create ("posts");
    
    //  Start server and bind to ephemeral TCP port. We can run many
    //  servers on the same box, for testing.
    zactor_t *server = zactor_new (hydra_server, NULL);
    if (verbose)
        zstr_send (server, "VERBOSE");

    //  Bind Hydra service to ephemeral port and get that port number
    char *command;
    int port_nbr;
    zsock_send (server, "ss", "CONFIGURE", "hydra.cfg");
    zsock_send (server, "ss", "BIND", "tcp://*:*");
    zsock_send (server, "s", "PORT");
    zsock_recv (server, "si", &command, &port_nbr);
    zsys_info ("hydrad: TCP server started on port=%d", port_nbr);
    assert (streq (command, "PORT"));
    free (command);

    //  We're going to use Zyre for discovery and presence, and our own
    //  Hydra protocol for content exchange
    zyre_t *zyre = zyre_new (NULL);
    if (verbose)
        zyre_set_verbose (zyre);

    char *hostname = zsys_hostname ();
    char *endpoint = zsys_sprintf ("tcp://%s:%d", hostname, port_nbr);
    zyre_set_header (zyre, "X-HYDRA", "%s", endpoint);
    zstr_free (&endpoint);
    zstr_free (&hostname);
    if (zyre_start (zyre)) {
        zsys_info ("hydrad: can't start Zyre discovery service");
        zactor_destroy (&server);
        zyre_destroy (&zyre);
        return 1;
    }
    //  When we get a new peer, handle it
    zpoller_t *poller = zpoller_new (zyre_socket (zyre), NULL);
    while (!zpoller_terminated (poller)) {
        void *which = zpoller_wait (poller, -1);
        if (which == zyre_socket (zyre)) {
            zyre_event_t *event = zyre_event_new (zyre);
            if (zyre_event_type (event) == ZYRE_EVENT_ENTER) {
                zsys_debug ("hydrad: new peer name=%s endpoint=%s",
                            zyre_event_name (event),
                            zyre_event_header (event, "X-HYDRA"));
                s_handle_peer (zyre_event_header (event, "X-HYDRA"), verbose);
            }
            zyre_event_destroy (&event);
        }
        else
            break;
    }
    zsys_info ("hydrad: shutting down...");
    zpoller_destroy (&poller);

    //  Shutdown all services
    zactor_destroy (&server);
    zyre_destroy (&zyre);
    zconfig_destroy (&config);
    return 0;
}