diff --git a/.gitignore b/.gitignore index 1d07f74c..499bf00f 100644 --- a/.gitignore +++ b/.gitignore @@ -88,6 +88,7 @@ tests/test_many_sockets tests/test_diffserv tests/test_srcfd tests/test_stream_disconnect +tests/test_proxy_chain tests/test*.log tests/test*.trs src/platform.hpp* diff --git a/doc/Makefile.am b/doc/Makefile.am index e193292e..936f6806 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -7,8 +7,9 @@ MAN3 = zmq_bind.3 zmq_unbind.3 zmq_connect.3 zmq_disconnect.3 zmq_close.3 \ zmq_msg_get.3 zmq_msg_set.3 zmq_msg_more.3 \ zmq_getsockopt.3 zmq_setsockopt.3 \ zmq_socket.3 zmq_socket_monitor.3 zmq_poll.3 \ - zmq_errno.3 zmq_strerror.3 zmq_version.3 zmq_proxy.3 zmq_proxy_steerable.3 \ + zmq_errno.3 zmq_strerror.3 zmq_version.3 \ zmq_sendmsg.3 zmq_recvmsg.3 zmq_init.3 zmq_term.3 \ + zmq_proxy.3 zmq_proxy_steerable.3 zmq_proxy_chain.3 zmq_proxy_hook.3 \ zmq_z85_encode.3 zmq_z85_decode.3 zmq_curve_keypair.3 MAN7 = zmq.7 zmq_tcp.7 zmq_pgm.7 zmq_epgm.7 zmq_inproc.7 zmq_ipc.7 \ diff --git a/doc/zmq_proxy_hook.txt b/doc/zmq_proxy_hook.txt index a93a0d99..e7dbddb2 100644 --- a/doc/zmq_proxy_hook.txt +++ b/doc/zmq_proxy_hook.txt @@ -29,7 +29,7 @@ it is sent to the backend. The second one, 'back2front_hook' is for the way back Both functions receive as an argument in addition to a pointer to the message, the pointer to the data passed in the 'zmq_proxy_hook_t' structure. This data makes it -possible to manage statefull behaviours in the proxy. They receive also the frame +possible to manage stateful behaviours in the proxy. They receive also the frame number n_ which is 1 for the first frame, n for the nth one, 0 for the last one. This enable to manage specifically the identity frame when ROUTER | STREAM sockets are concerned. Moreover, to give the hook full capabilities, the three sockets passed @@ -37,7 +37,7 @@ as parameters to the proxy are also provided to the hook functions, enabling to consume some frames or to add others: ---- -typedef int (*zmq_hook_f)(void *frontend, void *backend, void *capture, +typedef int (*zmq_hook_f)(void *frontend, void *backend, void *capture, zmq_msg_t* msg_, size_t n_, void *data_); typedef struct zmq_proxy_hook_t { void *data; @@ -57,36 +57,35 @@ EXAMPLE USAGE ------------- Filter ------- +~~~~~~ The most simple use is to simply filter the messages for example against vulgarity. Messages are simply scanned against a dictionnary and target words are replaced. ROUTER | STREAM / ROUTER | STREAM proxy ---------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The data field enables to multiplex as desired identities in a ROUTER/ROUTER or in a STREAM/STREAM proxy or what ever. Such architecture enables also custom load balancers. Sticky ROUTER / ROUTER proxy ----------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The data field enables to manage sticky identity pairing in a ROUTER/ROUTER proxy. Security mechanism proxying ---------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~ We expect to be able to proxy CURVE with the use of this feature. Tests ------ +~~~~~ In an existing application, just change zmq_proxy or zmq_proxy_steerable for zmq_proxy_hook to test anythink, even "Man in the middle" attacks ws security mechanisms with a STREAM/STREAM proxy. - RETURN VALUE ------------ The _zmq_proxy_hook()_ function returns the same values than zmq_proxy @@ -95,7 +94,7 @@ or zmq_proxy_steerable in the same conditions of use. EXAMPLE ------- -This simple example aims at uppercasing the traffic between the frontend and the +This simple example aims at uppercasing the traffic between the frontend and the backend, and lowercasing it on the way back. .Setup the hook @@ -134,9 +133,9 @@ lower_case(void*, void*, void*, zmq_msg_t* msg_, size_t n_, void *stats_) } zmq_proxy_hook_t hook = { - &stats, // data used by the hook functions, passed as void* data_ - upper_case, // hook for messages going from frontend to backend - lower_case // hook for messages going from backend to frontend + &stats, // data used by the hook functions, passed as void* data_ + upper_case, // hook for messages going from frontend to backend + lower_case // hook for messages going from backend to frontend }; ---- .in main: @@ -144,38 +143,38 @@ zmq_proxy_hook_t hook = { int main (void) { - setup_test_environment (); - void *context = zmq_ctx_new (); - assert (context); - // Create frontend, backend and control sockets - void *frontend = zmq_socket (context, ZMQ_ROUTER); - assert (backend); - void *backend = zmq_socket (context, ZMQ_DEALER); - assert (frontend); - void *control = zmq_socket (context, ZMQ_PUB); - assert (control); - - // Bind sockets to TCP ports - assert (zmq_bind (frontend, "tcp://*:5555") == 0); - assert (zmq_bind (backend, "tcp://*:5556") == 0); - assert (zmq_connect (control, "tcp://*:5557") == 0); - - // Start the queue proxy, which runs until ETERM or "TERMINATE" - // received on the control socket - zmq_proxy_hook (frontend, backend, NULL, &hook, control); - - printf("frontend to backend hook hits = %d\nbackend to frontend hook hits = %d\n", stats.qt_upper_case, stats.qt_lower_case); + setup_test_environment (); + void *context = zmq_ctx_new (); + assert (context); + // Create frontend, backend and control sockets + void *frontend = zmq_socket (context, ZMQ_ROUTER); + assert (backend); + void *backend = zmq_socket (context, ZMQ_DEALER); + assert (frontend); + void *control = zmq_socket (context, ZMQ_PUB); + assert (control); - // close sockets and context - rc = zmq_close (control); - assert (rc == 0); - rc = zmq_close (backend); - assert (rc == 0); - rc = zmq_close (frontend); - assert (rc == 0); - rc = zmq_ctx_term (ctx); - assert (rc == 0); - return 0; + // Bind sockets to TCP ports + assert (zmq_bind (frontend, "tcp://*:5555") == 0); + assert (zmq_bind (backend, "tcp://*:5556") == 0); + assert (zmq_connect (control, "tcp://*:5557") == 0); + + // Start the queue proxy, which runs until ETERM or "TERMINATE" + // received on the control socket + zmq_proxy_hook (frontend, backend, NULL, &hook, control); + + printf("frontend to backend hook hits = %d\nbackend to frontend hook hits = %d\n", stats.qt_upper_case, stats.qt_lower_case); + + // close sockets and context + rc = zmq_close (control); + assert (rc == 0); + rc = zmq_close (backend); + assert (rc == 0); + rc = zmq_close (frontend); + assert (rc == 0); + rc = zmq_ctx_term (ctx); + assert (rc == 0); + return 0; } ---- .somewhere, the proxy is stopped with: