fn main() -> noargs::Result<()> {
let mut args = noargs::raw_args();
args.metadata_mut().app_name = "send_msg";
args.metadata_mut().app_description = "Send a message to an Erlang node";
noargs::HELP_FLAG.take_help(&mut args);
let local_node: erl_dist::node::NodeName = noargs::opt("local")
.default("bar@localhost")
.doc("Local node name")
.take(&mut args)
.then(|a| a.value().parse())?;
let peer_node: erl_dist::node::NodeName = noargs::opt("peer")
.default("foo@localhost")
.doc("Peer node name")
.take(&mut args)
.then(|a| a.value().parse())?;
let cookie: String = noargs::opt("cookie")
.default("WPKYDIOSJIMJUURLRUHV")
.doc("Erlang cookie")
.take(&mut args)
.then(|a| a.value().parse())?;
let destination: String = noargs::opt("destination")
.short('d')
.default("foo")
.doc("Destination process name")
.take(&mut args)
.then(|a| a.value().parse())?;
let message: String = noargs::opt("message")
.short('m')
.default("hello_world")
.doc("Message to send")
.take(&mut args)
.then(|a| a.value().parse())?;
if let Some(help) = args.finish()? {
print!("{help}");
return Ok(());
}
smol::block_on(async {
let peer_node_info = {
let addr = (peer_node.host(), erl_dist::epmd::DEFAULT_EPMD_PORT);
let stream = smol::net::TcpStream::connect(addr).await?;
let epmd_client = erl_dist::epmd::EpmdClient::new(stream);
epmd_client
.get_node(&peer_node.name())
.await?
.ok_or("peer node not found")?
};
println!("Got peer node info: {:?}", peer_node_info);
let creation = erl_dist::node::Creation::random();
let stream = smol::net::TcpStream::connect((peer_node.host(), peer_node_info.port)).await?;
let local_node = erl_dist::node::LocalNode::new(local_node, creation);
let mut handshake =
erl_dist::handshake::ClientSideHandshake::new(stream, local_node.clone(), &cookie);
let _status = handshake
.execute_send_name(erl_dist::LOWEST_DISTRIBUTION_PROTOCOL_VERSION)
.await?;
let (connection, peer_node) = handshake.execute_rest(true).await?;
println!("Handshake finished: peer={:?}", peer_node);
let (mut tx, _) =
erl_dist::message::channel(connection, local_node.flags & peer_node.flags);
let pid = eetf::Pid::new(local_node.name.to_string(), 0, 0, creation.get());
let msg = erl_dist::message::Message::reg_send(
pid,
eetf::Atom::from(destination),
eetf::Atom::from(message).into(),
);
tx.send(msg).await?;
Ok::<(), Box<dyn std::error::Error>>(())
})?;
Ok(())
}