Part 4: Sending and receiving messages using the Marlin Network

Step 1 - Run two clients

Create second key pair.

    uint8_t static_sk2[crypto_box_SECRETKEYBYTES];
    uint8_t static_pk2[crypto_box_PUBLICKEYBYTES];
    crypto_box_keypair(static_pk2, static_sk2);

Add a second client inside main.cpp.

    DefaultMulticastClientOptions clop2 {
        static_sk2,
        {"goldfish"},
        "127.0.0.1:7002",
        "127.0.0.1:7000"
    };
    DefaultMulticastClient<MulticastDelegate> cl2(clop2);
    cl2.delegate = &del;

This time, we also set options that changes the ports used by the client since the default ports are taken up by the first client.

Step 2 - Handle new messages

Handle new messages inside the did_recv_message function in the delegate. For now, we simply log the messages to the console.

        SPDLOG_INFO(
            "Did recv message: {}",
            std::string(message.data(), message.data() + message.size())
        );

Step 3 - Send messages on some event

In real world scenarios, new messages are usually triggered by external events like timers, other messages, user actions, etc. For the purpose of this tutorial, we take advantage of the client calling did_subscribe to trigger a new message. Add the following to did_subscribe

        client.ps.send_message_on_channel(channel, "Hello!", 6);

Once you have followed the above instructions, you should have a main.cpp that looks like this:

#include <marlin/multicast/DefaultMulticastClient.hpp>


using namespace marlin::multicast;
using namespace marlin::net;

class MulticastDelegate {
public:
    void did_recv_message(
        DefaultMulticastClient<MulticastDelegate> &client,
        Buffer &&message,
        Buffer &&witness,
        std::string &channel,
        uint64_t message_id
    ) {
        SPDLOG_INFO(
            "Did recv message: {}",
            std::string(message.data(), message.data() + message.size())
        );
    }

    void did_subscribe(
        DefaultMulticastClient<MulticastDelegate> &client,
        std::string &channel
    ) {
        SPDLOG_INFO("Did subscribe to channel {}", channel);
        client.ps.send_message_on_channel(channel, "Hello!", 6);
    }

    void did_unsubscribe(
        DefaultMulticastClient<MulticastDelegate> &client,
        std::string &channel
    ) {
        SPDLOG_INFO("Did unsubscribe from channel {}", channel);
    }
};

int main() {
    uint8_t static_sk1[crypto_box_SECRETKEYBYTES];
    uint8_t static_pk1[crypto_box_PUBLICKEYBYTES];
    crypto_box_keypair(static_pk1, static_sk1);

    uint8_t static_sk2[crypto_box_SECRETKEYBYTES];
    uint8_t static_pk2[crypto_box_PUBLICKEYBYTES];
    crypto_box_keypair(static_pk2, static_sk2);

    MulticastDelegate del;

    DefaultMulticastClientOptions clop2 {
        static_sk2,
        {"goldfish"},
        "127.0.0.1:9002",
        "127.0.0.1:7002",
        "127.0.0.1:7000"
    };
    DefaultMulticastClient<MulticastDelegate> cl2(clop2);
    cl2.delegate = &del;

    DefaultMulticastClientOptions clop1 {
        static_sk1,
        {"goldfish"},
        "127.0.0.1:9002"
    };
    DefaultMulticastClient<MulticastDelegate> cl1(clop1);
    cl1.delegate = &del;

    return DefaultMulticastClient<MulticastDelegate>::run_event_loop();
}

Step 4 - Build and run executable

Build using

$ cmake .. -DCMAKE_BUILD_TYPE=Release
$ make

and run using

$ ./tutorial

Building should have worked and the executable should run. You should see subscription related logs printed here indicating a successful connection between both the clients and the Marlin Network. You should also see message logs indicating new messages sent and received using the Marlin Network both here and in the Goldfish node.

Conclusion

In this last part, we learnt how to use the Marlin Multicast SDK to send and receive messages using the Marlin Network.