332 lines
9.8 KiB
Markdown
332 lines
9.8 KiB
Markdown
# 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:
|
|
|
|
1. A running Mycelium node accessible via HTTP
|
|
> See https://github.com/threefoldtech/mycelium
|
|
2. 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:
|
|
|
|
```rhai
|
|
// 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:
|
|
1. Sets the API URL for your Mycelium node
|
|
2. Calls `mycelium_get_node_info()` to retrieve information about the node
|
|
3. Prints the node's subnet and public key
|
|
|
|
### Managing Peers
|
|
|
|
#### Listing Peers
|
|
|
|
To list all peers connected to your Mycelium node:
|
|
|
|
```rhai
|
|
// 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:
|
|
1. Calls `mycelium_list_peers()` to get all connected peers
|
|
2. Iterates through the peers and prints their details
|
|
|
|
#### Adding a Peer
|
|
|
|
To add a new peer to your Mycelium node:
|
|
|
|
```rhai
|
|
// 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:
|
|
1. Specifies a peer address to add
|
|
2. Calls `mycelium_add_peer()` to add the peer to your node
|
|
3. Prints whether the operation was successful
|
|
|
|
#### Removing a Peer
|
|
|
|
To remove a peer from your Mycelium node:
|
|
|
|
```rhai
|
|
// 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:
|
|
1. Specifies the peer ID to remove
|
|
2. Calls `mycelium_remove_peer()` to remove the peer
|
|
3. Prints whether the operation was successful
|
|
|
|
### Viewing Routing Information
|
|
|
|
#### Listing Selected Routes
|
|
|
|
To list the selected routes in your Mycelium node:
|
|
|
|
```rhai
|
|
// 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:
|
|
1. Calls `mycelium_list_selected_routes()` to get all selected routes
|
|
2. Iterates through the routes and prints their details
|
|
|
|
#### Listing Fallback Routes
|
|
|
|
To list the fallback routes in your Mycelium node:
|
|
|
|
```rhai
|
|
// 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:
|
|
1. Calls `mycelium_list_fallback_routes()` to get all fallback routes
|
|
2. 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.
|
|
|
|
```rhai
|
|
// 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:
|
|
1. Sets the API URL for your Mycelium node
|
|
2. Specifies the destination IP address, topic, message content, and deadline
|
|
3. Calls `mycelium_send_message()` to send the message
|
|
4. Prints the result, including the message ID if successful
|
|
|
|
### Important Parameters for Sending Messages
|
|
|
|
- `api_url`: The URL of your Mycelium node's API
|
|
- `destination`: The IP address of the destination node
|
|
- `topic`: The topic to send the message on (must match what the receiver is listening for)
|
|
- `message`: The content of the message
|
|
- `deadline_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.
|
|
|
|
```rhai
|
|
// 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:
|
|
1. Sets the API URL for your Mycelium node
|
|
2. Specifies the topic to listen on and how long to wait for messages
|
|
3. Calls `mycelium_receive_messages()` to receive messages
|
|
4. Processes and prints any received messages
|
|
|
|
### Important Parameters for Receiving Messages
|
|
|
|
- `api_url`: The URL of your Mycelium node's API
|
|
- `receive_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).
|
|
|
|
1. Run the `mycelium_receive_message.rhai` script to listen for messages. **Fill in the API address of node B**.
|
|
2. 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:
|
|
|
|
```rhai
|
|
// 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:
|
|
|
|
```rhai
|
|
// 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}`);
|
|
}
|
|
``` |