Files
zosbuilder/components/mycelium/docs/topic_configuration.md

5.8 KiB

Topic Configuration Guide

This document explains how to configure message topics in Mycelium, including how to add new topics, configure socket forwarding paths, and manage whitelisted subnets.

Overview

Mycelium's messaging system uses topics to categorize and route messages. Each topic can be configured with:

  • Whitelisted subnets: IP subnets that are allowed to send messages to this topic
  • Forward socket: A Unix domain socket path where messages for this topic will be forwarded

When a message is received with a topic that has a configured socket path, the content of the message is pushed to the socket, and the system waits for a reply from the socket, which is then sent back to the original sender.

Configuration Using JSON-RPC API

The JSON-RPC API provides a comprehensive set of methods for managing topics, socket forwarding paths, and whitelisted subnets.

Adding a New Topic

Using the JSON-RPC API

{
  "jsonrpc": "2.0",
  "method": "addTopic",
  "params": ["dGVzdC10b3BpYw=="],  // base64 encoding of "test-topic"
  "id": 1
}

Example using curl:

curl -X POST http://localhost:8990/rpc \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "addTopic",
    "params": ["dGVzdC10b3BpYw=="],
    "id": 1
  }'

Configuring a Socket Forwarding Path

When a topic is configured with a socket forwarding path, messages for that topic will be forwarded to the specified Unix domain socket instead of being pushed to the message queue.

Using the JSON-RPC API

{
  "jsonrpc": "2.0",
  "method": "setTopicForwardSocket",
  "params": ["dGVzdC10b3BpYw==", "/path/to/socket"],
  "id": 1
}

Example using curl:

curl -X POST http://localhost:8990/rpc \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "setTopicForwardSocket",
    "params": ["dGVzdC10b3BpYw==", "/path/to/socket"],
    "id": 1
  }'

## Adding a Whitelisted Subnet

Whitelisted subnets control which IP addresses are allowed to send messages to a specific topic. If a message is received from an IP that is not in the whitelist, it will be dropped.

### Using the JSON-RPC API

```json
{
  "jsonrpc": "2.0",
  "method": "addTopicSource",
  "params": ["dGVzdC10b3BpYw==", "192.168.1.0/24"],
  "id": 1
}

Example using curl:

curl -X POST http://localhost:8990/rpc \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "addTopicSource",
    "params": ["dGVzdC10b3BpYw==", "192.168.1.0/24"],
    "id": 1
  }'

## Setting the Default Topic Action

You can configure the default action to take for topics that don't have explicit whitelist configurations:

### Using the JSON-RPC API

```json
{
  "jsonrpc": "2.0",
  "method": "setDefaultTopicAction",
  "params": [true],
  "id": 1
}

Example using curl:

curl -X POST http://localhost:8990/rpc \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "setDefaultTopicAction",
    "params": [true],
    "id": 1
  }'

## Socket Protocol

When a message is forwarded to a socket, the raw message data is sent to the socket. The socket is expected to process the message and send a reply, which will be forwarded back to the original sender.

The socket protocol is simple:
1. The message data is written to the socket
2. The system waits for a reply from the socket (with a configurable timeout)
3. The reply data is read from the socket and sent back to the original sender

## Example: Creating a Socket Server

Here's an example of a simple socket server that echoes back the received data:

```rust
use std::{
    io::{Read, Write},
    os::unix::net::UnixListener,
    path::Path,
    thread,
};

fn main() {
    let socket_path = "/tmp/mycelium-socket";
    
    // Remove the socket file if it already exists
    if Path::new(socket_path).exists() {
        std::fs::remove_file(socket_path).unwrap();
    }
    
    // Create the Unix domain socket
    let listener = UnixListener::bind(socket_path).unwrap();
    println!("Socket server listening on {}", socket_path);
    
    // Accept connections in a loop
    for stream in listener.incoming() {
        match stream {
            Ok(mut stream) => {
                // Spawn a thread to handle the connection
                thread::spawn(move || {
                    // Read the data
                    let mut buffer = Vec::new();
                    stream.read_to_end(&mut buffer).unwrap();
                    println!("Received {} bytes", buffer.len());
                    
                    // Process the data (in this case, just echo it back)
                    // In a real application, you would parse and process the message here
                    
                    // Send the reply
                    stream.write_all(&buffer).unwrap();
                    println!("Sent reply");
                });
            }
            Err(e) => {
                eprintln!("Error accepting connection: {}", e);
            }
        }
    }
}

Troubleshooting

Message Not Being Forwarded to Socket

  1. Check that the topic is correctly configured with a socket path
  2. Verify that the socket server is running and the socket file exists
  3. Ensure that the sender's IP is in the whitelisted subnets for the topic
  4. Check the logs for any socket connection or timeout errors

Socket Server Not Receiving Messages

  1. Verify that the socket path is correct and accessible
  2. Check that the socket server has the necessary permissions to read/write to the socket
  3. Ensure that the socket server is properly handling the connection

Reply Not Being Sent Back

  1. Verify that the socket server is sending a reply
  2. Check for any timeout errors in the logs
  3. Ensure that the original sender is still connected and able to receive the reply