### Get Node Entry from EPMD using Rust Source: https://github.com/sile/erl_dist/blob/master/README.md Connects to the local EPMD and retrieves information about a specific Erlang node. This example demonstrates the usage of `EpmdClient` for querying node details. ```rust use erl_dist::epmd::{DEFAULT_EPMD_PORT, EpmdClient}; use tokio::net::TcpStream; // Connect to the local EPMD. let connection = TcpStream::connect(("localhost", DEFAULT_EPMD_PORT)).await?; let client = EpmdClient::new(connection); // Get the information of a node. let node_name = "foo"; if let Some(node) = client.get_node(node_name).await? { println!("Found: {:?}", node); } else { println!("Not found"); } ``` -------------------------------- ### Configure Erlang Distribution Flags (Rust) Source: https://context7.com/sile/erl_dist/llms.txt Manages node capability negotiation using distribution flags during the Erlang handshake. It shows how to get mandatory flags, create custom flag sets, add specific capabilities like PUBLISHED or SPAWN, and check for supported features. ```rust use erl_dist::DistributionFlags; fn configure_distribution_flags() { // Get mandatory flags (required for OTP 26 compatibility) let mandatory = DistributionFlags::mandatory(); // Default flags (same as mandatory) let default = DistributionFlags::new(); // Create custom flag set let mut custom_flags = DistributionFlags::mandatory(); // Add PUBLISHED flag to make node visible in cluster custom_flags |= DistributionFlags::PUBLISHED; // Add SPAWN flag to support remote spawn operations custom_flags |= DistributionFlags::SPAWN; // Add ALIAS flag for process alias support custom_flags |= DistributionFlags::ALIAS; // Check for specific capabilities if custom_flags.contains(DistributionFlags::HANDSHAKE_23) { println!("Supports OTP 23+ handshake"); } if custom_flags.contains(DistributionFlags::UNLINK_ID) { println!("Supports new link protocol"); } // Intersect flags during handshake for compatibility let peer_flags = DistributionFlags::mandatory() | DistributionFlags::SPAWN; let negotiated = custom_flags & peer_flags; println!("Negotiated flags: {:?}", negotiated); } ``` -------------------------------- ### Configure Local Node Information in Rust Source: https://context7.com/sile/erl_dist/llms.txt Shows how to initialize a local node with a unique creation identifier and distribution flags. This is essential for identifying the node within an Erlang cluster. ```rust use erl_dist::node::{LocalNode, Creation, NodeName}; use erl_dist::DistributionFlags; fn create_local_node() -> Result<(), Box> { let node_name: NodeName = "myapp@localhost".parse()?; // Generate a random creation (incarnation identifier) let creation = Creation::random(); // Create local node with default flags let local_node = LocalNode::new(node_name, creation); println!("Node: {}", local_node.name); println!("Creation: {}", local_node.creation.get()); println!("Flags: {:?}", local_node.flags); // Customize flags for a published node let mut published_node = local_node.clone(); published_node.flags |= DistributionFlags::PUBLISHED; Ok(()) } ``` -------------------------------- ### Parse and Create Node Names in Rust Source: https://context7.com/sile/erl_dist/llms.txt Demonstrates how to represent Erlang node names in 'name@host' format. It covers parsing from strings and programmatic creation using the NodeName struct. ```rust use erl_dist::node::NodeName; fn create_node_names() -> Result<(), Box> { // Parse from string let node_name: NodeName = "foo@localhost".parse()?; println!("Name: {}", node_name.name()); // "foo" println!("Host: {}", node_name.host()); // "localhost" println!("Full: {}", node_name); // "foo@localhost" // Create programmatically let node_name = NodeName::new("bar", "192.168.1.100")?; println!("Full: {}", node_name); // "bar@192.168.1.100" Ok(()) } ``` -------------------------------- ### Implement Erlang Distribution Client in Rust Source: https://context7.com/sile/erl_dist/llms.txt Demonstrates how to connect to an Erlang node by querying EPMD, performing a handshake, and sending a message. It utilizes the smol runtime for asynchronous networking. ```rust use erl_dist::LOWEST_DISTRIBUTION_PROTOCOL_VERSION; use erl_dist::epmd::{DEFAULT_EPMD_PORT, EpmdClient}; use erl_dist::node::{Creation, LocalNode}; use erl_dist::handshake::ClientSideHandshake; use erl_dist::message::{channel, Message}; use erl_dist::term::{Atom, Pid}; use smol::net::TcpStream; async fn send_to_erlang_node( peer_name: &str, peer_host: &str, cookie: &str, destination: &str, message: &str, ) -> Result<(), Box> { let epmd_connection = TcpStream::connect((peer_host, DEFAULT_EPMD_PORT)).await?; let epmd_client = EpmdClient::new(epmd_connection); let peer_info = epmd_client.get_node(peer_name).await? .ok_or("Peer node not found in EPMD")?; let connection = TcpStream::connect((peer_host, peer_info.port)).await?; let creation = Creation::random(); let local_node = LocalNode::new( format!("rust_client@{}", peer_host).parse()?, creation ); let mut handshake = ClientSideHandshake::new( connection, local_node.clone(), cookie ); let _status = handshake.execute_send_name(LOWEST_DISTRIBUTION_PROTOCOL_VERSION).await?; let (connection, peer_node) = handshake.execute_rest(true).await?; let capability_flags = local_node.flags & peer_node.flags; let (mut tx, _rx) = channel(connection, capability_flags); let from_pid = Pid::new(local_node.name.to_string(), 0, 0, creation.get()); let msg = Message::reg_send( from_pid, Atom::from(destination), Atom::from(message).into() ); tx.send(msg).await?; Ok(()) } ``` -------------------------------- ### Implement Erlang Distribution Server in Rust Source: https://context7.com/sile/erl_dist/llms.txt Demonstrates how to register a Rust node with EPMD, listen for incoming connections, and handle Erlang distribution messages. It includes logic for responding to heartbeat ticks and processing incoming messages. ```rust use erl_dist::epmd::{DEFAULT_EPMD_PORT, EpmdClient, NodeEntry}; use erl_dist::node::{Creation, LocalNode}; use erl_dist::handshake::{ServerSideHandshake, HandshakeStatus}; use erl_dist::message::{channel, Message}; use smol::net::{TcpListener, TcpStream}; use futures::stream::StreamExt; async fn run_erlang_node_server( node_name: &str, host: &str, cookie: &str, ) -> Result<(), Box> { let listener = TcpListener::bind("0.0.0.0:0").await?; let port = listener.local_addr()?.port(); let epmd_connection = TcpStream::connect((host, DEFAULT_EPMD_PORT)).await?; let epmd_client = EpmdClient::new(epmd_connection); let node_entry = NodeEntry::new_hidden(node_name, port); let (_keepalive, creation) = epmd_client.register(node_entry).await?; let mut incoming = listener.incoming(); while let Some(stream) = incoming.next().await { let stream = stream?; let local_node = LocalNode::new(format!("{}@{}", node_name, host).parse()?, creation); let cookie = cookie.to_string(); smol::spawn(async move { let _ = handle_connection(stream, local_node, &cookie).await; }).detach(); } Ok(()) } async fn handle_connection(stream: TcpStream, local_node: LocalNode, cookie: &str) -> Result<(), Box> { let mut handshake = ServerSideHandshake::new(stream, local_node.clone(), cookie); let _peer_name = handshake.execute_recv_name().await?; let (connection, peer_node) = handshake.execute_rest(HandshakeStatus::Ok).await?; let (mut tx, mut rx) = channel(connection, local_node.flags & peer_node.flags); loop { match rx.recv().await { Ok(Message::Tick) => { tx.send(Message::Tick).await?; } Ok(msg) => println!("Received: {:?}", msg), Err(_) => break, } } Ok(()) } ``` -------------------------------- ### Accept Server-Side Handshake in Rust Source: https://context7.com/sile/erl_dist/llms.txt Demonstrates how to accept incoming connections from Erlang nodes. It manages the server-side handshake, including receiving peer names and finalizing the connection. ```rust use erl_dist::node::{Creation, LocalNode}; use erl_dist::handshake::{ServerSideHandshake, HandshakeStatus}; use smol::net::{TcpListener, TcpStream}; async fn accept_connection( stream: TcpStream, cookie: &str, ) -> Result<(), Box> { let creation = Creation::random(); let local_node = LocalNode::new("server@localhost".parse()?, creation); // Initialize server-side handshake let mut handshake = ServerSideHandshake::new(stream, local_node.clone(), cookie); // Receive the peer's name let peer_name = handshake.execute_recv_name().await?; let status = if let Some(name) = peer_name { println!("Incoming connection from: {}", name); HandshakeStatus::Ok } else { // Peer requested dynamic name println!("Peer requested dynamic name, generating..."); HandshakeStatus::Named { name: "dynamic_node".to_owned(), creation: Creation::random(), } }; // Complete the handshake let (connection, peer_node) = handshake.execute_rest(status).await?; println!("Accepted connection from: {}", peer_node.name); Ok(()) } ``` -------------------------------- ### Send Message to Erlang Node using Rust Source: https://github.com/sile/erl_dist/blob/master/README.md Establishes a connection to a peer Erlang node, performs a handshake, and sends a message. This involves setting up local node information, executing the handshake process, and utilizing a channel to transmit the message. ```rust use erl_dist::LOWEST_DISTRIBUTION_PROTOCOL_VERSION; use erl_dist::node::{Creation, LocalNode}; use erl_dist::handshake::ClientSideHandshake; use erl_dist::term::{Atom, Pid}; use erl_dist::message::{channel, Message}; use tokio::net::TcpStream; // Connect to a peer node. let peer_host = "localhost"; let peer_port = 7483; // NOTE: Usually, port number is retrieved from EPMD. let connection = TcpStream::connect((peer_host, peer_port)).await?; // Local node information. let creation = Creation::random(); let local_node = LocalNode::new("foo@localhost".parse()?, creation); // Do handshake. let mut handshake = ClientSideHandshake::new(connection, local_node.clone(), "cookie"); let _status = handshake.execute_send_name(LOWEST_DISTRIBUTION_PROTOCOL_VERSION).await?; let (connection, peer_node) = handshake.execute_rest(true).await?; // Create a channel. let capability_flags = local_node.flags & peer_node.flags; let (mut tx, _) = channel(connection, capability_flags); // Send a message. let from_pid = Pid::new(local_node.name.to_string(), 0, 0, local_node.creation.get()); let to_name = Atom::from("bar"); let msg = Message::reg_send(from_pid, to_name, Atom::from("hello").into()); tx.send(msg).await?; ``` -------------------------------- ### Create EPMD Client in Rust Source: https://context7.com/sile/erl_dist/llms.txt Demonstrates creating an EpmdClient instance using an existing TCP connection to the EPMD service. This client is then used for interacting with the Erlang Port Mapper Daemon. ```rust use erl_dist::epmd::{DEFAULT_EPMD_PORT, EpmdClient}; use smol::net::TcpStream; async fn create_epmd_client() -> Result<(), Box> { // Connect to local EPMD on default port 4369 let connection = TcpStream::connect(("localhost", DEFAULT_EPMD_PORT)).await?; let client = EpmdClient::new(connection); // Client is now ready to query or register nodes Ok(()) } ``` -------------------------------- ### EPMD Client API Source: https://context7.com/sile/erl_dist/llms.txt Methods for interacting with the Erlang Port Mapper Daemon (EPMD) to manage node registration and discovery. ```APIDOC ## GET /epmd/node ### Description Queries EPMD for information about a specific registered node by its name. ### Method GET ### Endpoint /epmd/node?name={node_name} ### Parameters #### Query Parameters - **name** (string) - Required - The name of the node to look up. ### Response #### Success Response (200) - **name** (string) - Node name - **port** (u16) - Port number - **node_type** (enum) - Type of node (e.g., Normal, Hidden) - **highest_version** (u16) - Highest supported protocol version --- ## POST /epmd/register ### Description Registers a new node with EPMD. The registration remains active as long as the TCP connection is maintained. ### Method POST ### Request Body - **name** (string) - Required - Name of the node - **port** (u16) - Required - Port the node is listening on - **hidden** (bool) - Optional - Whether the node is hidden (C-node style) ### Response #### Success Response (200) - **creation** (u32) - The creation identifier for the registered node. ``` -------------------------------- ### Create Erlang Distribution Message Channel (Rust) Source: https://context7.com/sile/erl_dist/llms.txt Establishes a bidirectional message channel for Erlang distribution messages after a successful handshake. It takes an asynchronous read/write connection and distribution flags, returning sender and receiver halves of the channel. ```rust use erl_dist::message::{channel, Message, Sender, Receiver}; use erl_dist::term::{Atom, Pid}; use erl_dist::DistributionFlags; async fn create_channel( connection: T, local_flags: DistributionFlags, peer_flags: DistributionFlags, ) -> (Sender, Receiver) where T: futures::io::AsyncRead + futures::io::AsyncWrite + Unpin + Clone, { // Use intersection of flags for compatibility let capability_flags = local_flags & peer_flags; // Create the channel let (tx, rx) = channel(connection, capability_flags); (tx, rx) } ``` -------------------------------- ### DistributionFlags - Node Capability Negotiation Source: https://context7.com/sile/erl_dist/llms.txt Represents bit flags for Erlang node capabilities negotiated during the handshake. Allows configuration, checking, and intersection of flags for compatibility. ```APIDOC ## DistributionFlags - Node Capability Negotiation ### Description Bit flags representing node capabilities that are negotiated during the handshake process. Allows configuration, checking, and intersection of flags for compatibility. ### Method (Configuration and query methods) ### Endpoint (Not applicable, this is a data structure/type) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```rust use erl_dist::DistributionFlags; fn configure_distribution_flags() { // Get mandatory flags (required for OTP 26 compatibility) let mandatory = DistributionFlags::mandatory(); // Default flags (same as mandatory) let default = DistributionFlags::new(); // Create custom flag set let mut custom_flags = DistributionFlags::mandatory(); // Add PUBLISHED flag to make node visible in cluster custom_flags |= DistributionFlags::PUBLISHED; // Add SPAWN flag to support remote spawn operations custom_flags |= DistributionFlags::SPAWN; // Add ALIAS flag for process alias support custom_flags |= DistributionFlags::ALIAS; // Check for specific capabilities if custom_flags.contains(DistributionFlags::HANDSHAKE_23) { println!("Supports OTP 23+ handshake"); } if custom_flags.contains(DistributionFlags::UNLINK_ID) { println!("Supports new link protocol"); } // Intersect flags during handshake for compatibility let peer_flags = DistributionFlags::mandatory() | DistributionFlags::SPAWN; let negotiated = custom_flags & peer_flags; println!("Negotiated flags: {:?}", negotiated); } ``` ### Response #### Success Response (200) (N/A, this is configuration/querying of flags) #### Response Example (Prints information about flags to console or returns `DistributionFlags` objects.) ``` -------------------------------- ### Perform Client-Side Handshake in Rust Source: https://context7.com/sile/erl_dist/llms.txt Illustrates the process of connecting to a remote Erlang node as a client. It handles the handshake protocol, including name exchange and authentication via cookie. ```rust use erl_dist::LOWEST_DISTRIBUTION_PROTOCOL_VERSION; use erl_dist::node::{Creation, LocalNode}; use erl_dist::handshake::{ClientSideHandshake, HandshakeStatus}; use smol::net::TcpStream; async fn connect_to_node( peer_host: &str, peer_port: u16, cookie: &str, ) -> Result<(), Box> { // Connect to the peer node let connection = TcpStream::connect((peer_host, peer_port)).await?; // Create local node identity let creation = Creation::random(); let local_node = LocalNode::new("client@localhost".parse()?, creation); // Initialize handshake let mut handshake = ClientSideHandshake::new(connection, local_node.clone(), cookie); // Execute first phase - send name let status = handshake.execute_send_name(LOWEST_DISTRIBUTION_PROTOCOL_VERSION).await?; match status { HandshakeStatus::Ok | HandshakeStatus::OkSimultaneous => { println!("Handshake status OK, continuing..."); } HandshakeStatus::Alive => { println!("Node already connected, continuing anyway..."); } HandshakeStatus::Nok => { return Err("Handshake rejected: ongoing handshake".into()); } HandshakeStatus::NotAllowed => { return Err("Handshake rejected: not allowed".into()); } HandshakeStatus::Named { name, creation } => { println!("Received dynamic name: {} (creation: {})", name, creation.get()); } } // Execute second phase - complete handshake let (connection, peer_node) = handshake.execute_rest(true).await?; println!("Connected to: {}", peer_node.name); println!("Peer flags: {:?}", peer_node.flags); Ok(()) } ``` -------------------------------- ### Create Message Channel Source: https://context7.com/sile/erl_dist/llms.txt Creates a bidirectional message channel for sending and receiving Erlang distribution messages after a successful handshake. This function takes an asynchronous read/write connection and distribution flags to establish the channel. ```APIDOC ## channel - Create Message Channel ### Description Creates a bidirectional message channel for sending and receiving Erlang distribution messages after a successful handshake. ### Method (Implicitly POST or similar, as it establishes a channel) ### Endpoint (Not explicitly defined, but related to connection establishment) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```rust use erl_dist::message::{channel, Message, Sender, Receiver}; use erl_dist::term::{Atom, Pid}; use erl_dist::DistributionFlags; async fn create_channel( connection: T, local_flags: DistributionFlags, peer_flags: DistributionFlags, ) -> (Sender, Receiver) where T: futures::io::AsyncRead + futures::io::AsyncWrite + Unpin + Clone, { // Use intersection of flags for compatibility let capability_flags = local_flags & peer_flags; // Create the channel let (tx, rx) = channel(connection, capability_flags); (tx, rx) } ``` ### Response #### Success Response (200) - **Sender** (Sender) - A sender half of the message channel. - **Receiver** (Receiver) - A receiver half of the message channel. #### Response Example (Tuple containing Sender and Receiver objects) ``` -------------------------------- ### EPMD Utility API Source: https://context7.com/sile/erl_dist/llms.txt Administrative and debugging endpoints for EPMD interaction. ```APIDOC ## GET /epmd/names ### Description Retrieves a list of all currently registered node names and their associated ports from EPMD. ### Method GET ### Response #### Success Response (200) - **nodes** (list) - List of tuples containing (name, port) --- ## GET /epmd/dump ### Description Retrieves a full debug dump of all registered nodes and their internal state from EPMD. ### Method GET ### Response #### Success Response (200) - **dump_info** (string) - Formatted string containing active node details and file descriptors. ``` -------------------------------- ### List All Registered Nodes in EPMD in Rust Source: https://context7.com/sile/erl_dist/llms.txt Retrieves and lists all currently registered node names and their corresponding ports from EPMD. This is useful for monitoring active nodes in the Erlang network. ```rust use erl_dist::epmd::{DEFAULT_EPMD_PORT, EpmdClient}; use smol::net::TcpStream; async fn list_all_nodes() -> Result<(), Box> { let connection = TcpStream::connect(("localhost", DEFAULT_EPMD_PORT)).await?; let client = EpmdClient::new(connection); let nodes = client.get_names().await?; for (name, port) in nodes { println!("Node '{}' at port {}", name, port); } // Output example: // Node 'foo' at port 52431 // Node 'bar' at port 52432 Ok(()) } ``` -------------------------------- ### Receive Erlang Distribution Messages (Rust) Source: https://context7.com/sile/erl_dist/llms.txt Receives Erlang distribution messages from connected Erlang nodes. It handles various message types including 'Tick', 'RegSend', 'Send', 'Link', and 'Exit', and detects connection closure. ```rust use erl_dist::message::{channel, Message, RecvError}; use erl_dist::DistributionFlags; use smol::net::TcpStream; async fn receive_messages( connection: TcpStream, flags: DistributionFlags, ) -> Result<(), Box> { let (_tx, mut rx) = channel(connection, flags); loop { match rx.recv().await { Ok(Message::Tick) => { println!("Received tick (keepalive)"); } Ok(Message::RegSend(msg)) => { println!("Message from {} to {}: {:?}", msg.from_pid, msg.to_name, msg.message); } Ok(Message::Send(msg)) => { println!("Direct message to {}: {:?}", msg.to_pid, msg.message); } Ok(Message::Link(link)) => { println!("Link request: {} -> {}", link.from_pid, link.to_pid); } Ok(Message::Exit(exit)) => { println!("Exit: {} -> {} reason: {:?}", exit.from_pid, exit.to_pid, exit.reason); } Ok(msg) => { println!("Other message: {:?}", msg); } Err(RecvError::Closed) => { println!("Connection closed by peer"); break; } Err(e) => { eprintln!("Error receiving message: {}", e); return Err(e.into()); } } } Ok(()) } ``` -------------------------------- ### Retrieve EPMD Debug Dump in Rust Source: https://context7.com/sile/erl_dist/llms.txt Fetches and prints debug information about all nodes currently registered with EPMD. This is useful for diagnosing EPMD status and registered nodes. ```rust use erl_dist::epmd::{DEFAULT_EPMD_PORT, EpmdClient}; use smol::net::TcpStream; async fn dump_epmd() -> Result<(), Box> { let connection = TcpStream::connect(("localhost", DEFAULT_EPMD_PORT)).await?; let client = EpmdClient::new(connection); let dump_info = client.dump().await?; println!("{}", dump_info); // Output example: // active name foo at port 52431, fd = 5 // active name bar at port 52432, fd = 6 Ok(()) } ``` -------------------------------- ### Register Node with EPMD in Rust Source: https://context7.com/sile/erl_dist/llms.txt Registers a new node with EPMD, making it discoverable. The registration is maintained as long as the returned connection is kept alive; dropping the connection automatically unregisters the node. ```rust use erl_dist::epmd::{DEFAULT_EPMD_PORT, EpmdClient, NodeEntry}; use smol::net::TcpStream; async fn register_node() -> Result<(), Box> { let connection = TcpStream::connect(("localhost", DEFAULT_EPMD_PORT)).await?; let client = EpmdClient::new(connection); // Create a normal (visible) node entry let node = NodeEntry::new("mynode", 9000); // Or create a hidden node (C-node style) // let node = NodeEntry::new_hidden("mynode", 9000); // Register the node - keep the connection alive to stay registered let (keepalive_connection, creation) = client.register(node).await?; println!("Registered with creation: {:?}", creation.get()); // Node stays registered as long as keepalive_connection is held // When dropped, node is automatically unregistered Ok(()) } ``` -------------------------------- ### Send Erlang Distribution Messages (Rust) Source: https://context7.com/sile/erl_dist/llms.txt Sends various types of Erlang distribution messages to connected Erlang nodes. It supports sending to registered process names or specific PIDs, and includes sending a 'Tick' message for keepalive. ```rust use erl_dist::message::{channel, Message}; use erl_dist::term::{Atom, Pid}; use erl_dist::node::Creation; use erl_dist::DistributionFlags; use smol::net::TcpStream; async fn send_message( connection: TcpStream, flags: DistributionFlags, local_node_name: &str, creation: Creation, ) -> Result<(), Box> { let (mut tx, _rx) = channel(connection, flags); // Create a PID for the sender let from_pid = Pid::new(local_node_name.to_string(), 0, 0, creation.get()); // Send to a registered process name let to_name = Atom::from("my_process"); let message_content = Atom::from("hello_from_rust").into(); let msg = Message::reg_send(from_pid.clone(), to_name, message_content); tx.send(msg).await?; // Send to a specific PID let to_pid = Pid::new("peer@localhost".to_string(), 100, 0, 1); let message_content = Atom::from("direct_message").into(); let msg = Message::send(to_pid, message_content); tx.send(msg).await?; // Send a tick to keep connection alive (required periodically) tx.send(Message::Tick).await?; Ok(()) } ``` -------------------------------- ### Receiver::recv - Receive Messages from Erlang Nodes Source: https://context7.com/sile/erl_dist/llms.txt Receives distribution messages from connected Erlang nodes. Handles various message types including 'Tick', 'RegSend', 'Send', 'Link', and 'Exit'. It also manages connection closure. ```APIDOC ## Receiver::recv - Receive Messages from Erlang Nodes ### Description Receives distribution messages from connected Erlang nodes. Handles various message types including 'Tick', 'RegSend', 'Send', 'Link', and 'Exit'. It also manages connection closure. ### Method (Implicitly GET or similar, as it retrieves data) ### Endpoint (Not explicitly defined, but related to an established channel) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```rust use erl_dist::message::{channel, Message, RecvError}; use erl_dist::DistributionFlags; use smol::net::TcpStream; async fn receive_messages( connection: TcpStream, flags: DistributionFlags, ) -> Result<(), Box> { let (_tx, mut rx) = channel(connection, flags); loop { match rx.recv().await { Ok(Message::Tick) => { println!("Received tick (keepalive)"); } Ok(Message::RegSend(msg)) => { println!("Message from {} to {}: {:?}", msg.from_pid, msg.to_name, msg.message); } Ok(Message::Send(msg)) => { println!("Direct message to {}: {:?}", msg.to_pid, msg.message); } Ok(Message::Link(link)) => { println!("Link request: {} -> {}", link.from_pid, link.to_pid); } Ok(Message::Exit(exit)) => { println!("Exit: {} -> {} reason: {:?}", exit.from_pid, exit.to_pid, exit.reason); } Ok(msg) => { println!("Other message: {:?}", msg); } Err(RecvError::Closed) => { println!("Connection closed by peer"); break; } Err(e) => { eprintln!("Error receiving message: {}", e); return Err(e.into()); } } } Ok(()) } ``` ### Response #### Success Response (200) - **Message** (Enum) - A received Erlang distribution message. - **RecvError** (Enum) - An error encountered during message reception, such as `Closed`. #### Response Example (Prints received message details to console or returns `Ok(())` on success, `Err(RecvError)` on failure.) ``` -------------------------------- ### Sender::send - Send Messages to Erlang Nodes Source: https://context7.com/sile/erl_dist/llms.txt Sends distribution messages to connected Erlang nodes. Supports sending registered messages by name and direct messages to a specific process ID (PID). Includes sending a 'Tick' message for keepalive. ```APIDOC ## Sender::send - Send Messages to Erlang Nodes ### Description Sends distribution messages to connected Erlang nodes. Supports sending registered messages by name and direct messages to a specific process ID (PID). Includes sending a 'Tick' message for keepalive. ### Method (Implicitly POST or similar, as it sends data) ### Endpoint (Not explicitly defined, but related to an established channel) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body (Implicitly the `Message` object passed to `tx.send()`) ### Request Example ```rust use erl_dist::message::{channel, Message}; use erl_dist::term::{Atom, Pid}; use erl_dist::node::Creation; use erl_dist::DistributionFlags; use smol::net::TcpStream; async fn send_message( connection: TcpStream, flags: DistributionFlags, local_node_name: &str, creation: Creation, ) -> Result<(), Box> { let (mut tx, _rx) = channel(connection, flags); // Create a PID for the sender let from_pid = Pid::new(local_node_name.to_string(), 0, 0, creation.get()); // Send to a registered process name let to_name = Atom::from("my_process"); let message_content = Atom::from("hello_from_rust").into(); let msg = Message::reg_send(from_pid.clone(), to_name, message_content); tx.send(msg).await?; // Send to a specific PID let to_pid = Pid::new("peer@localhost".to_string(), 100, 0, 1); let message_content = Atom::from("direct_message").into(); let msg = Message::send(to_pid, message_content); tx.send(msg).await?; // Send a tick to keep connection alive (required periodically) tx.send(Message::Tick).await?; Ok(()) } ``` ### Response #### Success Response (200) Indicates the message was successfully sent over the channel. #### Response Example `Ok(())` ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.