Provided by: libczmq-dev_4.1.0-2_amd64 bug

NAME

       zproxy - Class for run a steerable proxy in the background

SYNOPSIS

       //  Create new zproxy actor instance. The proxy switches messages between
       //  a frontend socket and a backend socket; use the FRONTEND and BACKEND
       //  commands to configure these:
       //
       //      zactor_t *proxy = zactor_new (zproxy, NULL);
       //
       //  Destroy zproxy instance. This destroys the two sockets and stops any
       //  message flow between them:
       //
       //      zactor_destroy (&proxy);
       //
       //  Note that all zproxy commands are synchronous, so your application always
       //  waits for a signal from the actor after each command.
       //
       //  Enable verbose logging of commands and activity:
       //
       //      zstr_send (proxy, "VERBOSE");
       //      zsock_wait (proxy);
       //
       //  Specify frontend socket type -- see zsock_type_str () -- and attach to
       //  endpoints, see zsock_attach (). Note that a proxy socket is always
       //  serverish:
       //
       //      zstr_sendx (proxy, "FRONTEND", "XSUB", endpoints, NULL);
       //      zsock_wait (proxy);
       //
       //  Specify backend socket type -- see zsock_type_str () -- and attach to
       //  endpoints, see zsock_attach (). Note that a proxy socket is always
       //  serverish:
       //
       //      zstr_sendx (proxy, "BACKEND", "XPUB", endpoints, NULL);
       //      zsock_wait (proxy);
       //
       //  Capture all proxied messages; these are delivered to the application
       //  via an inproc PULL socket that you have already bound to the specified
       //  endpoint:
       //
       //      zstr_sendx (proxy, "CAPTURE", endpoint, NULL);
       //      zsock_wait (proxy);
       //
       //  Pause the proxy. A paused proxy will cease processing messages, causing
       //  them to be queued up and potentially hit the high-water mark on the
       //  frontend or backend socket, causing messages to be dropped, or writing
       //  applications to block:
       //
       //      zstr_sendx (proxy, "PAUSE", NULL);
       //      zsock_wait (proxy);
       //
       //  Resume the proxy. Note that the proxy starts automatically as soon as it
       //  has a properly attached frontend and backend socket:
       //
       //      zstr_sendx (proxy, "RESUME", NULL);
       //      zsock_wait (proxy);
       //
       //  Configure an authentication domain for the "FRONTEND" or "BACKEND" proxy
       //  socket -- see zsock_set_zap_domain (). Call before binding socket:
       //
       //      zstr_sendx (proxy, "DOMAIN", "FRONTEND", "global", NULL);
       //      zsock_wait (proxy);
       //
       //  Configure PLAIN authentication for the "FRONTEND" or "BACKEND" proxy
       //  socket -- see zsock_set_plain_server (). Call before binding socket:
       //
       //      zstr_sendx (proxy, "PLAIN", "BACKEND", NULL);
       //      zsock_wait (proxy);
       //
       //  Configure CURVE authentication for the "FRONTEND" or "BACKEND" proxy
       //  socket -- see zsock_set_curve_server () -- specifying both the public and
       //  secret keys of a certificate as Z85 armored strings -- see
       //  zcert_public_txt () and zcert_secret_txt (). Call before binding socket:
       //
       //      zstr_sendx (proxy, "CURVE", "FRONTEND", public_txt, secret_txt, NULL);
       //      zsock_wait (proxy);
       //
       //  This is the zproxy constructor as a zactor_fn; the argument is a
       //  character string specifying frontend and backend socket types as two
       //  uppercase strings separated by a hyphen:
       CZMQ_EXPORT void
           zproxy (zsock_t *pipe, void *unused);

       //  Selftest
       CZMQ_EXPORT void
           zproxy_test (bool verbose);
       Please add '@interface' section in './../src/zproxy.c'.

DESCRIPTION

       A zproxy actor switches messages between a frontend and a backend socket. It acts much
       like the zmq_proxy_steerable method, though it makes benefit of CZMQ’s facilities, to be
       somewhat simpler to set-up.

       This class replaces zproxy_v2, and is meant for applications that use the CZMQ v3 API
       (meaning, zsock).

EXAMPLE

       From zproxy_test method.

           //  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);

           //  Test socket creation dependency
           proxy = zactor_new (zproxy, NULL);
           assert (proxy);

           #ifdef  WIN32
                   sink = zsock_new_sub(">inproc://backend", "whatever");
           #else
           // vagrant vms don't like using shared storage for ipc pipes..
           if (streq(getenv("USER"), "vagrant"))
               sink = zsock_new_sub (">ipc:///tmp/backend", "whatever");
           else
                       sink = zsock_new_sub (">ipc://backend", "whatever");
           #endif //  WIN32
                   assert (sink);

           #ifdef WIN32
                   zstr_sendx (proxy, "BACKEND", "XPUB", "inproc://backend", NULL);
           #else
           // vagrant vms don't like using shared storage for ipc pipes..
           if (streq(getenv("USER"), "vagrant"))
               zstr_sendx(proxy, "BACKEND", "XPUB", "ipc:///tmp/backend", NULL);
           else
               zstr_sendx(proxy, "BACKEND", "XPUB", "ipc://backend", NULL);
           #endif
           zsock_wait (proxy);

           zsock_destroy(&sink);
           zactor_destroy(&proxy);

           #if (ZMQ_VERSION_MAJOR == 4)
           // Test authentication functionality
           const char *basedirpath = "src/selftest-rw/.test_zproxy";
           const char *passfilepath = "src/selftest-rw/.test_zproxy/password-file";
           const char *certfilepath = "src/selftest-rw/.test_zproxy/mycert.txt";

           // 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 (passfilepath);
           zsys_file_delete (certfilepath);
           zsys_dir_delete (basedirpath);

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

           char *frontend = NULL;
           char *backend = NULL;

           //  Check there's no authentication
           s_create_test_sockets (&proxy, &faucet, &sink, verbose);
           s_bind_test_sockets (proxy, &frontend, &backend);
           bool success = s_can_connect (&proxy, &faucet, &sink, frontend, backend,
               verbose, true);
           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_test_sockets (proxy, &frontend, &backend);
           success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose,
               true);
           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.
           zstr_sendx (proxy, "DOMAIN", "FRONTEND", "global", NULL);
           zsock_wait (proxy);
           s_bind_test_sockets (proxy, &frontend, &backend);
           success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose,
               true);
           assert (success);

           //  Blacklist 127.0.0.1, connection should fail
           zstr_sendx (proxy, "DOMAIN", "FRONTEND", "global", NULL);
           zsock_wait (proxy);
           s_bind_test_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,
               false);
           assert (!success);

           //  Whitelist our address, which overrides the blacklist
           zstr_sendx (proxy, "DOMAIN", "FRONTEND", "global", NULL);
           zsock_wait (proxy);
           zstr_sendx (proxy, "DOMAIN", "BACKEND", "global", NULL);
           zsock_wait (proxy);
           s_bind_test_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,
               true);
           assert (success);

           //  Try PLAIN authentication

           //  Test negative case (no server-side passwords defined)
           zstr_sendx (proxy, "PLAIN", "FRONTEND", NULL);
           zsock_wait (proxy);
           zstr_sendx (proxy, "DOMAIN", "FRONTEND", "global", NULL);
           zsock_wait (proxy);
           s_bind_test_sockets (proxy, &frontend, &backend);
           zsock_set_plain_username (faucet, "admin");
           zsock_set_plain_password (faucet, "Password");
           success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose,
               false);
           assert (!success);

           //  Test positive case (server-side passwords defined)
           FILE *password = fopen (passfilepath, "w");
           assert (password);
           fprintf (password, "admin=Password\n");
           fclose (password);
           zstr_sendx (proxy, "PLAIN", "FRONTEND", NULL);
           zsock_wait (proxy);
           zstr_sendx (proxy, "DOMAIN", "FRONTEND", "global", NULL);
           zsock_wait (proxy);
           zstr_sendx (proxy, "PLAIN", "BACKEND", NULL);
           zsock_wait (proxy);
           zstr_sendx (proxy, "DOMAIN", "BACKEND", "global", NULL);
           zsock_wait (proxy);
           s_bind_test_sockets (proxy, &frontend, &backend);
           zsock_set_plain_username (faucet, "admin");
           zsock_set_plain_password (faucet, "Password");
           zsock_set_plain_username (sink, "admin");
           zsock_set_plain_password (sink, "Password");
           zstr_sendx (auth, "PLAIN", passfilepath, NULL);
           zsock_wait (auth);
           success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose,
               true);
           assert (success);

           //  Test negative case (bad client password)
           zstr_sendx (proxy, "PLAIN", "FRONTEND", NULL);
           zsock_wait (proxy);
           zstr_sendx (proxy, "DOMAIN", "FRONTEND", "global", NULL);
           zsock_wait (proxy);
           s_bind_test_sockets (proxy, &frontend, &backend);
           zsock_set_plain_username (faucet, "admin");
           zsock_set_plain_password (faucet, "Bogus");
           success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose,
               false);
           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);
               const char *public_key = zcert_public_txt (server_cert);
               const char *secret_key = zcert_secret_txt (server_cert);

               //  Try CURVE authentication

               //  Test without setting-up any authentication
               zstr_sendx (proxy, "CURVE", "FRONTEND", public_key, secret_key, NULL);
               zsock_wait (proxy);
               zstr_sendx (proxy, "DOMAIN", "FRONTEND", "global", NULL);
               zsock_wait (proxy);
               s_bind_test_sockets (proxy, &frontend, &backend);
               zcert_apply (client_cert, faucet);
               zsock_set_curve_serverkey (faucet, public_key);
               success = s_can_connect (&proxy, &faucet, &sink, frontend, backend,
                   verbose, false);
               assert (!success);

               //  Test CURVE_ALLOW_ANY
               zstr_sendx (proxy, "CURVE", "FRONTEND", public_key, secret_key, NULL);
               zsock_wait (proxy);
               s_bind_test_sockets (proxy, &frontend, &backend);
               zcert_apply (client_cert, faucet);
               zsock_set_curve_serverkey (faucet, public_key);
               zstr_sendx (auth, "CURVE", CURVE_ALLOW_ANY, NULL);
               zsock_wait (auth);
               success = s_can_connect (&proxy, &faucet, &sink, frontend, backend,
                   verbose, true);
               assert (success);

               //  Test with client certificate file in authentication folder
               zstr_sendx (proxy, "CURVE", "FRONTEND", public_key, secret_key, NULL);
               zsock_wait (proxy);
               zstr_sendx (proxy, "CURVE", "BACKEND", public_key, secret_key, NULL);
               zsock_wait (proxy);
               s_bind_test_sockets (proxy, &frontend, &backend);
               zcert_apply (client_cert, faucet);
               zsock_set_curve_serverkey (faucet, public_key);
               zcert_apply (client_cert, sink);
               zsock_set_curve_serverkey (sink, public_key);
               zcert_save_public (client_cert, certfilepath);
               zstr_sendx (auth, "CURVE", basedirpath, NULL);
               zsock_wait (auth);
               success = s_can_connect (&proxy, &faucet, &sink, frontend, backend,
                   verbose, true);
               assert (success);

               zcert_destroy (&server_cert);
               zcert_destroy (&client_cert);
           }

           //  Remove the authenticator and check a normal connection works
           zactor_destroy (&auth);
           s_bind_test_sockets (proxy, &frontend, &backend);
           success = s_can_connect (&proxy, &faucet, &sink, frontend, backend, verbose,
               true);
           assert (success);

           //  Cleanup
           zsock_destroy (&faucet);
           zsock_destroy (&sink);
           zactor_destroy (&proxy);
           zstr_free (&frontend);
           zstr_free (&backend);

           //  Delete temporary directory and test files
           zsys_file_delete (passfilepath);
           zsys_file_delete (certfilepath);
           zsys_dir_delete (basedirpath);
           #endif

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

AUTHORS

       The czmq manual was written by the authors in the AUTHORS file.

RESOURCES

       Main web site:

       Report bugs to the email <zeromq-dev@lists.zeromq.org[1]>

COPYRIGHT

       Copyright (c) the Contributors as noted in the AUTHORS file. This file is part of CZMQ,
       the high-level C binding for 0MQ: http://czmq.zeromq.org. This Source Code Form is subject
       to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
       distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. LICENSE
       included with the czmq distribution.

NOTES

        1. zeromq-dev@lists.zeromq.org
           mailto:zeromq-dev@lists.zeromq.org