void zmonitor_test (bool verbose) { printf (" * zmonitor: "); if (verbose) printf ("\n"); #if defined (ZMQ_EVENT_ALL) // @selftest zsock_t *client = zsock_new (ZMQ_DEALER); assert (client); zactor_t *clientmon = zactor_new (zmonitor, client); assert (clientmon); if (verbose) zstr_sendx (clientmon, "VERBOSE", NULL); zstr_sendx (clientmon, "LISTEN", "LISTENING", "ACCEPTED", NULL); zstr_sendx (clientmon, "START", NULL); zsock_wait (clientmon); zsock_t *server = zsock_new (ZMQ_DEALER); assert (server); zactor_t *servermon = zactor_new (zmonitor, server); assert (servermon); if (verbose) zstr_sendx (servermon, "VERBOSE", NULL); zstr_sendx (servermon, "LISTEN", "CONNECTED", "DISCONNECTED", NULL); zstr_sendx (servermon, "START", NULL); zsock_wait (servermon); // Allow a brief time for the message to get there... zmq_poll (NULL, 0, 200); // Check client is now listening int port_nbr = zsock_bind (client, "tcp://127.0.0.1:*"); assert (port_nbr != -1); s_assert_event (clientmon, "LISTENING"); // Check server connected to client zsock_connect (server, "tcp://127.0.0.1:%d", port_nbr); s_assert_event (servermon, "CONNECTED"); // Check client accepted connection s_assert_event (clientmon, "ACCEPTED"); zactor_destroy (&clientmon); zactor_destroy (&servermon); zsock_destroy (&client); zsock_destroy (&server); #endif // @end printf ("OK\n"); }
static void s_bind_proxy_sockets (zactor_t *proxy, char **frontend, char **backend) { if (*frontend) zstr_free (frontend); if (*backend) zstr_free (backend); *frontend = zsys_sprintf (LOCALENDPOINT, s_get_available_port ()); *backend = zsys_sprintf (LOCALENDPOINT, s_get_available_port ()); zstr_sendx (proxy, "FRONTEND", "PULL", *frontend, NULL); zsock_wait (proxy); zstr_sendx (proxy, "BACKEND", "PUSH", *backend, NULL); zsock_wait (proxy); }
void zyre_stop (zyre_t *self) { assert (self); zstr_sendx (self->actor, "STOP", NULL); zsock_wait (self->actor); }
int zyre_start (zyre_t *self) { assert (self); zstr_sendx (self->actor, "START", NULL); return zsock_wait (self->actor) == 0? 0: -1; }
zactor_t * zactor_new (zactor_fn *actor, void *args) { zactor_t *self = (zactor_t *) zmalloc (sizeof (zactor_t)); if (!self) return NULL; self->tag = ZACTOR_TAG; shim_t *shim = (shim_t *) zmalloc (sizeof (shim_t)); if (!shim) return NULL; // Create front-to-back pipe pair self->pipe = zsock_new (ZMQ_PAIR); assert (self->pipe); char endpoint [32]; while (true) { sprintf (endpoint, "inproc://zactor-%04x-%04x\n", randof (0x10000), randof (0x10000)); if (zsock_bind (self->pipe, "%s", endpoint) == 0) break; } shim->pipe = zsock_new (ZMQ_PAIR); assert (shim->pipe); int rc = zsock_connect (shim->pipe, "%s", endpoint); assert (rc != -1); shim->handler = actor; shim->args = args; #if defined (__UNIX__) pthread_t thread; pthread_create (&thread, NULL, s_thread_shim, shim); pthread_detach (thread); #elif defined (__WINDOWS__) HANDLE handle = (HANDLE) _beginthreadex ( NULL, // Handle is private to this process 0, // Use a default stack size for new thread &s_thread_shim, // Start real thread function via this shim shim, // Which gets arguments shim CREATE_SUSPENDED, // Set thread priority before starting it NULL); // We don't use the thread ID assert (handle); // Set child thread priority to same as current int priority = GetThreadPriority (GetCurrentThread ()); SetThreadPriority (handle, priority); // Start thread & release resources ResumeThread (handle); CloseHandle (handle); #endif // Mandatory handshake for new actor so that constructor returns only // when actor has also initialized. This eliminates timing issues at // application start up. zsock_wait (self->pipe); return self; }
int main (void) { zactor_t *server = zactor_new (zccp_server, "zccpd"); zsock_send (server, "s", "VERBOSE"); zsock_send (server, "ss", "BIND", "ipc://@/zccp"); zsock_wait (server); zactor_destroy (&server); return 0; }
int main (int argc, char *argv[]) { setvbuf(stdout, NULL, _IONBF, 0); char executors_uri[256]; if (argc == 3) snprintf (executors_uri, 256, "tcp://%s:%s", argv[1], argv[2]); else snprintf (executors_uri, 256, "tcp://127.0.0.1:%s", argv[1]); zactor_t *executor = zactor_new (executor_actor, (void *) executors_uri); zstr_send (executor, "START"); zsock_wait (executor); // Wait for interrupted zsock_wait (executor); zactor_destroy (&executor); }
static int twps_create_ticket_printer(twps_server_t *self, zmsg_t *msg) { char *type = zmsg_popstr(msg); char *id = zmsg_popstr(msg); zstr_free(&id); char *path = zmsg_popstr(msg); char *model = zmsg_popstr(msg); wchar_t *manufacture = (wchar_t *) zmsg_popstr(msg); wchar_t *product = (wchar_t *) zmsg_popstr(msg); zactor_t *printer = NULL; if (streq(type, "HID")) { printer = zactor_new(ticket_hid_printer, path); } #ifdef __WIN32__ else if (streq(type, "SERIAL")) { printer = zactor_new(ticket_serial_printer, path); } #endif if (printer != NULL) { if (self->verbose) { zstr_send(printer, "VERBOSE"); } if (self->diagnostic) zstr_sendx(printer, "SETDIAGNOSTIC", NULL); zstr_sendx(printer, "START", TICKET_STORE_REP_ENDPOINT, NULL); zsock_wait(printer); zstr_sendx(printer, "SETPRINTERSTORE", PRINTER_STORE_REP_ENDPOINT, PRINTER_STORE_PUB_ENDPOINT, NULL); zsock_wait(printer); zsys_info("twps server: started ticket printer %s manufacturer|product|model %ls|%ls|%s", type, manufacture, product, model); zlistx_add_end(self->ticket_printers, printer); } else { zsys_warning("twps server: printer not added %s, %s", type, path); zmsg_print(msg); } zstr_free(&type); zstr_free(&path); zstr_free(&model); zstr_free((char **) &manufacture); zstr_free((char **) &product); return 0; }
int zyre_set_endpoint (zyre_t *self, const char *format, ...) { assert (self); va_list argptr; va_start (argptr, format); char *string = zsys_vprintf (format, argptr); va_end (argptr); zstr_sendx (self->actor, "SET ENDPOINT", string, NULL); free (string); return zsock_wait (self->actor) == 0? 0: -1; }
static twps_server_t *twps_new(bool verbose, bool proxy_log) { zsys_info("twps: TWPS is initializing."); twps_server_t *self = (twps_server_t *) calloc(1, sizeof(twps_server_t)); self->verbose = verbose; self->ticket_printers = zlistx_new(); self->ticket_store = zactor_new(ticket_store, NULL); self->printer_store = zactor_new(printer_store, NULL); self->client_proxy = zactor_new(client_proxy, NULL); zsys_info("twps: actors created."); if (verbose) { zstr_send(self->ticket_store, "VERBOSE"); zstr_send(self->printer_store, "VERBOSE"); } if (proxy_log) zstr_send(self->client_proxy, "VERBOSE"); zstr_sendx(self->ticket_store, "START", TICKET_STORE_REP_ENDPOINT, TICKET_STORE_PUB_ENDPOINT, NULL); zsock_wait(self->ticket_store); zsys_info("twps: ticket store started listening on %s and publishing on %s", TICKET_STORE_REP_ENDPOINT, TICKET_STORE_PUB_ENDPOINT); zstr_sendx(self->printer_store, "START", PRINTER_STORE_REP_ENDPOINT, PRINTER_STORE_PUB_ENDPOINT, NULL); zsock_wait(self->printer_store); zsys_info("twps: printer store started listening on %s and publishing on %s", PRINTER_STORE_REP_ENDPOINT, PRINTER_STORE_PUB_ENDPOINT); zstr_sendx(self->client_proxy, "START", CLIENT_PROXY_ROUTE_ENDPOINT, CLIENT_PROXY_PUB_ENDPOINT, NULL); zsock_wait(self->client_proxy); zsys_info("twps: client proxy started listening on %s and publishing on %s", CLIENT_PROXY_ROUTE_ENDPOINT, CLIENT_PROXY_PUB_ENDPOINT); zstr_sendx(self->client_proxy, "SETTICKETSTORE", TICKET_STORE_REP_ENDPOINT, TICKET_STORE_PUB_ENDPOINT, NULL); zsock_wait(self->client_proxy); zstr_sendx(self->client_proxy, "SETPRINTERSTORE", PRINTER_STORE_REP_ENDPOINT, PRINTER_STORE_PUB_ENDPOINT, NULL); zsock_wait(self->client_proxy); self->printer_store_sub = zsock_new_sub(PRINTER_STORE_PUB_ENDPOINT, ""); zsys_info("twps: initialized with ticket store, printer store and client proxy"); zsys_info("twps: scanning for printers"); zstr_send(self->printer_store,"SCANPRINTERS"); return self; }
void someactor_test (bool verbose) { printf (" * someactor: "); int rc = 0; // @selftest // Simple create/destroy test zactor_t *someactor = zactor_new (someactor_actor, NULL); zstr_send (someactor, "START"); rc = zsock_wait (someactor); // Wait until actor started assert (rc == 0); zstr_send (someactor, "STOP"); rc = zsock_wait (someactor); // Wait until actor stopped assert (rc == 0); zactor_destroy (&someactor); // @end printf ("OK\n"); }
void MessageProcessor::init(int port, zcert_t* transportKey) { if (port == 0) { OT_FAIL; } if (!zsys_has_curve()) { Log::vError("Error: libzmq has no libsodium support"); OT_FAIL; } zstr_sendx(zmqAuth_, "CURVE", CURVE_ALLOW_ANY, NULL); zsock_wait(zmqAuth_); zsock_set_zap_domain(zmqSocket_, "global"); zsock_set_curve_server(zmqSocket_, 1); zcert_apply(transportKey, zmqSocket_); zsock_bind(zmqSocket_, "tcp://*:%d", port); }
zactor_t * zactor_new (zactor_fn *actor, void *args) { zactor_t *self = (zactor_t *) zmalloc (sizeof (zactor_t)); if (!self) return NULL; self->tag = ZACTOR_TAG; shim_t *shim = (shim_t *) zmalloc (sizeof (shim_t)); if (!shim) { zactor_destroy (&self); return NULL; } shim->pipe = zsys_create_pipe (&self->pipe); shim->handler = actor; shim->args = args; #if defined (__UNIX__) pthread_t thread; pthread_create (&thread, NULL, s_thread_shim, shim); pthread_detach (thread); #elif defined (__WINDOWS__) HANDLE handle = (HANDLE) _beginthreadex ( NULL, // Handle is private to this process 0, // Use a default stack size for new thread &s_thread_shim, // Start real thread function via this shim shim, // Which gets arguments shim CREATE_SUSPENDED, // Set thread priority before starting it NULL); // We don't use the thread ID assert (handle); // Set child thread priority to same as current int priority = GetThreadPriority (GetCurrentThread ()); SetThreadPriority (handle, priority); // Start thread & release resources ResumeThread (handle); CloseHandle (handle); #endif // Mandatory handshake for new actor so that constructor returns only // when actor has also initialized. This eliminates timing issues at // application start up. zsock_wait (self->pipe); return self; }
void zactor_destroy (zactor_t **self_p) { assert (self_p); if (*self_p) { zactor_t *self = *self_p; assert (zactor_is (self)); // Signal the actor to end and wait for the thread exit code zstr_send (self->pipe, "$TERM"); zsock_wait (self->pipe); zsock_destroy (&self->pipe); self->tag = 0xDeadBeef; free (self); *self_p = NULL; } }
static void s_send_proxy_command (zactor_t *proxy, const char *command, int selected_sockets, const char *string, ...) { zmsg_t *msg = zmsg_new (); if (!msg) assert (false); va_list args; va_start (args, string); while (string) { zmsg_addstr (msg, string); string = va_arg (args, char *); } va_end (args); for (int index = 0; index < SOCKETS; index++) { if (selected_sockets & (1 << index)) { s_send_proxy_msg (proxy, command, (proxy_socket)index, zmsg_dup (msg)); zsock_wait (proxy); } } zmsg_destroy (&msg); }
int main(int argc, char* argv[]) { srand(time(NULL)); broker_t *broker = broker_new ( "ipc://contexts.ipc", "ipc://executors.ipc"); pthread_t broker_thread = broker_run_in_thread (&broker); zactor_t *executor = zactor_new (executor_actor, NULL); zstr_send (executor, "START"); zsock_wait (executor); sprk_ctx_t *ctx = sprk_ctx_new("ipc://contexts.ipc"); sprk_dataset_t *dataset = sprk_ctx_load_dense (ctx, "/tmp/gen.dat", 400); sleep (3); pthread_cancel (broker_thread); pthread_join (broker_thread, NULL); sprk_dataset_destroy (&dataset); zactor_destroy (&executor); sprk_ctx_destroy(&ctx); }
void zactor_destroy (zactor_t **self_p) { assert (self_p); if (*self_p) { zactor_t *self = *self_p; assert (zactor_is (self)); // Signal the actor to end and wait for the thread exit code // If the pipe isn't connected any longer, assume child thread // has already quit due to other reasons and don't collect the // exit signal. zsock_set_sndtimeo (self->pipe, 0); if (zstr_send (self->pipe, "$TERM") == 0) zsock_wait (self->pipe); zsock_destroy (&self->pipe); self->tag = 0xDeadBeef; free (self); *self_p = NULL; } }
static void s_create_test_sockets (zactor_t **proxy, zsock_t **faucet, zsock_t **sink, bool verbose) { if (*faucet) zsock_destroy (faucet); if (*sink) zsock_destroy (sink); if (*proxy) zactor_destroy (proxy); *faucet = zsock_new (ZMQ_PUSH); assert (*faucet); *sink = zsock_new (ZMQ_PULL); assert (*sink); *proxy = zactor_new (zproxy, NULL); assert (*proxy); if (verbose) { zstr_sendx (*proxy, "VERBOSE", NULL); zsock_wait (*proxy); } }
void zauth_test (bool verbose) { printf (" * zauth: "); #if (ZMQ_VERSION_MAJOR == 4) if (verbose) printf ("\n"); // @selftest // Create temporary directory for test files # define TESTDIR ".test_zauth" zsys_dir_create (TESTDIR); // Check there's no authentication zsock_t *server = zsock_new (ZMQ_PUSH); assert (server); zsock_t *client = zsock_new (ZMQ_PULL); assert (client); bool success = s_can_connect (&server, &client); assert (success); // Install the authenticator zactor_t *auth = zactor_new (zauth, NULL); assert (auth); if (verbose) { zstr_sendx (auth, "VERBOSE", NULL); zsock_wait (auth); } // Check there's no authentication on a default NULL server success = s_can_connect (&server, &client); assert (success); // When we set a domain on the server, we switch on authentication // for NULL sockets, but with no policies, the client connection // will be allowed. zsock_set_zap_domain (server, "global"); success = s_can_connect (&server, &client); assert (success); // Blacklist 127.0.0.1, connection should fail zsock_set_zap_domain (server, "global"); zstr_sendx (auth, "DENY", "127.0.0.1", NULL); zsock_wait (auth); success = s_can_connect (&server, &client); assert (!success); // Whitelist our address, which overrides the blacklist zsock_set_zap_domain (server, "global"); zstr_sendx (auth, "ALLOW", "127.0.0.1", NULL); zsock_wait (auth); success = s_can_connect (&server, &client); assert (success); // Try PLAIN authentication zsock_set_plain_server (server, 1); zsock_set_plain_username (client, "admin"); zsock_set_plain_password (client, "Password"); success = s_can_connect (&server, &client); assert (!success); FILE *password = fopen (TESTDIR "/password-file", "w"); assert (password); fprintf (password, "admin=Password\n"); fclose (password); zsock_set_plain_server (server, 1); zsock_set_plain_username (client, "admin"); zsock_set_plain_password (client, "Password"); zstr_sendx (auth, "PLAIN", TESTDIR "/password-file", NULL); zsock_wait (auth); success = s_can_connect (&server, &client); assert (success); zsock_set_plain_server (server, 1); zsock_set_plain_username (client, "admin"); zsock_set_plain_password (client, "Bogus"); success = s_can_connect (&server, &client); assert (!success); if (zsys_has_curve ()) { // Try CURVE authentication // We'll create two new certificates and save the client public // certificate on disk; in a real case we'd transfer this securely // from the client machine to the server machine. zcert_t *server_cert = zcert_new (); assert (server_cert); zcert_t *client_cert = zcert_new (); assert (client_cert); char *server_key = zcert_public_txt (server_cert); // Test without setting-up any authentication zcert_apply (server_cert, server); zcert_apply (client_cert, client); zsock_set_curve_server (server, 1); zsock_set_curve_serverkey (client, server_key); success = s_can_connect (&server, &client); assert (!success); // Test CURVE_ALLOW_ANY zcert_apply (server_cert, server); zcert_apply (client_cert, client); zsock_set_curve_server (server, 1); zsock_set_curve_serverkey (client, server_key); zstr_sendx (auth, "CURVE", CURVE_ALLOW_ANY, NULL); zsock_wait (auth); success = s_can_connect (&server, &client); assert (success); // Test full client authentication using certificates zcert_apply (server_cert, server); zcert_apply (client_cert, client); zsock_set_curve_server (server, 1); zsock_set_curve_serverkey (client, server_key); zcert_save_public (client_cert, TESTDIR "/mycert.txt"); zstr_sendx (auth, "CURVE", TESTDIR, NULL); zsock_wait (auth); success = s_can_connect (&server, &client); assert (success); zcert_destroy (&server_cert); zcert_destroy (&client_cert); } // Remove the authenticator and check a normal connection works zactor_destroy (&auth); success = s_can_connect (&server, &client); assert (success); zsock_destroy (&client); zsock_destroy (&server); // Delete all test files zdir_t *dir = zdir_new (TESTDIR, NULL); assert (dir); zdir_remove (dir, true); zdir_destroy (&dir); // @end #endif printf ("OK\n"); }
/// // Wait on a signal. Use this to coordinate between threads, over pipe // pairs. Blocks until the signal is received. Returns -1 on error, 0 or // greater on success. Accepts a zsock_t or a zactor_t as argument. // Takes a polymorphic socket reference. int QZsock::wait () { int rv = zsock_wait (self); return rv; }
int main (int argc, char *argv []) { // Let's start a new Malamute broker zactor_t *broker = zactor_new (mlm_server, NULL); // Switch on verbose tracing... this gets a little overwhelming so you // can comment or delete this when you're bored with it: zsock_send (broker, "s", "VERBOSE"); // We control the broker by sending it commands. It's a CZMQ actor, and // we can talk to it using the zsock API (or zstr, or zframe, or zmsg). // To get things started, let's tell the broker to bind to an endpoint: // zsock_send (broker, "ss", "BIND", "tcp://*:12345"); // This is how we configure a server from an external config file, which // is in http://rfc.zeromq.org/spec:4/ZPL format: zstr_sendx (broker, "LOAD", "src/malamute.cfg", NULL); // We can also, or alternatively, set server properties by sending it // SET commands like this (see malamute.cfg for details): zsock_send (broker, "sss", "SET", "server/timeout", "5000"); // For PLAIN authentication, we start a zauth instance. This handles // all client connection requests by checking against a password file zactor_t *auth = zactor_new (zauth, NULL); assert (auth); // We can switch on verbose tracing to debug authentication errors zstr_sendx (auth, "VERBOSE", NULL); zsock_wait (auth); // Now specify the password file; each line says 'username=password' zstr_sendx (auth, "PLAIN", "src/passwords.cfg", NULL); zsock_wait (auth); // The broker is now running. Let's start two clients, one to publish // messages and one to receive them. We're going to test the stream // pattern with some natty wildcard patterns. mlm_client_t *reader = mlm_client_new (); assert (reader); int rc = mlm_client_set_plain_auth (reader, "reader", "secret"); assert (rc == 0); rc = mlm_client_connect (reader, "tcp://127.0.0.1:9999", 1000, "reader"); assert (rc == 0); mlm_client_t *writer = mlm_client_new (); assert (writer); rc = mlm_client_set_plain_auth (writer, "writer", "secret"); assert (rc == 0); rc = mlm_client_connect (writer, "tcp://127.0.0.1:9999", 1000, "writer"); assert (rc == 0); // The writer publishes to the "weather" stream mlm_client_set_producer (writer, "weather"); // The reader consumes temperature messages off the "weather" stream mlm_client_set_consumer (reader, "weather", "temp.*"); // The writer sends a series of messages with various subjects. The // sendx method sends string data to the stream (we send the subject, // then one or more strings): mlm_client_sendx (writer, "temp.moscow", "1", NULL); mlm_client_sendx (writer, "rain.moscow", "2", NULL); mlm_client_sendx (writer, "temp.madrid", "3", NULL); mlm_client_sendx (writer, "rain.madrid", "4", NULL); mlm_client_sendx (writer, "temp.london", "5", NULL); mlm_client_sendx (writer, "rain.london", "6", NULL); // The simplest way to receive a message is via the recvx method, // which stores multipart string data: char *subject, *content; mlm_client_recvx (reader, &subject, &content, NULL); assert (streq (subject, "temp.moscow")); assert (streq (content, "1")); zstr_free (&subject); zstr_free (&content); // The last-received message has other properties: assert (streq (mlm_client_subject (reader), "temp.moscow")); assert (streq (mlm_client_command (reader), "STREAM DELIVER")); assert (streq (mlm_client_sender (reader), "writer")); assert (streq (mlm_client_address (reader), "weather")); // Let's get the other two messages: mlm_client_recvx (reader, &subject, &content, NULL); assert (streq (subject, "temp.madrid")); assert (streq (content, "3")); zstr_free (&subject); zstr_free (&content); mlm_client_recvx (reader, &subject, &content, NULL); assert (streq (subject, "temp.london")); assert (streq (content, "5")); zstr_free (&subject); zstr_free (&content); // Great, it all works. Now to shutdown, we use the destroy method, // which does a proper deconnect handshake internally: mlm_client_destroy (&reader); mlm_client_destroy (&writer); // Finally, shut down the broker by destroying the actor; this does // a proper shutdown so that all memory is freed as you'd expect. zactor_destroy (&broker); zactor_destroy (&auth); return 0; }
void zproxy_test (bool verbose) { printf (" * zproxy: "); if (verbose) printf ("\n"); // @selftest // Create and configure our proxy zactor_t *proxy = zactor_new (zproxy, NULL); assert (proxy); if (verbose) { zstr_sendx (proxy, "VERBOSE", NULL); zsock_wait (proxy); } zstr_sendx (proxy, "FRONTEND", "PULL", "inproc://frontend", NULL); zsock_wait (proxy); zstr_sendx (proxy, "BACKEND", "PUSH", "inproc://backend", NULL); zsock_wait (proxy); // Connect application sockets to proxy zsock_t *faucet = zsock_new_push (">inproc://frontend"); assert (faucet); zsock_t *sink = zsock_new_pull (">inproc://backend"); assert (sink); // Send some messages and check they arrived char *hello, *world; zstr_sendx (faucet, "Hello", "World", NULL); zstr_recvx (sink, &hello, &world, NULL); assert (streq (hello, "Hello")); assert (streq (world, "World")); zstr_free (&hello); zstr_free (&world); // Test pause/resume functionality zstr_sendx (proxy, "PAUSE", NULL); zsock_wait (proxy); zstr_sendx (faucet, "Hello", "World", NULL); zsock_set_rcvtimeo (sink, 100); zstr_recvx (sink, &hello, &world, NULL); assert (!hello && !world); zstr_sendx (proxy, "RESUME", NULL); zsock_wait (proxy); zstr_recvx (sink, &hello, &world, NULL); assert (streq (hello, "Hello")); assert (streq (world, "World")); zstr_free (&hello); zstr_free (&world); // Test capture functionality zsock_t *capture = zsock_new_pull ("inproc://capture"); assert (capture); // Switch on capturing, check that it works zstr_sendx (proxy, "CAPTURE", "inproc://capture", NULL); zsock_wait (proxy); zstr_sendx (faucet, "Hello", "World", NULL); zstr_recvx (sink, &hello, &world, NULL); assert (streq (hello, "Hello")); assert (streq (world, "World")); zstr_free (&hello); zstr_free (&world); zstr_recvx (capture, &hello, &world, NULL); assert (streq (hello, "Hello")); assert (streq (world, "World")); zstr_free (&hello); zstr_free (&world); zsock_destroy (&faucet); zsock_destroy (&sink); zsock_destroy (&capture); zactor_destroy (&proxy); // @end printf ("OK\n"); }
static rsRetVal initCZMQ(instanceData* pData) { DEFiRet; /* tell czmq to not use it's own signal handler */ putenv ("ZSYS_SIGHANDLER=false"); /* create new auth actor */ DBGPRINTF ("omczmq: starting auth actor...\n"); pData->authActor = zactor_new (zauth, NULL); if (!pData->authActor) { errmsg.LogError (0, RS_RET_NO_ERRCODE, "omczmq: could not create auth service"); ABORT_FINALIZE (RS_RET_NO_ERRCODE); } /* create our zeromq socket */ DBGPRINTF ("omczmq: creating zeromq socket...\n"); pData->sock = zsock_new (pData->sockType); if (!pData->sock) { errmsg.LogError (0, RS_RET_NO_ERRCODE, "omczmq: new socket failed for endpoints: %s", pData->sockEndpoints); ABORT_FINALIZE(RS_RET_NO_ERRCODE); } bool is_server = false; /* if we are a CURVE server */ if (!strcmp(pData->authType, "CURVESERVER")) { DBGPRINTF("omczmq: we are a curve server...\n"); is_server = true; /* set global auth domain */ zsock_set_zap_domain(pData->sock, "global"); /* set that we are a curve server */ zsock_set_curve_server(pData->sock, 1); /* get and set our server cert */ DBGPRINTF("omczmq: server cert is %s...\n", pData->serverCertPath); pData->serverCert = zcert_load(pData->serverCertPath); if (!pData->serverCert) { errmsg.LogError(0, NO_ERRCODE, "could not load server cert"); ABORT_FINALIZE(RS_RET_ERR); } zcert_apply(pData->serverCert, pData->sock); /* set allowed clients */ DBGPRINTF("omczmq: allowed clients are %s...\n", pData->clientCertPath); zstr_sendx(pData->authActor, "CURVE", pData->clientCertPath, NULL); zsock_wait(pData->authActor); } /* if we are a CURVE client */ if (!strcmp(pData->authType, "CURVECLIENT")) { DBGPRINTF("omczmq: we are a curve client...\n"); is_server = false; /* get our client cert */ pData->clientCert = zcert_load(pData->clientCertPath); if (!pData->clientCert) { errmsg.LogError(0, NO_ERRCODE, "could not load client cert"); ABORT_FINALIZE(RS_RET_ERR); } /* apply the client cert to the socket */ zcert_apply(pData->clientCert, pData->sock); /* get the server cert */ DBGPRINTF("omczmq: server cert is %s...\n", pData->serverCertPath); pData->serverCert = zcert_load(pData->serverCertPath); if (!pData->serverCert) { errmsg.LogError(0, NO_ERRCODE, "could not load server cert"); ABORT_FINALIZE(RS_RET_ERR); } /* get the server public key and set it for the socket */ char *server_key = zcert_public_txt(pData->serverCert); DBGPRINTF("omczmq: server public key is %s...\n", server_key); zsock_set_curve_serverkey (pData->sock, server_key); } /* we default to CONNECT unless told otherwise */ int rc = zsock_attach(pData->sock, (const char*)pData->sockEndpoints, is_server); if (rc == -1) { errmsg.LogError(0, NO_ERRCODE, "zsock_attach to %s failed", pData->sockEndpoints); ABORT_FINALIZE(RS_RET_ERR); } finalize_it: RETiRet; }
static rsRetVal rcvData(){ DEFiRet; if(!listenerList) { listenerList = zlist_new(); if(!listenerList) { errmsg.LogError(0, NO_ERRCODE, "could not allocate list"); ABORT_FINALIZE(RS_RET_ERR); } } zactor_t *authActor; zcert_t *serverCert; if(runModConf->authenticator == 1) { authActor = zactor_new(zauth, NULL); zstr_sendx(authActor, "CURVE", runModConf->clientCertPath, NULL); zsock_wait(authActor); } instanceConf_t *inst; for(inst = runModConf->root; inst != NULL; inst=inst->next) { CHKiRet(addListener(inst)); } zpoller_t *poller = zpoller_new(NULL); if(!poller) { errmsg.LogError(0, NO_ERRCODE, "could not create poller"); ABORT_FINALIZE(RS_RET_ERR); } DBGPRINTF("imczmq: created poller\n"); struct listener_t *pData; pData = zlist_first(listenerList); if(!pData) { errmsg.LogError(0, NO_ERRCODE, "imczmq: no listeners were " "started, input not activated.\n"); ABORT_FINALIZE(RS_RET_NO_RUN); } while(pData) { int rc = zpoller_add(poller, pData->sock); if(rc != 0) { errmsg.LogError(0, NO_ERRCODE, "imczmq: could not add " "socket to poller, input not activated.\n"); ABORT_FINALIZE(RS_RET_NO_RUN); } pData = zlist_next(listenerList); } zframe_t *frame; zsock_t *which = (zsock_t *)zpoller_wait(poller, -1); while(which) { if (zpoller_terminated(poller)) { break; } pData = zlist_first(listenerList); while(pData->sock != which) { pData = zlist_next(listenerList); } if(which == pData->sock) { DBGPRINTF("imczmq: found matching socket\n"); } frame = zframe_recv(which); char *buf = zframe_strdup(frame); if(buf == NULL) { DBGPRINTF("imczmq: null buffer\n"); continue; } smsg_t *pMsg; if(msgConstruct(&pMsg) == RS_RET_OK) { MsgSetRawMsg(pMsg, buf, strlen(buf)); MsgSetInputName(pMsg, s_namep); MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName())); MsgSetRcvFrom(pMsg, glbl.GetLocalHostNameProp()); MsgSetRcvFromIP(pMsg, glbl.GetLocalHostIP()); MsgSetMSGoffs(pMsg, 0); MsgSetFlowControlType(pMsg, eFLOWCTL_NO_DELAY); MsgSetRuleset(pMsg, pData->ruleset); pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME; submitMsg2(pMsg); } free(buf); which = (zsock_t *)zpoller_wait(poller, -1); } finalize_it: zframe_destroy(&frame); zpoller_destroy(&poller); pData = zlist_first(listenerList); while(pData) { zsock_destroy(&pData->sock); free(pData->ruleset); pData = zlist_next(listenerList); } zlist_destroy(&listenerList); zactor_destroy(&authActor); zcert_destroy(&serverCert); RETiRet; }
void zsock_test (bool verbose) { printf (" * zsock: "); // @selftest zsock_t *writer = zsock_new_push ("@tcp://127.0.0.1:5560"); assert (writer); assert (zsock_resolve (writer) != writer); assert (streq (zsock_type_str (writer), "PUSH")); int rc; #if (ZMQ_VERSION >= ZMQ_MAKE_VERSION (3,2,0)) // Check unbind rc = zsock_unbind (writer, "tcp://127.0.0.1:%d", 5560); assert (rc == 0); // In some cases and especially when running under Valgrind, doing // a bind immediately after an unbind causes an EADDRINUSE error. // Even a short sleep allows the OS to release the port for reuse. zclock_sleep (100); // Bind again rc = zsock_bind (writer, "tcp://127.0.0.1:%d", 5560); assert (rc == 5560); assert (streq (zsock_endpoint (writer), "tcp://127.0.0.1:5560")); #endif zsock_t *reader = zsock_new_pull (">tcp://127.0.0.1:5560"); assert (reader); assert (zsock_resolve (reader) != reader); assert (streq (zsock_type_str (reader), "PULL")); zstr_send (writer, "Hello, World"); zmsg_t *msg = zsock_recv (reader); assert (msg); char *string = zmsg_popstr (msg); assert (streq (string, "Hello, World")); free (string); zmsg_destroy (&msg); // Test binding to ephemeral ports, sequential and random int port = zsock_bind (writer, "tcp://127.0.0.1:*"); assert (port >= DYNAMIC_FIRST && port <= DYNAMIC_LAST); port = zsock_bind (writer, "tcp://127.0.0.1:*[50000-]"); assert (port >= 50000 && port <= DYNAMIC_LAST); port = zsock_bind (writer, "tcp://127.0.0.1:*[-50001]"); assert (port >= DYNAMIC_FIRST && port <= 50001); port = zsock_bind (writer, "tcp://127.0.0.1:*[60000-60010]"); assert (port >= 60000 && port <= 60010); port = zsock_bind (writer, "tcp://127.0.0.1:!"); assert (port >= DYNAMIC_FIRST && port <= DYNAMIC_LAST); port = zsock_bind (writer, "tcp://127.0.0.1:![50000-]"); assert (port >= 50000 && port <= DYNAMIC_LAST); port = zsock_bind (writer, "tcp://127.0.0.1:![-50001]"); assert (port >= DYNAMIC_FIRST && port <= 50001); port = zsock_bind (writer, "tcp://127.0.0.1:![60000-60010]"); assert (port >= 60000 && port <= 60010); // Test zsock_endpoint method rc = zsock_bind (writer, "inproc://test.%s", "writer"); assert (rc == 0); assert (streq (zsock_endpoint (writer), "inproc://test.writer")); // Test error state when connecting to an invalid socket type // ('txp://' instead of 'tcp://', typo intentional) rc = zsock_connect (reader, "txp://127.0.0.1:5560"); assert (rc == -1); rc = zsock_signal (writer, 123); assert (rc == 0); rc = zsock_wait (reader); assert (rc == 123); zsock_destroy (&reader); zsock_destroy (&writer); // Test zsock_attach method zsock_t *server = zsock_new (ZMQ_DEALER); rc = zsock_attach (server, "@inproc://myendpoint,tcp://127.0.0.1:5556,inproc://others", true); assert (rc == 0); rc = zsock_attach (server, "", false); assert (rc == 0); rc = zsock_attach (server, NULL, true); assert (rc == 0); rc = zsock_attach (server, ">a,@b, c,, ", false); assert (rc == -1); zsock_destroy (&server); // @end printf ("OK\n"); }
JNIEXPORT jint JNICALL Java_org_zeromq_czmq_Zsock__1_1wait (JNIEnv *env, jclass c, jlong self) { jint wait_ = (jint) zsock_wait ((zsock_t *) (intptr_t) self); return wait_; }
static rsRetVal addListener(instanceConf_t* iconf){ struct lstn_s* pData; DEFiRet; CHKmalloc(pData=(struct lstn_s*)MALLOC(sizeof(struct lstn_s))); pData->next = NULL; pData->pRuleset = iconf->pBindRuleset; /* Create the zeromq socket */ /* ------------------------ */ pData->sock = zsock_new(iconf->sockType); if (!pData->sock) { errmsg.LogError(0, RS_RET_NO_ERRCODE, "imczmq: new socket failed for endpoints: %s", iconf->sockEndpoints); ABORT_FINALIZE(RS_RET_NO_ERRCODE); } DBGPRINTF ("imczmq: created socket...\n"); /* Create the beacon actor if configured */ /* ------------------------------------- */ if((iconf->beacon != NULL) && (iconf->beaconPort > 0)) { DBGPRINTF ("imczmq: starting beacon actor...\n"); pData->beaconActor = zactor_new(zbeacon, NULL); if (!pData->beaconActor) { errmsg.LogError(0, RS_RET_NO_ERRCODE, "imczmq: could not create beacon service"); ABORT_FINALIZE (RS_RET_NO_ERRCODE); } zsock_send(pData->beaconActor, "si", "CONFIGURE", iconf->beaconPort); char *hostname = zstr_recv(pData->beaconActor); if (!*hostname) { errmsg.LogError(0, RS_RET_NO_ERRCODE, "imczmq: no UDP broadcasting available"); ABORT_FINALIZE (RS_RET_NO_ERRCODE); } zsock_send(pData->beaconActor, "sbi", "PUBLISH", pData->beaconActor, strlen(iconf->beacon)); DBGPRINTF ("omczmq: beacon is lit: hostname: '%s', port: '%d'...\n", hostname, iconf->beaconPort); } DBGPRINTF("imczmq: authtype is: %s\n", iconf->authType); if (iconf->authType != NULL) { /* CURVESERVER */ /* ----------- */ if (!strcmp(iconf->authType, "CURVESERVER")) { zsock_set_zap_domain(pData->sock, "global"); zsock_set_curve_server(pData->sock, 1); pData->serverCert = zcert_load(iconf->serverCertPath); if (!pData->serverCert) { errmsg.LogError(0, NO_ERRCODE, "could not load server cert"); ABORT_FINALIZE(RS_RET_ERR); } zcert_apply(pData->serverCert, pData->sock); zstr_sendx(authActor, "CURVE", iconf->clientCertPath, NULL); zsock_wait(authActor); DBGPRINTF("imczmq: CURVESERVER: serverCertPath: '%s'\n", iconf->serverCertPath); DBGPRINTF("mczmq: CURVESERVER: clientCertPath: '%s'\n", iconf->clientCertPath); } /* CURVECLIENT */ /* ----------- */ else if (!strcmp(iconf->authType, "CURVECLIENT")) { if (!strcmp(iconf->clientCertPath, "*")) { pData->clientCert = zcert_new(); } else { pData->clientCert = zcert_load(iconf->clientCertPath); } if (!pData->clientCert) { errmsg.LogError(0, NO_ERRCODE, "could not load client cert"); ABORT_FINALIZE(RS_RET_ERR); } zcert_apply(pData->clientCert, pData->sock); pData->serverCert = zcert_load(iconf->serverCertPath); if (!pData->serverCert) { errmsg.LogError(0, NO_ERRCODE, "could not load server cert"); ABORT_FINALIZE(RS_RET_ERR); } char *server_key = zcert_public_txt(pData->serverCert); zsock_set_curve_serverkey (pData->sock, server_key); DBGPRINTF("imczmq: CURVECLIENT: serverCertPath: '%s'\n", iconf->serverCertPath); DBGPRINTF("imczmq: CURVECLIENT: clientCertPath: '%s'\n", iconf->clientCertPath); DBGPRINTF("imczmq: CURVECLIENT: server_key: '%s'\n", server_key); } else { errmsg.LogError(0, NO_ERRCODE, "unrecognized auth type: '%s'", iconf->authType); ABORT_FINALIZE(RS_RET_ERR); } } /* subscribe to topics */ /* ------------------- */ if (iconf->sockType == ZMQ_SUB) { char topic[256], *list = iconf->topicList; while (list) { char *delimiter = strchr(list, ','); if (!delimiter) { delimiter = list + strlen (list); } if (delimiter - list > 255) { errmsg.LogError(0, NO_ERRCODE, "iconf->topicList must be under 256 characters"); ABORT_FINALIZE(RS_RET_ERR); } memcpy(topic, list, delimiter - list); topic[delimiter - list] = 0; zsock_set_subscribe(pData->sock, topic); if (*delimiter == 0) { break; } list = delimiter + 1; } } switch (iconf->sockType) { case ZMQ_SUB: iconf->serverish = false; break; case ZMQ_PULL: case ZMQ_ROUTER: iconf->serverish = true; break; } int rc = zsock_attach(pData->sock, (const char*)iconf->sockEndpoints, iconf->serverish); if (rc == -1) { errmsg.LogError(0, NO_ERRCODE, "zsock_attach to %s", iconf->sockEndpoints); ABORT_FINALIZE(RS_RET_ERR); } /* add this struct to the global */ /* ----------------------------- */ if(lcnfRoot == NULL) { lcnfRoot = pData; } if(lcnfLast == NULL) { lcnfLast = pData; } else { lcnfLast->next = pData; lcnfLast = pData; } finalize_it: RETiRet; }
void zgossip_test (bool verbose) { printf (" * zgossip: "); if (verbose) printf ("\n"); // @selftest // Test basic client-to-server operation of the protocol zactor_t *server = zactor_new (zgossip, "server"); assert (server); if (verbose) zstr_send (server, "VERBOSE"); zstr_sendx (server, "BIND", "inproc://zgossip", NULL); zsock_t *client = zsock_new (ZMQ_DEALER); assert (client); zsock_set_rcvtimeo (client, 2000); int rc = zsock_connect (client, "inproc://zgossip"); assert (rc == 0); // Send HELLO, which gets no message zgossip_msg_t *message = zgossip_msg_new (); zgossip_msg_set_id (message, ZGOSSIP_MSG_HELLO); zgossip_msg_send (message, client); // Send PING, expect PONG back zgossip_msg_set_id (message, ZGOSSIP_MSG_PING); zgossip_msg_send (message, client); zgossip_msg_recv (message, client); assert (zgossip_msg_id (message) == ZGOSSIP_MSG_PONG); zgossip_msg_destroy (&message); zactor_destroy (&server); zsock_destroy (&client); // Test peer-to-peer operations zactor_t *base = zactor_new (zgossip, "base"); assert (base); if (verbose) zstr_send (base, "VERBOSE"); // Set a 100msec timeout on clients so we can test expiry zstr_sendx (base, "SET", "server/timeout", "100", NULL); zstr_sendx (base, "BIND", "inproc://base", NULL); zactor_t *alpha = zactor_new (zgossip, "alpha"); assert (alpha); zstr_sendx (alpha, "CONNECT", "inproc://base", NULL); zstr_sendx (alpha, "PUBLISH", "inproc://alpha-1", "service1", NULL); zstr_sendx (alpha, "PUBLISH", "inproc://alpha-2", "service2", NULL); zactor_t *beta = zactor_new (zgossip, "beta"); assert (beta); zstr_sendx (beta, "CONNECT", "inproc://base", NULL); zstr_sendx (beta, "PUBLISH", "inproc://beta-1", "service1", NULL); zstr_sendx (beta, "PUBLISH", "inproc://beta-2", "service2", NULL); // got nothing zclock_sleep (200); zstr_send (alpha, "STATUS"); char *command, *status, *key, *value; zstr_recvx (alpha, &command, &key, &value, NULL); assert (streq (command, "DELIVER")); assert (streq (key, "inproc://alpha-1")); assert (streq (value, "service1")); zstr_free (&command); zstr_free (&key); zstr_free (&value); zstr_recvx (alpha, &command, &key, &value, NULL); assert (streq (command, "DELIVER")); assert (streq (key, "inproc://alpha-2")); assert (streq (value, "service2")); zstr_free (&command); zstr_free (&key); zstr_free (&value); zstr_recvx (alpha, &command, &key, &value, NULL); assert (streq (command, "DELIVER")); assert (streq (key, "inproc://beta-1")); assert (streq (value, "service1")); zstr_free (&command); zstr_free (&key); zstr_free (&value); zstr_recvx (alpha, &command, &key, &value, NULL); assert (streq (command, "DELIVER")); assert (streq (key, "inproc://beta-2")); assert (streq (value, "service2")); zstr_free (&command); zstr_free (&key); zstr_free (&value); zstr_recvx (alpha, &command, &status, NULL); assert (streq (command, "STATUS")); assert (atoi (status) == 4); zstr_free (&command); zstr_free (&status); zactor_destroy (&base); zactor_destroy (&alpha); zactor_destroy (&beta); #ifdef CZMQ_BUILD_DRAFT_API // DRAFT-API: Security // curve if (zsys_has_curve()) { if (verbose) printf("testing CURVE support"); zclock_sleep (2000); zactor_t *auth = zactor_new(zauth, NULL); assert (auth); if (verbose) { zstr_sendx (auth, "VERBOSE", NULL); zsock_wait (auth); } zstr_sendx(auth,"ALLOW","127.0.0.1",NULL); zsock_wait(auth); zstr_sendx (auth, "CURVE", CURVE_ALLOW_ANY, NULL); zsock_wait (auth); server = zactor_new (zgossip, "server"); if (verbose) zstr_send (server, "VERBOSE"); assert (server); zcert_t *client1_cert = zcert_new (); zcert_t *server_cert = zcert_new (); zstr_sendx (server, "SET PUBLICKEY", zcert_public_txt (server_cert), NULL); zstr_sendx (server, "SET SECRETKEY", zcert_secret_txt (server_cert), NULL); zstr_sendx (server, "ZAP DOMAIN", "TEST", NULL); zstr_sendx (server, "BIND", "tcp://127.0.0.1:*", NULL); zstr_sendx (server, "PORT", NULL); zstr_recvx (server, &command, &value, NULL); assert (streq (command, "PORT")); int port = atoi (value); zstr_free (&command); zstr_free (&value); char endpoint [32]; sprintf (endpoint, "tcp://127.0.0.1:%d", port); zactor_t *client1 = zactor_new (zgossip, "client"); if (verbose) zstr_send (client1, "VERBOSE"); assert (client1); zstr_sendx (client1, "SET PUBLICKEY", zcert_public_txt (client1_cert), NULL); zstr_sendx (client1, "SET SECRETKEY", zcert_secret_txt (client1_cert), NULL); zstr_sendx (client1, "ZAP DOMAIN", "TEST", NULL); const char *public_txt = zcert_public_txt (server_cert); zstr_sendx (client1, "CONNECT", endpoint, public_txt, NULL); zstr_sendx (client1, "PUBLISH", "tcp://127.0.0.1:9001", "service1", NULL); zclock_sleep (500); zstr_send (server, "STATUS"); zclock_sleep (500); zstr_recvx (server, &command, &key, &value, NULL); assert (streq (command, "DELIVER")); assert (streq (value, "service1")); zstr_free (&command); zstr_free (&key); zstr_free (&value); zstr_sendx (client1, "$TERM", NULL); zstr_sendx (server, "$TERM", NULL); zclock_sleep(500); zcert_destroy (&client1_cert); zcert_destroy (&server_cert); zactor_destroy (&client1); zactor_destroy (&server); zactor_destroy (&auth); } #endif #if defined (__WINDOWS__) zsys_shutdown(); #endif // @end printf ("OK\n"); }
// Authentication test procedure for zproxy sockets - matches zauth_test steps static void zproxy_test_authentication (int selected_sockets, bool verbose) { # define TESTDIR ".test_zproxy" # define TESTPWDS TESTDIR "/password-file" # define TESTCERT TESTDIR "/mycert.txt" # define TESTFRONTEND (selected_sockets & FRONTEND_SOCKET) # define TESTBACKEND (selected_sockets & BACKEND_SOCKET) // Demarcate test boundaries zsys_info ("zproxy: TEST authentication type=%s%s%s", TESTFRONTEND? "FRONTEND": "", TESTFRONTEND && TESTBACKEND? "+": "", TESTBACKEND? "BACKEND": ""); // Create temporary directory for test files zsys_dir_create (TESTDIR); // Clear out any test files from previous run if (zsys_file_exists (TESTPWDS)) zsys_file_delete (TESTPWDS); if (zsys_file_exists (TESTCERT)) zsys_file_delete (TESTCERT); zactor_t *proxy = NULL; zsock_t *faucet = NULL; zsock_t *sink = NULL; char *frontend = NULL; char *backend = NULL; // Check there's no authentication s_create_test_sockets (&proxy, &faucet, &sink, verbose); s_bind_proxy_sockets (proxy, &frontend, &backend); bool success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose); assert (success); // Install the authenticator zactor_t *auth = zactor_new (zauth, NULL); assert (auth); if (verbose) { zstr_sendx (auth, "VERBOSE", NULL); zsock_wait (auth); } // Check there's no authentication on a default NULL server s_bind_proxy_sockets (proxy, &frontend, &backend); success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose); assert (success); // When we set a domain on the server, we switch on authentication // for NULL sockets, but with no policies, the client connection // will be allowed. s_send_proxy_command (proxy, "DOMAIN", selected_sockets, "global", NULL); s_bind_proxy_sockets (proxy, &frontend, &backend); success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose); assert (success); // Blacklist 127.0.0.1, connection should fail s_send_proxy_command (proxy, "DOMAIN", selected_sockets, "global", NULL); s_bind_proxy_sockets (proxy, &frontend, &backend); zstr_sendx (auth, "DENY", "127.0.0.1", NULL); zsock_wait (auth); success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose); assert (!success); // Whitelist our address, which overrides the blacklist s_send_proxy_command (proxy, "DOMAIN", selected_sockets, "global", NULL); s_bind_proxy_sockets (proxy, &frontend, &backend); zstr_sendx (auth, "ALLOW", "127.0.0.1", NULL); zsock_wait (auth); success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose); assert (success); // Try PLAIN authentication // Test negative case (no server-side passwords defined) s_send_proxy_command (proxy, "PLAIN", selected_sockets, NULL); s_bind_proxy_sockets (proxy, &frontend, &backend); s_configure_plain_auth (faucet, sink, selected_sockets, "admin", "Password"); success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose); assert (!success); // Test positive case (server-side passwords defined) FILE *password = fopen (TESTPWDS, "w"); assert (password); fprintf (password, "admin=Password\n"); fclose (password); s_send_proxy_command (proxy, "PLAIN", selected_sockets, NULL); s_bind_proxy_sockets (proxy, &frontend, &backend); s_configure_plain_auth (faucet, sink, selected_sockets, "admin", "Password"); zstr_sendx (auth, "PLAIN", TESTPWDS, NULL); zsock_wait (auth); success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose); assert (success); // Test negative case (bad client password) s_send_proxy_command (proxy, "PLAIN", selected_sockets, NULL); s_bind_proxy_sockets (proxy, &frontend, &backend); s_configure_plain_auth (faucet, sink, selected_sockets, "admin", "Bogus"); success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose); assert (!success); if (zsys_has_curve ()) { // We'll create two new certificates and save the client public // certificate on disk zcert_t *server_cert = zcert_new (); assert (server_cert); zcert_t *client_cert = zcert_new (); assert (client_cert); char *public_key = zcert_public_txt (server_cert); char *secret_key = zcert_secret_txt (server_cert); // Try CURVE authentication // Test without setting-up any authentication s_send_proxy_command (proxy, "CURVE", selected_sockets, public_key, secret_key, NULL); s_bind_proxy_sockets (proxy, &frontend, &backend); s_configure_curve_auth (faucet, sink, selected_sockets, client_cert, public_key); success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose); assert (!success); // Test CURVE_ALLOW_ANY s_send_proxy_command (proxy, "CURVE", selected_sockets, public_key, secret_key, NULL); s_bind_proxy_sockets (proxy, &frontend, &backend); s_configure_curve_auth (faucet, sink, selected_sockets, client_cert, public_key); zstr_sendx (auth, "CURVE", CURVE_ALLOW_ANY, NULL); zsock_wait (auth); success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose); assert (success); // Test with client certificate file in authentication folder s_send_proxy_command (proxy, "CURVE", selected_sockets, public_key, secret_key, NULL); s_bind_proxy_sockets (proxy, &frontend, &backend); s_configure_curve_auth (faucet, sink, selected_sockets, client_cert, public_key); zcert_save_public (client_cert, TESTCERT); zstr_sendx (auth, "CURVE", TESTDIR, NULL); zsock_wait (auth); success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose); assert (success); zcert_destroy (&server_cert); zcert_destroy (&client_cert); } // Remove the authenticator and check a normal connection works zactor_destroy (&auth); s_bind_proxy_sockets (proxy, &frontend, &backend); success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose); assert (success); zsock_destroy (&faucet); zsock_destroy (&sink); zactor_destroy (&proxy); zstr_free (&frontend); zstr_free (&backend); }
void zyre_test (bool verbose) { printf (" * zyre: "); if (verbose) printf ("\n"); // @selftest // We'll use inproc gossip discovery so that this works without networking uint64_t version = zyre_version (); assert ((version / 10000) % 100 == ZYRE_VERSION_MAJOR); assert ((version / 100) % 100 == ZYRE_VERSION_MINOR); assert (version % 100 == ZYRE_VERSION_PATCH); // Create two nodes zyre_t *node1 = zyre_new ("node1"); assert (node1); assert (streq (zyre_name (node1), "node1")); zyre_set_header (node1, "X-HELLO", "World"); if (verbose) zyre_set_verbose (node1); // Set inproc endpoint for this node int rc = zyre_set_endpoint (node1, "inproc://zyre-node1"); assert (rc == 0); // Set up gossip network for this node zyre_gossip_bind (node1, "inproc://gossip-hub"); rc = zyre_start (node1); assert (rc == 0); zyre_t *node2 = zyre_new ("node2"); assert (node2); assert (streq (zyre_name (node2), "node2")); if (verbose) zyre_set_verbose (node2); // Set inproc endpoint for this node // First, try to use existing name, it'll fail rc = zyre_set_endpoint (node2, "inproc://zyre-node1"); assert (rc == -1); // Now use available name and confirm that it succeeds rc = zyre_set_endpoint (node2, "inproc://zyre-node2"); assert (rc == 0); // Set up gossip network for this node zyre_gossip_connect (node2, "inproc://gossip-hub"); rc = zyre_start (node2); assert (rc == 0); assert (strneq (zyre_uuid (node1), zyre_uuid (node2))); zyre_join (node1, "GLOBAL"); zyre_join (node2, "GLOBAL"); // Give time for them to interconnect zclock_sleep (250); if (verbose) zyre_dump (node1); zlist_t *peers = zyre_peers (node1); assert (peers); assert (zlist_size (peers) == 1); zlist_destroy (&peers); zyre_join (node1, "node1 group of one"); zyre_join (node2, "node2 group of one"); // Give them time to join their groups zclock_sleep (250); zlist_t *own_groups = zyre_own_groups (node1); assert (own_groups); assert (zlist_size (own_groups) == 2); zlist_destroy (&own_groups); zlist_t *peer_groups = zyre_peer_groups (node1); assert (peer_groups); assert (zlist_size (peer_groups) == 2); zlist_destroy (&peer_groups); char *value = zyre_peer_header_value (node2, zyre_uuid (node1), "X-HELLO"); assert (streq (value, "World")); zstr_free (&value); // One node shouts to GLOBAL zyre_shouts (node1, "GLOBAL", "Hello, World"); // Second node should receive ENTER, JOIN, and SHOUT zmsg_t *msg = zyre_recv (node2); assert (msg); char *command = zmsg_popstr (msg); assert (streq (command, "ENTER")); zstr_free (&command); assert (zmsg_size (msg) == 4); char *peerid = zmsg_popstr (msg); char *name = zmsg_popstr (msg); assert (streq (name, "node1")); zstr_free (&name); zframe_t *headers_packed = zmsg_pop (msg); char *address = zmsg_popstr (msg); char *endpoint = zyre_peer_address (node2, peerid); assert (streq (address, endpoint)); zstr_free (&peerid); zstr_free (&endpoint); zstr_free (&address); assert (headers_packed); zhash_t *headers = zhash_unpack (headers_packed); assert (headers); zframe_destroy (&headers_packed); assert (streq ((char *) zhash_lookup (headers, "X-HELLO"), "World")); zhash_destroy (&headers); zmsg_destroy (&msg); msg = zyre_recv (node2); assert (msg); command = zmsg_popstr (msg); assert (streq (command, "JOIN")); zstr_free (&command); assert (zmsg_size (msg) == 3); zmsg_destroy (&msg); msg = zyre_recv (node2); assert (msg); command = zmsg_popstr (msg); assert (streq (command, "JOIN")); zstr_free (&command); assert (zmsg_size (msg) == 3); zmsg_destroy (&msg); msg = zyre_recv (node2); assert (msg); command = zmsg_popstr (msg); assert (streq (command, "SHOUT")); zstr_free (&command); zmsg_destroy (&msg); zyre_stop (node2); msg = zyre_recv (node2); assert (msg); command = zmsg_popstr (msg); assert (streq (command, "STOP")); zstr_free (&command); zmsg_destroy (&msg); zyre_stop (node1); zyre_destroy (&node1); zyre_destroy (&node2); printf ("OK\n"); #ifdef ZYRE_BUILD_DRAFT_API if (zsys_has_curve()){ printf (" * zyre-curve: "); if (verbose) printf ("\n"); if (verbose) zsys_debug("----------------TESTING CURVE --------------"); zactor_t *speaker = zactor_new (zbeacon, NULL); assert (speaker); if (verbose) zstr_sendx (speaker, "VERBOSE", NULL); // ensuring we have a broadcast address zsock_send (speaker, "si", "CONFIGURE", 9999); char *hostname = zstr_recv (speaker); if (!*hostname) { printf ("OK (skipping test, no UDP broadcasting)\n"); zactor_destroy (&speaker); freen (hostname); return; } freen (hostname); zactor_destroy (&speaker); // zap setup zactor_t *auth = zactor_new(zauth, NULL); assert (auth); if (verbose) { zstr_sendx(auth, "VERBOSE", NULL); zsock_wait(auth); } zstr_sendx (auth, "CURVE", CURVE_ALLOW_ANY, NULL); zsock_wait (auth); zyre_t *node3 = zyre_new ("node3"); zyre_t *node4 = zyre_new ("node4"); assert (node3); assert (node4); zyre_set_verbose (node3); zyre_set_verbose (node4); zyre_set_zap_domain(node3, "TEST"); zyre_set_zap_domain(node4, "TEST"); zsock_set_rcvtimeo(node3->inbox, 10000); zsock_set_rcvtimeo(node4->inbox, 10000); zcert_t *node3_cert = zcert_new (); zcert_t *node4_cert = zcert_new (); assert (node3_cert); assert (node4_cert); zyre_set_zcert(node3, node3_cert); zyre_set_zcert(node4, node4_cert); zyre_set_header(node3, "X-PUBLICKEY", "%s", zcert_public_txt(node3_cert)); zyre_set_header(node4, "X-PUBLICKEY", "%s", zcert_public_txt(node4_cert)); // test beacon if (verbose) zsys_debug ("----------------TESTING BEACON----------------"); rc = zyre_start(node3); assert (rc == 0); rc = zyre_start(node4); assert (rc == 0); zyre_join (node3, "GLOBAL"); zyre_join (node4, "GLOBAL"); zclock_sleep (1500); if (verbose) { zyre_dump (node3); zyre_dump (node4); } zyre_shouts (node3, "GLOBAL", "Hello, World"); // Second node should receive ENTER, JOIN, and SHOUT msg = zyre_recv (node4); assert (msg); command = zmsg_popstr (msg); assert (streq (command, "ENTER")); zstr_free (&command); char *peerid = zmsg_popstr (msg); assert (peerid); name = zmsg_popstr (msg); assert (streq (name, "node3")); zmsg_destroy (&msg); msg = zyre_recv (node4); assert (msg); command = zmsg_popstr (msg); assert (streq (command, "JOIN")); zstr_free (&command); zmsg_destroy(&msg); msg = zyre_recv (node4); assert (msg); command = zmsg_popstr (msg); assert (streq (command, "SHOUT")); zstr_free (&command); zmsg_destroy(&msg); zyre_leave(node3, "GLOBAL"); zyre_leave(node4, "GLOBAL"); zstr_free (&name); zstr_free (&peerid); zstr_free (&command); zyre_stop (node3); zyre_stop (node4); // give things a chance to settle... zclock_sleep (250); zyre_destroy(&node3); zyre_destroy(&node4); zcert_destroy(&node3_cert); zcert_destroy(&node4_cert); // test gossip if (verbose) zsys_debug ("----------------TESTING GOSSIP----------------"); zyre_t *node5 = zyre_new ("node5"); zyre_t *node6 = zyre_new ("node6"); assert (node5); assert (node6); if (verbose) { zyre_set_verbose (node5); zyre_set_verbose (node6); } // if it takes more than 10s, something probably went terribly wrong zsock_set_rcvtimeo(node5->inbox, 10000); zsock_set_rcvtimeo(node6->inbox, 10000); zcert_t *node5_cert = zcert_new (); zcert_t *node6_cert = zcert_new (); assert (node5_cert); assert (node6_cert); zyre_set_zcert(node5, node5_cert); zyre_set_zcert(node6, node6_cert); zyre_set_header(node5, "X-PUBLICKEY", "%s", zcert_public_txt(node5_cert)); zyre_set_header(node6, "X-PUBLICKEY", "%s", zcert_public_txt(node6_cert)); const char *gossip_cert = zcert_public_txt (node5_cert); // TODO- need to add zyre_gossip_port functions to get port from gossip bind(?) zyre_gossip_bind(node5, "tcp://127.0.0.1:9001"); zyre_gossip_connect_curve(node6, gossip_cert, "tcp://127.0.0.1:9001"); zyre_start(node5); zsock_wait(node5); zyre_start(node6); zsock_wait(node6); zyre_join (node5, "GLOBAL"); zyre_join (node6, "GLOBAL"); // give things a chance to settle... zclock_sleep (1500); if (verbose) { zyre_dump (node5); zyre_dump (node6); } zyre_shouts (node5, "GLOBAL", "Hello, World"); // Second node should receive ENTER, JOIN, and SHOUT msg = zyre_recv (node6); assert (msg); command = zmsg_popstr (msg); zsys_info(command); assert (streq (command, "ENTER")); zstr_free (&command); peerid = zmsg_popstr (msg); assert (peerid); name = zmsg_popstr (msg); zmsg_destroy (&msg); assert (streq (name, "node5")); zstr_free (&name); zyre_leave(node5, "GLOBAL"); zyre_leave(node6, "GLOBAL"); zyre_stop (node5); zyre_stop (node6); // give things a chance to settle... zclock_sleep (250); zstr_free (&peerid); zcert_destroy (&node5_cert); zcert_destroy (&node6_cert); zyre_destroy(&node5); zyre_destroy(&node6); zactor_destroy(&auth); printf ("OK\n"); } #endif }