9.8 KiB
Mycelium Tutorial for Rhai
This tutorial explains how to use the Mycelium networking functionality in Rhai scripts. Mycelium is a peer-to-peer networking system that allows nodes to communicate with each other, and the Rhai bindings provide an easy way to interact with Mycelium from your scripts.
Introduction
The Mycelium module for Rhai provides the following capabilities:
- Getting node information
- Managing peers (listing, adding, removing)
- Viewing routing information
- Sending and receiving messages between nodes
This tutorial will walk you through using these features with example scripts.
Prerequisites
Before using the Mycelium functionality in Rhai, you need:
- A running Mycelium node accessible via HTTP
- The Rhai runtime with Mycelium module enabled
Basic Mycelium Operations
Let's start by exploring the basic operations available in Mycelium using the mycelium_basic.rhai
example.
Getting Node Information
To get information about your Mycelium node:
// API URL for Mycelium
let api_url = "http://localhost:8989";
// Get node information
print("Getting node information:");
try {
let node_info = mycelium_get_node_info(api_url);
print(`Node subnet: ${node_info.nodeSubnet}`);
print(`Node public key: ${node_info.nodePubkey}`);
} catch(err) {
print(`Error getting node info: ${err}`);
}
This code:
- Sets the API URL for your Mycelium node
- Calls
mycelium_get_node_info()
to retrieve information about the node - Prints the node's subnet and public key
Managing Peers
Listing Peers
To list all peers connected to your Mycelium node:
// List all peers
print("\nListing all peers:");
try {
let peers = mycelium_list_peers(api_url);
if peers.is_empty() {
print("No peers connected.");
} else {
for peer in peers {
print(`Peer Endpoint: ${peer.endpoint.proto}://${peer.endpoint.socketAddr}`);
print(` Type: ${peer.type}`);
print(` Connection State: ${peer.connectionState}`);
print(` Bytes sent: ${peer.txBytes}`);
print(` Bytes received: ${peer.rxBytes}`);
}
}
} catch(err) {
print(`Error listing peers: ${err}`);
}
This code:
- Calls
mycelium_list_peers()
to get all connected peers - Iterates through the peers and prints their details
Adding a Peer
To add a new peer to your Mycelium node:
// Add a new peer
print("\nAdding a new peer:");
let new_peer_address = "tcp://65.21.231.58:9651";
try {
let result = mycelium_add_peer(api_url, new_peer_address);
print(`Peer added: ${result.success}`);
} catch(err) {
print(`Error adding peer: ${err}`);
}
This code:
- Specifies a peer address to add
- Calls
mycelium_add_peer()
to add the peer to your node - Prints whether the operation was successful
Removing a Peer
To remove a peer from your Mycelium node:
// Remove a peer
print("\nRemoving a peer:");
let peer_id = "tcp://65.21.231.58:9651"; // This is the peer we added earlier
try {
let result = mycelium_remove_peer(api_url, peer_id);
print(`Peer removed: ${result.success}`);
} catch(err) {
print(`Error removing peer: ${err}`);
}
This code:
- Specifies the peer ID to remove
- Calls
mycelium_remove_peer()
to remove the peer - Prints whether the operation was successful
Viewing Routing Information
Listing Selected Routes
To list the selected routes in your Mycelium node:
// List selected routes
print("\nListing selected routes:");
try {
let routes = mycelium_list_selected_routes(api_url);
if routes.is_empty() {
print("No selected routes.");
} else {
for route in routes {
print(`Subnet: ${route.subnet}`);
print(` Next hop: ${route.nextHop}`);
print(` Metric: ${route.metric}`);
}
}
} catch(err) {
print(`Error listing routes: ${err}`);
}
This code:
- Calls
mycelium_list_selected_routes()
to get all selected routes - Iterates through the routes and prints their details
Listing Fallback Routes
To list the fallback routes in your Mycelium node:
// List fallback routes
print("\nListing fallback routes:");
try {
let routes = mycelium_list_fallback_routes(api_url);
if routes.is_empty() {
print("No fallback routes.");
} else {
for route in routes {
print(`Subnet: ${route.subnet}`);
print(` Next hop: ${route.nextHop}`);
print(` Metric: ${route.metric}`);
}
}
} catch(err) {
print(`Error listing fallback routes: ${err}`);
}
This code:
- Calls
mycelium_list_fallback_routes()
to get all fallback routes - Iterates through the routes and prints their details
Sending Messages
Now let's look at how to send messages using the mycelium_send_message.rhai
example.
// API URL for Mycelium
let api_url = "http://localhost:1111";
// Send a message
print("\nSending a message:");
let destination = "5af:ae6b:dcd8:ffdb:b71:7dde:d3:1033"; // Replace with the actual destination IP address
let topic = "test_topic";
let message = "Hello from Rhai sender!";
let deadline_secs = -10; // Seconds we wait for a reply
try {
print(`Attempting to send message to ${destination} on topic '${topic}'`);
let result = mycelium_send_message(api_url, destination, topic, message, deadline_secs);
print(`result: ${result}`);
print(`Message sent: ${result.success}`);
if result.id != "" {
print(`Message ID: ${result.id}`);
}
} catch(err) {
print(`Error sending message: ${err}`);
}
This code:
- Sets the API URL for your Mycelium node
- Specifies the destination IP address, topic, message content, and deadline
- Calls
mycelium_send_message()
to send the message - Prints the result, including the message ID if successful
Important Parameters for Sending Messages
api_url
: The URL of your Mycelium node's APIdestination
: The IP address of the destination nodetopic
: The topic to send the message on (must match what the receiver is listening for)message
: The content of the messagedeadline_secs
: Time in seconds to wait for a reply. Use a negative value if you don't want to wait for a reply.
Receiving Messages
Now let's look at how to receive messages using the mycelium_receive_message.rhai
example.
// API URL for Mycelium
let api_url = "http://localhost:2222";
// Receive messages
print("\nReceiving messages:");
let receive_topic = "test_topic";
let wait_deadline_secs = 100;
print(`Listening for messages on topic '${receive_topic}'...`);
try {
let messages = mycelium_receive_messages(api_url, receive_topic, wait_deadline_secs);
if messages.is_empty() {
// print("No new messages received in this poll.");
} else {
print("Received a message:");
print(` Message id: ${messages.id}`);
print(` Message from: ${messages.srcIp}`);
print(` Topic: ${messages.topic}`);
print(` Payload: ${messages.payload}`);
}
} catch(err) {
print(`Error receiving messages: ${err}`);
}
print("Finished attempting to receive messages.");
This code:
- Sets the API URL for your Mycelium node
- Specifies the topic to listen on and how long to wait for messages
- Calls
mycelium_receive_messages()
to receive messages - Processes and prints any received messages
Important Parameters for Receiving Messages
api_url
: The URL of your Mycelium node's APIreceive_topic
: The topic to listen for messages on (must match what the sender is using)wait_deadline_secs
: Time in seconds to wait for messages to arrive. The function will block for this duration if no messages are immediately available.
Complete Messaging Example
To set up a complete messaging system, you would typically run two instances of Mycelium (node A sender, node B receiver).
- Run the
mycelium_receive_message.rhai
script to listen for messages. Fill in the API address of node B. - Run the
mycelium_send_message.rhai
script to send messages. Fill in the API address of node A, and fill in the overlay address of node B as destination.
Setting Up the Receiver
First, start a Mycelium node and run the receiver script:
// API URL for Mycelium
let api_url = "http://localhost:2222"; // Your receiver node's API URL
// Receive messages
let receive_topic = "test_topic";
let wait_deadline_secs = 100; // Wait up to 100 seconds for messages
print(`Listening for messages on topic '${receive_topic}'...`);
try {
let messages = mycelium_receive_messages(api_url, receive_topic, wait_deadline_secs);
if messages.is_empty() {
print("No new messages received in this poll.");
} else {
print("Received a message:");
print(` Message id: ${messages.id}`);
print(` Message from: ${messages.srcIp}`);
print(` Topic: ${messages.topic}`);
print(` Payload: ${messages.payload}`);
}
} catch(err) {
print(`Error receiving messages: ${err}`);
}
Setting Up the Sender
Then, on another Mycelium node, run the sender script:
// API URL for Mycelium
let api_url = "http://localhost:1111"; // Your sender node's API URL
// Send a message
let destination = "5af:ae6b:dcd8:ffdb:b71:7dde:d3:1033"; // The receiver node's IP address
let topic = "test_topic"; // Must match the receiver's topic
let message = "Hello from Rhai sender!";
let deadline_secs = -10; // Don't wait for a reply
try {
print(`Attempting to send message to ${destination} on topic '${topic}'`);
let result = mycelium_send_message(api_url, destination, topic, message, deadline_secs);
print(`Message sent: ${result.success}`);
if result.id != "" {
print(`Message ID: ${result.id}`);
}
} catch(err) {
print(`Error sending message: ${err}`);
}