GSP
Quick Navigator

Search Site

Unix VPS
A - Starter
B - Basic
C - Preferred
D - Commercial
MPS - Dedicated
Previous VPSs
* Sign Up! *

Support
Contact Us
Online Help
Handbooks
Domain Status
Man Pages

FAQ
Virtual Servers
Pricing
Billing
Technical

Network
Facilities
Connectivity
Topology Map

Miscellaneous
Server Agreement
Year 2038
Credits
 

USA Flag

 

 

Man Pages
ZPROXY(3) CZMQ Manual ZPROXY(3)

zproxy - Class for run a steerable proxy in the background

//  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'.

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

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

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

Main web site:

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

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.

1.
zeromq-dev@lists.zeromq.org
mailto:zeromq-dev@lists.zeromq.org
04/09/2022 CZMQ 4.2.1

Search for    or go to Top of page |  Section 3 |  Main Index

Powered by GSP Visit the GSP FreeBSD Man Page Interface.
Output converted with ManDoc.