diff --git a/demo/pubsub_forwarder/CMakeLists.txt b/demo/pubsub_forwarder/CMakeLists.txt new file mode 100644 index 000000000..821e05c00 --- /dev/null +++ b/demo/pubsub_forwarder/CMakeLists.txt @@ -0,0 +1,18 @@ +# This software is supplied under the terms of the MIT License, a +# copy of which should be located in the distribution where this +# file was obtained (LICENSE.txt). A copy of the license may also be +# found online at https://opensource.org/licenses/MIT. + +cmake_minimum_required(VERSION 3.10) +project(pubsub_forwarder C) + +# Find the nng library +find_package(nng REQUIRED) + +# Add the executable target +add_executable(pubsub_forwarder pubsub_forwarder.c) + +target_compile_options(pubsub_forwarder PRIVATE -Wall -Wextra -Wpedantic -Werror -O2) + +# Link against the nng library +target_link_libraries(pubsub_forwarder PRIVATE nng) diff --git a/demo/pubsub_forwarder/README.adoc b/demo/pubsub_forwarder/README.adoc new file mode 100644 index 000000000..55832b9a1 --- /dev/null +++ b/demo/pubsub_forwarder/README.adoc @@ -0,0 +1,62 @@ += PubSub Forwarder + +This is a trivial example of a forwarder/proxy for the pub/sub pattern. + +The concept is as follows: the forwarder will listen for connections on +both a front-end port and a back-end port. The front-end will act as a +subscriber so that publishers can publish to it. The back-end will act +as a publisher so that subscribers can subscribe to it. The front-end +then forwards to the back end. + +== Compiling + +CMake with ninja-build is simplest: + +[source, bash] +---- +cmake -GNinja -B build +cd build +ninja +---- + +Or if you prefer a traditional approach, +the following is an example typical of UNIX and similar systems like +Linux and macOS may appeal: + +[source, bash] +---- +export CPPFLAGS="-I /usr/local/include" +export LDFLAGS="-L /usr/local/lib -lnng" +export CC="cc" +${CC} ${CPPFLAGS} pubsub_forwarder.c -o pubsub_forwarder ${LDFLAGS} +---- + +== Running + +An example setup for running this example would involve the following: + +. Step 1: Run this example binary (in the background or a terminal, etc) +. Step 2: In a new terminal, run the following + +[source, bash] +---- +nngcat --sub --dial "tcp://localhost:3328" --quoted +---- + +. Step 3: In a second terminal, run the same command again to give us two subscribers + +[source, bash] +---- +nngcat --sub --dial "tcp://localhost:3328" --quoted +---- + + +. In a third terminal, run the following to publish a counter + +[source, bash] +---- +for n in $(seq 0 99); do nngcat --pub --dial "tcp://localhost:3327" --data "$n"; done +---- + + + diff --git a/demo/pubsub_forwarder/pubsub_forwarder.c b/demo/pubsub_forwarder/pubsub_forwarder.c new file mode 100644 index 000000000..e79c04b00 --- /dev/null +++ b/demo/pubsub_forwarder/pubsub_forwarder.c @@ -0,0 +1,96 @@ +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +// +// Forwarder example based on https://github.com/C-o-r-E/nng_pubsub_proxy +// +// This example shows how to use raw sockets to set up a forwarder or proxy for +// pub/sub. +// +// An example setup for running this example would involve the following: +// +// - Run this example binary (in the background or a terminal, etc) +// - In a new terminal, run +// `nngcat --sub --dial "tcp://localhost:3328" --quoted` +// - In a second terminal, run +// `nngcat --sub --dial "tcp://localhost:3328" --quoted` +// - In a third terminal, run +// `for n in $(seq 0 99);` +// `do nngcat --pub --dial "tcp://localhost:3327" --data "$n";` +// `done` +// +#include +#include +#include + +#include +#include +#include + +#define PROXY_FRONT_URL "tcp://localhost:3327" +#define PROXY_BACK_URL "tcp://localhost:3328" + +void +panic_on_error(int should_panic, const char *format, ...) +{ + if (should_panic) { + va_list args; + va_start(args, format); + vprintf(format, args); + va_end(args); + exit(EXIT_FAILURE); + } +} + +int +main() +{ + nng_socket sock_front_end = NNG_SOCKET_INITIALIZER; + nng_socket sock_back_end = NNG_SOCKET_INITIALIZER; + int ret = 0; + + // + // First we need some nng sockets. Not to be confused with network + // sockets + // + ret = nng_sub0_open_raw(&sock_front_end); + panic_on_error(ret, "Failed to open front end socket\n"); + + ret = nng_pub0_open_raw(&sock_back_end); + panic_on_error(ret, "Failed to open back end socket\n"); + + // + // Now we need to set up a listener for each socket so that they have + // addresses + // + + nng_listener front_ls = NNG_LISTENER_INITIALIZER; + nng_listener back_ls = NNG_LISTENER_INITIALIZER; + + ret = nng_listener_create(&front_ls, sock_front_end, PROXY_FRONT_URL); + panic_on_error(ret, "Failed to create front listener\n"); + + ret = nng_listener_create(&back_ls, sock_back_end, PROXY_BACK_URL); + panic_on_error(ret, "Failed to create back listener\n"); + + ret = nng_listener_start(front_ls, 0); + panic_on_error(ret, "Failed to start front listener\n"); + + ret = nng_listener_start(back_ls, 0); + panic_on_error(ret, "Failed to start back listener\n"); + + // + // Finally let nng do the forwarding/proxying + // + + ret = nng_device(sock_front_end, sock_back_end); + panic_on_error( + ret, "nng_device returned %d: %s\n", ret, nng_strerror(ret)); + + printf("done"); + return 0; +} \ No newline at end of file