Skip site navigation (1)Skip section navigation (2)

  
 
  

home | help
ZPROXY(3)			   CZMQ Manual			       ZPROXY(3)

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);
     //
     //  When the socket type is XSUB or SUB, topic(s) string(s) can be passed as
     //  additional arguments (NOTE: in DRAFT state) and the socket will subscribe
     //  using them.
     //
     //  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);

	 char *frontend = NULL;
	 char *backend = NULL;
	 backend = zsys_sprintf (LOCALENDPOINT, s_get_available_port ());
	 zclock_sleep (200);
	 sink = zsock_new_sub (backend, "whatever");
	 assert (sink);

	 zstr_sendx (proxy, "BACKEND", "XPUB", backend, NULL);
	 zsock_wait (proxy);

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

	 #ifdef CZMQ_BUILD_DRAFT_API
	 //  Create and configure our proxy with PUB/SUB to test subscriptions
	 proxy = zactor_new (zproxy, NULL);
	 assert (proxy);
	 if (verbose) {
	     zstr_sendx (proxy, "VERBOSE", NULL);
	     zsock_wait (proxy);
	 }
	 zstr_sendx (proxy, "FRONTEND", "SUB", "inproc://frontend", "He", "b", NULL);
	 zsock_wait (proxy);
	 zstr_sendx (proxy, "BACKEND", "PUB", "inproc://backend", NULL);
	 zsock_wait (proxy);

	 //  Connect application sockets to proxy
	 faucet = zsock_new_pub (">inproc://frontend");
	 assert (faucet);
	 sink = zsock_new_sub (">inproc://backend", "");
	 assert (sink);

	 //  Send some messages and check they arrived
	 zstr_sendx (faucet, "Hello", "World", NULL);
	 // since SUB is binding, subscription might be lost see:
	 // https://github.com/zeromq/libzmq/issues/2267
	 zsock_set_rcvtimeo (sink, 100);
	 hello = zstr_recv (sink);
	 if (hello) {
	     assert (streq (hello, "Hello"));
	     world = zstr_recv (sink);
	     assert (streq (world, "World"));
	     zstr_free (&hello);
	     zstr_free (&world);
	 }

	 zsock_destroy (&faucet);
	 zsock_destroy (&sink);
	 zactor_destroy(&proxy);
	 #endif // CZMQ_BUILD_DRAFT_API

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

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

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

	 //  Allow our address, which overrides the block list
	 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  Li-
     cense, 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

CZMQ 4.2.1			   08/27/2026			       ZPROXY(3)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=zproxy&sektion=3&manpath=FreeBSD+Ports+15.1.quarterly>

home | help