Skip to content

Commit

Permalink
Add forwarder demo
Browse files Browse the repository at this point in the history
  • Loading branch information
C-o-r-E committed Jul 9, 2023
1 parent c5e9d8a commit 5954c0d
Show file tree
Hide file tree
Showing 3 changed files with 166 additions and 0 deletions.
18 changes: 18 additions & 0 deletions demo/pubsub_forwarder/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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)
62 changes: 62 additions & 0 deletions demo/pubsub_forwarder/README.adoc
Original file line number Diff line number Diff line change
@@ -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
----



86 changes: 86 additions & 0 deletions demo/pubsub_forwarder/pubsub_forwarder.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
//
// 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 <stdarg.h>
#include <stdio.h>
#include <stdlib.h>

#include <nng/nng.h>
#include <nng/protocol/pubsub0/sub.h>
#include <nng/protocol/pubsub0/pub.h>

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

0 comments on commit 5954c0d

Please sign in to comment.