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

FreeBSD Manual Pages

  
 
  

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 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

CZMQ 4.2.1			  11/01/2025			     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.0>

home | help